mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-12 05:21:29 +00:00
Corrected some character name reservation logic Adjusted telnet console so it does not throw 'Command Unknown' when simply hitting enter key Adjusted System MSG for worldshutdown to use minutes instead of seconds Added warning for when Shared platinum is disabled at the rule level for players to NOT put platinum in the shared bank when they insert platinum in the shared platinum slot Changed a place in the code where disciplines were trained, someone had uint16 allocated to CharacterID and this was causing issues for characters with large ID's in the database Added a fix for bind points getting overwritten with invalid zone data, setting everything to 0,0,0,0 - Since I've added this change I've had no issues for players Fixed some spell book swap logic in the code, removed swap function. Fixed issue with guild ranks not loading properly Commented out some of the non-working tell-que code Took out some of the auto increment settings in the auto database conversion that don't affect anything anyways Added some additional escape string sequences for queries that needed them Added ThrowDBError logging to catch any potential query issues with saves or load functions
871 lines
28 KiB
C++
871 lines
28 KiB
C++
/* EQEMu: Everquest Server Emulator
|
|
Copyright (C) 2001-2002 EQEMu Development Team (http://eqemu.org)
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; version 2 of the License.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
|
are required to give you total support for your newly bought product;
|
|
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
#include "../common/debug.h"
|
|
#include <iostream>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <stdlib.h>
|
|
|
|
|
|
#include "../common/version.h"
|
|
#include "console.h"
|
|
#include "zoneserver.h"
|
|
#include "worlddb.h"
|
|
#include "../common/packet_dump.h"
|
|
#include "../common/seperator.h"
|
|
#include "../common/eq_packet_structs.h"
|
|
#include "../common/eq_packet.h"
|
|
#include "login_server.h"
|
|
#include "login_server_list.h"
|
|
#include "../common/serverinfo.h"
|
|
#include "../common/md5.h"
|
|
#include "../common/opcodemgr.h"
|
|
#include "../common/rulesys.h"
|
|
#include "../common/ruletypes.h"
|
|
#include "../common/string_util.h"
|
|
#include "world_config.h"
|
|
#include "zoneserver.h"
|
|
#include "zonelist.h"
|
|
#include "clientlist.h"
|
|
#include "launcher_list.h"
|
|
#include "ucs.h"
|
|
#include "queryserv.h"
|
|
|
|
#ifdef _WINDOWS
|
|
#define snprintf _snprintf
|
|
#define strncasecmp _strnicmp
|
|
#define strcasecmp _stricmp
|
|
#endif
|
|
|
|
extern ZSList zoneserver_list;
|
|
extern uint32 numzones;
|
|
extern LoginServerList loginserverlist;
|
|
extern ClientList client_list;
|
|
extern LauncherList launcher_list;
|
|
extern UCSConnection UCSLink;
|
|
extern QueryServConnection QSLink;
|
|
extern volatile bool RunLoops;
|
|
|
|
ConsoleList console_list;
|
|
void CatchSignal(int sig_num);
|
|
|
|
Console::Console(EmuTCPConnection* itcpc)
|
|
: WorldTCPConnection(),
|
|
timeout_timer(RuleI(Console, SessionTimeOut)),
|
|
prompt_timer(1000)
|
|
{
|
|
tcpc = itcpc;
|
|
tcpc->SetEcho(true);
|
|
state = 0;
|
|
paccountid = 0;
|
|
memset(paccountname, 0, sizeof(paccountname));
|
|
admin = 0;
|
|
pAcceptMessages = false;
|
|
}
|
|
|
|
Console::~Console() {
|
|
if (tcpc)
|
|
tcpc->Free();
|
|
}
|
|
|
|
void Console::Die() {
|
|
state = CONSOLE_STATE_CLOSED;
|
|
struct in_addr in;
|
|
in.s_addr = GetIP();
|
|
_log(WORLD__CONSOLE,"Removing console from %s:%d",inet_ntoa(in),GetPort());
|
|
tcpc->Disconnect();
|
|
}
|
|
|
|
bool Console::SendChannelMessage(const ServerChannelMessage_Struct* scm) {
|
|
if (!pAcceptMessages)
|
|
return false;
|
|
switch (scm->chan_num) {
|
|
if(RuleB(Chat, ServerWideAuction)){
|
|
case 4: {
|
|
SendMessage(1, "%s auctions, '%s'", scm->from, scm->message);
|
|
break;
|
|
}
|
|
}
|
|
if(RuleB(Chat, ServerWideOOC)){
|
|
case 5: {
|
|
SendMessage(1, "%s says ooc, '%s'", scm->from, scm->message);
|
|
break;
|
|
}
|
|
}
|
|
case 6: {
|
|
SendMessage(1, "%s BROADCASTS, '%s'", scm->from, scm->message);
|
|
break;
|
|
}
|
|
case 7: {
|
|
SendMessage(1, "[%s] tells you, '%s'", scm->from, scm->message);
|
|
ServerPacket* pack = new ServerPacket(ServerOP_ChannelMessage, sizeof(ServerChannelMessage_Struct) + strlen(scm->message) + 1);
|
|
memcpy(pack->pBuffer, scm, pack->size);
|
|
ServerChannelMessage_Struct* scm2 = (ServerChannelMessage_Struct*) pack->pBuffer;
|
|
strcpy(scm2->deliverto, scm2->from);
|
|
scm2->noreply = true;
|
|
client_list.SendPacket(scm->from, pack);
|
|
safe_delete(pack);
|
|
break;
|
|
}
|
|
case 11: {
|
|
SendMessage(1, "%s GMSAYS, '%s'", scm->from, scm->message);
|
|
break;
|
|
}
|
|
default: {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Console::SendEmoteMessage(uint32 type, const char* message, ...) {
|
|
if (!message)
|
|
return false;
|
|
if (!pAcceptMessages)
|
|
return false;
|
|
va_list argptr;
|
|
char buffer[1024];
|
|
|
|
va_start(argptr, message);
|
|
vsnprintf(buffer, sizeof(buffer), message, argptr);
|
|
va_end(argptr);
|
|
|
|
SendMessage(1, message);
|
|
return true;
|
|
}
|
|
|
|
bool Console::SendEmoteMessageRaw(uint32 type, const char* message) {
|
|
if (!message)
|
|
return false;
|
|
if (!pAcceptMessages)
|
|
return false;
|
|
SendMessage(1, message);
|
|
return true;
|
|
}
|
|
|
|
void Console::SendEmoteMessage(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message, ...) {
|
|
if (!message)
|
|
return;
|
|
if (to_guilddbid != 0 || to_minstatus > Admin())
|
|
return;
|
|
va_list argptr;
|
|
char buffer[1024];
|
|
|
|
va_start(argptr, message);
|
|
vsnprintf(buffer, sizeof(buffer), message, argptr);
|
|
va_end(argptr);
|
|
|
|
SendEmoteMessageRaw(to, to_guilddbid, to_minstatus, type, buffer);
|
|
}
|
|
|
|
void Console::SendEmoteMessageRaw(const char* to, uint32 to_guilddbid, int16 to_minstatus, uint32 type, const char* message) {
|
|
if (!message)
|
|
return;
|
|
if (to_guilddbid != 0 || to_minstatus > Admin())
|
|
return;
|
|
SendMessage(1, message);
|
|
}
|
|
|
|
void Console::SendMessage(uint8 newline, const char* message, ...) {
|
|
if (!message)
|
|
return;
|
|
char* buffer = 0;
|
|
uint32 bufsize = 1500;
|
|
if (message)
|
|
bufsize += strlen(message);
|
|
buffer = new char[bufsize];
|
|
memset(buffer, 0, bufsize);
|
|
if (message != 0) {
|
|
va_list argptr;
|
|
|
|
va_start(argptr, message);
|
|
vsnprintf(buffer, bufsize - 512, message, argptr);
|
|
va_end(argptr);
|
|
}
|
|
|
|
if (newline) {
|
|
char outbuf[3];
|
|
outbuf[0] = 13;
|
|
outbuf[1] = 10;
|
|
outbuf[2] = 0;
|
|
for (int i=0; i < newline; i++)
|
|
strcat(buffer, outbuf);
|
|
}
|
|
tcpc->Send((uchar*) buffer, strlen(buffer));
|
|
safe_delete_array(buffer);
|
|
}
|
|
|
|
bool Console::Process() {
|
|
if (state == CONSOLE_STATE_CLOSED)
|
|
return false;
|
|
|
|
if (!tcpc->Connected()) {
|
|
struct in_addr in;
|
|
in.s_addr = GetIP();
|
|
_log(WORLD__CONSOLE,"Removing console (!tcpc->Connected) from %s:%d",inet_ntoa(in),GetPort());
|
|
return false;
|
|
}
|
|
//if we have not gotten the special markers after this timer, send login prompt
|
|
if(prompt_timer.Check()) {
|
|
prompt_timer.Disable();
|
|
if(tcpc->GetMode() == EmuTCPConnection::modeConsole)
|
|
tcpc->Send((const uchar*) "Username: ", strlen("Username: "));
|
|
}
|
|
|
|
if (timeout_timer.Check()) {
|
|
SendMessage(1, 0);
|
|
SendMessage(1, "Timeout, disconnecting...");
|
|
struct in_addr in;
|
|
in.s_addr = GetIP();
|
|
_log(WORLD__CONSOLE,"TCP connection timeout from %s:%d",inet_ntoa(in),GetPort());
|
|
return false;
|
|
}
|
|
|
|
if (tcpc->GetMode() == EmuTCPConnection::modePacket) {
|
|
struct in_addr in;
|
|
in.s_addr = GetIP();
|
|
if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeZone) {
|
|
ZoneServer* zs = new ZoneServer(tcpc);
|
|
_log(WORLD__CONSOLE,"New zoneserver #%d from %s:%d", zs->GetID(), inet_ntoa(in), GetPort());
|
|
zoneserver_list.Add(zs);
|
|
numzones++;
|
|
tcpc = 0;
|
|
} else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeLauncher) {
|
|
_log(WORLD__CONSOLE,"New launcher from %s:%d", inet_ntoa(in), GetPort());
|
|
launcher_list.Add(tcpc);
|
|
tcpc = 0;
|
|
}
|
|
else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeUCS)
|
|
{
|
|
_log(WORLD__CONSOLE,"New UCS Connection from %s:%d", inet_ntoa(in), GetPort());
|
|
UCSLink.SetConnection(tcpc);
|
|
tcpc = 0;
|
|
}
|
|
else if(tcpc->GetPacketMode() == EmuTCPConnection::packetModeQueryServ)
|
|
{
|
|
_log(WORLD__CONSOLE,"New QS Connection from %s:%d", inet_ntoa(in), GetPort());
|
|
QSLink.SetConnection(tcpc);
|
|
tcpc = 0;
|
|
}
|
|
else {
|
|
_log(WORLD__CONSOLE,"Unsupported packet mode from %s:%d", inet_ntoa(in), GetPort());
|
|
}
|
|
return false;
|
|
}
|
|
char* command = 0;
|
|
while ((command = tcpc->PopLine())) {
|
|
timeout_timer.Start();
|
|
ProcessCommand(command);
|
|
delete command;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void ConsoleList::Add(Console* con) {
|
|
list.Insert(con);
|
|
}
|
|
|
|
void ConsoleList::Process() {
|
|
LinkedListIterator<Console*> iterator(list);
|
|
iterator.Reset();
|
|
|
|
while(iterator.MoreElements()) {
|
|
if (!iterator.GetData()->Process())
|
|
iterator.RemoveCurrent();
|
|
else
|
|
iterator.Advance();
|
|
}
|
|
}
|
|
|
|
void ConsoleList::KillAll() {
|
|
LinkedListIterator<Console*> iterator(list);
|
|
iterator.Reset();
|
|
|
|
while(iterator.MoreElements()) {
|
|
iterator.GetData()->Die();
|
|
iterator.RemoveCurrent();
|
|
}
|
|
}
|
|
|
|
void ConsoleList::SendConsoleWho(WorldTCPConnection* connection, const char* to, int16 admin, char** output, uint32* outsize, uint32* outlen) {
|
|
LinkedListIterator<Console*> iterator(list);
|
|
iterator.Reset();
|
|
struct in_addr in;
|
|
int x = 0;
|
|
|
|
while(iterator.MoreElements()) {
|
|
in.s_addr = iterator.GetData()->GetIP();
|
|
if (admin >= iterator.GetData()->Admin())
|
|
AppendAnyLenString(output, outsize, outlen, " Console: %s:%i AccID: %i AccName: %s", inet_ntoa(in), iterator.GetData()->GetPort(), iterator.GetData()->AccountID(), iterator.GetData()->AccountName());
|
|
else
|
|
AppendAnyLenString(output, outsize, outlen, " Console: AccID: %i AccName: %s", iterator.GetData()->AccountID(), iterator.GetData()->AccountName());
|
|
if (*outlen >= 3584) {
|
|
connection->SendEmoteMessageRaw(to, 0, 0, 10, *output);
|
|
safe_delete(*output);
|
|
*outsize = 0;
|
|
*outlen = 0;
|
|
}
|
|
else {
|
|
if (connection->IsConsole())
|
|
AppendAnyLenString(output, outsize, outlen, "\r\n");
|
|
else
|
|
AppendAnyLenString(output, outsize, outlen, "\n");
|
|
}
|
|
x++;
|
|
iterator.Advance();
|
|
}
|
|
AppendAnyLenString(output, outsize, outlen, "%i consoles connected", x);
|
|
}
|
|
|
|
void ConsoleList::SendChannelMessage(const ServerChannelMessage_Struct* scm) {
|
|
LinkedListIterator<Console*> iterator(list);
|
|
iterator.Reset();
|
|
|
|
while(iterator.MoreElements()) {
|
|
iterator.GetData()->SendChannelMessage(scm);
|
|
iterator.Advance();
|
|
}
|
|
}
|
|
|
|
void ConsoleList::SendEmoteMessage(uint32 type, const char* message, ...) {
|
|
va_list argptr;
|
|
char buffer[1024];
|
|
|
|
va_start(argptr, message);
|
|
vsnprintf(buffer, sizeof(buffer), message, argptr);
|
|
va_end(argptr);
|
|
|
|
SendEmoteMessageRaw(type, buffer);
|
|
}
|
|
|
|
void ConsoleList::SendEmoteMessageRaw(uint32 type, const char* message) {
|
|
LinkedListIterator<Console*> iterator(list);
|
|
iterator.Reset();
|
|
|
|
while(iterator.MoreElements()) {
|
|
iterator.GetData()->SendEmoteMessageRaw(type, message);
|
|
iterator.Advance();
|
|
}
|
|
}
|
|
|
|
Console* ConsoleList::FindByAccountName(const char* accname) {
|
|
LinkedListIterator<Console*> iterator(list);
|
|
iterator.Reset();
|
|
|
|
while(iterator.MoreElements()) {
|
|
if (strcasecmp(iterator.GetData()->AccountName(), accname) == 0)
|
|
return iterator.GetData();
|
|
|
|
iterator.Advance();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void Console::ProcessCommand(const char* command) {
|
|
switch(state)
|
|
{
|
|
case CONSOLE_STATE_USERNAME:
|
|
{
|
|
if (strlen(command) >= 16) {
|
|
SendMessage(1, 0);
|
|
SendMessage(2, "Username buffer overflow.");
|
|
SendMessage(1, "Bye Bye.");
|
|
state = CONSOLE_STATE_CLOSED;
|
|
return;
|
|
}
|
|
strcpy(paccountname, command);
|
|
state = CONSOLE_STATE_PASSWORD;
|
|
SendMessage(0, "Password: ");
|
|
tcpc->SetEcho(false);
|
|
break;
|
|
}
|
|
case CONSOLE_STATE_PASSWORD:
|
|
{
|
|
if (strlen(command) >= 16) {
|
|
SendMessage(1, 0);
|
|
SendMessage(2, "Password buffer overflow.");
|
|
SendMessage(1, "Bye Bye.");
|
|
state = CONSOLE_STATE_CLOSED;
|
|
return;
|
|
}
|
|
paccountid = database.CheckLogin(paccountname,command);
|
|
if (paccountid == 0) {
|
|
SendMessage(1, 0);
|
|
SendMessage(2, "Login failed.");
|
|
SendMessage(1, "Bye Bye.");
|
|
state = CONSOLE_STATE_CLOSED;
|
|
return;
|
|
}
|
|
database.GetAccountName(paccountid, paccountname); // fixes case and stuff
|
|
admin = database.CheckStatus(paccountid);
|
|
if (!(admin >= consoleLoginStatus)) {
|
|
SendMessage(1, 0);
|
|
SendMessage(2, "Access denied.");
|
|
SendMessage(1, "Bye Bye.");
|
|
state = CONSOLE_STATE_CLOSED;
|
|
return;
|
|
}
|
|
_log(WORLD__CONSOLE,"TCP console authenticated: Username=%s, Admin=%d",paccountname,admin);
|
|
SendMessage(1, 0);
|
|
SendMessage(2, "Login accepted.");
|
|
state = CONSOLE_STATE_CONNECTED;
|
|
tcpc->SetEcho(true);
|
|
SendPrompt();
|
|
break;
|
|
}
|
|
case CONSOLE_STATE_CONNECTED: {
|
|
_log(WORLD__CONSOLE,"TCP command: %s: \"%s\"",paccountname,command);
|
|
Seperator sep(command);
|
|
if (strcasecmp(sep.arg[0], "help") == 0 || strcmp(sep.arg[0], "?") == 0) {
|
|
SendMessage(1, " whoami");
|
|
SendMessage(1, " who");
|
|
SendMessage(1, " zonestatus");
|
|
SendMessage(1, " uptime [zoneID#]");
|
|
SendMessage(1, " emote [zonename or charname or world] [type] [message]");
|
|
SendMessage(1, " echo [on/off]");
|
|
SendMessage(1, " acceptmessages [on/off]");
|
|
SendMessage(1, " tell [name] [message]");
|
|
SendMessage(1, " broadcast [message]");
|
|
SendMessage(1, " gmsay [message]");
|
|
SendMessage(1, " ooc [message]");
|
|
SendMessage(1, " auction [message]");
|
|
if (admin >= consoleKickStatus)
|
|
SendMessage(1, " kick [charname]");
|
|
if (admin >= consoleLockStatus)
|
|
SendMessage(1, " lock/unlock");
|
|
if (admin >= consoleZoneStatus) {
|
|
SendMessage(1, " zoneshutdown [zonename or ZoneServerID]");
|
|
SendMessage(1, " zonebootup [ZoneServerID] [zonename]");
|
|
SendMessage(1, " zonelock [list|lock|unlock] [zonename]");
|
|
}
|
|
if (admin >= consoleFlagStatus)
|
|
SendMessage(1, " flag [status] [accountname]");
|
|
if (admin >= consolePassStatus)
|
|
SendMessage(1, " setpass [accountname] [newpass]");
|
|
if (admin >= consoleWorldStatus) {
|
|
SendMessage(1, " version");
|
|
SendMessage(1, " worldshutdown");
|
|
}
|
|
if (admin >= 201) {
|
|
SendMessage(1, " IPLookup [name]");
|
|
}
|
|
if (admin >= 100) {
|
|
SendMessage(1, " LSReconnect");
|
|
SendMessage(1, " signalcharbyname charname ID");
|
|
SendMessage(1, " reloadworld");
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "ping") == 0) {
|
|
// do nothing
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "signalcharbyname") == 0) {
|
|
SendMessage(1, "Signal Sent to %s with ID %i", (char*) sep.arg[1], atoi(sep.arg[2]));
|
|
uint32 message_len = strlen((char*) sep.arg[1]) + 1;
|
|
ServerPacket* pack = new ServerPacket(ServerOP_CZSignalClientByName, sizeof(CZClientSignalByName_Struct) + message_len);
|
|
CZClientSignalByName_Struct* CZSC = (CZClientSignalByName_Struct*) pack->pBuffer;
|
|
strn0cpy(CZSC->Name, (char*) sep.arg[1], 64);
|
|
CZSC->data = atoi(sep.arg[2]);
|
|
zoneserver_list.SendPacket(pack);
|
|
safe_delete(pack);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "setpass") == 0 && admin >= consolePassStatus) {
|
|
if (sep.argnum != 2)
|
|
SendMessage(1, "Format: setpass accountname password");
|
|
else {
|
|
|
|
int16 tmpstatus = 0;
|
|
uint32 tmpid = database.GetAccountIDByName(sep.arg[1], &tmpstatus);
|
|
if (!tmpid)
|
|
SendMessage(1, "Error: Account not found");
|
|
else if (tmpstatus > admin)
|
|
SendMessage(1, "Cannot change password: Account's status is higher than yours");
|
|
else if (database.SetLocalPassword(tmpid, sep.arg[2]))
|
|
SendMessage(1, "Password changed.");
|
|
else
|
|
SendMessage(1, "Error changing password.");
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "uptime") == 0) {
|
|
if (sep.IsNumber(1) && atoi(sep.arg[1]) > 0) {
|
|
ServerPacket* pack = new ServerPacket(ServerOP_Uptime, sizeof(ServerUptime_Struct));
|
|
ServerUptime_Struct* sus = (ServerUptime_Struct*) pack->pBuffer;
|
|
snprintf(sus->adminname, sizeof(sus->adminname), "*%s", this->GetName());
|
|
sus->zoneserverid = atoi(sep.arg[1]);
|
|
ZoneServer* zs = zoneserver_list.FindByID(sus->zoneserverid);
|
|
if (zs)
|
|
zs->SendPacket(pack);
|
|
else
|
|
SendMessage(1, "Zoneserver not found.");
|
|
delete pack;
|
|
}
|
|
else {
|
|
ZSList::ShowUpTime(this);
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "md5") == 0) {
|
|
uint8 md5[16];
|
|
MD5::Generate((const uchar*) sep.argplus[1], strlen(sep.argplus[1]), md5);
|
|
SendMessage(1, "MD5: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", md5[0], md5[1], md5[2], md5[3], md5[4], md5[5], md5[6], md5[7], md5[8], md5[9], md5[10], md5[11], md5[12], md5[13], md5[14], md5[15]);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "whoami") == 0) {
|
|
SendMessage(1, "You are logged in as '%s'", this->AccountName());
|
|
SendMessage(1, "You are known as '*%s'", this->AccountName());
|
|
SendMessage(1, "AccessLevel: %d", this->Admin());
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "echo") == 0) {
|
|
if (strcasecmp(sep.arg[1], "on") == 0)
|
|
tcpc->SetEcho(true);
|
|
else if (strcasecmp(sep.arg[1], "off") == 0) {
|
|
if (pAcceptMessages)
|
|
SendMessage(1, "Echo can not be turned off while acceptmessages is on");
|
|
else
|
|
tcpc->SetEcho(false);
|
|
}
|
|
else
|
|
SendMessage(1, "Usage: echo [on/off]");
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "acceptmessages") == 0) {
|
|
if (strcasecmp(sep.arg[1], "on") == 0)
|
|
if (tcpc->GetEcho())
|
|
SendMessage(1, "AcceptMessages can not be turned on while echo is on");
|
|
else
|
|
pAcceptMessages = true;
|
|
else if (strcasecmp(sep.arg[1], "off") == 0)
|
|
pAcceptMessages = false;
|
|
else
|
|
SendMessage(1, "Usage: acceptmessages [on/off]");
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "tell") == 0) {
|
|
char tmpname[64];
|
|
tmpname[0] = '*';
|
|
strcpy(&tmpname[1], paccountname);
|
|
zoneserver_list.SendChannelMessage(tmpname, sep.arg[1], 7, 0, sep.argplus[2]);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "broadcast") == 0) {
|
|
char tmpname[64];
|
|
tmpname[0] = '*';
|
|
strcpy(&tmpname[1], paccountname);
|
|
zoneserver_list.SendChannelMessage(tmpname, 0, 6, 0, sep.argplus[1]);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "ooc") == 0) {
|
|
char tmpname[64];
|
|
tmpname[0] = '*';
|
|
strcpy(&tmpname[1], paccountname);
|
|
zoneserver_list.SendChannelMessage(tmpname, 0, 5, 0, sep.argplus[1]);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "auction") == 0) {
|
|
char tmpname[64];
|
|
tmpname[0] = '*';
|
|
strcpy(&tmpname[1], paccountname);
|
|
zoneserver_list.SendChannelMessage(tmpname, 0, 4, 0, sep.argplus[1]);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "gmsay") == 0 || strcasecmp(sep.arg[0], "pr") == 0) {
|
|
char tmpname[64];
|
|
tmpname[0] = '*';
|
|
strcpy(&tmpname[1], paccountname);
|
|
zoneserver_list.SendChannelMessage(tmpname, 0, 11, 0, sep.argplus[1]);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "emote") == 0) {
|
|
if (strcasecmp(sep.arg[1], "world") == 0)
|
|
zoneserver_list.SendEmoteMessageRaw(0, 0, 0, atoi(sep.arg[2]), sep.argplus[3]);
|
|
else {
|
|
ZoneServer* zs = zoneserver_list.FindByName(sep.arg[1]);
|
|
if (zs != 0)
|
|
zs->SendEmoteMessageRaw(0, 0, 0, atoi(sep.arg[2]), sep.argplus[3]);
|
|
else
|
|
zoneserver_list.SendEmoteMessageRaw(sep.arg[1], 0, 0, atoi(sep.arg[2]), sep.argplus[3]);
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "movechar") == 0) {
|
|
if(sep.arg[1][0]==0 || sep.arg[2][0] == 0)
|
|
SendMessage(1, "Usage: movechar [charactername] [zonename]");
|
|
else {
|
|
if (!database.GetZoneID(sep.arg[2]))
|
|
SendMessage(1, "Error: Zone '%s' not found", sep.arg[2]);
|
|
else if (!database.CheckUsedName((char*) sep.arg[1])) {
|
|
if (!database.MoveCharacterToZone((char*) sep.arg[1], (char*) sep.arg[2]))
|
|
SendMessage(1, "Character Move Failed!");
|
|
else
|
|
SendMessage(1, "Character has been moved.");
|
|
}
|
|
else
|
|
SendMessage(1, "Character Does Not Exist");
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "flag") == 0 && this->Admin() >= consoleFlagStatus) {
|
|
// SCORPIOUS2K - reversed parameter order for flag
|
|
if(sep.arg[2][0]==0 || !sep.IsNumber(1))
|
|
SendMessage(1, "Usage: flag [status] [accountname]");
|
|
else
|
|
{
|
|
if (atoi(sep.arg[1]) > this->Admin())
|
|
SendMessage(1, "You cannot set people's status to higher than your own");
|
|
else if (atoi(sep.arg[1]) < 0 && this->Admin() < consoleFlagStatus)
|
|
SendMessage(1, "You have too low of status to change flags");
|
|
else if (!database.SetAccountStatus(sep.arg[2], atoi(sep.arg[1])))
|
|
SendMessage(1, "Unable to flag account!");
|
|
else
|
|
SendMessage(1, "Account Flaged");
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "kick") == 0 && admin >= consoleKickStatus) {
|
|
char tmpname[64];
|
|
tmpname[0] = '*';
|
|
strcpy(&tmpname[1], paccountname);
|
|
ServerPacket* pack = new ServerPacket;
|
|
pack->opcode = ServerOP_KickPlayer;
|
|
pack->size = sizeof(ServerKickPlayer_Struct);
|
|
pack->pBuffer = new uchar[pack->size];
|
|
ServerKickPlayer_Struct* skp = (ServerKickPlayer_Struct*) pack->pBuffer;
|
|
strcpy(skp->adminname, tmpname);
|
|
strcpy(skp->name, sep.arg[1]);
|
|
skp->adminrank = this->Admin();
|
|
zoneserver_list.SendPacket(pack);
|
|
delete pack;
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "who") == 0) {
|
|
Who_All_Struct* whom = new Who_All_Struct;
|
|
memset(whom, 0, sizeof(Who_All_Struct));
|
|
whom->lvllow = 0xFFFF;
|
|
whom->lvlhigh = 0xFFFF;
|
|
whom->wclass = 0xFFFF;
|
|
whom->wrace = 0xFFFF;
|
|
whom->gmlookup = 0xFFFF;
|
|
for (int i=1; i<=sep.argnum; i++) {
|
|
if (strcasecmp(sep.arg[i], "gm") == 0)
|
|
whom->gmlookup = 1;
|
|
else if (sep.IsNumber(i)) {
|
|
if (whom->lvllow == 0xFFFF) {
|
|
whom->lvllow = atoi(sep.arg[i]);
|
|
whom->lvlhigh = whom->lvllow;
|
|
}
|
|
else if (atoi(sep.arg[i]) > int(whom->lvllow))
|
|
whom->lvlhigh = atoi(sep.arg[i]);
|
|
else
|
|
whom->lvllow = atoi(sep.arg[i]);
|
|
}
|
|
else
|
|
strn0cpy(whom->whom, sep.arg[i], sizeof(whom->whom));
|
|
}
|
|
client_list.ConsoleSendWhoAll(0, admin, whom, this);
|
|
delete whom;
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "zonestatus") == 0) {
|
|
zoneserver_list.SendZoneStatus(0, admin, this);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "exit") == 0 || strcasecmp(sep.arg[0], "quit") == 0) {
|
|
SendMessage(1, "Bye Bye.");
|
|
state = CONSOLE_STATE_CLOSED;
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "zoneshutdown") == 0 && admin >= consoleZoneStatus) {
|
|
if (sep.arg[1][0] == 0) {
|
|
SendMessage(1, "Usage: zoneshutdown zoneshortname");
|
|
} else {
|
|
char tmpname[64];
|
|
tmpname[0] = '*';
|
|
strcpy(&tmpname[1], paccountname);
|
|
|
|
ServerPacket* pack = new ServerPacket;
|
|
pack->size = sizeof(ServerZoneStateChange_struct);
|
|
pack->pBuffer = new uchar[pack->size];
|
|
memset(pack->pBuffer, 0, sizeof(ServerZoneStateChange_struct));
|
|
ServerZoneStateChange_struct* s = (ServerZoneStateChange_struct *) pack->pBuffer;
|
|
pack->opcode = ServerOP_ZoneShutdown;
|
|
strcpy(s->adminname, tmpname);
|
|
if (sep.arg[1][0] >= '0' && sep.arg[1][0] <= '9')
|
|
s->ZoneServerID = atoi(sep.arg[1]);
|
|
else
|
|
s->zoneid = database.GetZoneID(sep.arg[1]);
|
|
|
|
ZoneServer* zs = 0;
|
|
if (s->ZoneServerID != 0)
|
|
zs = zoneserver_list.FindByID(s->ZoneServerID);
|
|
else if (s->zoneid != 0)
|
|
zs = zoneserver_list.FindByName(database.GetZoneName(s->zoneid));
|
|
else
|
|
SendMessage(1, "Error: ZoneShutdown: neither ID nor name specified");
|
|
|
|
if (zs == 0)
|
|
SendMessage(1, "Error: ZoneShutdown: zoneserver not found");
|
|
else
|
|
zs->SendPacket(pack);
|
|
|
|
delete pack;
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "zonebootup") == 0 && admin >= consoleZoneStatus) {
|
|
if (sep.arg[2][0] == 0 || !sep.IsNumber(1)) {
|
|
SendMessage(1, "Usage: zonebootup ZoneServerID# zoneshortname");
|
|
} else {
|
|
char tmpname[64];
|
|
tmpname[0] = '*';
|
|
strcpy(&tmpname[1], paccountname);
|
|
|
|
_log(WORLD__CONSOLE,"Console ZoneBootup: %s, %s, %s",tmpname,sep.arg[2],sep.arg[1]);
|
|
zoneserver_list.SOPZoneBootup(tmpname, atoi(sep.arg[1]), sep.arg[2], (bool) (strcasecmp(sep.arg[3], "static") == 0));
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "worldshutdown") == 0 && admin >= consoleWorldStatus) {
|
|
int32 time, interval;
|
|
if(sep.IsNumber(1) && sep.IsNumber(2) && ((time=atoi(sep.arg[1]))>0) && ((interval=atoi(sep.arg[2]))>0)) {
|
|
zoneserver_list.WorldShutDown(time, interval);
|
|
}
|
|
else if(strcasecmp(sep.arg[1], "now") == 0) {
|
|
zoneserver_list.WorldShutDown(0, 0);
|
|
}
|
|
else if(strcasecmp(sep.arg[1], "disable") == 0) {
|
|
SendEmoteMessage(0,0,0,15,"<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World shutdown aborted.");
|
|
zoneserver_list.SendEmoteMessage(0,0,0,15,"<SYSTEMWIDE MESSAGE>:SYSTEM MSG:World shutdown aborted.");
|
|
zoneserver_list.shutdowntimer->Disable();
|
|
zoneserver_list.reminder->Disable();
|
|
}
|
|
else {
|
|
SendMessage(1, "Usage: worldshutdown [now] [disable] ([time] [interval])");
|
|
//Go ahead and shut down since that's what this used to do when invoked this way.
|
|
zoneserver_list.WorldShutDown(0, 0);
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "lock") == 0 && admin >= consoleLockStatus) {
|
|
WorldConfig::LockWorld();
|
|
if (loginserverlist.Connected()) {
|
|
loginserverlist.SendStatus();
|
|
SendMessage(1, "World locked.");
|
|
}
|
|
else {
|
|
SendMessage(1, "World locked, but login server not connected.");
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "unlock") == 0 && admin >= consoleLockStatus) {
|
|
WorldConfig::UnlockWorld();
|
|
if (loginserverlist.Connected()) {
|
|
loginserverlist.SendStatus();
|
|
SendMessage(1, "World unlocked.");
|
|
}
|
|
else {
|
|
SendMessage(1, "World unlocked, but login server not connected.");
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "version") == 0 && admin >= consoleWorldStatus) {
|
|
SendMessage(1, "Current version information.");
|
|
SendMessage(1, " %s", CURRENT_VERSION);
|
|
SendMessage(1, " Compiled on: %s at %s", COMPILE_DATE, COMPILE_TIME);
|
|
SendMessage(1, " Last modified on: %s", LAST_MODIFIED);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "serverinfo") == 0 && admin >= 200) {
|
|
if (strcasecmp(sep.arg[1], "os") == 0) {
|
|
#ifdef _WINDOWS
|
|
GetOS();
|
|
char intbuffer [sizeof(unsigned long)];
|
|
SendMessage(1, "Operating system information.");
|
|
SendMessage(1, " %s", Ver_name);
|
|
SendMessage(1, " Build number: %s", ultoa(Ver_build, intbuffer, 10));
|
|
SendMessage(1, " Minor version: %s", ultoa(Ver_min, intbuffer, 10));
|
|
SendMessage(1, " Major version: %s", ultoa(Ver_maj, intbuffer, 10));
|
|
SendMessage(1, " Platform Id: %s", ultoa(Ver_pid, intbuffer, 10));
|
|
#else
|
|
char os_string[100];
|
|
SendMessage(1, "Operating system information.");
|
|
SendMessage(1, " %s", GetOS(os_string));
|
|
#endif
|
|
}
|
|
else {
|
|
SendMessage(1, "Usage: Serverinfo [type]");
|
|
SendMessage(1, " OS - Operating system version information.");
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "IPLookup") == 0 && admin >= 201) {
|
|
client_list.SendCLEList(admin, 0, this, sep.argplus[1]);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "LSReconnect") == 0 && admin >= 100) {
|
|
#ifdef _WINDOWS
|
|
_beginthread(AutoInitLoginServer, 0, nullptr);
|
|
#else
|
|
pthread_t thread;
|
|
pthread_create(&thread, nullptr, &AutoInitLoginServer, nullptr);
|
|
#endif
|
|
RunLoops = true;
|
|
SendMessage(1, " Login Server Reconnect manually restarted by Console");
|
|
_log(WORLD__CONSOLE,"Login Server Reconnect manually restarted by Console");
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "zonelock") == 0 && admin >= consoleZoneStatus) {
|
|
if (strcasecmp(sep.arg[1], "list") == 0) {
|
|
zoneserver_list.ListLockedZones(0, this);
|
|
}
|
|
else if (strcasecmp(sep.arg[1], "lock") == 0 && admin >= 101) {
|
|
uint16 tmp = database.GetZoneID(sep.arg[2]);
|
|
if (tmp) {
|
|
if (zoneserver_list.SetLockedZone(tmp, true))
|
|
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone locked: %s", database.GetZoneName(tmp));
|
|
else
|
|
SendMessage(1, "Failed to change lock");
|
|
}
|
|
else
|
|
SendMessage(1, "Usage: #zonelock lock [zonename]");
|
|
}
|
|
else if (strcasecmp(sep.arg[1], "unlock") == 0 && admin >= 101) {
|
|
uint16 tmp = database.GetZoneID(sep.arg[2]);
|
|
if (tmp) {
|
|
if (zoneserver_list.SetLockedZone(tmp, false))
|
|
zoneserver_list.SendEmoteMessage(0, 0, 80, 15, "Zone unlocked: %s", database.GetZoneName(tmp));
|
|
else
|
|
SendMessage(1, "Failed to change lock");
|
|
}
|
|
else
|
|
SendMessage(1, "Usage: #zonelock unlock [zonename]");
|
|
}
|
|
else {
|
|
SendMessage(1, "#zonelock sub-commands");
|
|
SendMessage(1, " list");
|
|
if (admin >= 101) {
|
|
SendMessage(1, " lock [zonename]");
|
|
SendMessage(1, " unlock [zonename]");
|
|
}
|
|
}
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "reloadworld") == 0 && admin > 101)
|
|
{
|
|
SendEmoteMessage(0,0,0,15,"Reloading World...");
|
|
ServerPacket* pack = new ServerPacket(ServerOP_ReloadWorld, sizeof(ReloadWorld_Struct));
|
|
ReloadWorld_Struct* RW = (ReloadWorld_Struct*) pack->pBuffer;
|
|
RW->Option = 1;
|
|
zoneserver_list.SendPacket(pack);
|
|
safe_delete(pack);
|
|
}
|
|
else if (strcasecmp(sep.arg[0], "") == 0){
|
|
/* Hit Enter with no command */
|
|
}
|
|
else {
|
|
SendMessage(1, "Command unknown.");
|
|
}
|
|
if (state == CONSOLE_STATE_CONNECTED)
|
|
SendPrompt();
|
|
break;
|
|
}
|
|
default: {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Console::SendPrompt() {
|
|
if (tcpc->GetEcho())
|
|
SendMessage(0, "%s> ", paccountname);
|
|
}
|
|
|