uox3/source/cConsole.cpp
Xoduz c9e4c29367 0.99.4v
Added JS command to reload dictionaries
	'reloaddictionaries
Fixed a server crash related to casting of spells
Fixed some issues with Line-of-Sight checks related to items under/above ground, LoS checks between different floors of buildings, etc.
Updated handling of skill-training keywords to be based on language-independent keyword IDs rather than trying to match player-input text to specific skill-names
Updated animal-trainer/stablemasterscript (js/npc/ai/stablemaster.js) with several changes:
	Fixed an issue where the same pet would be stabled in all available slots if payment was taken from player's bank account instead of their backpack
	Fixed an issue where stablemaster would not pause walking for a while when a player interacts with them
	Converted all system messages and text messages in stablemaster script to dictionary entries
Added new NPC AI type to source - AI_STABLEMASTER (9) - and assigned this to animal trainers. This is used to identify this type of NPCs for the purpose of displaying relevant context menus
Reworked banker AI script (js/npc/ai/banker.js) to use triggerwords from client instead of hard-defined strings, to work better with multiple languages (and work with all relevant triggerwords)
Fixed a bug with banker AI script (js/npc/ai/banker.js) that prevented players from using the "withdraw" command
Re-added NPC AI 8 to banker NPCs (dfndata/npc/male_vendors.dfn and female_vendors.dfn) so code can check for presence of this AI when handling context menus
Removed remaining hard-coded banking functionality - all handled by script anyway
Added new context menu option for NPC bankers - Open Bankbox
Updated code handling of context menus to only show context menus when relevant:
	Open Paperdoll - Shows for all characters with a paperdoll
	Open Backpack - Shows for player's character, pack animals and hirelings
	Open Bankbox - Shows for banker NPCs (if within 8 tiles)
	Buy/Sell - Shows for vendor NPCs (if within 8 tiles, and if they have anything for sale/are buying anything)
Added new context menu entries for pets, which can be used if player is within 12 tiles of pet:
	Command: Kill
	Command: Stop
	Command: Follow
	Command: Stay
	Command: Guard
	Add Friend
	Remove Friend
	Transfer
	Release
Added new context menu entries for stablemasters/animal trainers:
	Claim All Pets
	Stable Pet
Added new context menu entries for Escort Quest NPCs
	Ask Destination (if within 3 tiles)
	Accept Escort (if within 3 tiles)
	Abandon Escort
Added new context menus for NPCs that can teach skills to players (limited to max 10 per NPC)
	Train [skillName]
Added new AI script for NPC hirelings (3204=js/npc/ai/hireling.js), who can be hired to follow the player around for a limited amount of time, and function the same way as pets. In addition to the regular pet commands, these speech commands are supported:
	hire 	// The hireling will respond with the cost to hire them
	dismiss // Replaces the "release" command for pets; will dismiss the hireling
	patrol 	// The hireling will patrol between it's current location and a second targeted location nearby
	move 	// The hireling will try to shuffle out of the way
	fetch 	// The hireling will try to fetch a targeted item
	drop 	// The hireling will drop to the ground all loot they're currently carrying
	report 	// The hireling will report on the remaining time they're hired for
Added new NPC DFN tag used by code to detect hireling NPCs for the purpose of displaying context menus:
	HIRELING 	// No additional value/data needed for tag
Added new context menu entries for Hireling NPCs, in addition to the ones for regular pets:
	Hire 	// Can be used within 3 steps of the hireling, who will respond with cost to hire them
	Dismiss // Replaces the "release" command for pets, will dismiss the hireling
Added HIRELING tag and SCRIPT=3204 to and updated stats of various NPCs that will be hireable:
	m_fighter, f_fighter, m_beggar, f_beggar, m_peasant, f_peasant, m_sailor, f_sailor, m_pirate, f_pirate
Added new hireling NPC:
	m_paladin, f_paladin
Added new UOX ini setting to enable/disable context menus
	CONTEXTMENUS=1/0 (defaults to 1)
Added new Item JS Method to check if an item's ID is on a specified food list
	.IsOnFoodList( foodList )	// Returns true/false if item's ID is on specified foodList
Added new OMNIVORE food list and assigned it to [basehuman] DFN section
Added new Character JS Properties
	.isGuarded 		// Gets/Sets whether character is guarded by a pet/hireling
	.guarding 		// Gets/Sets the object (if any) being guarded by a pet/hireling
Fixed multiple issues with health bars, flagging and character highlighting
Added some crash protection for invalid data used with CUSTOMINTTAG and CUSTOMSTRINGTAG DFN tags for Items, NPCs and Multis
Fixed an issue which prevented hard-coded checks from running when using items
Added new global js object (Timer) to make the use of character timers in JS more robust, with properties matching timer names from enum in source.
	Properties:
		.TIMEOUT 		// Time until next attack can be done in combat
		.INVIS			// Time until invisible character becomes visible
		.HUNGER			// Time until character grows more hungry
		.THIRST			// Time until character grows more thirsty
		.POISONTIME		// Time until next tick of poison damage
		.POISONTEXT		// Time until next message about suffering from poison
		.POISONWEAROFF	// Time until poison wears off
		.SPELLTIME		// Time until spell cast is completed. Can be set to 0 to interrupt
		.ANTISPAM		// Time until next speech message can be sent (for anti spam purposes)
		.CRIMFLAG		// Time until criminal flag runs out
		.MURDERRATE		// Time until next murder count decay
		.PEACETIMER		// Time until character can re-enter combat after being affected by peacemaking
		.FLYINGTOGGLE	// Time until next time flying ability can be toggled for gargoyles
		.MOVETIME		// Time until NPC can move again
		.SPATIMER		// Time until next time NPC can cast a spell
		.SUMMONTIME		// Time until a summoned NPC will vanish
		.EVADETIME		// Time until an NPC will exit evade state
		.LOGOUT			// Time it takes for a player char to vanish after logout
	Examples of use:
		var hungerTimer = myChar.GetTimer( Timer.HUNGER )
		myChar.SetTimer( Timer.HUNGER, 15000 )
Added new Character JS Methods to add, remove and list friends of a pet/hireling:
	.AddFriend( playerToAdd )		// Adds player to friend list
	.RemoveFriend( playerToRemove )	// Removes player from friend list
	.GetFriendList()				// Gets list of friends
	.ClearFriendList()				// Clears list of friends
Added new Character JS Method to fetch a player character's list of pets/followers
	.GetPetList()		// Gets list of pets/followers
Added new persistent NPC property to keep track of a pet's previous owners, whether those tamed the pet or had it transferred to them. Every time a pet is tamed, or is transferred to a new owner, this list is updated:
	GenericList< CChar * >	petOwnerList
Added new Character JS Method to check if a player is on a pet's owner list as a previous owner:
	.HasBeenOwner( mChar )
Previous owners of a pet can re-tame it with guaranteed chance of success
Updated JS Method Refresh() to be usable with both items or characters, to send updated state of object to nearby players
Added character tooltip [Guarded] for characters being guarded by a pet/hireling
Pets/hirelings that are transferred will now immediately start following their new master instead of wandering freely
Pets/hirelings can no longer be transferred between players as long as either party is flagged as a criminal
Pets/hirelings can no longer be transferred to dead players
Pets/hirelings can no longer be transferred to NPCs
Summoned creatures can no longer be transferred to other players
Summoned creatures can no longer have friends
Friend lists of pets/hirelings are now cleared when the pet/hireling is transferred to another player
Added new UOX.INI settings to control how many pets players can have active:
	MAXCONTROLSLOTS=0 	// Maximum number of pet control slots available to player. Disabled if 0
	MAXFOLLOWERS=5 		// Maximum pets/followers a player can have active at the same time. Used if control slots are disabled
	MAXPETOWNERS=5 		// Maximum number of different owners a pet can have over its lifetime before it becomes impossible to retame
Added new NPC property and NPC DFN tag that keeps track of how many pet control slots an NPC would take up if owned by a player:
	UI08 controlSlots 	// source property
	CONTROLSLOTS=# 		// DFN tag
Added new Character JS properties:
	.ownerCount		// Get the total number of owners a pet/hireling has had, based on NPC's petOwnerList
	.controlSlots 	// Get/Set number of pet control slots an NPC will occupy
	.controlSlotsUsed // Get/Set the number of control slots used by a player
Updated get (js/commands/targeting/get.js) and set (js/commands/targeting/set.js) commands to support getting/setting the following character properties:
	deaths
	ownerCount (read only)
	controlSlots
	controlSlotsUsed
Updated NPC DFNs with default CONTROLSLOT=# tags
Increased the max distance from player that onSpeech JS event will trigger from 7 to 12
Updated how "all attack" and "all follow" commands for pets are handled. Now loops through all pets owned by character and executes command for each eligible pet
Fixed an issue where NPCs could follow characters in different worlds/instances than them selves
Updated default max amount of items that can be sold to NPC vendors from 5 to 250
Guards can no longer train players in skills
Updated equipment itemlists (dfndata/items/itemlists/itemlists.dfn) with blank entries to introduce some more variety in the type of clothes NPCs wear in general
Added new NPCs to DFNs (dfndata/npc/undead.dfn) and added them to undead npclist:
	[skeletalmage]		// variation of [bonemage]
	[skeletalknight]  	// variation of [boneknight]
Updated Titles (dfndata/titles/titles.dfn) with up-to-date titles for skills around Pub 15, and added titles for skills added after that. Also added "Elder" and "Legendary" titles for 110 and 120 skillpoints
Updated EQUIPITEM tag in newbie.dfn (dfndata/newbie/newbie.dfn) to support an optional hue parameter (EQUIPITEM=id,hue)
Updated starting equipment for new characters (dfndata/newbie/newbie.dfn), with commented out practice weapons. Uncomment to use
Added item definitions for practice weapons (dfndata/items/gear/weapons/practice_weapons.dfn):
	practice_skinning_knife
	practice_hatchet
	practice_axe
	practice_mace
	practice_longsword
	practice_spear
	practice_bow
	practice_club
	practice_crook
	practice_gnarled_staff
Updated mount statues DFN (dfndata/items/misc/mount-statues.dfn) and JS (js/npc/pets/*.js) files to include pet control slot related stuff
Pets now inherit the karma of their owners, but revert to their original karma upon release
Pets and hirelings will no longer follow the ghosts of their dead owners, but stay to guard their corpse
Added optional 9th parameter for JS Function CreateDFNItem to specify a color for item created. This comes before the other optional parameters - worldNumber and instanceID (which are only used if character is NULL):
	CreateDFNItem( mSock, mChar, sectionName, inPack, iAmount, itemType, iColor, worldNumber, instanceID )
Added ID of Giant Beetle to various pack animal checks
Pack animals will now drop any newbie/blessed items stored in their packs upon death
Added new NPC properties to track pet loyalty, and exposed these as Character JS properties, and NPC DFN tags:
	JS Properties
		.maxLoyalty 	// Defaults to 100
		.loyalty 		// Starts at 25
	DFN Tags
		MAXLOYALTY=# 	// Defaults to 100
		LOYALTY=# 		// Starts at 25
Updated TriggerEvent JS function to support return values (int, bool, string, object) from called script
Updated various JS scripts to make use of new TriggerEvent functionality and reduce reliance on custom tags:
	js/item/archerybutte.js
	js/item/trainingdummy.js
	js/server/data/combatanims.js
	js/server/data/weapontypes.js
Updated archerybutte script to use dictionary for system and text messages
Updated archerybutte script to support increased range, distance penalty and dex/str bonuses when calculating score
Added new UOX.INI settings under [pets and hirelings] section related to pet control and loyalty:
	CHECKPETCONTROLDIFFICULTY=1 	// Enable/Disable pet control difficulty system
	PETLOYALTYGAINONSUCCESS=1 		// Amount of pet loyalty gained on successful pet command use
	PETLOYALTYLOSSONFAILURE=3 		// Amount of pet loyalty lost on failed pet command use
	PETLOYALTYRATE=900 				// Amount of seconds between each time pet loyalty is automatically reduced by 1. Takes 25 hours to deplete completely from max
Added new persistent NPC property that keeps track of the difficulty of taming and controlling a pet, and exposed it as a Character JS property:
	.orneriness
Every time a tamed pet is released or goes wild, its "orneriness" increases, making it more difficult for other players to tame, and more difficult for anyone to control.
Updated CBasePetResponse::canControlPet() function to use pet control difficulty system if enabled, which checks player's animal taming/animal lore skill vs a pet's "orneriness" to determine chance of pet accepting a given pet command
	On successful use of pet command, increases pet loyalty by value defined in PETLOYALTYGAINONSUCCESS ini setting
	On failed use of pet command, decreases pet loyalty by value defined in PETLOYALTYLOSSONFAILURE ini setting
Added new Character JS Method to calculate chance of a player successfully controlling the pet:
	.CalculateControlChance( mChar )	// Returns value between 0 and 1000 indicating chance of success
Feeding a pet will now restore its loyalty to maximum
Pets will now lose loyalty on hunger checks when at maximum hunger
Pets that are maximum hungry will now only have a chance to go wild if loyalty has dropped to zero
Added new DFN tag for creatures.dfn - TYPE - which contains a string describing the type of creature
Added secure pet trading. Players who trade pets will now see a pet transfer deed appear in a secure trade window with the name and type of creature, and upon completion of the trade the associated pet will be instantly transferred to the other player
Updated resource JS scripts (js/server/resource/*) to use dictionaries for all system messages
Updated skill JS scripts (js/skill/*) to use dictionaries for all system messages
Updated housing JS scripts (js/server/house/*) to use dictionaries for all system messages
Updated item JS scripts (js/item/*) to use dictionaries for all system messages
Updated magic JS scripts (js/magic/*) to use dictionaries for all system messages
Updated NPC AI JS scripts (js/npc/ai/*) to use dictionaries for all system messages
Updated command JS scripts (js/commands/*) to use dictionaries for all system messages, gump tooltips, etc
Updated code to use dictionaries for all system messages
Fixed incorrect spelling for UOX.INI setting HIDEW(H)ILEMOUNTED and updated hiding skill (js/skill/hiding.js) to actually allow/disallow hiding while mounted based on this setting
Added new Character JS Method to make it easier to make one NPC initiate combat with another:
	.InitiateCombat( targetChar )	// Character attempts to initiate combat with target character
Updated parrying portion of combat code to be in line with Pub15/pre-AoS parrying mechanics. High AR shields now absorb more damage on a successful parry, while low AR shields have a higher chance of parrying. Shields are also now more effective against archery attacks (full absorption potential) than melee attacks (half absorption potential).
Updated combat damage calculations to be in line with Pub15/pre-AoS damage calculations
Adjusted default value of COMBATNPCDAMAGERATE ini setting (damage divisor when target is a player) from 2 to 1 to account for these changes.
Removed dictionary.UNK, and made dictionary.ZRO the default dictionary used for all unsupported languages
Added dictionary support for additional languages: Portuguese, Italian, Czech
Updated default dictionaries for the following languages: English, French
Added default dictionaries for the following languages: German, Spanish, Portuguese, Italian, Czech (note that translations have been provided by automatic services and will contain inaccuracies!)
Added new UOX.INI setting to allow specifying a default dictionary language for server, which if set will force that language for all dictionary messages, regardless of client settings:
	SERVERLANGUAGE=0 	// Set default server dictionary language. Supported languages: 0 - None/language used by each client, 1 - English, 2 - German, 3 - Spanish, 5 - French, 6 - Portuguese, 7 - Italian, 8 - Czech
Added new function in combat.cpp - AdjustArmorClassDamage() - which adjusts the damage dealt in combat based on whether armour class (AC DFN tag or .ac JS property) of weapon and armour equipped on hit location of target match up. A weapon with armour class 1 would essentially be doubly effective against armour of armour class 1. Allows setting up things like piercing weapons being better against some armor types than mace weapons, etc.
Added new UOX.INI setting under [combat] to enable/disable double damage from armour class bonuses:
	ARMORCLASSDAMAGEBONUS=0/1 //defaults to 0)
2021-07-28 16:02:56 +08:00

1341 lines
49 KiB
C++

//o-----------------------------------------------------------------------------------------------o
//| cConsole.cpp
//o-----------------------------------------------------------------------------------------------o
//| In essence, CConsole is our nice generic class for outputting display.
//| As long as the interface is kept the same, we can display whatever we wish
//| too. We store a set of coordinates being the window corner and size, for
//| systems with windowing support, which describes the window we are in.
//o-----------------------------------------------------------------------------------------------o
//| Version History
//| 1.7 Added comments (29. October 2001)
//| 2.0 Added filter masking (22nd January 2002)
//o-----------------------------------------------------------------------------------------------o
// Header
#include "uox3.h"
#include "cConsole.h"
#include "cThreadQueue.h"
#include "ObjectFactory.h"
#include "network.h"
#include "ssection.h"
#include "CJSMapping.h"
#include "teffect.h"
#include "cMagic.h"
#include "magic.h"
#include "regions.h"
#include "commands.h"
#include "cServerDefinitions.h"
#include "cHTMLSystem.h"
#include "cRaces.h"
#include "cGuild.h"
#include "cScript.h"
#include "StringUtility.hpp"
#include <iostream>
#include <cctype>
#if PLATFORM != WINDOWS
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
struct termios initial_terminal_state;
#else
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <conio.h>
#undef min
#undef max
DWORD initial_terminal_state;
#endif
CConsole Console; // no *, else we can't overload <<
CEndL myendl;
const UI08 NORMALMODE = 0;
const UI08 WARNINGMODE = 1;
const UI08 ERRORMODE = 2;
//const UI08 COLOURMODE = 3;
// Forward function declarations
void endmessage( SI32 x );
void LoadCustomTitle( void );
void LoadSkills( void );
void LoadSpawnRegions( void );
void LoadRegions( void );
void LoadTeleportLocations( void );
void LoadCreatures( void );
void LoadPlaces( void );
void UnloadRegions( void );
void UnloadSpawnRegions( void );
void LoadTeleportLocations( void );
//o-----------------------------------------------------------------------------------------------o
//| Function - CConsole()
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Class Constructor and deconstructor
//o-----------------------------------------------------------------------------------------------o
CConsole::CConsole() : width( 80 ), height( 25 ),
currentMode( NORMALMODE ), previousColour( CNORMAL ), logEcho( false )
{
initialize();
}
CConsole::~CConsole()
{
MoveTo(1,height);
reset();
}
//o-----------------------------------------------------------------------------------------------o
//| Function - CConsole()::initialize()
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Prepare console/terminal for UOX3 output
//o-----------------------------------------------------------------------------------------------o
void CConsole::initialize()
{
#if !defined(_WIN32)
tcgetattr(1, &initial_terminal_state); // get the current state of the terminal
auto temp = initial_terminal_state;
temp.c_lflag = temp.c_lflag & (~ECHO) & (~ICANON); // Disable echo and canonical (line) mode
temp.c_cc[VMIN] = 0; // in non canonical mode we non blocking read
temp.c_cc[VTIME] = 0; // in non canonical mode we non blocking read
tcsetattr(1, TCSANOW, &temp);
#else
// Set the input to non echo and non canonical (line) mode
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleMode(hco, &initial_terminal_state);
auto temp = initial_terminal_state;
temp = (temp & (~ENABLE_ECHO_INPUT) & (~ENABLE_LINE_INPUT) & (~ENABLE_MOUSE_INPUT));
SetConsoleMode(hco,initial_terminal_state);
#endif
}
//o-----------------------------------------------------------------------------------------------o
//| Function - CConsole()::reset()
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Reset console/terminal to its original state
//o-----------------------------------------------------------------------------------------------o
void CConsole::reset()
{
std::cout.flush();
#if !defined(_WIN32)
tcsetattr(1, TCSAFLUSH, &initial_terminal_state);
std::cout << std::endl;
#else
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleMode(hco,initial_terminal_state);
#endif
}
//o-----------------------------------------------------------------------------------------------o
//| Function - CConsole()::setTitle( const std::string &value )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Set console/terminal window title
//o-----------------------------------------------------------------------------------------------o
void CConsole::setTitle( const std::string &value )
{
#if !defined(_WIN32)
auto cmd = SETTITLE;
auto loc = cmd.find("TITLE");
cmd.replace(loc, 5, value);
sendCMD(cmd);
#else
SetConsoleTitle( value.c_str() );
#endif
}
//o-----------------------------------------------------------------------------------------------o
//| Function - CConsole()::sendCMD( const std::string& cmd )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Send cmd to terminal
//o-----------------------------------------------------------------------------------------------o
CConsole& CConsole::sendCMD( const std::string& cmd )
{
std::cout << cmd;
std::cout.flush();
return *this;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - CConsole()::windowSize()
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Set window size in columns and rows
//o-----------------------------------------------------------------------------------------------o
std::tuple<int,int> CConsole::windowSize()
{
int row =0;
int col =0;
#if !defined(_WIN32)
// Get the window size
winsize winsz;
ioctl(0,TIOCGWINSZ,&winsz);
col = winsz.ws_col;
row = winsz.ws_row;
#else
HANDLE hco = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO csbi;
GetConsoleScreenBufferInfo( hco, &csbi );
col = csbi.dwSize.X;
row = csbi.dwSize.Y;
#endif
return std::make_tuple(row,col);
}
//o-----------------------------------------------------------------------------------------------o
//| Function - CConsole()::clearScreen()
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Clears the screen
//o-----------------------------------------------------------------------------------------------o
void CConsole::clearScreen()
{
#if defined(_WIN32)
unsigned long y;
COORD xy;
xy.X = 0;
xy.Y = 0;
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
FillConsoleOutputCharacter( hco, ' ', width * height, xy, &y );
SetConsoleCursorPosition( hco, xy );
#else
std::string cmd = CSI;
cmd = cmd + std::string("2J");
sendCMD(cmd);
#endif
}
//o-----------------------------------------------------------------------------------------------o
//| Function - << Overrriding
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Let you use << and >>
//o-----------------------------------------------------------------------------------------------o
CConsole& CConsole::operator<<( const SI08 *outPut )
{
StartOfLineCheck();
(*this) << (const char *)outPut;
return (*this);
}
CConsole& CConsole::operator<<( const char *outPut )
{
StartOfLineCheck();
#if PLATFORM == WINDOWS
CONSOLE_SCREEN_BUFFER_INFO ScrBuffInfo;
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo( hco, &ScrBuffInfo );
std::string toDisplay = outPut;
if( ScrBuffInfo.dwCursorPosition.X + toDisplay.length() > ScrBuffInfo.dwSize.X )
{
bool wrapDone = false;
while( !wrapDone )
{
GetConsoleScreenBufferInfo( hco, &ScrBuffInfo );
SI32 diff = ScrBuffInfo.dwSize.X - ScrBuffInfo.dwCursorPosition.X - 1;
if( diff > toDisplay.length() )
{
std::cout << toDisplay;
wrapDone = true;
}
else
{
std::cout << toDisplay.substr( 0, diff );
(*this) << myendl;
StartOfLineCheck();
toDisplay = toDisplay.substr( diff );
}
}
}
else
#endif
{
std::cout << outPut;
}
return (*this);
}
CConsole& CConsole::operator<<( const UI08 *outPut )
{
StartOfLineCheck();
(*this) << (const char *)outPut;
return (*this);
}
CConsole& CConsole::operator<<( const SI08 &outPut )
{
StartOfLineCheck();
std::cout << outPut;
return (*this);
}
CConsole& CConsole::operator<<( const UI08 &outPut )
{
StartOfLineCheck();
std::cout << outPut;
return (*this);
}
CConsole& CConsole::operator<<( const SI16 &outPut )
{
StartOfLineCheck();
std::cout << outPut;
return (*this);
}
CConsole& CConsole::operator<<( const UI16 &outPut )
{
StartOfLineCheck();
std::cout << outPut;
return (*this);
}
CConsole& CConsole::operator<<( const SI32 &outPut )
{
StartOfLineCheck();
std::cout << outPut;
return (*this);
}
CConsole& CConsole::operator<<( const UI32 &outPut )
{
StartOfLineCheck();
std::cout << outPut;
return (*this);
}
CConsole& CConsole::operator<<( const SI64 &outPut )
{
StartOfLineCheck();
std::cout << outPut;
return ( *this );
}
CConsole& CConsole::operator<<( const UI64 &outPut )
{
StartOfLineCheck();
std::cout << outPut;
return (*this);
}
CConsole& CConsole::operator<<( const CBaseObject *outPut )
{
StartOfLineCheck();
(*this) << outPut->GetSerial();
return (*this);
}
CConsole& CConsole::operator<<( const std::string &outPut )
{
StartOfLineCheck();
std::cout << outPut.c_str();
return (*this);
}
/*CConsole& CConsole::operator<<( const std::ostream& outPut )
{
StartOfLineCheck();
std::cout << outPut;
return (*this);
}*/
CConsole& CConsole::operator<<( CBaseObject *outPut )
{
StartOfLineCheck();
(*this) << outPut->GetSerial();
return (*this);
}
CConsole& CConsole::operator<<( CEndL& myObj )
{
if( curLeft == 0 )
PrintStartOfLine();
std::cout << std::endl;
curLeft = 0;
++curTop;
return (*this);
}
CConsole& CConsole::operator<<( const R32 &outPut )
{
StartOfLineCheck();
std::cout << outPut;
return (*this);
}
CConsole& CConsole::operator<<( const R64 &outPut )
{
StartOfLineCheck();
std::cout << outPut;
return (*this);
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void print( const std::string& msg )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Prints the console with the "|"
//o-----------------------------------------------------------------------------------------------o
void CConsole::print( const std::string& msg )
{
StartOfLineCheck();
std::cout << msg;
if ((msg.size() > 0) && (msg[msg.size()-1]=='\n'))
{
curLeft = 0;
}
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void log( const std::string& msg, const std::string& filename )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Writes to the logfile
//o-----------------------------------------------------------------------------------------------o
void CConsole::log( const std::string& msg, const std::string& filename )
{
if( !cwmWorldState->ServerData()->ServerConsoleLog() )
return;
std::ofstream toWrite;
std::string realFileName; // 022602: in windows a path can be max 512 chars, this at 128 coud potentially cause crashes if the path is longer than 128 chars
if( cwmWorldState != nullptr )
realFileName = cwmWorldState->ServerData()->Directory( CSDDP_LOGS ) + filename;
else
realFileName = filename;
char timeStr[256];
RealTime( timeStr );
toWrite.open( realFileName.c_str(), std::ios::out | std::ios::app );
if( toWrite.is_open() )
toWrite << "[" << timeStr << "] " << msg << std::endl;
toWrite.close();
if( LogEcho() )
{
print( strutil::format( "%s%s\n", timeStr, msg.c_str()));
}
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void log( const std::string& msg)
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Log to the console.log file
//o-----------------------------------------------------------------------------------------------o
void CConsole::log( const std::string& msg )
{
if( !cwmWorldState->ServerData()->ServerConsoleLog() )
return;
log( msg, "console.log" );
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void error( const std::string& msg )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Writes to the error log and the console.
//o-----------------------------------------------------------------------------------------------o
void CConsole::error( const std::string& msg )
{
UI08 oldMode = CurrentMode();
CurrentMode( ERRORMODE );
log( msg, "error.log" );
if( curLeft != 0 )
(*this) << myendl;
TurnRed();
(*this) << "ERROR: " << (const char*)&msg[0] << myendl;
TurnNormal();
CurrentMode( oldMode );
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void PrintSectionBegin( void )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Prints a section seperator
//o-----------------------------------------------------------------------------------------------o
void CConsole::PrintSectionBegin( void )
{
TurnBrightWhite();
std::cout << "o";
for( SI32 j = 1; j < width - 1; ++j )
std::cout << "-";
std::cout << "o";
curLeft = 0;
curTop = 0;
TurnNormal();
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void Start( char *temp )
//| Date - 24th December, 2001
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Migration of constart function to here
//o-----------------------------------------------------------------------------------------------o
void CConsole::Start( const std::string& temp )
{
auto size = windowSize();
width = std::get<1>(size);
height = std::get<0>(size);
setTitle(temp);
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void TurnYellow( void )
//| Date - 24th December, 2001
///o-----------------------------------------------------------------------------------------------o
//| Purpose - Turns the text yellow
//o-----------------------------------------------------------------------------------------------o
void CConsole::TurnYellow( void )
{
#if PLATFORM == WINDOWS
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute( hco, FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY );
#else
std::cout << "\033[1;33m";
#endif
previousColour = CYELLOW;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void TurnRed( void )
//| Date - 24th December, 2001
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Turns the text red
//o-----------------------------------------------------------------------------------------------o
void CConsole::TurnRed( void )
{
#if PLATFORM == WINDOWS
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute( hco, FOREGROUND_RED | FOREGROUND_INTENSITY );
#else
std::cout << "\033[1;31m";
#endif
previousColour = CRED;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void TurnGreen( void )
//| Date - 24th December, 2001
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Turns the text green
//o-----------------------------------------------------------------------------------------------o
void CConsole::TurnGreen( void )
{
#if PLATFORM == WINDOWS
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute( hco, FOREGROUND_GREEN | FOREGROUND_INTENSITY );
#else
std::cout << "\033[1;32m";
#endif
previousColour = CGREEN;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void TurnBlue( void )
//| Date - 24th December, 2001
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Turns the text blue
//o-----------------------------------------------------------------------------------------------o
void CConsole::TurnBlue( void )
{
#if PLATFORM == WINDOWS
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute( hco, FOREGROUND_BLUE | FOREGROUND_INTENSITY );
#else
std::cout << "\033[1;34m";
#endif
previousColour = CBLUE;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void TurnNormal( void )
//| Date - 24th December, 2001
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Returns text to normal white
//o-----------------------------------------------------------------------------------------------o
void CConsole::TurnNormal( void )
{
#if PLATFORM == WINDOWS
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute( hco, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN );
#else
std::cout << "\033[0;37m";
#endif
previousColour = CNORMAL;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void TurnBrightWhite( void )
//| Date - 22nd January, 2002
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Returns text to bright white
//o-----------------------------------------------------------------------------------------------o
void CConsole::TurnBrightWhite( void )
{
#if PLATFORM == WINDOWS
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute( hco, FOREGROUND_BLUE | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY );
#else
std::cout << "\033[1;37m";
#endif
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void PrintDone( void )
//| Date - 24th December, 2001
//| Changes - 7th February, 2003 - Made it use PrintSpecial
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Prints colored "[done]" message
//o-----------------------------------------------------------------------------------------------o
void CConsole::PrintDone( void )
{
PrintSpecial( CGREEN, "done" );
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void PrintFailed( void )
//| Date - 24th December, 2001
//| Changes - 7th February, 2003 - Made it use PrintSpecial
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Prints colored "[failed]" message
//o-----------------------------------------------------------------------------------------------o
void CConsole::PrintFailed( void )
{
PrintSpecial( CRED, "Failed" );
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void PrintPassed( void )
//| Date - 17th February, 2002
//| Changes - 7th February, 2003 - Made it use PrintSpecial
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Prints colored "[skipped]" message
//o-----------------------------------------------------------------------------------------------o
void CConsole::PrintPassed( void )
{
PrintSpecial( CYELLOW, "Skipped" );
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void ClearScreen( void )
//| Date - 24th December, 2001
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Clears the screen
//o-----------------------------------------------------------------------------------------------o
void CConsole::ClearScreen( void )
{
clearScreen();
}
void CConsole::PrintBasedOnVal( bool value )
{
if( value )
PrintDone();
else
PrintFailed();
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void warning( const std::string& msg )
//| Date - 21st January, 2002
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Writes to the warning log and the console.
//o-----------------------------------------------------------------------------------------------o
void CConsole::warning( const std::string& msg )
{
UI08 oldMode = CurrentMode();
CurrentMode( WARNINGMODE );
log( msg, "warning.log" );
if( curLeft != 0 )
(*this) << myendl;
TurnBlue();
(*this) << "WARNING: " << (const char*)&msg[0] << myendl;
TurnNormal();
CurrentMode( oldMode );
}
//o-----------------------------------------------------------------------------------------------o
//| Function - UI08 CurrentMode( void ) const
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Gets/Sets console's output mode
//o-----------------------------------------------------------------------------------------------o
UI08 CConsole::CurrentMode( void ) const
{
return currentMode;
}
void CConsole::CurrentMode( UI08 value )
{
currentMode = value;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void PrintStartOfLine( void )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Set colour of console text at start of a new line
//o-----------------------------------------------------------------------------------------------o
void CConsole::PrintStartOfLine( void )
{
TurnBrightWhite();
std::cout << "| ";
switch( previousColour )
{
case CBLUE: TurnBlue(); break;
case CRED: TurnRed(); break;
case CGREEN: TurnGreen(); break;
case CYELLOW: TurnYellow(); break;
case CBWHITE: break; // current colour
case CNORMAL:
default: TurnNormal(); break;
}
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void MoveTo( SI32 x, SI32 y )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Set console cursor position
//o-----------------------------------------------------------------------------------------------o
#if PLATFORM == WINDOWS
void CConsole::MoveTo( SI32 x, SI32 y )
{
auto hco = GetStdHandle(STD_OUTPUT_HANDLE);
COORD Pos;
if( y == -1 )
{
CONSOLE_SCREEN_BUFFER_INFO ScrBuffInfo;
GetConsoleScreenBufferInfo( hco, &ScrBuffInfo );
Pos.Y = ScrBuffInfo.dwCursorPosition.Y;
Pos.X = (UI16)x;
SetConsoleCursorPosition( hco, Pos );
}
else
{
Pos.X = (UI16)x;
Pos.Y = (UI16)y;
SetConsoleCursorPosition( hco, Pos );
}
}
#else
void CConsole::MoveTo( SI32 x, SI32 y )
{
std::cout << "\033[255D";
std::cout << "\033[" << x << "C";
}
#endif
//o-----------------------------------------------------------------------------------------------o
//| Function - bool LogEcho( void )
//| Date - 2/03/2003
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Checks whether console should echo log messages
//o-----------------------------------------------------------------------------------------------o
bool CConsole::LogEcho( void )
{
return logEcho;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void LogEcho( bool value )
//| Date - 2/03/2003
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Enables/Disables whether console should echo log messages
//o-----------------------------------------------------------------------------------------------o
void CConsole::LogEcho( bool value )
{
logEcho = value;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void StartOfLineCheck( void )
//| Date - 2/3/2003
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Reduces excess work in overloaded functions by checking
//| to see if the start of line has to be done here
//o-----------------------------------------------------------------------------------------------o
void CConsole::StartOfLineCheck( void )
{
if( curLeft == 0 )
{
PrintStartOfLine();
curLeft = 1;
}
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void PrintSpecial( UI08 colour, const std::string& msg )
//| Date - 2/7/2003
//o-----------------------------------------------------------------------------------------------o
//| Purpose - This is much like PrintFailed, PrintDone and so on except
//| we specify the text and the colour
//o-----------------------------------------------------------------------------------------------o
void CConsole::PrintSpecial( UI08 colour, const std::string& msg )
{
StartOfLineCheck();
size_t stringLength = msg.size() + 3;
MoveTo( static_cast< SI32 >(width - stringLength) );
TurnNormal();
(*this) << "[";
switch( colour )
{
default:
case CNORMAL: break;
case CBLUE: TurnBlue(); break;
case CRED: TurnRed(); break;
case CGREEN: TurnGreen(); break;
case CYELLOW: TurnYellow(); break;
case CBWHITE: TurnBrightWhite(); break;
}
(*this) << msg;
TurnNormal();
(*this) << "]" << myendl;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - SI32 cl_getch( void )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Read a character from stdin, in a cluox compatble way.
//| This routine is non-blocking!
//| Returns - >0 -> character read
//| -1 -> no char available.
//o-----------------------------------------------------------------------------------------------o
//| Notes - now cluox is GUI wrapper over uox using stdin and stdout redirection to capture
//| the console, if it is active uox can't use kbhit() to determine if there is a
//| character aviable, it can only get one directly by getch().
//| However the problem arises that uox will get blocked if none is aviable.
//| The solution to this problem is that cluox also hands over the second pipe-end
//| of stdin so uox can write itself into this stream. To determine if a character is
//| now done that way. UOX write's itself a ZERO on the other end of the pipe, and reads
//| a charecter, if it is again the same ZERO just putted in nothing was entered. However
//| it is not a zero the user has entered a char.
//o-----------------------------------------------------------------------------------------------o
SI32 CConsole::cl_getch( void )
{
#if PLATFORM != WINDOWS
char buffer[2];
std::string rvalue = "";
buffer[1] = 0;
auto a = ::read(0, buffer, 1); // This doesn't block on getting a line due to initalization
if( a > 0 )
{
return static_cast<SI32>(buffer[0]);
}
else
{
return -1;
}
#else
// uox is not wrapped simply use the kbhit routine
if( _kbhit() )
return _getch();
else
return -1;
#endif
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void Poll( void )
//| Date - Unknown
//| Changes - 25 January, 2006
//| Moved into the console class and renamed from checkkey() to Poll()
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Facilitate console control. SysOp keys, and localhost
//| controls.
//o-----------------------------------------------------------------------------------------------o
void CConsole::Poll( void )
{
SI32 c = cl_getch();
if( c > 0 )
{
c = std::toupper(c);
Process( c );
}
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void Process( SI32 c )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Handle keypresses in console
//| Changes - 05042004 - added some console debugging stuff.
//| Ideally this will all be placed onto a DEBUG menu which
//| a user will be able to select using the <, and > keys
//| respectivly. This functionality hasn't been implemented
//| at the current time of writing, but will be when possible.
//o-----------------------------------------------------------------------------------------------o
void CConsole::Process( SI32 c )
{
if( c == '*' )
{
if( cwmWorldState->GetSecure() )
messageLoop << "Secure mode disabled. Press ? for a commands list";
else
messageLoop << "Secure mode re-enabled";
cwmWorldState->SetSecure( !cwmWorldState->GetSecure() );
return;
}
else
{
if( cwmWorldState->GetSecure() )
{
messageLoop << "Secure mode prevents keyboard commands! Press '*' to disable";
return;
}
JSCONSOLEKEYMAP_ITERATOR toFind = JSKeyHandler.find( c );
if( toFind != JSKeyHandler.end() )
{
if( toFind->second.isEnabled )
{
cScript *toExecute = JSMapping->GetScript( toFind->second.scriptID );
if( toExecute != nullptr )
{ // All commands that execute are of the form: command_commandname (to avoid possible clashes)
#if defined( UOX_DEBUG_MODE )
print(strutil::format( "Executing JS keystroke %c %s\n", c, toFind->second.cmdName.c_str()) );
#endif
jsval eventRetVal;
toExecute->CallParticularEvent( toFind->second.cmdName.c_str(), nullptr, 0, &eventRetVal );
}
return;
}
}
CSocket *tSock = nullptr;
//char outputline[128], temp[1024];
std::string outputline, temp;
SI32 indexcount = 0;
bool kill = false;
SI32 j = 0;
switch( c )
{
case '!':
// Force server to save accounts file
messageLoop << "CMD: Saving Accounts... ";
Accounts->Save();
messageLoop << MSG_PRINTDONE;
break;
case '@':
// Force server to save all files.(Manual save)
messageLoop << MSG_WORLDSAVE;
break;
case 'Y':
SI32 keyresp;
std::cout << "System: ";
std::cout.flush();
while( !kill )
{
keyresp = cl_getch();
switch( keyresp )
{
case -1: // no key pressed
case 0:
break;
case 0x1B:
outputline = "";
indexcount = 0;
kill = true;
std::cout << std::endl;
messageLoop << "CMD: System broadcast canceled.";
break;
case 0x08:
--indexcount;
if( indexcount < 0 )
indexcount = 0;
else
std::cout << "\b \b";
break;
case 0x0A:
case 0x0D:
outputline[indexcount] = 0;
messageLoop.NewMessage( MSG_CONSOLEBCAST, outputline.c_str() );
indexcount = 0;
kill = true;
std::cout << std::endl;
temp=strutil::format( "CMD: System broadcast sent message \"%s\"", outputline.c_str() );
outputline = "";
messageLoop << temp;
break;
default:
outputline = outputline + std::string(1, static_cast<SI08>(keyresp));
indexcount = indexcount + 1;
std::cout << static_cast<SI08>(keyresp);
std::cout.flush();
break;
}
keyresp = 0x00;
}
break;
case '[':
{
// We want to group all the contents of the multimap container numerically by group. We rely on the self ordering in the multimap implementation to do this.
messageLoop << " ";
messageLoop << "Auto-AddMenu Statistics";
messageLoop << " ";
std::string szBuffer;
// We need to get an iteration into the map first of all the top level ULONGs then we can get an equal range.
std::map< UI32, UI08 > localMap;
localMap.clear();
for( ADDMENUMAP_CITERATOR CJ = g_mmapAddMenuMap.begin(); CJ != g_mmapAddMenuMap.end(); CJ++ )
{
// check to see if the group id has been checked already
if( localMap.find( CJ->first ) == localMap.end() )
{
localMap.insert( std::make_pair( CJ->first, 0 ) );
szBuffer = "";
szBuffer=strutil::format( "AddMenuGroup %u:", CJ->first );
messageLoop << szBuffer;
std::pair< ADDMENUMAP_CITERATOR, ADDMENUMAP_CITERATOR > pairRange = g_mmapAddMenuMap.equal_range( CJ->first );
SI32 count = 0;
for( ADDMENUMAP_CITERATOR CI=pairRange.first;CI != pairRange.second; CI++ )
{
count++;
}
szBuffer = "";
szBuffer=strutil::format( " Found %i Auto-AddMenu Item(s).", count );
messageLoop << szBuffer;
}
}
messageLoop << MSG_SECTIONBEGIN;
break;
}
case '<':
messageLoop << "Function not implemented.";
break;
case '>':
messageLoop << "Function not implemented.";
break;
case 0x1B:
case 'Q':
messageLoop << MSG_SECTIONBEGIN;
messageLoop << "CMD: Immediate Shutdown initialized!";
messageLoop << MSG_SHUTDOWN;
break;
case '0':
if( !cwmWorldState->GetReloadingScripts() )
{
cwmWorldState->SetReloadingScripts( true );
// Reload all the files. If there are issues with these files change the order reloaded from here first.
cwmWorldState->ServerData()->Load();
messageLoop << "CMD: Loading All";
messageLoop << " Server INI... ";
// Reload accounts, and update Access.adm if new accounts available.
messageLoop << " Loading Accounts... ";
Accounts->Load();
messageLoop << MSG_PRINTDONE;
// Reload Region Files
messageLoop << " Loading Regions... ";
UnloadRegions();
LoadRegions();
messageLoop << MSG_PRINTDONE;
messageLoop << " Loading Teleport Locations... ";
LoadTeleportLocations();
messageLoop << MSG_PRINTDONE;
// Reload the serve spawn regions
messageLoop << " Loading Spawn Regions... ";
UnloadSpawnRegions();
LoadSpawnRegions();
messageLoop << MSG_PRINTDONE;
// Reload the server command list
messageLoop << " Loading commands... ";
Commands->Load();
messageLoop << MSG_PRINTDONE;
// Reload DFN's
messageLoop << " Loading Server DFN... ";
FileLookup->Reload();
messageLoop << MSG_PRINTDONE;
// messageLoop access is REQUIRED, as this function is executing in a different thread, so we need thread safety
messageLoop << " Loading JSE Scripts... ";
// Reload the current Spells
messageLoop << " Loading spells... ";
Magic->LoadScript();
messageLoop << MSG_PRINTDONE;
// Reload the HTML output templates
messageLoop << " Loading HTML Templates... ";
HTMLTemplates->Unload();
HTMLTemplates->Load();
cwmWorldState->SetReloadingScripts( false );
messageLoop << MSG_PRINTDONE;
}
else
messageLoop << "Server can only load one script at a time";
break;
case 'T':
// Timed shut down(10 minutes)
messageLoop << "CMD: 10 Minute Server Shutdown Announced(Timed)";
cwmWorldState->SetEndTime( BuildTimeValue( 600 ) );
endmessage(0);
break;
case 'D':
// Disconnect account 0 (useful when client crashes)
for( tSock = Network->LastSocket(); tSock != nullptr; tSock = Network->PrevSocket() )
{
if( tSock->AcctNo() == 0 )
Network->Disconnect( tSock );
}
messageLoop << "CMD: Socket Disconnected(Account 0).";
break;
case 'K':
{
for( tSock = Network->FirstSocket(); !Network->FinishedSockets(); tSock = Network->NextSocket() )
{
Network->Disconnect( tSock );
}
messageLoop << "CMD: All Connections Closed.";
}
break;
case 'P':
{
UI32 networkTimeCount = cwmWorldState->ServerProfile()->NetworkTimeCount();
UI32 timerTimeCount = cwmWorldState->ServerProfile()->TimerTimeCount();
UI32 autoTimeCount = cwmWorldState->ServerProfile()->AutoTimeCount();
UI32 loopTimeCount = cwmWorldState->ServerProfile()->LoopTimeCount();
// 1/13/2003 - Dreoth - Log Performance Information enhancements
LogEcho( true );
log( "--- Starting Performance Dump ---", "performance.log");
log( "\tPerformance Dump:", "performance.log");
log( strutil::format("\tNetwork code: %.2fmsec [%i samples]",(R32)((R32)cwmWorldState->ServerProfile()->NetworkTime()/(R32)networkTimeCount), networkTimeCount), "performance.log" );
log( strutil::format("\tTimer code: %.2fmsec [%i samples]", (R32)((R32)cwmWorldState->ServerProfile()->TimerTime()/(R32)timerTimeCount), timerTimeCount), "performance.log");
log( strutil::format("\tAuto code: %.2fmsec [%i samples]", (R32)((R32)cwmWorldState->ServerProfile()->AutoTime()/(R32)autoTimeCount), autoTimeCount), "performance.log");
log( strutil::format("\tLoop Time: %.2fmsec [%i samples]", (R32)((R32)cwmWorldState->ServerProfile()->LoopTime()/(R32)loopTimeCount), loopTimeCount), "performance.log");
log( strutil::format("\tCharacters: %i/%i - Items: %i/%i (Dynamic)", ObjectFactory::getSingleton().CountOfObjects( OT_CHAR ), ObjectFactory::getSingleton().SizeOfObjects( OT_CHAR ), ObjectFactory::getSingleton().CountOfObjects( OT_ITEM ), ObjectFactory::getSingleton().SizeOfObjects( OT_ITEM )), "performance.log" );
log( strutil::format("\tSimulation Cycles: %f per sec", (1000.0*(1.0/(R32)((R32)cwmWorldState->ServerProfile()->LoopTime()/(R32)loopTimeCount)))), "performance.log");
log( strutil::format("\tBytes sent: %i", cwmWorldState->ServerProfile()->GlobalSent()), "performance.log");
log( strutil::format("\tBytes Received: %i", cwmWorldState->ServerProfile()->GlobalReceived()), "performance.log");
log( "--- Performance Dump Complete ---", "performance.log");
LogEcho( false );
break;
}
case 'W':
{
// Display logged in chars
messageLoop << "CMD: Current Users in the World:";
CSocket *iSock;
{ //std::scoped_lock lock(Network->internallock);
Network->pushConn();
for( iSock = Network->FirstSocket(); !Network->FinishedSockets(); iSock = Network->NextSocket() )
{
++j;
CChar *mChar = iSock->CurrcharObj();
temp = strutil::format( " %i) %s [%x %x %x %x]", j - 1, mChar->GetName().c_str(), mChar->GetSerial( 1 ), mChar->GetSerial( 2 ), mChar->GetSerial( 3 ), mChar->GetSerial( 4 ) );
messageLoop << temp;
}
Network->popConn();
}
temp = strutil::format( " Total users online: %i", j );
messageLoop << temp;
break;
}
case 'M':
UI32 tmp, total;
total = 0;
tmp = 0;
messageLoop << "CMD: UOX Memory Information:";
messageLoop << " Cache:";
temp = strutil::format( " Tiles: %zu bytes", Map->GetTileMem() );
messageLoop << temp;
temp = strutil::format( " Multis: %zu bytes", Map->GetMultisMem() );
messageLoop << temp;
UI32 m, n;
m = static_cast<std::uint32_t>(ObjectFactory::getSingleton().SizeOfObjects( OT_CHAR ));
total += tmp = m + m*sizeof(CTEffect) + m*sizeof(SI08) + m*sizeof(intptr_t)*5;
temp = strutil::format( " Characters: %u bytes [%u chars ( %u allocated )]", tmp, ObjectFactory::getSingleton().CountOfObjects( OT_CHAR ), m );
messageLoop << temp;
n = static_cast<std::uint32_t>(ObjectFactory::getSingleton().SizeOfObjects( OT_ITEM ));
total += tmp = n + n * sizeof( intptr_t ) * 4;
temp = strutil::format( " Items: %u bytes [%u items ( %u allocated )]", tmp, ObjectFactory::getSingleton().CountOfObjects( OT_ITEM ), n );
messageLoop << temp;
temp = strutil::format( " You save I: %lu & C: %lu bytes!", m * sizeof(CItem) - ObjectFactory::getSingleton().CountOfObjects( OT_ITEM ), m * sizeof( CChar ) - ObjectFactory::getSingleton().CountOfObjects( OT_CHAR ) );
total += tmp = 69 * sizeof( SpellInfo );
temp = strutil::format( temp, " Spells: %i bytes", tmp );
messageLoop << " Sizes:";
temp = strutil::format(" CItem : %lu bytes", sizeof( CItem ) );
messageLoop << temp;
temp = strutil::format( " CChar : %lu bytes", sizeof( CChar ) );
messageLoop << temp;
temp = strutil::format( " TEffect: %lu bytes %lui total)", sizeof( CTEffect ), sizeof( CTEffect ) * cwmWorldState->tempEffects.Num() );
messageLoop << temp;
tmp = static_cast<std::uint32_t>(Map->GetTileMem() + Map->GetMultisMem());
total += tmp;
temp = strutil::format( " Approximate Total: %i bytes", total );
messageLoop << temp;
break;
case '?':
messageLoop << MSG_SECTIONBEGIN;
messageLoop << "Console commands:";
messageLoop << MSG_SECTIONBEGIN;
messageLoop << " ShardOP:";
messageLoop << " * - Lock/Unlock Console ? - Commands list(this)";
messageLoop << " C - Configuration H - Unused";
messageLoop << " Y - Console Broadcast Q - Quit/Exit ";
messageLoop << " Load Commands:";
messageLoop << " 1 - Ini 2 - Accounts";
messageLoop << " 3 - Regions 4 - Spawn Regions";
messageLoop << " 5 - Spells 6 - Commands";
messageLoop << " 7 - Dfn's 8 - JavaScript";
messageLoop << " 9 - HTML Templates 0 - ALL(1-9)";
messageLoop << " Save Commands:";
messageLoop << " ! - Accounts @ - World(w/AccountImport)";
messageLoop << " # - Unused $ - Unused";
messageLoop << " % - Unused ^ - Unused";
messageLoop << " & - Unused ( - Unused";
messageLoop << " ) - Unused";
messageLoop << " Server Maintenence:";
messageLoop << " P - Performance W - Characters Online";
messageLoop << " M - Memory Information T - 10 Minute Shutdown";
messageLoop << " F - Display Priority Maps";
messageLoop << " Network Maintenence:";
messageLoop << " D - Disconnect Acct0 K - Disconnect All";
messageLoop << " Z - Socket Logging ";
messageLoop << MSG_SECTIONBEGIN;
break;
case 'z':
case 'Z':
{
bool loggingEnabled = false;
{
//std::scoped_lock lock(Network->internallock);
// Log socket activity
Network->pushConn();
CSocket *snSock = Network->FirstSocket();
if( snSock != nullptr )
loggingEnabled = !snSock->Logging();
for( ; !Network->FinishedSockets(); snSock = Network->NextSocket() )
{
if( snSock != nullptr )
snSock->Logging( !snSock->Logging() );
}
Network->popConn();
}
if( loggingEnabled )
messageLoop << "CMD: Network Logging Enabled.";
else
messageLoop << "CMD: Network Logging Disabled.";
break;
}
case 'c':
case 'C':
// Shows a configuration header
DisplaySettings();
break;
case 'f':
case 'F':
FileLookup->DisplayPriorityMap();
break;
default:
temp = strutil::format( "Key \'%c\' [%i] does not perform a function", (SI08)c, c );
messageLoop << temp;
break;
}
}
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void DisplaySettings( void )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - UOX startup stuff
//| Moved that here because we need it in processkey now
//|
//| Changes - 10/21/2002 - found the bug in one spot, just
//| happened upon this quick fix. for BackUp operation.
//o-----------------------------------------------------------------------------------------------o
void CConsole::DisplaySettings( void )
{
std::map< bool, std::string > activeMap;
activeMap[true] = "Activated!";
activeMap[false] = "Disabled!";
// UOX.ini status
(*this) << "Server Settings:" << myendl;
(*this) << " -Archiving[";
if( cwmWorldState->ServerData()->ServerBackupStatus() )
(*this) << "Enabled]. (" << cwmWorldState->ServerData()->Directory( CSDDP_BACKUP ) << ")" << myendl;
else
(*this) << "Disabled]" << myendl;
(*this) << " -Weapons & Armour Rank System: ";
(*this) << activeMap[cwmWorldState->ServerData()->RankSystemStatus()] << myendl;
(*this) << " -Vendors buy by item name: ";
(*this) << activeMap[cwmWorldState->ServerData()->SellByNameStatus()] << myendl;
(*this) << " -Adv. Trade System: ";
(*this) << activeMap[cwmWorldState->ServerData()->TradeSystemStatus()] << myendl;
(*this) << " -Races: " << static_cast< UI32 >(Races->Count()) << myendl;
(*this) << " -Guilds: " << static_cast< UI32 >(GuildSys->NumGuilds()) << myendl;
(*this) << " -Char count: " << ObjectFactory::getSingleton().CountOfObjects( OT_CHAR ) << myendl;
(*this) << " -Item count: " << ObjectFactory::getSingleton().CountOfObjects( OT_ITEM ) << myendl;
(*this) << " -Num Accounts: " << Accounts->size() << myendl;
(*this) << " Directories: " << myendl;
(*this) << " -Shared: " << cwmWorldState->ServerData()->Directory( CSDDP_SHARED ) << myendl;
(*this) << " -Archive: " << cwmWorldState->ServerData()->Directory( CSDDP_BACKUP ) << myendl;
(*this) << " -Data: " << cwmWorldState->ServerData()->Directory( CSDDP_DATA ) << myendl;
(*this) << " -Defs: " << cwmWorldState->ServerData()->Directory( CSDDP_DEFS ) << myendl;
(*this) << " -Scripts: " << cwmWorldState->ServerData()->Directory( CSDDP_SCRIPTS ) << myendl;
(*this) << " -ScriptData: " << cwmWorldState->ServerData()->Directory( CSDDP_SCRIPTDATA ) << myendl;
(*this) << " -HTML: " << cwmWorldState->ServerData()->Directory( CSDDP_HTML ) << myendl;
(*this) << " -Books: " << cwmWorldState->ServerData()->Directory( CSDDP_BOOKS ) << myendl;
(*this) << " -MessageBoards: " << cwmWorldState->ServerData()->Directory( CSDDP_MSGBOARD ) << myendl;
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void RegisterKey( SI32 key, std::string cmdName, UI16 scriptID )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Registers key input for detection in console
//o-----------------------------------------------------------------------------------------------o
void CConsole::RegisterKey( SI32 key, std::string cmdName, UI16 scriptID )
{
#if defined( UOX_DEBUG_MODE )
messageLoop << strutil::format(" Registering key \"%c\"", key );
#endif
JSKeyHandler[key] = JSConsoleEntry( scriptID, cmdName );
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void SetKeyStatus( SI32 key, bool isEnabled )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Enabling/Disabling specific key input in console
//o-----------------------------------------------------------------------------------------------o
void CConsole::SetKeyStatus( SI32 key, bool isEnabled )
{
JSCONSOLEKEYMAP_ITERATOR toFind = JSKeyHandler.find( key );
if( toFind != JSKeyHandler.end() )
{
toFind->second.isEnabled = isEnabled;
}
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void RegisterFunc( const std::string &cmdFunc, const std::string &cmdName, UI16 scriptID )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Registers console function
//o-----------------------------------------------------------------------------------------------o
void CConsole::RegisterFunc( const std::string &cmdFunc, const std::string &cmdName, UI16 scriptID )
{
#if defined( UOX_DEBUG_MODE )
print(strutil::format( " Registering console func \"%s\"\n", cmdFunc.c_str() ));
#endif
JSConsoleFunctions[strutil::upper(cmdFunc)] = JSConsoleEntry( scriptID, cmdName );
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void SetFuncStatus( const std::string &cmdFunc, bool isEnabled )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Enables/disables console function
//o-----------------------------------------------------------------------------------------------o
void CConsole::SetFuncStatus( const std::string &cmdFunc, bool isEnabled )
{
std::string upper = cmdFunc;
upper = strutil::upper( upper );
JSCONSOLEFUNCMAP_ITERATOR toFind = JSConsoleFunctions.find( upper );
if( toFind != JSConsoleFunctions.end() )
{
toFind->second.isEnabled = isEnabled;
}
}
//o-----------------------------------------------------------------------------------------------o
//| Function - void Registration( void )
//o-----------------------------------------------------------------------------------------------o
//| Purpose - Registers console script
//o-----------------------------------------------------------------------------------------------o
void CConsole::Registration( void )
{
CJSMappingSection *spellSection = JSMapping->GetSection( SCPT_CONSOLE );
for( cScript *ourScript = spellSection->First(); !spellSection->Finished(); ourScript = spellSection->Next() )
{
if( ourScript != nullptr )
ourScript->ScriptRegistration( "Console" );
}
}