mirror of
https://github.com/UOX3DevTeam/UOX3
synced 2026-08-13 12:27:04 -04:00
Removed arbitrary and hidden restrictions on refreshing list of online players shown with 'wholist command
Fixed an issue where player ghosts that get teleported would not see themselves get updated to new location
Fixed a server crash from clients disconnecting while running server in debug mode
Improved how container updates are sent to players; now only sends to clients that have actually opened the container, and who are still within range
Added more information about UO data files being loaded during server startup
Enhanced the GM 'add menu to allow clicking directly on images of items/npcs to add them, and adjusted size of menus to accommodate this
Fixed an issue with fleeing NPCs that could cause them to attempt to flee across time and space, regardless of distance to target/attacker in combat
Added NPC AI that runs away from players if they get too close (even outside combat). Applied to hind, rabbits, squirrels, ferrets and various birds by default:
AI_ANIMAL_SCARED (aitype 12)
Fixed issues with NPCs fleeing forever, or getting stuck in flee/don't flee loop, by introducing max fleeing distance (50 tiles) and cooldown (30 sec) on fleeing
Updated onNameRequest JS Event to include third parameter with origin of name request, so script responses can be tailored appropriately:
onNameRequest( myObj, requestedBy, requestSource )
Potential values for requestSource:
0 - Speech/System Messages
1 - Guild Menus
2 - Stat Window (self)
3 - Stat Window (other)
4 - Tooltip
5 - Paperdoll Journal
6 - Paperdoll
7 - Single Click / All-Names
8 - System
9 - Secure Trade Window
Added Adaptive Performance System (APS) that dynamically adjust how often NPC AI/movement is checked based on overall shard performance. If performance drops below defined threshold, UOX3 gradually slows down checks for NPC AI/movement to prioritize player movement/speech/command responsiveness. If performance climbs back up above threshold, slowdowns are gradually removed. The following UOX.INI options have been added under [system] category to support this system:
APSPERFTHRESHOLD=50 // Performance threshold (measured in simulation cycles/sec) below which the APS kicks in
APSINTERVAL=100 // How often (in milliseconds) the APS checks performance and makes adjustments (if needed) to balance out shard performance
APSDELAYSTEP=50 // How much the delay timer is modified by (in milliseconds) each time APS makes adjustments
APSDELAYMAXCAP=2000 // Max amount of of delay APS can introduce for NPC AI/movement handling when attempting to restore shard performance
Added new JS Methods for Region objects:
.GetOrePrefs( oreType ) // Get ore preference data for ore type found in town region. Returned as an array containing the following data:
orePrefData -> [
oreName, // name of ore
color, // color of ore
minskill, // min skill to mine ore
ingotName, // name of ingot created from ore
makemenu, // makemenu entry for crafting something from ingot
oreChance, // default global chance of finding this ore type
scriptID // script attached to mined ore
],
orePrefChance // Chance of finding this ore type in given town region
.GetOreChance() // Get base chance of finding any ore in town region
Moved Mining skill plus gravedigging feature from hard code to scripts (js/skill/mining.js) to make it easier to maintain and/or customize, and removed hard coded variants
Gravedigging now relies on the ore resource system behind the scenes to restrict how often graves in a given area can be dug up
Fixed some incorrect references to .worldNumber Character property in misc scripts (should be .worldnumber)
Made some "hard-scripted" system messages in misc scripts use dictionary system instead
Added spawn region for banker NPCs in Serpent's Hold (dfndata/spawn/felucca/spawn_town_serpents_hold.dfn, dfndata/spawn/trammel/spawn_town_serpents_hold.dfn)
Fixed region definition of Ocllo to actually cover the entire town (dfndata/regions/regions.dfn)
Added numerous additional locations accessible with 'goplace # command, for key locations in Ilshenar, Malas, Tokuno Islands and Ter Mur (dfndata/location/location.dfn)
Revised travel-menu portion of GM menu (shortcut: 'travel) to include more travel options based on new locations (dfndata/items/travelmenu.dfn and travelmenu.bulk.dfn)
Fixed an issue where NPCs could attempt to attack targets in other worlds/instances
Added new JS Event that triggers for characters who are about to deal damage in combat. Complimentary to onDamage, which triggers for chars receiving damage:
onDamageDeal( dmgDealer, dmgReceiver, damageValue, damageType )
Added new JS Event that can trigger in global script upon creation of new player chars. Note that this will trigger in place of onCreateDFN event for player characters:
onCreatePlayer( pChar )
Added new JS Event that triggers for characters selecting a target with a spell. Complimentary to onSpellTarget, which triggers for targets selected with a spell:
onSpellTargetSelect( caster, target, spellNum )
Updated onCombatStart and onCombatEnd JS Events to also trigger for the other party in combat
Updated onPickup JS Event to include a third parameter - the potential container item was picked up from. Event now also triggers event in scripts attached to said containers:
onPickup( iPickedUp, pChar, iCont )
Added tracking of total playtime per individual character, and per account across all characters, and exposed these properties to JS engine:
.totalPlayTime // Account property, total playtime across all chars
.playTime // Character property, total playtime on given character only
Added new player-accessible command ('playtime) to spit out the playtime of current character/account as a whole (js/commands/playtime.js)
Implemented first version of Young Player System:
Replaced the UNUSED9 account flag with YOUNG, to be used by Young/New Player System
Added new JS Account property that gets/sets whether player account is considered Young:
.isYoung
Added new Char timers:
TIMER_YOUNGHEAL // Restricts how often Young players are healed by NPC healers
TIMER_YOUNGMESSAGE // Restricts how often Young players are warned about dangerous looking monsters in overworld
Updated GM commands 'get and 'set to get/set .isYoung property of player's account (js/commands/targeting/get.js and set.js)
Added new UOX.INI setting to enable/disable Young Player System (enabled by default):
YOUNGPLAYERSYSTEM=1
If Young Player System is enabled, all newly created player accounts are automatically marked with Young flag
Added new script to handle various restrictions and functions related to Young characters (js/player/young_player.js):
Young characters will have [Young] displayed over their head
Young characters will have their Young status checked and verified on every login + every stat/skill gain, to revoke the Young status if any of the following is true:
Account has a total playtime of more than 40 hours
Any character has more than 350 total (base) skill points
Any character has more than 70 skill points in a single skill
Any character has more than 150 total stat points
Any character has more than 80 stat points in a single stat
Young characters can renounce their Young status manually by saying the words "I renounce my young player status"
Young characters get two additional items upon creation:
a new player ticket (can be combined with any other players new player ticket for both players to get a reward)
a sextant (shows Young players directions to nearest moongate/bank regardless of where they are, as long as outdoors)
Young characters cannot target other player characters with hostile spells or skills
Young characters cannot be the target of other player characters' hostile spells or skills
Young characters can only cast beneficial spells upon themselves or other Young characters
Young characters can only be the target of beneficial spells from other Young players
Young players (and their pets/followers) cannot attack or harm any other players (or their pets/followers), nor themselves be attacked or harmed by any other players (or their pets/followers), whether from combat, spells, skills or items
Young players don't lose any of their items on death, and are teleported to the nearest healer upon death with all their items intact
Young players receive a warning upon entering dungeons that monsters there will be hostile
Updated global script (js/server/global.js) to:
Check/Verify Young status of players upon login
Attach young player script on login/creation for players on Young accounts
Give specific items to Young players upon creation
Added new script (js/item/corpse.js) that is assigned to all freshly created corpses. This script handles restrictions related to Young players interactions with corpses, and the interactions of other players with corpses of Young players
Updated JS Method .Carve() to return true/false depending on whether carving a corpse was successful
Updated Healer AI in code to heal nearby injured Young players
Updated Evil AI and Evil Caster AI in code to avoid selecting Young players as targets in combat outside of dungeons
Added a new section to UOX.INI - [young player starting locations] - that can be used to define starting locations for Young players. If only one such location is provided, all players start there. Otherwise, it matches the same starting location setup as the regular one - with one entry per town in Britannia.
Restricted transferring and/or friending of pets (code) and hirelings (hirelings.js) between Young and non-Young players
Restricted Young players from recalling or gating to Felucca facet
Young players can instantly logout from anywhere, at any time
1463 lines
53 KiB
C++
1463 lines
53 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>
|
|
#include <stdexcept>
|
|
|
|
#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
|
|
using namespace std::string_literals;
|
|
CEndL myendl;
|
|
|
|
constexpr auto NORMALMODE = std::uint8_t( 0 );
|
|
constexpr auto WARNINGMODE = std::uint8_t( 1 );
|
|
constexpr auto ERRORMODE = std::uint8_t( 2 );
|
|
//const UI08 COLOURMODE = 3;
|
|
const std::string CConsole::ESC = "\x1b"s;
|
|
const std::string CConsole::CSI = CConsole::ESC + "["s;
|
|
const std::string CConsole::BEL = "\x07"s;
|
|
// Command sequences
|
|
const std::string CConsole::ATTRIBUTE = CConsole::CSI +"#m"s; // find/replace on # with attribute number
|
|
const std::string CConsole::MOVE = CConsole::CSI + "ROW;COLH"s; // we are going to find/replace on ROW/COL
|
|
const std::string CConsole::HORIZMOVE = CConsole::CSI + "COLG"s;
|
|
const std::string CConsole::VERTMOVE = CConsole::CSI + "ROWd"s;
|
|
const std::string CConsole::OFFCURSOR = CConsole::CSI + "?25l"s;
|
|
const std::string CConsole::ONCURSOR = CConsole::CSI + "?25h"s;
|
|
|
|
const std::string CConsole::ONGRAPHIC = CConsole::ESC + "(0"s;
|
|
const std::string CConsole::OFFGRAPHIC = CConsole::ESC + "(B"s;
|
|
|
|
const std::string CConsole::SETTITLE = CConsole::ESC + "]2;TITLEs"s + CConsole::BEL;
|
|
|
|
const std::string CConsole::CLEAR = CConsole::CSI +"2J"s;
|
|
|
|
// Forward function declarations
|
|
auto EndMessage( SI32 x ) -> void;
|
|
auto LoadCustomTitle() -> void;
|
|
auto LoadSkills() -> void;
|
|
auto LoadSpawnRegions() -> void;
|
|
auto LoadRegions() -> void;
|
|
auto LoadTeleportLocations() -> void;
|
|
auto LoadCreatures() -> void;
|
|
auto LoadPlaces() -> void;
|
|
auto UnloadRegions() -> void;
|
|
auto UnloadSpawnRegions() -> void;
|
|
auto 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 )
|
|
{
|
|
is_initialized = false;
|
|
}
|
|
|
|
CConsole::~CConsole()
|
|
{
|
|
if( is_initialized )
|
|
{
|
|
MoveTo( 1, height );
|
|
Reset();
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::Initialize()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Prepare console/terminal for UOX3 output
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::Initialize() -> void
|
|
{
|
|
is_initialized = true;
|
|
#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
|
|
auto CConsole::Reset() -> void
|
|
{
|
|
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()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Set console/terminal window title
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::SetTitle( const std::string &value ) -> void
|
|
{
|
|
#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()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Send cmd to terminal
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::SendCMD( const std::string& cmd ) ->CConsole&
|
|
{
|
|
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
|
|
auto CConsole::WindowSize() -> std::pair<int, int>
|
|
{
|
|
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_pair( row, col );
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole()::DoClearScreen()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Clears the screen
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::DoClearScreen() -> void
|
|
{
|
|
#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
|
|
auto CConsole::operator << ( const char *output ) ->CConsole&
|
|
{
|
|
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
|
|
{
|
|
std::cout << output;
|
|
}
|
|
#else
|
|
std::cout << output;
|
|
#endif
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const std::uint8_t *output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << reinterpret_cast<const char*>( output );
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const std::int8_t *output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << reinterpret_cast<const char*>( output );
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const std::uint8_t &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << static_cast<UI16>( output );
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const std::int8_t &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << static_cast<std::int16_t>( output );
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const UI16 &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << output;
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const std::int16_t &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << output;
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const std::uint32_t &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << output;
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const std::int32_t &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << output;
|
|
return ( *this );
|
|
}
|
|
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const std::uint64_t &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << output;
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const std::int64_t &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << output;
|
|
return ( *this );
|
|
}
|
|
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const float &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << output;
|
|
return ( *this );
|
|
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const double &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << output;
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const long double &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << output;
|
|
return ( *this );
|
|
}
|
|
|
|
//================================================================================================
|
|
auto CConsole::operator << ( CBaseObject *output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
(*this) << output->GetSerial();
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const CBaseObject *output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
(*this) << output->GetSerial();
|
|
return ( *this );
|
|
}
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const CBaseObject &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
(*this) << output.GetSerial();
|
|
return ( *this );
|
|
}
|
|
|
|
//================================================================================================
|
|
auto CConsole::operator << ( const std::string &output ) -> CConsole&
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << output;
|
|
return ( *this );
|
|
}
|
|
|
|
//================================================================================================
|
|
auto CConsole::operator << ( [[maybe_unused]] CEndL& myObj ) -> CConsole&
|
|
{
|
|
if( curLeft == 0 )
|
|
{
|
|
PrintStartOfLine();
|
|
}
|
|
std::cout << std::endl;
|
|
curLeft = 0;
|
|
++curTop;
|
|
return ( *this );
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::Print()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Prints the console with the "|"
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::Print( const std::string& msg ) -> void
|
|
{
|
|
StartOfLineCheck();
|
|
std::cout << msg;
|
|
if(( msg.size() > 0 ) && ( msg[msg.size() - 1] == '\n' ))
|
|
{
|
|
curLeft = 0;
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::Log()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Writes to the logfile
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::Log( const std::string& msg, const std::string& filename ) -> void
|
|
{
|
|
if( cwmWorldState )
|
|
{
|
|
if( cwmWorldState->ServerData()->ServerConsoleLog() )
|
|
{
|
|
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( oldstrutil::format( "%s%s\n", timeStr, msg.c_str() ));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::Log()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Log to the console.log file
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::Log( const std::string& msg ) -> void
|
|
{
|
|
if( cwmWorldState->ServerData()->ServerConsoleLog() )
|
|
{
|
|
Log( msg, "console.log" );
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::Error()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Writes to the error log and the console.
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::Error(const std::string& msg) -> void
|
|
{
|
|
try
|
|
{
|
|
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 );
|
|
}
|
|
catch( const std::exception &e )
|
|
{
|
|
std::cerr << "Error print reporting 'error'. Error was: " << msg << std::endl;
|
|
exit( 1 );
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::PrintSectionBegin()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Prints a section seperator
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::PrintSectionBegin() -> void
|
|
{
|
|
TurnBrightWhite();
|
|
std::cout << "o";
|
|
for( auto j = 1; j < width - 1; ++j )
|
|
{
|
|
std::cout << "-";
|
|
}
|
|
std::cout << "o";
|
|
curLeft = 0;
|
|
curTop = 0;
|
|
TurnNormal();
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::Start()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Migration of constart function to here
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::Start(const std::string& temp) -> void
|
|
{
|
|
auto size = WindowSize();
|
|
width = std::get<1>( size );
|
|
height = std::get<0>( size );
|
|
SetTitle( temp );
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::TurnYellow()
|
|
///o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Turns the text yellow
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto 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 - CConsole::TurnRed()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Turns the text red
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto 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 - CConsole::TurnGreen()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Turns the text green
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto 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 - CConsole::TurnBlue()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Turns the text blue
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto 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 - CConsole::TurnNormal()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns text to normal white
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto 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 - CConsole::TurnBrightWhite()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Returns text to bright white
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto 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 - CConsole::PrintDone()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Prints colored "[done]" message
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::PrintDone() -> void
|
|
{
|
|
PrintSpecial( CGREEN, "done" );
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::PrintFailed()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Prints colored "[failed]" message
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::PrintFailed() -> void
|
|
{
|
|
PrintSpecial( CRED, "Failed" );
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::PrintPassed()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Prints colored "[skipped]" message
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::PrintPassed() -> void
|
|
{
|
|
PrintSpecial( CYELLOW, "Skipped" );
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::ClearScreen()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Clears the screen
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::ClearScreen() -> void
|
|
{
|
|
DoClearScreen();
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::PrintBasedOnVal()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Prints "done" or "failed" messages based on boolean passed in
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::PrintBasedOnVal( bool value ) -> void
|
|
{
|
|
if( value )
|
|
{
|
|
PrintDone();
|
|
}
|
|
else
|
|
{
|
|
PrintFailed();
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::Warning()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Writes to the warning log and the console.
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::Warning( const std::string& msg ) -> void
|
|
{
|
|
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 - Console::CurrentMode()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Gets/Sets console's output mode
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::CurrentMode() const -> std::uint8_t
|
|
{
|
|
return currentMode;
|
|
}
|
|
auto CConsole::CurrentMode( std::uint8_t value ) -> void
|
|
{
|
|
currentMode = value;
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::PrintStartOfLine()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Set colour of console text at start of a new line
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto 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 - CConsole::MoveTo( SI32 x, SI32 y )
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Set console cursor position
|
|
//o------------------------------------------------------------------------------------------------o
|
|
#if PLATFORM == WINDOWS
|
|
auto CConsole::MoveTo( SI32 x, SI32 y ) -> void
|
|
{
|
|
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 = static_cast<UI16>( x );
|
|
SetConsoleCursorPosition( hco, Pos );
|
|
}
|
|
else
|
|
{
|
|
Pos.X = static_cast<UI16>( x );
|
|
Pos.Y = static_cast<UI16>( y );
|
|
SetConsoleCursorPosition( hco, Pos );
|
|
}
|
|
}
|
|
#else
|
|
void CConsole::MoveTo( SI32 x, [[maybe_unused]] SI32 y )
|
|
{
|
|
std::cout << "\033[255D";
|
|
std::cout << "\033[" << x << "C";
|
|
}
|
|
#endif
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::LogEcho()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Checks whether console should echo log messages
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::LogEcho() const -> bool
|
|
{
|
|
return logEcho;
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::LogEcho()
|
|
//| Date - 2/03/2003
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Enables/Disables whether console should echo log messages
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::LogEcho( bool value ) -> void
|
|
{
|
|
logEcho = value;
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::StartOfLineCheck()
|
|
//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
|
|
auto CConsole::StartOfLineCheck() -> void
|
|
{
|
|
if( curLeft == 0 )
|
|
{
|
|
PrintStartOfLine();
|
|
curLeft = 1;
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::PrintSpecial()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - This is much like PrintFailed, PrintDone and so on except
|
|
//| we specify the text and the colour
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::PrintSpecial( UI08 colour, const std::string& msg ) -> void
|
|
{
|
|
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 - CConsole::cl_getch()
|
|
//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
|
|
auto CConsole::cl_getch() -> std::int32_t
|
|
{
|
|
#if PLATFORM != WINDOWS
|
|
char data = 0;
|
|
auto a = ::read( 0, &data, 1); // This doesn't block on getting a line due to initalization
|
|
if( a > 0 )
|
|
{
|
|
// Look for escape!
|
|
if( data == 27 )
|
|
{
|
|
// This was an escape, see if we have another item
|
|
a = ::read( 0, &data, 1 );
|
|
if( a > 0 )
|
|
{
|
|
// See if this is a CSI
|
|
if( data == '[' )
|
|
{
|
|
// It is an control sequence!
|
|
// Some sequences end with a ~, some dont. So, we now get to see
|
|
a = ::read( 0, &data, 1 );
|
|
while( a > 0 )
|
|
{
|
|
if(( data == 'A' ) || ( data == 'B' ) || ( data == 'C' ) || ( data == 'D' ) || (( data == 'H' ) && ( data == 'F' )) || ( data == '~' ))
|
|
{
|
|
break;
|
|
}
|
|
a = ::read( 0, &data, 1 );
|
|
}
|
|
return -1;
|
|
}
|
|
else if( data == 'O' ) // this could be F1-F4
|
|
{
|
|
a = ::read( 0, &data, 1 );
|
|
if( a > 0 )
|
|
{
|
|
if(( data == 'P' ) || ( data == 'Q' ) || ( data == 'R' ) || ( data == 'S' ))
|
|
{
|
|
// It was F1,F2,F3,F4
|
|
return -1;
|
|
}
|
|
// Soooooo, we have now lost two characters, this one and the preceeding O that where after the ESC
|
|
return 27;
|
|
}
|
|
// It wasnt, so we have a choice, return -1 (since we got ESC O, or return ESC and lose O
|
|
return 27;
|
|
}
|
|
else
|
|
{
|
|
// Ok, it isn't an CSI (Control Sequence). But we have all ready lost/read the next
|
|
// character. That will be lost, return escape
|
|
return 27;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// There was nothing after the escape, so just send the escape
|
|
return 27; // return escape
|
|
}
|
|
}
|
|
// Not escape if here, so just return it
|
|
return static_cast<SI32>( data );
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
#else
|
|
// uox is not wrapped simply use the kbhit routine
|
|
if( _kbhit() )
|
|
{
|
|
return _getch();
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::Poll()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Facilitate console control. SysOp keys, and localhost
|
|
//| controls.
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::Poll() -> void
|
|
{
|
|
SI32 c = cl_getch();
|
|
if( c > 0 )
|
|
{
|
|
c = std::toupper( c );
|
|
Process( c );
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::Process()
|
|
//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
|
|
auto CConsole::Process(std::int32_t c) -> void
|
|
{
|
|
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 )
|
|
{
|
|
// All commands that execute are of the form: command_commandname (to avoid possible clashes)
|
|
#if defined( UOX_DEBUG_MODE )
|
|
Print( oldstrutil::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 = oldstrutil::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 = oldstrutil::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 = oldstrutil::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( auto &tSock : Network->connClients )
|
|
{
|
|
if( tSock->AcctNo() == 0 )
|
|
{
|
|
Network->Disconnect( tSock );
|
|
}
|
|
}
|
|
messageLoop << "CMD: Socket Disconnected(Account 0).";
|
|
break;
|
|
case 'K':
|
|
{
|
|
for( auto &tSock : Network->connClients )
|
|
{
|
|
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( oldstrutil::format( "\tNetwork code: %.2fmsec [%i samples]", static_cast<R32>( static_cast<R32>( cwmWorldState->ServerProfile()->NetworkTime() ) / static_cast<R32>( networkTimeCount )), networkTimeCount ), "performance.log" );
|
|
Log( oldstrutil::format( "\tTimer code: %.2fmsec [%i samples]", static_cast<R32>( static_cast<R32>( cwmWorldState->ServerProfile()->TimerTime() ) / static_cast<R32>( timerTimeCount )), timerTimeCount ), "performance.log" );
|
|
Log( oldstrutil::format( "\tAuto code: %.2fmsec [%i samples]", static_cast<R32>( static_cast<R32>( cwmWorldState->ServerProfile()->AutoTime() ) / static_cast<R32>( autoTimeCount )), autoTimeCount ), "performance.log" );
|
|
Log( oldstrutil::format( "\tLoop Time: %.2fmsec [%i samples]", static_cast<R32>( static_cast<R32>( cwmWorldState->ServerProfile()->LoopTime() ) / static_cast<R32>( loopTimeCount )), loopTimeCount ), "performance.log" );
|
|
|
|
Log( oldstrutil::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( oldstrutil::format( "\tSimulation Cycles: %f per sec", (1000.0*(1.0/static_cast<R32>( static_cast<R32>( cwmWorldState->ServerProfile()->LoopTime() ) / static_cast<R32>( loopTimeCount ))))), "performance.log" );
|
|
Log( oldstrutil::format( "\tBytes sent: %i", cwmWorldState->ServerProfile()->GlobalSent() ), "performance.log" );
|
|
Log( oldstrutil::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:";
|
|
{
|
|
for( auto &iSock : Network->connClients )
|
|
{
|
|
++j;
|
|
CChar *mChar = iSock->CurrcharObj();
|
|
|
|
temp = oldstrutil::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;
|
|
}
|
|
}
|
|
|
|
temp = oldstrutil::format( " Total users online: %i", j );
|
|
messageLoop << temp;
|
|
break;
|
|
}
|
|
case 'M':
|
|
UI32 tmp, total;
|
|
total = 0;
|
|
tmp = 0;
|
|
messageLoop << "CMD: UOX Memory Information:";
|
|
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 = oldstrutil::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 = oldstrutil::format( " Items: %u bytes [%u items ( %u allocated )]", tmp, ObjectFactory::GetSingleton().CountOfObjects( OT_ITEM ), n );
|
|
messageLoop << temp;
|
|
temp = oldstrutil::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( CSpellInfo );
|
|
temp = oldstrutil::format( temp, " Spells: %i bytes", tmp );
|
|
messageLoop << " Sizes:";
|
|
temp = oldstrutil::format(" CItem : %lu bytes", sizeof( CItem ));
|
|
messageLoop << temp;
|
|
temp = oldstrutil::format( " CChar : %lu bytes", sizeof( CChar ));
|
|
messageLoop << temp;
|
|
temp = oldstrutil::format( " TEffect: %lu bytes %lui total)", sizeof( CTEffect ), sizeof( CTEffect ) * cwmWorldState->tempEffects.Num() );
|
|
messageLoop << temp;
|
|
temp = oldstrutil::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':
|
|
{
|
|
auto loggingEnabled = false;
|
|
{
|
|
for( auto &snSock : Network->connClients )
|
|
{
|
|
if( snSock )
|
|
{
|
|
snSock->Logging( !snSock->Logging() );
|
|
}
|
|
}
|
|
auto iter = Network->connClients.begin();
|
|
if( iter != Network->connClients.end() )
|
|
{
|
|
loggingEnabled = ( *iter )->Logging();
|
|
}
|
|
}
|
|
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 = oldstrutil::format( "Key \'%c\' [%i] does not perform a function", static_cast<SI08>( c ), c );
|
|
messageLoop << temp;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::DisplaySettings()
|
|
//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
|
|
auto 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()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Registers key input for detection in console
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::RegisterKey( SI32 key, std::string cmdName, UI16 scriptId ) -> void
|
|
{
|
|
#if defined( UOX_DEBUG_MODE )
|
|
messageLoop << oldstrutil::format( " Registering key \"%c\"", key );
|
|
#endif
|
|
JSKeyHandler[key] = JSConsoleEntry_st( scriptId, cmdName );
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::SetKeyStatus()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Enabling/Disabling specific key input in console
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::SetKeyStatus( SI32 key, bool isEnabled ) -> void
|
|
{
|
|
auto toFind = JSKeyHandler.find( key );
|
|
if( toFind != JSKeyHandler.end() )
|
|
{
|
|
toFind->second.isEnabled = isEnabled;
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::RegisterFunc()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Registers console function
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::RegisterFunc( const std::string &cmdFunc, const std::string &cmdName, UI16 scriptId ) -> void
|
|
{
|
|
#if defined( UOX_DEBUG_MODE )
|
|
Print( oldstrutil::format( " Registering console func \"%s\"\n", cmdFunc.c_str() ));
|
|
#endif
|
|
JSConsoleFunctions[oldstrutil::upper( cmdFunc )] = JSConsoleEntry_st( scriptId, cmdName );
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::SetFuncStatus()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Enables/disables console function
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::SetFuncStatus( const std::string &cmdFunc, bool isEnabled ) -> void
|
|
{
|
|
auto upper = oldstrutil::upper( cmdFunc );
|
|
auto toFind = JSConsoleFunctions.find( upper );
|
|
if( toFind != JSConsoleFunctions.end() )
|
|
{
|
|
toFind->second.isEnabled = isEnabled;
|
|
}
|
|
}
|
|
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Function - CConsole::Registration()
|
|
//o------------------------------------------------------------------------------------------------o
|
|
//| Purpose - Registers console script
|
|
//o------------------------------------------------------------------------------------------------o
|
|
auto CConsole::Registration() -> void
|
|
{
|
|
auto spellSection = JSMapping->GetSection( SCPT_CONSOLE );
|
|
for( const auto &[spellname, ourScript] : spellSection->collection() )
|
|
{
|
|
if( ourScript )
|
|
{
|
|
ourScript->ScriptRegistration( "Console" );
|
|
}
|
|
}
|
|
}
|