Browse Source

Moved data processing from RenX::Core to RenX::Server. Added line preservation.

pull/3/head
JustinAJ 10 years ago
parent
commit
933b9f0e0b
  1. BIN
      Release/Bot.lib
  2. BIN
      Release/Plugins/RenX.Core.lib
  3. 459
      RenX.Core/RenX_Core.cpp
  4. 2
      RenX.Core/RenX_Core.h
  5. 459
      RenX.Core/RenX_Server.cpp
  6. 23
      RenX.Core/RenX_Server.h

BIN
Release/Bot.lib

Binary file not shown.

BIN
Release/Plugins/RenX.Core.lib

Binary file not shown.

459
RenX.Core/RenX_Core.cpp

@ -146,463 +146,14 @@ int RenX::Core::addCommand(RenX::GameCommand *command)
return RenX::Core::servers.size(); return RenX::Core::servers.size();
} }
// This shouldn't be needed later.
/*#define PARSE_PLAYER_DATA(STRING, OFFSET) \
char *name = nullptr; int id; char team; \
const char *p = strstr(buff, STRING); \
if (p - buff - OFFSET < 12) { } \
team = *(p - 3); \
if (*(p - 9) == '<') id = atoi(p - 8); \
else id = atoi(p - 9); \
name = charToChar(buff + OFFSET + 1, 0, (int)(p - 10 - (buff + OFFSET + 1)));*/
#define PARSE_PLAYER_DATA() \
Jupiter::ReferenceString name; \
TeamType team; \
int id; \
bool isBot = false; { \
Jupiter::ReferenceString idToken; \
if (playerData[0] == ',') { \
name = playerData.gotoWord(1, ","); \
idToken = playerData.getWord(0, ","); \
team = Other; \
} else { \
name = playerData.gotoWord(2, ","); \
idToken = playerData.getWord(1, ","); \
team = RenX::getTeam(playerData[0]); \
} \
if (idToken[0] == 'b') { idToken.shiftRight(1); isBot = true; } \
id = idToken.asInt(10); } \
RenX::PlayerInfo *player = getPlayerOrAdd(server, name, id, team, isBot);
inline RenX::PlayerInfo *getPlayerOrAdd(RenX::Server *server, const Jupiter::ReadableString &name, int id, RenX::TeamType team, bool isBot)
{
RenX::PlayerInfo *r = server->getPlayer(id);
if (r == nullptr)
{
r = new RenX::PlayerInfo();
r->id = id;
r->name = name;
r->isBot = isBot;
r->joinTime = time(nullptr);
if (id != 0) server->players.add(r);
}
else if (r->name.size() == 0) r->name = name;
r->team = team;
return r;
}
inline void onPreGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore)
{
RenX::PlayerInfo *player;
if (server->players.size() != 0)
{
for (Jupiter::DLList<RenX::PlayerInfo>::Node *n = server->players.getNode(0); n != nullptr; n = n->next)
{
player = n->data;
if (player != nullptr)
{
if (player->team == team)
player->wins++;
else player->loses++;
}
}
}
}
inline void onPostGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore)
{
RenX::PlayerInfo *player;
if (server->players.size() != 0)
{
for (Jupiter::DLList<RenX::PlayerInfo>::Node *n = server->players.getNode(0); n != nullptr; n = n->next)
{
player = n->data;
if (player != nullptr)
{
player->kills = 0;
player->deaths = 0;
player->suicides = 0;
player->headshots = 0;
player->vehicleKills = 0;
player->buildingKills = 0;
player->defenceKills = 0;
}
}
}
}
inline void onChat(RenX::Server *server, RenX::PlayerInfo *player, const Jupiter::ReadableString &message, bool isPublic)
{
const Jupiter::ReadableString &prefix = server->getCommandPrefix();
if (message.find(prefix) == 0 && message.size() != prefix.size())
{
Jupiter::ReferenceString command;
Jupiter::ReferenceString parameters;
if (containsSymbol(WHITESPACE, message.get(prefix.size())))
{
command = Jupiter::ReferenceString::getWord(message, 1, WHITESPACE);
parameters = Jupiter::ReferenceString::gotoWord(message, 2, WHITESPACE);
}
else
{
command = Jupiter::ReferenceString::getWord(message, 0, WHITESPACE);
command.shiftRight(prefix.size());
parameters = Jupiter::ReferenceString::gotoWord(message, 1, WHITESPACE);
}
server->triggerCommand(command, player, parameters);
}
}
int RenX::Core::think() int RenX::Core::think()
{ {
// Change this later to just call server->think(). size_t a = 0;
RenX::Server *server; while (a < RenX::Core::servers.size())
for (size_t a = 0; a < RenX::Core::servers.size(); a++) if (RenX::Core::servers.get(a)->think() != 0)
{ delete RenX::Core::servers.remove(a);
server = RenX::Core::servers.get(a); else a++;
if (server->isConnected() == false)
{
if (time(0) >= server->getLastAttempt() + server->getDelay())
{
if (server->connect()) server->sendLogChan(IRCCOLOR "03[RenX]" IRCCOLOR " Socket successfully reconnected to Renegade-X server.");
else server->sendLogChan(IRCCOLOR "04[Error]" IRCCOLOR " Failed to reconnect to Renegade-X server.");
}
}
else
{
if (server->sock.recv() > 0)
{
Jupiter::ReferenceString buffer = server->sock.getBuffer();
unsigned int totalLines = buffer.wordCount(ENDL);
for (unsigned int currentLine = 0; currentLine != totalLines; currentLine++)
{
Jupiter::ReferenceString buff = buffer.getWord(currentLine, ENDL);
Jupiter::ReferenceString header = buff.getWord(0, RenX::DelimS);
Jupiter::ReferenceString playerData = buff.getWord(1, RenX::DelimS);
Jupiter::ReferenceString action = buff.getWord(2, RenX::DelimS);
//printf("[RenX Dump] %.*s - %.*s - %.*s" ENDL, header.size(), header.ptr(), playerData.size(), playerData.ptr(), action.size(), action.ptr());
if (buff.size() != 0)
{
switch (header[0])
{
case 'l':
if (header.equals("lGAME:"))
{
if (action.equals("deployed"))
{
PARSE_PLAYER_DATA();
Jupiter::ReferenceString objectType = buff.getWord(3, RenX::DelimS);
if (objectType.match("*Beacon")) player->beaconPlacements++;
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnDeploy(server, player, objectType);
}
else if (action.equals("suicided by"))
{
PARSE_PLAYER_DATA();
player->deaths++;
player->suicides++;
Jupiter::ReferenceString damageType = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnSuicide(server, player, damageType);
}
else if (action.equals("killed"))
{
PARSE_PLAYER_DATA();
Jupiter::ReferenceString victimData = buff.getWord(3, RenX::DelimS);
Jupiter::ReferenceString vname = victimData.getWord(2, ",");
Jupiter::ReferenceString vidToken = victimData.getWord(1, ",");
int vid;
bool visBot = false;
if (vidToken[0] == 'b')
{
vidToken.shiftRight(1);
visBot = true;
}
vid = vidToken.asInt(10);
TeamType vteam = RenX::getTeam(victimData.getWord(0, ",")[0]);
Jupiter::ReferenceString damageType = buff.getWord(5, RenX::DelimS);
RenX::PlayerInfo *victim = getPlayerOrAdd(server, vname, vid, vteam, visBot);
player->kills++;
if (damageType.equals("Rx_DmgType_Headshot")) player->headshots++;
victim->deaths++;
if (server->needsCList)
{
server->sendData(STRING_LITERAL_AS_REFERENCE("clogclientlist\n"));
server->needsCList = false;
}
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnKill(server, player, victim, damageType);
}
else if (action.match("died by"))
{
PARSE_PLAYER_DATA();
player->deaths++;
Jupiter::ReferenceString damageType = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnDie(server, player, damageType);
}
else if (action.match("destroyed*"))
{
PARSE_PLAYER_DATA();
Jupiter::ReferenceString victim = buff.getWord(3, RenX::DelimS);
Jupiter::ReferenceString damageType = buff.getWord(5, RenX::DelimS);
ObjectType type;
if (action.equals("destroyed building"))
{
type = Building;
player->buildingKills++;
}
else if (victim.match("Rx_Defence_*"))
{
type = Defence;
player->defenceKills++;
}
else
{
type = Vehicle;
player->vehicleKills++;
}
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnDestroy(server, player, victim, damageType, type);
}
else if (playerData.match("??? wins (*)"))
{
TeamType team = RenX::getTeam(playerData[0]);
int gScore = buff.getWord(2, RenX::DelimS).gotoWord(1, "=").asInt(10);
int nScore = buff.getWord(3, RenX::DelimS).gotoWord(1, "=").asInt(10);
Jupiter::ReferenceString winType = Jupiter::ReferenceString::substring(playerData, 10);
winType.truncate(1);
WinType iWinType = Unknown;
if (gScore == nScore)
iWinType = Tie;
else if (winType.equals("TimeLimit"))
iWinType = Score;
else if (winType.equals("Buildings"))
iWinType = Base;
server->needsCList = true;
onPreGameOver(server, iWinType, team, gScore, nScore);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnGameOver(server, iWinType, team, gScore, nScore);
onPostGameOver(server, iWinType, team, gScore, nScore);
}
else if (playerData.equals("Tie"))
{
int gScore = action.gotoWord(1, "=").asInt(10);
int nScore = buff.getWord(3, RenX::DelimS).gotoWord(1, "=").asInt(10);
server->needsCList = true;
if (gScore == nScore)
{
onPreGameOver(server, Tie, Other, gScore, nScore);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnGameOver(server, Tie, Other, gScore, nScore);
onPostGameOver(server, Tie, Other, gScore, nScore);
}
else
{
TeamType winTeam = gScore > nScore ? RenX::getTeam('G') : RenX::getTeam('N');
onPreGameOver(server, Shutdown, winTeam, gScore, nScore);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnGameOver(server, Shutdown, winTeam, gScore, nScore);
onPostGameOver(server, Shutdown, winTeam, gScore, nScore);
}
}
else for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnGame(server, buff.gotoWord(1, RenX::DelimS));
}
else if (header.equals("lCHAT:"))
{
if (action.equals("teamsay:"))
{
PARSE_PLAYER_DATA();
Jupiter::ReferenceString message = buff.getWord(3, RenX::DelimS);
onChat(server, player, message, false);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnTeamChat(server, player, message);
}
else if (action.equals("say:"))
{
PARSE_PLAYER_DATA();
Jupiter::ReferenceString message = buff.getWord(3, RenX::DelimS);
onChat(server, player, message, true);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnChat(server, player, message);
}
}
else if (header.equals("lPLAYER:"))
{
PARSE_PLAYER_DATA();
if (action.equals("disconnected"))
{
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnPart(server, player);
server->removePlayer(player);
player = nullptr;
}
else if (action.equals("entered from"))
{
player->ip = buff.getWord(3, RenX::DelimS);
if (buff.getWord(4, RenX::DelimS).equals("steamid")) player->steamid = buff.getWord(5, RenX::DelimS);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnJoin(server, player);
}
else if (action.equals("changed name to:"))
{
Jupiter::ReferenceString newName = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnNameChange(server, player, newName);
player->name = newName;
}
}
else if (header.equals("lRCON:"))
{
if (action.equals("executed:"))
{
Jupiter::ReferenceString command = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnExecute(server, playerData, command);
}
else if (action.equals("subscribed")) for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnSubscribe(server, playerData);
else for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnRCON(server, buff.gotoWord(1, RenX::DelimS));
}
else if (header.equals("lADMIN:"))
{
PARSE_PLAYER_DATA();
if (action.equals("logged in as"))
{
player->adminType = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnAdminLogin(server, player);
}
else if (action.equals("logged out of"))
{
Jupiter::ReferenceString type = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnAdminLogout(server, player);
player->adminType = "";
}
else for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnAdmin(server, buff.gotoWord(1, RenX::DelimS));
}
else if (header.equals("lC-LIST:"))
{
// ID IP SteamID Team Name
if (playerData.isEmpty())
break;
int id;
bool isBot = false;
if (playerData.get(0) == 'b')
{
isBot = true;
playerData.shiftRight(1);
id = playerData.asInt(10);
playerData.shiftLeft(1);
}
else id = playerData.asInt(10);
Jupiter::ReferenceString ip = playerData.getWord(1, WHITESPACE);
Jupiter::ReferenceString steamid = playerData.getWord(2, WHITESPACE);
RenX::TeamType team;
Jupiter::ReferenceString name;
if (steamid.equals("-----NO")) // RCONv2-2a
{
steamid = "";
Jupiter::ReferenceString &teamToken = playerData.getWord(4, WHITESPACE);
if (teamToken.isEmpty())
break;
team = getTeam(teamToken.get(0));
name = playerData.gotoWord(5, WHITESPACE);
}
else
{
if (steamid.equals("-----NO-STEAM-----")) // RCONv2-2.5a
steamid = "";
Jupiter::ReferenceString &teamToken = playerData.getWord(3, WHITESPACE);
if (teamToken.isEmpty())
break;
team = getTeam(teamToken.get(0));
name = playerData.gotoWord(4, WHITESPACE);
}
RenX::PlayerInfo *player = getPlayerOrAdd(server, name, id, team, isBot);
if (player->ip.size() == 0)
{
player->ip = ip;
player->steamid = steamid;
}
}
else
{
buff.shiftRight(1);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnLog(server, buff);
buff.shiftLeft(1);
}
break;
case 'c':
buff.shiftRight(1);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnCommand(server, buff);
buff.shiftLeft(1);
break;
case 'e':
buff.shiftRight(1);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnError(server, buff);
buff.shiftLeft(1);
break;
case 'v':
buff.shiftRight(1);
server->rconVersion = buff.asInt(10);
server->gameVersion = buff.substring(3);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnVersion(server, buff);
buff.shiftLeft(1);
break;
case 'a':
buff.shiftRight(1);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnAuthorized(server, buff);
buff.shiftLeft(1);
break;
default:
buff.shiftRight(1);
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnOther(server, header[0], buff);
buff.shiftLeft(1);
break;
}
for (size_t i = 0; i < RenX::Core::plugins.size(); i++)
RenX::Core::plugins.get(i)->RenX_OnRaw(server, buff);
}
}
}
else if (Jupiter::Socket::getLastError() != 10035) // This is a serious error
{
if (server->reconnect()) server->sendLogChan(IRCCOLOR "07[Warning]" IRCCOLOR " Connection lost to Renegade-X server lost. Reconnection attempt in progress.");
else
{
server->wipeData();
server->sendLogChan(IRCCOLOR "04[Error]" IRCCOLOR " Connection lost to Renegade-X server lost. Reconnection attempt failed.");
}
}
}
}
return Jupiter::Plugin::think(); return Jupiter::Plugin::think();
} }

2
RenX.Core/RenX_Core.h

@ -51,7 +51,7 @@ namespace RenX
public: public:
/** /**
* @brief Loops through the Renegade-X servers and parses data. * @brief Loops through the Renegade-X servers.
* This should only be called by main(). * This should only be called by main().
* *
* @return Result of Jupiter::Plugin::Think(). * @return Result of Jupiter::Plugin::Think().

459
RenX.Core/RenX_Server.cpp

@ -24,6 +24,49 @@
#include "RenX_PlayerInfo.h" #include "RenX_PlayerInfo.h"
#include "RenX_GameCommand.h" #include "RenX_GameCommand.h"
#include "RenX_Functions.h" #include "RenX_Functions.h"
#include "RenX_Plugin.h"
int RenX::Server::think()
{
if (RenX::Server::connected == false)
{
if (time(0) >= RenX::Server::lastAttempt + RenX::Server::delay)
{
if (RenX::Server::connect())
RenX::Server::sendLogChan(IRCCOLOR "03[RenX]" IRCCOLOR " Socket successfully reconnected to Renegade-X server.");
else RenX::Server::sendLogChan(IRCCOLOR "04[Error]" IRCCOLOR " Failed to reconnect to Renegade-X server.");
}
}
else
{
if (RenX::Server::sock.recv() > 0)
{
Jupiter::ReferenceString buffer = RenX::Server::sock.getBuffer();
unsigned int totalLines = buffer.tokenCount('\n');
RenX::Server::lastLine.concat(buffer.getToken(0, '\n'));
if (totalLines != 0)
{
RenX::Server::processLine(RenX::Server::lastLine);
RenX::Server::lastLine = buffer.getToken(totalLines - 1, '\n');
for (unsigned int currentLine = 1; currentLine != totalLines - 1; currentLine++)
RenX::Server::processLine(buffer.getToken(currentLine, '\n'));
}
}
else if (Jupiter::Socket::getLastError() != 10035) // This is a serious error
{
if (RenX::Server::reconnect())
RenX::Server::sendLogChan(IRCCOLOR "07[Warning]" IRCCOLOR " Connection lost to Renegade-X server lost. Reconnection attempt in progress.");
else
{
RenX::Server::wipeData();
RenX::Server::sendLogChan(IRCCOLOR "04[Error]" IRCCOLOR " Connection lost to Renegade-X server lost. Reconnection attempt failed.");
}
}
}
return 0;
}
bool RenX::Server::isConnected() const bool RenX::Server::isConnected() const
{ {
@ -367,6 +410,419 @@ void RenX::Server::sendLogChan(const char *fmt, ...) const
} }
} }
#define PARSE_PLAYER_DATA() \
Jupiter::ReferenceString name; \
TeamType team; \
int id; \
bool isBot = false; { \
Jupiter::ReferenceString idToken; \
if (playerData[0] == ',') { \
name = playerData.gotoWord(1, ","); \
idToken = playerData.getWord(0, ","); \
team = Other; \
} else { \
name = playerData.gotoWord(2, ","); \
idToken = playerData.getWord(1, ","); \
team = RenX::getTeam(playerData[0]); \
} \
if (idToken[0] == 'b') { idToken.shiftRight(1); isBot = true; } \
id = idToken.asInt(10); } \
RenX::PlayerInfo *player = getPlayerOrAdd(this, name, id, team, isBot);
inline RenX::PlayerInfo *getPlayerOrAdd(RenX::Server *server, const Jupiter::ReadableString &name, int id, RenX::TeamType team, bool isBot)
{
RenX::PlayerInfo *r = server->getPlayer(id);
if (r == nullptr)
{
r = new RenX::PlayerInfo();
r->id = id;
r->name = name;
r->isBot = isBot;
r->joinTime = time(nullptr);
if (id != 0) server->players.add(r);
}
else if (r->name.size() == 0) r->name = name;
r->team = team;
return r;
}
inline void onPreGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore)
{
RenX::PlayerInfo *player;
if (server->players.size() != 0)
{
for (Jupiter::DLList<RenX::PlayerInfo>::Node *n = server->players.getNode(0); n != nullptr; n = n->next)
{
player = n->data;
if (player != nullptr)
{
if (player->team == team)
player->wins++;
else player->loses++;
}
}
}
}
inline void onPostGameOver(RenX::Server *server, RenX::WinType winType, RenX::TeamType team, int gScore, int nScore)
{
RenX::PlayerInfo *player;
if (server->players.size() != 0)
{
for (Jupiter::DLList<RenX::PlayerInfo>::Node *n = server->players.getNode(0); n != nullptr; n = n->next)
{
player = n->data;
if (player != nullptr)
{
player->kills = 0;
player->deaths = 0;
player->suicides = 0;
player->headshots = 0;
player->vehicleKills = 0;
player->buildingKills = 0;
player->defenceKills = 0;
}
}
}
}
inline void onChat(RenX::Server *server, RenX::PlayerInfo *player, const Jupiter::ReadableString &message, bool isPublic)
{
const Jupiter::ReadableString &prefix = server->getCommandPrefix();
if (message.find(prefix) == 0 && message.size() != prefix.size())
{
Jupiter::ReferenceString command;
Jupiter::ReferenceString parameters;
if (containsSymbol(WHITESPACE, message.get(prefix.size())))
{
command = Jupiter::ReferenceString::getWord(message, 1, WHITESPACE);
parameters = Jupiter::ReferenceString::gotoWord(message, 2, WHITESPACE);
}
else
{
command = Jupiter::ReferenceString::getWord(message, 0, WHITESPACE);
command.shiftRight(prefix.size());
parameters = Jupiter::ReferenceString::gotoWord(message, 1, WHITESPACE);
}
server->triggerCommand(command, player, parameters);
}
}
void RenX::Server::processLine(const Jupiter::ReadableString &line)
{
Jupiter::ReferenceString buff = line;
Jupiter::ArrayList<RenX::Plugin> &xPlugins = *RenX::getCore()->getPlugins();
Jupiter::ReferenceString header = buff.getWord(0, RenX::DelimS);
Jupiter::ReferenceString playerData = buff.getWord(1, RenX::DelimS);
Jupiter::ReferenceString action = buff.getWord(2, RenX::DelimS);
if (buff.size() != 0)
{
switch (header[0])
{
case 'l':
if (header.equals("lGAME:"))
{
if (action.equals("deployed"))
{
PARSE_PLAYER_DATA();
Jupiter::ReferenceString objectType = buff.getWord(3, RenX::DelimS);
if (objectType.match("*Beacon")) player->beaconPlacements++;
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnDeploy(this, player, objectType);
}
else if (action.equals("suicided by"))
{
PARSE_PLAYER_DATA();
player->deaths++;
player->suicides++;
Jupiter::ReferenceString damageType = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnSuicide(this, player, damageType);
}
else if (action.equals("killed"))
{
PARSE_PLAYER_DATA();
Jupiter::ReferenceString victimData = buff.getWord(3, RenX::DelimS);
Jupiter::ReferenceString vname = victimData.getWord(2, ",");
Jupiter::ReferenceString vidToken = victimData.getWord(1, ",");
int vid;
bool visBot = false;
if (vidToken[0] == 'b')
{
vidToken.shiftRight(1);
visBot = true;
}
vid = vidToken.asInt(10);
TeamType vteam = RenX::getTeam(victimData.getWord(0, ",")[0]);
Jupiter::ReferenceString damageType = buff.getWord(5, RenX::DelimS);
RenX::PlayerInfo *victim = getPlayerOrAdd(this, vname, vid, vteam, visBot);
player->kills++;
if (damageType.equals("Rx_DmgType_Headshot")) player->headshots++;
victim->deaths++;
if (this->needsCList)
{
this->sendData(STRING_LITERAL_AS_REFERENCE("clogclientlist\n"));
this->needsCList = false;
}
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnKill(this, player, victim, damageType);
}
else if (action.match("died by"))
{
PARSE_PLAYER_DATA();
player->deaths++;
Jupiter::ReferenceString damageType = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnDie(this, player, damageType);
}
else if (action.match("destroyed*"))
{
PARSE_PLAYER_DATA();
Jupiter::ReferenceString victim = buff.getWord(3, RenX::DelimS);
Jupiter::ReferenceString damageType = buff.getWord(5, RenX::DelimS);
ObjectType type;
if (action.equals("destroyed building"))
{
type = Building;
player->buildingKills++;
}
else if (victim.match("Rx_Defence_*"))
{
type = Defence;
player->defenceKills++;
}
else
{
type = Vehicle;
player->vehicleKills++;
}
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnDestroy(this, player, victim, damageType, type);
}
else if (playerData.match("??? wins (*)"))
{
TeamType team = RenX::getTeam(playerData[0]);
int gScore = buff.getWord(2, RenX::DelimS).gotoWord(1, "=").asInt(10);
int nScore = buff.getWord(3, RenX::DelimS).gotoWord(1, "=").asInt(10);
Jupiter::ReferenceString winType = Jupiter::ReferenceString::substring(playerData, 10);
winType.truncate(1);
WinType iWinType = Unknown;
if (gScore == nScore)
iWinType = Tie;
else if (winType.equals("TimeLimit"))
iWinType = Score;
else if (winType.equals("Buildings"))
iWinType = Base;
this->needsCList = true;
onPreGameOver(this, iWinType, team, gScore, nScore);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnGameOver(this, iWinType, team, gScore, nScore);
onPostGameOver(this, iWinType, team, gScore, nScore);
}
else if (playerData.equals("Tie"))
{
int gScore = action.gotoWord(1, "=").asInt(10);
int nScore = buff.getWord(3, RenX::DelimS).gotoWord(1, "=").asInt(10);
this->needsCList = true;
if (gScore == nScore)
{
onPreGameOver(this, Tie, Other, gScore, nScore);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnGameOver(this, Tie, Other, gScore, nScore);
onPostGameOver(this, Tie, Other, gScore, nScore);
}
else
{
TeamType winTeam = gScore > nScore ? RenX::getTeam('G') : RenX::getTeam('N');
onPreGameOver(this, Shutdown, winTeam, gScore, nScore);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnGameOver(this, Shutdown, winTeam, gScore, nScore);
onPostGameOver(this, Shutdown, winTeam, gScore, nScore);
}
}
else for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnGame(this, buff.gotoWord(1, RenX::DelimS));
}
else if (header.equals("lCHAT:"))
{
if (action.equals("teamsay:"))
{
PARSE_PLAYER_DATA();
Jupiter::ReferenceString message = buff.getWord(3, RenX::DelimS);
onChat(this, player, message, false);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnTeamChat(this, player, message);
}
else if (action.equals("say:"))
{
PARSE_PLAYER_DATA();
Jupiter::ReferenceString message = buff.getWord(3, RenX::DelimS);
onChat(this, player, message, true);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnChat(this, player, message);
}
}
else if (header.equals("lPLAYER:"))
{
PARSE_PLAYER_DATA();
if (action.equals("disconnected"))
{
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnPart(this, player);
this->removePlayer(player);
player = nullptr;
}
else if (action.equals("entered from"))
{
player->ip = buff.getWord(3, RenX::DelimS);
if (buff.getWord(4, RenX::DelimS).equals("steamid")) player->steamid = buff.getWord(5, RenX::DelimS);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnJoin(this, player);
}
else if (action.equals("changed name to:"))
{
Jupiter::ReferenceString newName = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnNameChange(this, player, newName);
player->name = newName;
}
}
else if (header.equals("lRCON:"))
{
if (action.equals("executed:"))
{
Jupiter::ReferenceString command = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnExecute(this, playerData, command);
}
else if (action.equals("subscribed")) for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnSubscribe(this, playerData);
else for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnRCON(this, buff.gotoWord(1, RenX::DelimS));
}
else if (header.equals("lADMIN:"))
{
PARSE_PLAYER_DATA();
if (action.equals("logged in as"))
{
player->adminType = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnAdminLogin(this, player);
}
else if (action.equals("logged out of"))
{
Jupiter::ReferenceString type = buff.getWord(3, RenX::DelimS);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnAdminLogout(this, player);
player->adminType = "";
}
else for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnAdmin(this, buff.gotoWord(1, RenX::DelimS));
}
else if (header.equals("lC-LIST:"))
{
// ID IP SteamID Team Name
if (playerData.isEmpty())
break;
int id;
bool isBot = false;
if (playerData.get(0) == 'b')
{
isBot = true;
playerData.shiftRight(1);
id = playerData.asInt(10);
playerData.shiftLeft(1);
}
else id = playerData.asInt(10);
Jupiter::ReferenceString ip = playerData.getWord(1, WHITESPACE);
Jupiter::ReferenceString steamid = playerData.getWord(2, WHITESPACE);
RenX::TeamType team;
Jupiter::ReferenceString name;
if (steamid.equals("-----NO")) // RCONv2-2a
{
steamid = "";
Jupiter::ReferenceString &teamToken = playerData.getWord(4, WHITESPACE);
if (teamToken.isEmpty())
break;
team = getTeam(teamToken.get(0));
name = playerData.gotoWord(5, WHITESPACE);
}
else
{
if (steamid.equals("-----NO-STEAM-----")) // RCONv2-2.5a
steamid = "";
Jupiter::ReferenceString &teamToken = playerData.getWord(3, WHITESPACE);
if (teamToken.isEmpty())
break;
team = getTeam(teamToken.get(0));
name = playerData.gotoWord(4, WHITESPACE);
}
RenX::PlayerInfo *player = getPlayerOrAdd(this, name, id, team, isBot);
if (player->ip.size() == 0)
{
player->ip = ip;
player->steamid = steamid;
}
}
else
{
buff.shiftRight(1);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnLog(this, buff);
buff.shiftLeft(1);
}
break;
case 'c':
buff.shiftRight(1);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnCommand(this, buff);
buff.shiftLeft(1);
break;
case 'e':
buff.shiftRight(1);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnError(this, buff);
buff.shiftLeft(1);
break;
case 'v':
buff.shiftRight(1);
this->rconVersion = buff.asInt(10);
this->gameVersion = buff.substring(3);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnVersion(this, buff);
buff.shiftLeft(1);
break;
case 'a':
buff.shiftRight(1);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnAuthorized(this, buff);
buff.shiftLeft(1);
break;
default:
buff.shiftRight(1);
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnOther(this, header[0], buff);
buff.shiftLeft(1);
break;
}
for (size_t i = 0; i < xPlugins.size(); i++)
xPlugins.get(i)->RenX_OnRaw(this, buff);
}
}
void RenX::Server::disconnect() void RenX::Server::disconnect()
{ {
RenX::Server::sock.closeSocket(); RenX::Server::sock.closeSocket();
@ -398,7 +854,8 @@ bool RenX::Server::reconnect()
void RenX::Server::wipeData() void RenX::Server::wipeData()
{ {
while (RenX::Server::players.size() != 0) delete RenX::Server::players.remove(0U); while (RenX::Server::players.size() != 0)
delete RenX::Server::players.remove(0U);
RenX::Server::commands.emptyAndDelete(); RenX::Server::commands.emptyAndDelete();
} }

23
RenX.Core/RenX_Server.h

@ -29,6 +29,7 @@
#include "Jupiter/String.h" #include "Jupiter/String.h"
#include "Jupiter/CString.h" #include "Jupiter/CString.h"
#include "Jupiter/INIFile.h" #include "Jupiter/INIFile.h"
#include "Jupiter/Thinker.h"
#include "RenX.h" #include "RenX.h"
/** DLL Linkage Nagging */ /** DLL Linkage Nagging */
@ -48,10 +49,18 @@ namespace RenX
* @brief Represents a connection to an individiaul Renegade-X server. * @brief Represents a connection to an individiaul Renegade-X server.
* There are often more than one of these, such as when communities run multiple servers. * There are often more than one of these, such as when communities run multiple servers.
*/ */
class RENX_API Server class RENX_API Server : public Jupiter::Thinker
{ {
friend class RenX::Core; public: // Jupiter::Thinker
public:
/**
* @brief Checks and processes raw socket data.
*
* @return Zero if no error occurs, a non-zero value otherwise.
*/
int think();
public: // RenX::Server
Jupiter::DLList<RenX::PlayerInfo> players; /** A list of players in the server */ Jupiter::DLList<RenX::PlayerInfo> players; /** A list of players in the server */
Jupiter::INIFile varData; /** This may be replaced later with a more dedicated type. */ Jupiter::INIFile varData; /** This may be replaced later with a more dedicated type. */
@ -352,6 +361,13 @@ namespace RenX
*/ */
void sendLogChan(const char *fmt, ...) const; void sendLogChan(const char *fmt, ...) const;
/**
* @brief Processes a line of RCON input data. Input data SHOULD NOT include a new-line ('\n') terminator.
*
* @param line Line to process
*/
void processLine(const Jupiter::ReadableString &line);
/** /**
* @brief Disconnects from a server's RCON interface. * @brief Disconnects from a server's RCON interface.
*/ */
@ -418,6 +434,7 @@ namespace RenX
Jupiter::StringS IRCPrefix; Jupiter::StringS IRCPrefix;
Jupiter::StringS CommandPrefix; Jupiter::StringS CommandPrefix;
Jupiter::StringS gameVersion; Jupiter::StringS gameVersion;
Jupiter::String lastLine;
Jupiter::ArrayList<RenX::GameCommand> commands; Jupiter::ArrayList<RenX::GameCommand> commands;
}; };

Loading…
Cancel
Save