void CConsole::Process( int c ) { char outputline[128], temp[1024]; bool kill = false; int indexcount = 0; int j; int keyresp; CSocket *tSock = NULL; 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 != NULL ) { // All commands that execute are of the form: command_commandname (to avoid possible clashes) #if defined( UOX_DEBUG_MODE ) Print( "Executing JS keystroke %c %s\n", c, toFind->second.cmdName.c_str() ); #endif toExecute->CallParticularEvent( toFind->second.cmdName.c_str(), NULL, 0 ); } return; } } 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': std::cout << "System: "; while( !kill ) { keyresp = cl_getch(); switch( keyresp ) { case -1: // no key pressed case 0: break; case 0x1B: memset( outputline, 0x00, sizeof( 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 ); indexcount = 0; kill = true; std::cout << std::endl; sprintf( temp, "CMD: System broadcast sent message \"%s\"", outputline ); memset( outputline, 0x00, sizeof( outputline ) ); messageLoop << temp; break; default: if( static_cast<size_t>(indexcount) < sizeof( outputline ) ) { outputline[indexcount++] = (UI08)(keyresp); std::cout << (char)keyresp; } 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 << " "; char szBuffer[128]; // 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 ) ); memset( szBuffer, 0x00, sizeof( szBuffer ) ); sprintf( szBuffer, "AddMenuGroup %lu:", CJ->first ); messageLoop << szBuffer; std::pair< ADDMENUMAP_CITERATOR, ADDMENUMAP_CITERATOR > pairRange = g_mmapAddMenuMap.equal_range( CJ->first ); int count = 0; for( ADDMENUMAP_CITERATOR CI=pairRange.first;CI != pairRange.second; CI++ ) { count++; } memset( szBuffer, 0x00, sizeof( szBuffer ) ); sprintf( szBuffer, " 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; // 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(); LoadTeleportLocations(); 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 != NULL; 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( "\tPerformace Dump:", "performance.log"); Log( "\tNetwork code: %.2fmsec [%i samples]", "performance.log", (R32)((R32)cwmWorldState->ServerProfile()->NetworkTime()/(R32)networkTimeCount), networkTimeCount); Log( "\tTimer code: %.2fmsec [%i samples]", "performance.log", (R32)((R32)cwmWorldState->ServerProfile()->TimerTime()/(R32)timerTimeCount), timerTimeCount); Log( "\tAuto code: %.2fmsec [%i samples]", "performance.log", (R32)((R32)cwmWorldState->ServerProfile()->AutoTime()/(R32)autoTimeCount), autoTimeCount); Log( "\tLoop Time: %.2fmsec [%i samples]", "performance.log", (R32)((R32)cwmWorldState->ServerProfile()->LoopTime()/(R32)loopTimeCount), loopTimeCount); ObjectFactory *ourFac = ObjectFactory::getSingletonPtr(); Log( "\tCharacters: %i/%i - Items: %i/%i (Dynamic)", "performance.log", ourFac->CountOfObjects( OT_CHAR ), ourFac->SizeOfObjects( OT_CHAR ), ourFac->CountOfObjects( OT_ITEM ), ourFac->SizeOfObjects( OT_ITEM ) ); Log( "\tSimulation Cycles: %f per sec", "performance.log", (1000.0*(1.0/(R32)((R32)cwmWorldState->ServerProfile()->LoopTime()/(R32)loopTimeCount)))); Log( "\tBytes sent: %i", "performance.log", cwmWorldState->ServerProfile()->GlobalSent()); Log( "\tBytes Received: %i", "performance.log", cwmWorldState->ServerProfile()->GlobalReceived()); Log( "--- Performance Dump Complete ---", "performance.log"); LogEcho( false ); break; } case 'W': // Display logged in chars messageLoop << "CMD: Current Users in the World:"; j = 0; CSocket *iSock; Network->PushConn(); for( iSock = Network->FirstSocket(); !Network->FinishedSockets(); iSock = Network->NextSocket() ) { ++j; CChar *mChar = iSock->CurrcharObj(); sprintf( temp, " %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(); sprintf( temp, " Total users online: %i", j ); messageLoop << temp; break; case 'M': size_t tmp, total; total = 0; tmp = 0; messageLoop << "CMD: UOX Memory Information:"; messageLoop << " Cache:"; sprintf( temp, " Tiles: %u bytes", Map->GetTileMem() ); messageLoop << temp; sprintf( temp, " Multis: %u bytes", Map->GetMultisMem() ); messageLoop << temp; size_t m, n; m = ObjectFactory::getSingleton().SizeOfObjects( OT_CHAR ); total += tmp = m + m*sizeof( CTEffect ) + m*sizeof(char) + m*sizeof(int)*5; sprintf( temp, " Characters: %u bytes [%u chars ( %u allocated )]", tmp, ObjectFactory::getSingleton().CountOfObjects( OT_CHAR ), m ); messageLoop << temp; n = ObjectFactory::getSingleton().SizeOfObjects( OT_ITEM ); total += tmp = n + n * sizeof( int ) * 4; sprintf( temp, " Items: %u bytes [%u items ( %u allocated )]", tmp, ObjectFactory::getSingleton().CountOfObjects( OT_ITEM ), n ); messageLoop << temp; sprintf( temp, " You save I: %i & C: %i bytes!", m * sizeof(CItem) - ObjectFactory::getSingleton().CountOfObjects( OT_ITEM ), m * sizeof( CChar ) - ObjectFactory::getSingleton().CountOfObjects( OT_CHAR ) ); total += tmp = 69 * sizeof( SpellInfo ); sprintf( temp, " Spells: %i bytes", tmp ); messageLoop << " Sizes:"; sprintf( temp, " CItem : %i bytes", sizeof( CItem ) ); messageLoop << temp; sprintf( temp, " CChar : %i bytes", sizeof( CChar ) ); messageLoop << temp; sprintf( temp, " TEffect: %i bytes (%i total)", sizeof( CTEffect ), sizeof( CTEffect ) * cwmWorldState->tempEffects.Num() ); messageLoop << temp; total += tmp = Map->GetTileMem() + Map->GetMultisMem(); sprintf( temp, " 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 << " V - Dump Lookups(Devs) F - Display Priority Maps"; messageLoop << " Network Maintenence:"; messageLoop << " D - Disconnect Acct0 K - Disconnect All"; messageLoop << " Z - Socket Logging "; messageLoop << MSG_SECTIONBEGIN; break; case 'v': case 'V': // Dump look up data to files so developers working with extending the ini will have a table to use messageLoop << "| CMD: Creating Server.scp and Uox3.ini Tag Lookup files(For Developers)...."; cwmWorldState->ServerData()->dumpLookup( 0 ); cwmWorldState->ServerData()->save( "./uox.tst.ini" ); messageLoop << MSG_PRINTDONE; break; case 'z': case 'Z': { // Log socket activity Network->PushConn(); bool loggingEnabled = false; CSocket *snSock = Network->FirstSocket(); if( snSock != NULL ) loggingEnabled = !snSock->Logging(); for( ; !Network->FinishedSockets(); snSock = Network->NextSocket() ) { if( snSock != NULL ) 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: sprintf( temp, "Key \'%c\' [%i] does not perform a function", (char)c, c ); messageLoop << temp; break; } } }