mirror of
https://github.com/ErikasKontenis/SabrehavenServer.git
synced 2025-10-14 06:34:55 +02:00
@@ -187,32 +187,13 @@ void Connection::parsePacket(const boost::system::error_code& error)
|
||||
return;
|
||||
}
|
||||
|
||||
// 870
|
||||
//Check packet checksum
|
||||
uint32_t checksum;
|
||||
int32_t len = msg.getLength() - msg.getBufferPosition() - NetworkMessage::CHECKSUM_LENGTH;
|
||||
if (len > 0) {
|
||||
checksum = adlerChecksum(msg.getBuffer() + msg.getBufferPosition() + NetworkMessage::CHECKSUM_LENGTH, len);
|
||||
}
|
||||
else {
|
||||
checksum = 0;
|
||||
}
|
||||
|
||||
uint32_t recvChecksum = msg.get<uint32_t>();
|
||||
if (recvChecksum != checksum) {
|
||||
// it might not have been the checksum, step back
|
||||
msg.skipBytes(-NetworkMessage::CHECKSUM_LENGTH);
|
||||
}
|
||||
// 870
|
||||
|
||||
if (!receivedFirst) {
|
||||
// First message received
|
||||
receivedFirst = true;
|
||||
|
||||
if (!protocol) {
|
||||
// Game protocol has already been created at this point
|
||||
//protocol = service_port->make_protocol(msg, shared_from_this()); 792
|
||||
protocol = service_port->make_protocol(recvChecksum == checksum, msg, shared_from_this()); //870
|
||||
protocol = service_port->make_protocol(msg, shared_from_this());
|
||||
if (!protocol) {
|
||||
close(FORCE_CLOSE);
|
||||
return;
|
||||
|
@@ -363,7 +363,6 @@ enum ClientVersion_t : uint16_t {
|
||||
CLIENT_VERSION_781 = 781,
|
||||
CLIENT_VERSION_790 = 790,
|
||||
CLIENT_VERSION_792 = 792,
|
||||
CLIENT_VERSION_870 = 860,
|
||||
};
|
||||
|
||||
static constexpr int32_t CHANNEL_GUILD = 0x00;
|
||||
|
@@ -3747,8 +3747,6 @@ void Game::addDistanceEffect(const Position& fromPos, const Position& toPos, uin
|
||||
SpectatorVec spectators;
|
||||
map.getSpectators(spectators, fromPos, false, true);
|
||||
map.getSpectators(spectators, toPos, false, true);
|
||||
spectators.addSpectators(spectators);
|
||||
|
||||
addDistanceEffect(spectators, fromPos, toPos, effect);
|
||||
}
|
||||
|
||||
|
@@ -4409,20 +4409,19 @@ int LuaScriptInterface::luaPositionIsSightClear(lua_State* L)
|
||||
int LuaScriptInterface::luaPositionSendMagicEffect(lua_State* L)
|
||||
{
|
||||
// position:sendMagicEffect(magicEffect[, player = nullptr])
|
||||
SpectatorVec spectators;
|
||||
SpectatorVec list;
|
||||
if (lua_gettop(L) >= 3) {
|
||||
Player* player = getPlayer(L, 3);
|
||||
if (player) {
|
||||
spectators.emplace_back(player);
|
||||
list.insert(player);
|
||||
}
|
||||
}
|
||||
|
||||
MagicEffectClasses magicEffect = getNumber<MagicEffectClasses>(L, 2);
|
||||
const Position& position = getPosition(L, 1);
|
||||
if (!spectators.empty()) {
|
||||
Game::addMagicEffect(spectators, position, magicEffect);
|
||||
}
|
||||
else {
|
||||
if (!list.empty()) {
|
||||
Game::addMagicEffect(list, position, magicEffect);
|
||||
} else {
|
||||
g_game.addMagicEffect(position, magicEffect);
|
||||
}
|
||||
|
||||
@@ -4433,21 +4432,20 @@ int LuaScriptInterface::luaPositionSendMagicEffect(lua_State* L)
|
||||
int LuaScriptInterface::luaPositionSendDistanceEffect(lua_State* L)
|
||||
{
|
||||
// position:sendDistanceEffect(positionEx, distanceEffect[, player = nullptr])
|
||||
SpectatorVec spectators;
|
||||
SpectatorVec list;
|
||||
if (lua_gettop(L) >= 4) {
|
||||
Player* player = getPlayer(L, 4);
|
||||
if (player) {
|
||||
spectators.emplace_back(player);
|
||||
list.insert(player);
|
||||
}
|
||||
}
|
||||
|
||||
ShootType_t distanceEffect = getNumber<ShootType_t>(L, 3);
|
||||
const Position& positionEx = getPosition(L, 2);
|
||||
const Position& position = getPosition(L, 1);
|
||||
if (!spectators.empty()) {
|
||||
Game::addDistanceEffect(spectators, position, positionEx, distanceEffect);
|
||||
}
|
||||
else {
|
||||
if (!list.empty()) {
|
||||
Game::addDistanceEffect(list, position, positionEx, distanceEffect);
|
||||
} else {
|
||||
g_game.addDistanceEffect(position, positionEx, distanceEffect);
|
||||
}
|
||||
|
||||
@@ -6875,7 +6873,7 @@ int LuaScriptInterface::luaCreatureTeleportTo(lua_State* L)
|
||||
|
||||
int LuaScriptInterface::luaCreatureSay(lua_State* L)
|
||||
{
|
||||
// creature:say(text[, type = TALKTYPE_MONSTER_SAY[, ghost = false[, target = nullptr[, position]]]])
|
||||
// creature:say(text, type[, ghost = false[, target = nullptr[, position]]])
|
||||
int parameters = lua_gettop(L);
|
||||
|
||||
Position position;
|
||||
@@ -6895,7 +6893,7 @@ int LuaScriptInterface::luaCreatureSay(lua_State* L)
|
||||
|
||||
bool ghost = getBoolean(L, 4, false);
|
||||
|
||||
SpeakClasses type = getNumber<SpeakClasses>(L, 3, TALKTYPE_MONSTER_SAY);
|
||||
SpeakClasses type = getNumber<SpeakClasses>(L, 3);
|
||||
const std::string& text = getString(L, 2);
|
||||
Creature* creature = getUserdata<Creature>(L, 1);
|
||||
if (!creature) {
|
||||
@@ -6903,16 +6901,15 @@ int LuaScriptInterface::luaCreatureSay(lua_State* L)
|
||||
return 1;
|
||||
}
|
||||
|
||||
SpectatorVec spectators;
|
||||
SpectatorVec list;
|
||||
if (target) {
|
||||
spectators.emplace_back(target);
|
||||
list.insert(target);
|
||||
}
|
||||
|
||||
if (position.x != 0) {
|
||||
pushBoolean(L, g_game.internalCreatureSay(creature, type, text, ghost, &spectators, &position));
|
||||
}
|
||||
else {
|
||||
pushBoolean(L, g_game.internalCreatureSay(creature, type, text, ghost, &spectators));
|
||||
pushBoolean(L, g_game.internalCreatureSay(creature, type, text, ghost, &list, &position));
|
||||
} else {
|
||||
pushBoolean(L, g_game.internalCreatureSay(creature, type, text, ghost, &list));
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
89
src/map.cpp
89
src/map.cpp
@@ -243,18 +243,16 @@ void Map::moveCreature(Creature& creature, Tile& newTile, bool forceTeleport/* =
|
||||
|
||||
bool teleport = forceTeleport || !newTile.getGround() || !Position::areInRange<1, 1, 0>(oldPos, newPos);
|
||||
|
||||
SpectatorVec spectators, newPosSpectators;
|
||||
getSpectators(spectators, oldPos, true);
|
||||
getSpectators(newPosSpectators, newPos, true);
|
||||
spectators.addSpectators(newPosSpectators);
|
||||
SpectatorVec list;
|
||||
getSpectators(list, oldPos, true);
|
||||
getSpectators(list, newPos, true);
|
||||
|
||||
std::vector<int32_t> oldStackPosVector;
|
||||
for (Creature* spectator : spectators) {
|
||||
for (Creature* spectator : list) {
|
||||
if (Player* tmpPlayer = spectator->getPlayer()) {
|
||||
if (tmpPlayer->canSeeCreature(&creature)) {
|
||||
oldStackPosVector.push_back(oldTile.getClientIndexOfCreature(tmpPlayer, &creature));
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
oldStackPosVector.push_back(-1);
|
||||
}
|
||||
}
|
||||
@@ -278,22 +276,20 @@ void Map::moveCreature(Creature& creature, Tile& newTile, bool forceTeleport/* =
|
||||
if (!teleport) {
|
||||
if (oldPos.y > newPos.y) {
|
||||
creature.setDirection(DIRECTION_NORTH);
|
||||
}
|
||||
else if (oldPos.y < newPos.y) {
|
||||
} else if (oldPos.y < newPos.y) {
|
||||
creature.setDirection(DIRECTION_SOUTH);
|
||||
}
|
||||
|
||||
if (oldPos.x < newPos.x) {
|
||||
creature.setDirection(DIRECTION_EAST);
|
||||
}
|
||||
else if (oldPos.x > newPos.x) {
|
||||
} else if (oldPos.x > newPos.x) {
|
||||
creature.setDirection(DIRECTION_WEST);
|
||||
}
|
||||
}
|
||||
|
||||
//send to client
|
||||
size_t i = 0;
|
||||
for (Creature* spectator : spectators) {
|
||||
for (Creature* spectator : list) {
|
||||
if (Player* tmpPlayer = spectator->getPlayer()) {
|
||||
//Use the correct stackpos
|
||||
int32_t stackpos = oldStackPosVector[i++];
|
||||
@@ -304,7 +300,7 @@ void Map::moveCreature(Creature& creature, Tile& newTile, bool forceTeleport/* =
|
||||
}
|
||||
|
||||
//event method
|
||||
for (Creature* spectator : spectators) {
|
||||
for (Creature* spectator : list) {
|
||||
spectator->onCreatureMove(&creature, &newTile, newPos, &oldTile, oldPos, teleport);
|
||||
}
|
||||
|
||||
@@ -312,7 +308,7 @@ void Map::moveCreature(Creature& creature, Tile& newTile, bool forceTeleport/* =
|
||||
newTile.postAddNotification(&creature, &oldTile, 0);
|
||||
}
|
||||
|
||||
void Map::getSpectatorsInternal(SpectatorVec& spectators, const Position& centerPos, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY, int32_t minRangeZ, int32_t maxRangeZ, bool onlyPlayers) const
|
||||
void Map::getSpectatorsInternal(SpectatorVec& list, const Position& centerPos, int32_t minRangeX, int32_t maxRangeX, int32_t minRangeY, int32_t maxRangeY, int32_t minRangeZ, int32_t maxRangeZ, bool onlyPlayers) const
|
||||
{
|
||||
int_fast16_t min_y = centerPos.y + minRangeY;
|
||||
int_fast16_t min_x = centerPos.x + minRangeX;
|
||||
@@ -352,25 +348,23 @@ void Map::getSpectatorsInternal(SpectatorVec& spectators, const Position& center
|
||||
continue;
|
||||
}
|
||||
|
||||
spectators.emplace_back(creature);
|
||||
list.insert(creature);
|
||||
}
|
||||
leafE = leafE->leafE;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
leafE = QTreeNode::getLeafStatic<const QTreeLeafNode*, const QTreeNode*>(&root, nx + FLOOR_SIZE, ny);
|
||||
}
|
||||
}
|
||||
|
||||
if (leafS) {
|
||||
leafS = leafS->leafS;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
leafS = QTreeNode::getLeafStatic<const QTreeLeafNode*, const QTreeNode*>(&root, startx1, ny + FLOOR_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Map::getSpectators(SpectatorVec& spectators, const Position& centerPos, bool multifloor /*= false*/, bool onlyPlayers /*= false*/, int32_t minRangeX /*= 0*/, int32_t maxRangeX /*= 0*/, int32_t minRangeY /*= 0*/, int32_t maxRangeY /*= 0*/)
|
||||
void Map::getSpectators(SpectatorVec& list, const Position& centerPos, bool multifloor /*= false*/, bool onlyPlayers /*= false*/, int32_t minRangeX /*= 0*/, int32_t maxRangeX /*= 0*/, int32_t minRangeY /*= 0*/, int32_t maxRangeY /*= 0*/)
|
||||
{
|
||||
if (centerPos.z >= MAP_MAX_LAYERS) {
|
||||
return;
|
||||
@@ -388,12 +382,11 @@ void Map::getSpectators(SpectatorVec& spectators, const Position& centerPos, boo
|
||||
if (onlyPlayers) {
|
||||
auto it = playersSpectatorCache.find(centerPos);
|
||||
if (it != playersSpectatorCache.end()) {
|
||||
if (!spectators.empty()) {
|
||||
const SpectatorVec& cachedSpectators = it->second;
|
||||
spectators.insert(spectators.end(), cachedSpectators.begin(), cachedSpectators.end());
|
||||
}
|
||||
else {
|
||||
spectators = it->second;
|
||||
if (!list.empty()) {
|
||||
const SpectatorVec& cachedList = it->second;
|
||||
list.insert(cachedList.begin(), cachedList.end());
|
||||
} else {
|
||||
list = it->second;
|
||||
}
|
||||
|
||||
foundCache = true;
|
||||
@@ -404,26 +397,23 @@ void Map::getSpectators(SpectatorVec& spectators, const Position& centerPos, boo
|
||||
auto it = spectatorCache.find(centerPos);
|
||||
if (it != spectatorCache.end()) {
|
||||
if (!onlyPlayers) {
|
||||
if (!spectators.empty()) {
|
||||
const SpectatorVec& cachedSpectators = it->second;
|
||||
spectators.insert(spectators.end(), cachedSpectators.begin(), cachedSpectators.end());
|
||||
if (!list.empty()) {
|
||||
const SpectatorVec& cachedList = it->second;
|
||||
list.insert(cachedList.begin(), cachedList.end());
|
||||
} else {
|
||||
list = it->second;
|
||||
}
|
||||
else {
|
||||
spectators = it->second;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const SpectatorVec& cachedSpectators = it->second;
|
||||
for (Creature* spectator : cachedSpectators) {
|
||||
} else {
|
||||
const SpectatorVec& cachedList = it->second;
|
||||
for (Creature* spectator : cachedList) {
|
||||
if (spectator->getPlayer()) {
|
||||
spectators.emplace_back(spectator);
|
||||
list.insert(spectator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foundCache = true;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
cacheResult = true;
|
||||
}
|
||||
}
|
||||
@@ -440,33 +430,28 @@ void Map::getSpectators(SpectatorVec& spectators, const Position& centerPos, boo
|
||||
//8->15
|
||||
minRangeZ = std::max<int32_t>(centerPos.getZ() - 2, 0);
|
||||
maxRangeZ = std::min<int32_t>(centerPos.getZ() + 2, MAP_MAX_LAYERS - 1);
|
||||
}
|
||||
else if (centerPos.z == 6) {
|
||||
} else if (centerPos.z == 6) {
|
||||
minRangeZ = 0;
|
||||
maxRangeZ = 8;
|
||||
}
|
||||
else if (centerPos.z == 7) {
|
||||
} else if (centerPos.z == 7) {
|
||||
minRangeZ = 0;
|
||||
maxRangeZ = 9;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
minRangeZ = 0;
|
||||
maxRangeZ = 7;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
minRangeZ = centerPos.z;
|
||||
maxRangeZ = centerPos.z;
|
||||
}
|
||||
|
||||
getSpectatorsInternal(spectators, centerPos, minRangeX, maxRangeX, minRangeY, maxRangeY, minRangeZ, maxRangeZ, onlyPlayers);
|
||||
getSpectatorsInternal(list, centerPos, minRangeX, maxRangeX, minRangeY, maxRangeY, minRangeZ, maxRangeZ, onlyPlayers);
|
||||
|
||||
if (cacheResult) {
|
||||
if (onlyPlayers) {
|
||||
playersSpectatorCache[centerPos] = spectators;
|
||||
}
|
||||
else {
|
||||
spectatorCache[centerPos] = spectators;
|
||||
playersSpectatorCache[centerPos] = list;
|
||||
} else {
|
||||
spectatorCache[centerPos] = list;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -34,13 +34,11 @@ class NetworkMessage
|
||||
typedef uint16_t MsgSize_t;
|
||||
// Headers:
|
||||
// 2 bytes for unencrypted message size
|
||||
// 4 bytes for checksum
|
||||
// 2 bytes for encrypted message size
|
||||
static constexpr MsgSize_t INITIAL_BUFFER_POSITION = 8;
|
||||
static constexpr MsgSize_t INITIAL_BUFFER_POSITION = 4;
|
||||
enum { HEADER_LENGTH = 2 };
|
||||
enum { CHECKSUM_LENGTH = 4 };
|
||||
enum { XTEA_MULTIPLE = 8 };
|
||||
enum { MAX_BODY_LENGTH = NETWORKMESSAGE_MAXSIZE - HEADER_LENGTH - CHECKSUM_LENGTH - XTEA_MULTIPLE };
|
||||
enum { MAX_BODY_LENGTH = NETWORKMESSAGE_MAXSIZE - HEADER_LENGTH - XTEA_MULTIPLE };
|
||||
enum { MAX_PROTOCOL_BODY_LENGTH = MAX_BODY_LENGTH - 10 };
|
||||
|
||||
NetworkMessage() = default;
|
||||
|
@@ -185,14 +185,11 @@ void mainLoader(int, char*[], ServiceManager* services)
|
||||
else if (clientVersion == 792) {
|
||||
g_game.setClientVersion(CLIENT_VERSION_792);
|
||||
}
|
||||
else if (clientVersion == 870) {
|
||||
g_game.setClientVersion(CLIENT_VERSION_870);
|
||||
}
|
||||
else {
|
||||
std::cout << std::endl;
|
||||
|
||||
std::ostringstream ss;
|
||||
ss << "> ERROR: Unknown client version: " << g_config.getNumber(ConfigManager::CLIENT_VERSION) << ", valid client versions are: 780, 781, 790, 792, 870.";
|
||||
ss << "> ERROR: Unknown client version: " << g_config.getNumber(ConfigManager::CLIENT_VERSION) << ", valid client versions are: 780, 781, 790, 792.";
|
||||
startupErrorMessage(ss.str());
|
||||
return;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* The Forgotten Server - a free and open-source MMORPG server emulator
|
||||
* Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
|
||||
* Tibia GIMUD Server - a free and open-source MMORPG server emulator
|
||||
* Copyright (C) 2019 Sabrehaven and Mark Samman <mark.samman@gmail.com>
|
||||
*
|
||||
* 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
|
||||
@@ -28,80 +28,76 @@ class Protocol;
|
||||
|
||||
class OutputMessage : public NetworkMessage
|
||||
{
|
||||
public:
|
||||
OutputMessage() = default;
|
||||
public:
|
||||
OutputMessage() = default;
|
||||
|
||||
// non-copyable
|
||||
OutputMessage(const OutputMessage&) = delete;
|
||||
OutputMessage& operator=(const OutputMessage&) = delete;
|
||||
// non-copyable
|
||||
OutputMessage(const OutputMessage&) = delete;
|
||||
OutputMessage& operator=(const OutputMessage&) = delete;
|
||||
|
||||
uint8_t* getOutputBuffer() {
|
||||
return buffer + outputBufferStart;
|
||||
}
|
||||
uint8_t* getOutputBuffer() {
|
||||
return buffer + outputBufferStart;
|
||||
}
|
||||
|
||||
void writeMessageLength() {
|
||||
add_header(info.length);
|
||||
}
|
||||
void writeMessageLength() {
|
||||
add_header(info.length);
|
||||
}
|
||||
|
||||
void addCryptoHeader(bool addChecksum) {
|
||||
if (addChecksum) {
|
||||
add_header(adlerChecksum(buffer + outputBufferStart, info.length));
|
||||
}
|
||||
void addCryptoHeader() {
|
||||
writeMessageLength();
|
||||
}
|
||||
|
||||
writeMessageLength();
|
||||
}
|
||||
inline void append(const NetworkMessage& msg) {
|
||||
auto msgLen = msg.getLength();
|
||||
memcpy(buffer + info.position, msg.getBuffer() + 4, msgLen);
|
||||
info.length += msgLen;
|
||||
info.position += msgLen;
|
||||
}
|
||||
|
||||
void append(const NetworkMessage& msg) {
|
||||
auto msgLen = msg.getLength();
|
||||
memcpy(buffer + info.position, msg.getBuffer() + 8, msgLen);
|
||||
info.length += msgLen;
|
||||
info.position += msgLen;
|
||||
}
|
||||
inline void append(const OutputMessage_ptr& msg) {
|
||||
auto msgLen = msg->getLength();
|
||||
memcpy(buffer + info.position, msg->getBuffer() + 4, msgLen);
|
||||
info.length += msgLen;
|
||||
info.position += msgLen;
|
||||
}
|
||||
|
||||
void append(const OutputMessage_ptr& msg) {
|
||||
auto msgLen = msg->getLength();
|
||||
memcpy(buffer + info.position, msg->getBuffer() + 8, msgLen);
|
||||
info.length += msgLen;
|
||||
info.position += msgLen;
|
||||
}
|
||||
protected:
|
||||
template <typename T>
|
||||
inline void add_header(T add) {
|
||||
assert(outputBufferStart >= sizeof(T));
|
||||
outputBufferStart -= sizeof(T);
|
||||
memcpy(buffer + outputBufferStart, &add, sizeof(T));
|
||||
//added header size to the message size
|
||||
info.length += sizeof(T);
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
void add_header(T add) {
|
||||
assert(outputBufferStart >= sizeof(T));
|
||||
outputBufferStart -= sizeof(T);
|
||||
memcpy(buffer + outputBufferStart, &add, sizeof(T));
|
||||
//added header size to the message size
|
||||
info.length += sizeof(T);
|
||||
}
|
||||
|
||||
MsgSize_t outputBufferStart = INITIAL_BUFFER_POSITION;
|
||||
MsgSize_t outputBufferStart = INITIAL_BUFFER_POSITION;
|
||||
};
|
||||
|
||||
class OutputMessagePool
|
||||
{
|
||||
public:
|
||||
// non-copyable
|
||||
OutputMessagePool(const OutputMessagePool&) = delete;
|
||||
OutputMessagePool& operator=(const OutputMessagePool&) = delete;
|
||||
public:
|
||||
// non-copyable
|
||||
OutputMessagePool(const OutputMessagePool&) = delete;
|
||||
OutputMessagePool& operator=(const OutputMessagePool&) = delete;
|
||||
|
||||
static OutputMessagePool& getInstance() {
|
||||
static OutputMessagePool instance;
|
||||
return instance;
|
||||
}
|
||||
static OutputMessagePool& getInstance() {
|
||||
static OutputMessagePool instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void sendAll();
|
||||
void scheduleSendAll();
|
||||
void sendAll();
|
||||
void scheduleSendAll();
|
||||
|
||||
static OutputMessage_ptr getOutputMessage();
|
||||
static OutputMessage_ptr getOutputMessage();
|
||||
|
||||
void addProtocolToAutosend(Protocol_ptr protocol);
|
||||
void removeProtocolFromAutosend(const Protocol_ptr& protocol);
|
||||
private:
|
||||
OutputMessagePool() = default;
|
||||
//NOTE: A vector is used here because this container is mostly read
|
||||
//and relatively rarely modified (only when a client connects/disconnects)
|
||||
std::vector<Protocol_ptr> bufferedProtocols;
|
||||
void addProtocolToAutosend(Protocol_ptr protocol);
|
||||
void removeProtocolFromAutosend(const Protocol_ptr& protocol);
|
||||
private:
|
||||
OutputMessagePool() = default;
|
||||
//NOTE: A vector is used here because this container is mostly read
|
||||
//and relatively rarely modified (only when a client connects/disconnects)
|
||||
std::vector<Protocol_ptr> bufferedProtocols;
|
||||
};
|
||||
|
||||
|
||||
|
@@ -579,21 +579,6 @@ bool Player::canSeeCreature(const Creature* creature) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Player::canWalkthroughEx(const Creature* creature) const
|
||||
{
|
||||
if (group->access) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const Player* player = creature->getPlayer();
|
||||
if (!player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const Tile* playerTile = player->getTile();
|
||||
return playerTile && (playerTile->hasFlag(TILESTATE_PROTECTIONZONE) || player->getLevel() <= static_cast<uint32_t>(g_config.getNumber(ConfigManager::PROTECTION_LEVEL)));
|
||||
}
|
||||
|
||||
void Player::onReceiveMail(uint32_t townId) const
|
||||
{
|
||||
if (isNearDepotBox(townId)) {
|
||||
|
@@ -439,8 +439,6 @@ class Player final : public Creature, public Cylinder
|
||||
bool canSee(const Position& pos) const final;
|
||||
bool canSeeCreature(const Creature* creature) const final;
|
||||
|
||||
bool canWalkthroughEx(const Creature* creature) const;
|
||||
|
||||
RaceType_t getRace() const final {
|
||||
return RACE_BLOOD;
|
||||
}
|
||||
@@ -691,11 +689,6 @@ class Player final : public Creature, public Cylinder
|
||||
client->sendCreatureLight(creature);
|
||||
}
|
||||
}
|
||||
void sendCreatureWalkthrough(const Creature* creature, bool walkthrough) {
|
||||
if (client) {
|
||||
client->sendCreatureWalkthrough(creature, walkthrough);
|
||||
}
|
||||
}
|
||||
void sendCreatureShield(const Creature* creature) {
|
||||
if (client) {
|
||||
client->sendCreatureShield(creature);
|
||||
|
@@ -22,7 +22,6 @@
|
||||
#include "protocol.h"
|
||||
#include "outputmessage.h"
|
||||
#include "rsa.h"
|
||||
#include "xtea.h"
|
||||
|
||||
extern RSA g_RSA;
|
||||
|
||||
@@ -33,7 +32,7 @@ void Protocol::onSendMessage(const OutputMessage_ptr& msg) const
|
||||
|
||||
if (encryptionEnabled) {
|
||||
XTEA_encrypt(*msg);
|
||||
msg->addCryptoHeader(checksumEnabled);
|
||||
msg->addCryptoHeader();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,27 +61,73 @@ OutputMessage_ptr Protocol::getOutputBuffer(int32_t size)
|
||||
|
||||
void Protocol::XTEA_encrypt(OutputMessage& msg) const
|
||||
{
|
||||
const uint32_t delta = 0x61C88647;
|
||||
|
||||
// The message must be a multiple of 8
|
||||
size_t paddingBytes = msg.getLength() % 8u;
|
||||
size_t paddingBytes = msg.getLength() % 8;
|
||||
if (paddingBytes != 0) {
|
||||
msg.addPaddingBytes(8 - paddingBytes);
|
||||
}
|
||||
|
||||
uint8_t* buffer = msg.getOutputBuffer();
|
||||
xtea::encrypt(buffer, msg.getLength(), key);
|
||||
const size_t messageLength = msg.getLength();
|
||||
size_t readPos = 0;
|
||||
const uint32_t k[] = { key[0], key[1], key[2], key[3] };
|
||||
while (readPos < messageLength) {
|
||||
uint32_t v0;
|
||||
memcpy(&v0, buffer + readPos, 4);
|
||||
uint32_t v1;
|
||||
memcpy(&v1, buffer + readPos + 4, 4);
|
||||
|
||||
uint32_t sum = 0;
|
||||
|
||||
for (int32_t i = 32; --i >= 0;) {
|
||||
v0 += ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]);
|
||||
sum -= delta;
|
||||
v1 += ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[(sum >> 11) & 3]);
|
||||
}
|
||||
|
||||
memcpy(buffer + readPos, &v0, 4);
|
||||
readPos += 4;
|
||||
memcpy(buffer + readPos, &v1, 4);
|
||||
readPos += 4;
|
||||
}
|
||||
}
|
||||
|
||||
bool Protocol::XTEA_decrypt(NetworkMessage& msg) const
|
||||
{
|
||||
if (((msg.getLength() - 6) & 7) != 0) {
|
||||
if (((msg.getLength() - 2) & 7) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t* buffer = msg.getBuffer() + msg.getBufferPosition();
|
||||
xtea::decrypt(buffer, msg.getLength() - 6, key);
|
||||
const uint32_t delta = 0x61C88647;
|
||||
|
||||
uint16_t innerLength = msg.get<uint16_t>();
|
||||
if (innerLength + 8 > msg.getLength()) {
|
||||
uint8_t* buffer = msg.getBuffer() + msg.getBufferPosition();
|
||||
const size_t messageLength = (msg.getLength() - 2);
|
||||
size_t readPos = 0;
|
||||
const uint32_t k[] = { key[0], key[1], key[2], key[3] };
|
||||
while (readPos < messageLength) {
|
||||
uint32_t v0;
|
||||
memcpy(&v0, buffer + readPos, 4);
|
||||
uint32_t v1;
|
||||
memcpy(&v1, buffer + readPos + 4, 4);
|
||||
|
||||
uint32_t sum = 0xC6EF3720;
|
||||
|
||||
for (int32_t i = 32; --i >= 0;) {
|
||||
v1 -= ((v0 << 4 ^ v0 >> 5) + v0) ^ (sum + k[(sum >> 11) & 3]);
|
||||
sum += delta;
|
||||
v0 -= ((v1 << 4 ^ v1 >> 5) + v1) ^ (sum + k[sum & 3]);
|
||||
}
|
||||
|
||||
memcpy(buffer + readPos, &v0, 4);
|
||||
readPos += 4;
|
||||
memcpy(buffer + readPos, &v1, 4);
|
||||
readPos += 4;
|
||||
}
|
||||
|
||||
int innerLength = msg.get<uint16_t>();
|
||||
if (innerLength > msg.getLength() - 4) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -92,7 +137,7 @@ bool Protocol::XTEA_decrypt(NetworkMessage& msg) const
|
||||
|
||||
bool Protocol::RSA_decrypt(NetworkMessage& msg)
|
||||
{
|
||||
if ((msg.getLength() - msg.getBufferPosition()) < 128) {
|
||||
if ((msg.getLength() - msg.getBufferPosition()) != 128) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -21,7 +21,6 @@
|
||||
#define FS_PROTOCOL_H_D71405071ACF4137A4B1203899DE80E1
|
||||
|
||||
#include "connection.h"
|
||||
#include "xtea.h"
|
||||
|
||||
class Protocol : public std::enable_shared_from_this<Protocol>
|
||||
{
|
||||
@@ -72,11 +71,8 @@ protected:
|
||||
void enableXTEAEncryption() {
|
||||
encryptionEnabled = true;
|
||||
}
|
||||
void setXTEAKey(xtea::key key) {
|
||||
this->key = std::move(key);
|
||||
}
|
||||
void disableChecksum() {
|
||||
checksumEnabled = false;
|
||||
void setXTEAKey(const uint32_t* key) {
|
||||
memcpy(this->key, key, sizeof(*key) * 4);
|
||||
}
|
||||
|
||||
void XTEA_encrypt(OutputMessage& msg) const;
|
||||
@@ -93,9 +89,8 @@ protected:
|
||||
OutputMessage_ptr outputBuffer;
|
||||
private:
|
||||
const ConnectionWeak_ptr connection;
|
||||
xtea::key key;
|
||||
uint32_t key[4];
|
||||
bool encryptionEnabled;
|
||||
bool checksumEnabled = true;
|
||||
bool rawMessages;
|
||||
};
|
||||
|
||||
|
@@ -247,13 +247,13 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg)
|
||||
return;
|
||||
}
|
||||
|
||||
xtea::key key;
|
||||
uint32_t key[4];
|
||||
key[0] = msg.get<uint32_t>();
|
||||
key[1] = msg.get<uint32_t>();
|
||||
key[2] = msg.get<uint32_t>();
|
||||
key[3] = msg.get<uint32_t>();
|
||||
enableXTEAEncryption();
|
||||
setXTEAKey(std::move(key));
|
||||
setXTEAKey(key);
|
||||
|
||||
if (operatingSystem >= CLIENTOS_OTCLIENT_LINUX) {
|
||||
NetworkMessage opcodeMessage;
|
||||
@@ -265,8 +265,7 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg)
|
||||
|
||||
msg.skipBytes(1); // gamemaster flag
|
||||
|
||||
std::string accountName = msg.getString();
|
||||
uint32_t accountNumber = 1234567;
|
||||
uint32_t accountNumber = msg.get<uint32_t>();
|
||||
std::string characterName = msg.getString();
|
||||
std::string password = msg.getString();
|
||||
|
||||
@@ -319,30 +318,8 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg)
|
||||
|
||||
void ProtocolGame::onConnect()
|
||||
{
|
||||
auto output = OutputMessagePool::getOutputMessage();
|
||||
static std::random_device rd;
|
||||
static std::ranlux24 generator(rd());
|
||||
static std::uniform_int_distribution<uint16_t> randNumber(0x00, 0xFF);
|
||||
|
||||
// Skip checksum
|
||||
output->skipBytes(sizeof(uint32_t));
|
||||
|
||||
// Packet length & type
|
||||
output->add<uint16_t>(0x0006);
|
||||
output->addByte(0x1F);
|
||||
|
||||
// Add timestamp & random number
|
||||
challengeTimestamp = static_cast<uint32_t>(time(nullptr));
|
||||
output->add<uint32_t>(challengeTimestamp);
|
||||
|
||||
challengeRandom = randNumber(generator);
|
||||
output->addByte(challengeRandom);
|
||||
|
||||
// Go back and write checksum
|
||||
output->skipBytes(-12);
|
||||
output->add<uint32_t>(adlerChecksum(output->getOutputBuffer() + sizeof(uint32_t), 8));
|
||||
|
||||
send(output);
|
||||
}
|
||||
|
||||
void ProtocolGame::disconnectClient(const std::string& message) const
|
||||
@@ -484,7 +461,8 @@ void ProtocolGame::GetTileDescription(const Tile* tile, NetworkMessage& msg)
|
||||
count++;
|
||||
if (count == 9 && tile->getPosition() == player->getPosition()) {
|
||||
break;
|
||||
} else if (count == 10) {
|
||||
}
|
||||
else if (count == 10) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -587,7 +565,7 @@ void ProtocolGame::checkCreatureAsKnown(uint32_t id, bool& known, uint32_t& remo
|
||||
|
||||
known = false;
|
||||
|
||||
if (knownCreatureSet.size() > 250) {
|
||||
if (knownCreatureSet.size() > 150) {
|
||||
// Look for a creature to remove
|
||||
for (auto it = knownCreatureSet.begin(), end = knownCreatureSet.end(); it != end; ++it) {
|
||||
Creature* creature = g_game.getCreatureByID(*it);
|
||||
@@ -693,7 +671,7 @@ void ProtocolGame::parseOpenPrivateChannel(NetworkMessage& msg)
|
||||
void ProtocolGame::parseAutoWalk(NetworkMessage& msg)
|
||||
{
|
||||
uint8_t numdirs = msg.getByte();
|
||||
if (numdirs == 0 || (msg.getBufferPosition() + numdirs) != (msg.getLength() + 8)) {
|
||||
if (numdirs == 0 || (msg.getBufferPosition() + numdirs) != (msg.getLength() + 4)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1040,19 +1018,6 @@ void ProtocolGame::sendWorldLight(const LightInfo& lightInfo)
|
||||
writeToOutputBuffer(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendCreatureWalkthrough(const Creature* creature, bool walkthrough)
|
||||
{
|
||||
if (!canSee(creature)) {
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkMessage msg;
|
||||
msg.addByte(0x92);
|
||||
msg.add<uint32_t>(creature->getID());
|
||||
msg.addByte(walkthrough ? 0x00 : 0x01);
|
||||
writeToOutputBuffer(msg);
|
||||
}
|
||||
|
||||
void ProtocolGame::sendCreatureShield(const Creature* creature)
|
||||
{
|
||||
if (!canSee(creature)) {
|
||||
@@ -1636,7 +1601,8 @@ void ProtocolGame::sendAddCreature(const Creature* creature, const Position& pos
|
||||
msg.addByte(0x0A);
|
||||
|
||||
msg.add<uint32_t>(player->getID());
|
||||
msg.add<uint16_t>(0x32); // beat duration (50)
|
||||
msg.addByte(0x32); // beat duration (50)
|
||||
msg.addByte(0x00);
|
||||
|
||||
// can report bugs?
|
||||
if (player->getAccountType() >= ACCOUNT_TYPE_TUTOR) {
|
||||
@@ -1958,7 +1924,6 @@ void ProtocolGame::AddCreature(NetworkMessage& msg, const Creature* creature, bo
|
||||
|
||||
msg.addByte(player->getSkullClient(creature));
|
||||
msg.addByte(player->getPartyShield(otherPlayer));
|
||||
msg.addByte(player->canWalkthroughEx(creature) ? 0x00 : 0x01);
|
||||
}
|
||||
|
||||
void ProtocolGame::AddPlayerStats(NetworkMessage& msg)
|
||||
|
@@ -52,8 +52,7 @@ class ProtocolGame final : public Protocol
|
||||
// static protocol information
|
||||
enum { server_sends_first = true };
|
||||
enum { protocol_identifier = 0 }; // Not required as we send first
|
||||
enum { use_checksum = true };
|
||||
|
||||
|
||||
static const char* protocol_name() {
|
||||
return "gameworld protocol";
|
||||
}
|
||||
@@ -170,7 +169,6 @@ class ProtocolGame final : public Protocol
|
||||
void sendTextMessage(const TextMessage& message);
|
||||
void sendAnimatedText(const Position& pos, uint8_t color, const std::string& text);
|
||||
|
||||
void sendCreatureWalkthrough(const Creature* creature, bool walkthrough);
|
||||
void sendCreatureShield(const Creature* creature);
|
||||
void sendCreatureSkull(const Creature* creature);
|
||||
|
||||
|
@@ -128,13 +128,13 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
|
||||
return;
|
||||
}
|
||||
|
||||
xtea::key key;
|
||||
uint32_t key[4];
|
||||
key[0] = msg.get<uint32_t>();
|
||||
key[1] = msg.get<uint32_t>();
|
||||
key[2] = msg.get<uint32_t>();
|
||||
key[3] = msg.get<uint32_t>();
|
||||
enableXTEAEncryption();
|
||||
setXTEAKey(std::move(key));
|
||||
setXTEAKey(key);
|
||||
|
||||
if (!isProtocolAllowed(version)) {
|
||||
std::ostringstream ss;
|
||||
@@ -170,12 +170,11 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
|
||||
return;
|
||||
}
|
||||
|
||||
//uint32_t accountNumber = msg.get<uint32_t>();
|
||||
std::string accountName = msg.getString();
|
||||
//if (!accountNumber) {
|
||||
// disconnectClient("Invalid account number.", version);
|
||||
// return;
|
||||
// }
|
||||
uint32_t accountNumber = msg.get<uint32_t>();
|
||||
if (!accountNumber) {
|
||||
disconnectClient("Invalid account number.", version);
|
||||
return;
|
||||
}
|
||||
|
||||
std::string password = msg.getString();
|
||||
if (password.empty()) {
|
||||
@@ -184,7 +183,7 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
|
||||
}
|
||||
|
||||
auto thisPtr = std::static_pointer_cast<ProtocolLogin>(shared_from_this());
|
||||
g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, 1234567, password, version)));
|
||||
g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountNumber, password, version)));
|
||||
}
|
||||
|
||||
|
||||
|
@@ -32,7 +32,6 @@ class ProtocolLogin : public Protocol
|
||||
// static protocol information
|
||||
enum {server_sends_first = false};
|
||||
enum {protocol_identifier = 0x01};
|
||||
enum { use_checksum = true };
|
||||
static const char* protocol_name() {
|
||||
return "login protocol";
|
||||
}
|
||||
|
@@ -29,7 +29,6 @@ class ProtocolStatus final : public Protocol
|
||||
// static protocol information
|
||||
enum {server_sends_first = false};
|
||||
enum {protocol_identifier = 0xFF};
|
||||
enum { use_checksum = false };
|
||||
static const char* protocol_name() {
|
||||
return "status protocol";
|
||||
}
|
||||
|
@@ -136,7 +136,7 @@ void ServicePort::onAccept(Connection_ptr connection, const boost::system::error
|
||||
}
|
||||
}
|
||||
|
||||
Protocol_ptr ServicePort::make_protocol(bool checksummed, NetworkMessage& msg, const Connection_ptr& connection) const
|
||||
Protocol_ptr ServicePort::make_protocol(NetworkMessage& msg, const Connection_ptr& connection) const
|
||||
{
|
||||
uint8_t protocolID = msg.getByte();
|
||||
for (auto& service : services) {
|
||||
@@ -144,9 +144,7 @@ Protocol_ptr ServicePort::make_protocol(bool checksummed, NetworkMessage& msg, c
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((checksummed && service->is_checksummed()) || !service->is_checksummed()) {
|
||||
return service->make_protocol(connection);
|
||||
}
|
||||
return service->make_protocol(connection);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
@@ -29,7 +29,6 @@ class ServiceBase
|
||||
{
|
||||
public:
|
||||
virtual bool is_single_socket() const = 0;
|
||||
virtual bool is_checksummed() const = 0;
|
||||
virtual uint8_t get_protocol_identifier() const = 0;
|
||||
virtual const char* get_protocol_name() const = 0;
|
||||
|
||||
@@ -43,9 +42,6 @@ public:
|
||||
bool is_single_socket() const final {
|
||||
return ProtocolType::server_sends_first;
|
||||
}
|
||||
bool is_checksummed() const override {
|
||||
return ProtocolType::use_checksum;
|
||||
}
|
||||
uint8_t get_protocol_identifier() const final {
|
||||
return ProtocolType::protocol_identifier;
|
||||
}
|
||||
@@ -75,7 +71,7 @@ public:
|
||||
std::string get_protocol_names() const;
|
||||
|
||||
bool add_service(const Service_ptr& new_svc);
|
||||
Protocol_ptr make_protocol(bool checksummed, NetworkMessage& msg, const Connection_ptr& connection) const;
|
||||
Protocol_ptr make_protocol(NetworkMessage& msg, const Connection_ptr& connection) const;
|
||||
|
||||
void onStopServer();
|
||||
void onAccept(Connection_ptr connection, const boost::system::error_code& error);
|
||||
|
@@ -1,83 +0,0 @@
|
||||
/**
|
||||
* The Forgotten Server - a free and open-source MMORPG server emulator
|
||||
* Copyright (C) 2019 Mark Samman <mark.samman@gmail.com>
|
||||
*
|
||||
* 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; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; 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.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#ifndef FS_SPECTATORS_H_D78A7CCB7080406E8CAA6B1D31D3DA71
|
||||
#define FS_SPECTATORS_H_D78A7CCB7080406E8CAA6B1D31D3DA71
|
||||
|
||||
#include <vector>
|
||||
|
||||
class Creature;
|
||||
|
||||
class SpectatorVec
|
||||
{
|
||||
using Vec = std::vector<Creature*>;
|
||||
using Iterator = Vec::iterator;
|
||||
using ConstIterator = Vec::const_iterator;
|
||||
public:
|
||||
SpectatorVec() {
|
||||
vec.reserve(32);
|
||||
}
|
||||
|
||||
void addSpectators(const SpectatorVec& spectators) {
|
||||
const size_t size = vec.size();
|
||||
for (Creature* spectator : spectators.vec) {
|
||||
bool duplicate = false;
|
||||
for (size_t i = 0; i < size; ++i) {
|
||||
if (vec[i] == spectator) {
|
||||
duplicate = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!duplicate) {
|
||||
vec.emplace_back(spectator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void erase(Creature* spectator) {
|
||||
for (size_t i = 0, len = vec.size(); i < len; i++) {
|
||||
if (vec[i] == spectator) {
|
||||
Creature* tmp = vec[len - 1];
|
||||
vec[len - 1] = vec[i];
|
||||
vec[i] = tmp;
|
||||
vec.pop_back();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t size() const { return vec.size(); }
|
||||
inline bool empty() const { return vec.empty(); }
|
||||
inline Iterator begin() { return vec.begin(); }
|
||||
inline ConstIterator begin() const { return vec.begin(); }
|
||||
inline ConstIterator cbegin() const { return vec.cbegin(); }
|
||||
inline Iterator end() { return vec.end(); }
|
||||
inline ConstIterator end() const { return vec.end(); }
|
||||
inline ConstIterator cend() const { return vec.cend(); }
|
||||
inline void emplace_back(Creature* c) { return vec.emplace_back(c); }
|
||||
|
||||
template<class InputIterator>
|
||||
inline void insert(Iterator pos, InputIterator first, InputIterator last) { vec.insert(pos, first, last); }
|
||||
|
||||
private:
|
||||
Vec vec;
|
||||
};
|
||||
|
||||
#endif
|
@@ -25,7 +25,6 @@
|
||||
#include "cylinder.h"
|
||||
#include "item.h"
|
||||
#include "tools.h"
|
||||
#include "spectators.h"
|
||||
|
||||
class Creature;
|
||||
class Teleport;
|
||||
@@ -37,6 +36,7 @@ class BedItem;
|
||||
|
||||
typedef std::vector<Creature*> CreatureVector;
|
||||
typedef std::vector<Item*> ItemVector;
|
||||
typedef std::unordered_set<Creature*> SpectatorVec;
|
||||
|
||||
enum tileflags_t : uint32_t {
|
||||
TILESTATE_NONE = 0,
|
||||
|
@@ -1258,9 +1258,6 @@ std::string getClientVersionString(ClientVersion_t version)
|
||||
case CLIENT_VERSION_792:
|
||||
result = "7.92";
|
||||
break;
|
||||
case CLIENT_VERSION_870:
|
||||
result = "8.60";
|
||||
break;
|
||||
default:
|
||||
result = "Unknown";
|
||||
break;
|
||||
@@ -1268,29 +1265,3 @@ std::string getClientVersionString(ClientVersion_t version)
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t adlerChecksum(const uint8_t* data, size_t length)
|
||||
{
|
||||
if (length > NETWORKMESSAGE_MAXSIZE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint16_t adler = 65521;
|
||||
|
||||
uint32_t a = 1, b = 0;
|
||||
|
||||
while (length > 0) {
|
||||
size_t tmp = length > 5552 ? 5552 : length;
|
||||
length -= tmp;
|
||||
|
||||
do {
|
||||
a += *data++;
|
||||
b += a;
|
||||
} while (--tmp);
|
||||
|
||||
a %= adler;
|
||||
b %= adler;
|
||||
}
|
||||
|
||||
return (b << 16) | a;
|
||||
}
|
@@ -103,8 +103,6 @@ void getFilesInDirectory(const boost::filesystem::path& root, const std::string&
|
||||
std::string getClientVersionString(uint32_t version);
|
||||
std::string getClientVersionString(ClientVersion_t version);
|
||||
|
||||
uint32_t adlerChecksum(const uint8_t* data, size_t length);
|
||||
|
||||
inline int64_t OTSYS_TIME()
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
Reference in New Issue
Block a user