diff --git a/config.lua b/config.lua
index e354f60..0383f6a 100644
--- a/config.lua
+++ b/config.lua
@@ -52,7 +52,7 @@ timeBetweenExActions = 1000
-- Map
-- NOTE: set mapName WITHOUT .otbm at the end
-mapName = "map"
+mapName = "mymap"
mapAuthor = "CipSoft"
-- MySQL
diff --git a/data/world/mymap-house.xml b/data/world/mymap-house.xml
new file mode 100644
index 0000000..9d137e4
--- /dev/null
+++ b/data/world/mymap-house.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/data/world/mymap-spawn.xml b/data/world/mymap-spawn.xml
new file mode 100644
index 0000000..2bde032
--- /dev/null
+++ b/data/world/mymap-spawn.xml
@@ -0,0 +1,2 @@
+
+
diff --git a/data/world/mymap.otbm b/data/world/mymap.otbm
new file mode 100644
index 0000000..b0ed9ec
Binary files /dev/null and b/data/world/mymap.otbm differ
diff --git a/src/configmanager.cpp b/src/configmanager.cpp
index 5b2b7a0..6610b74 100644
--- a/src/configmanager.cpp
+++ b/src/configmanager.cpp
@@ -74,6 +74,7 @@ bool ConfigManager::load()
boolean[FREE_PREMIUM] = getGlobalBoolean(L, "freePremium", false);
boolean[REPLACE_KICK_ON_LOGIN] = getGlobalBoolean(L, "replaceKickOnLogin", true);
boolean[ALLOW_CLONES] = getGlobalBoolean(L, "allowClones", false);
+ boolean[STAMINA_SYSTEM] = getGlobalBoolean(L, "staminaSystem", true);
boolean[WARN_UNSAFE_SCRIPTS] = getGlobalBoolean(L, "warnUnsafeScripts", true);
boolean[CONVERT_UNSAFE_SCRIPTS] = getGlobalBoolean(L, "convertUnsafeScripts", true);
boolean[TELEPORT_NEWBIES] = getGlobalBoolean(L, "teleportNewbies", true);
diff --git a/src/configmanager.h b/src/configmanager.h
index 1461eb0..2d7b0db 100644
--- a/src/configmanager.h
+++ b/src/configmanager.h
@@ -37,6 +37,7 @@ class ConfigManager
ALLOW_CLONES,
BIND_ONLY_GLOBAL_ADDRESS,
OPTIMIZE_DATABASE,
+ STAMINA_SYSTEM,
WARN_UNSAFE_SCRIPTS,
CONVERT_UNSAFE_SCRIPTS,
TELEPORT_NEWBIES,
diff --git a/src/connection.cpp b/src/connection.cpp
index 56a3861..dce33eb 100644
--- a/src/connection.cpp
+++ b/src/connection.cpp
@@ -187,29 +187,13 @@ void Connection::parsePacket(const boost::system::error_code& error)
return;
}
- //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();
- if (recvChecksum != checksum) {
- // it might not have been the checksum, step back
- msg.skipBytes(-NetworkMessage::CHECKSUM_LENGTH);
- }
-
if (!receivedFirst) {
// First message received
receivedFirst = true;
if (!protocol) {
// Game protocol has already been created at this point
- protocol = service_port->make_protocol(recvChecksum == checksum, msg, shared_from_this());
+ protocol = service_port->make_protocol(msg, shared_from_this());
if (!protocol) {
close(FORCE_CLOSE);
return;
@@ -242,6 +226,7 @@ void Connection::parsePacket(const boost::system::error_code& error)
}
+
void Connection::send(const OutputMessage_ptr& msg)
{
std::lock_guard lockClass(connectionLock);
diff --git a/src/iologindata.cpp b/src/iologindata.cpp
index 4fb9fbc..3a52c64 100644
--- a/src/iologindata.cpp
+++ b/src/iologindata.cpp
@@ -188,7 +188,7 @@ bool IOLoginData::preloadPlayer(Player* player, const std::string& name)
bool IOLoginData::loadPlayerById(Player* player, uint32_t id)
{
std::ostringstream query;
- query << "SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `blessings`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `conditions`, `skulltime`, `skull`, `town_id`, `balance`, `skill_fist`, `skill_fist_tries`, `skill_club`, `skill_club_tries`, `skill_sword`, `skill_sword_tries`, `skill_axe`, `skill_axe_tries`, `skill_dist`, `skill_dist_tries`, `skill_shielding`, `skill_shielding_tries`, `skill_fishing`, `skill_fishing_tries` FROM `players` WHERE `id` = " << id;
+ query << "SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `blessings`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `lookaddons`, `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `conditions`, `skulltime`, `skull`, `town_id`, `balance`, `stamina`, `skill_fist`, `skill_fist_tries`, `skill_club`, `skill_club_tries`, `skill_sword`, `skill_sword_tries`, `skill_axe`, `skill_axe_tries`, `skill_dist`, `skill_dist_tries`, `skill_shielding`, `skill_shielding_tries`, `skill_fishing`, `skill_fishing_tries` FROM `players` WHERE `id` = " << id;
return loadPlayer(player, Database::getInstance()->storeQuery(query.str()));
}
@@ -196,7 +196,7 @@ bool IOLoginData::loadPlayerByName(Player* player, const std::string& name)
{
Database* db = Database::getInstance();
std::ostringstream query;
- query << "SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `blessings`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `conditions`, `skulltime`, `skull`, `town_id`, `balance`, `skill_fist`, `skill_fist_tries`, `skill_club`, `skill_club_tries`, `skill_sword`, `skill_sword_tries`, `skill_axe`, `skill_axe_tries`, `skill_dist`, `skill_dist_tries`, `skill_shielding`, `skill_shielding_tries`, `skill_fishing`, `skill_fishing_tries` FROM `players` WHERE `name` = " << db->escapeString(name);
+ query << "SELECT `id`, `name`, `account_id`, `group_id`, `sex`, `vocation`, `experience`, `level`, `maglevel`, `health`, `healthmax`, `blessings`, `mana`, `manamax`, `manaspent`, `soul`, `lookbody`, `lookfeet`, `lookhead`, `looklegs`, `looktype`, `lookaddons`, `posx`, `posy`, `posz`, `cap`, `lastlogin`, `lastlogout`, `lastip`, `conditions`, `skulltime`, `skull`, `town_id`, `balance`, `stamina`, `skill_fist`, `skill_fist_tries`, `skill_club`, `skill_club_tries`, `skill_sword`, `skill_sword_tries`, `skill_axe`, `skill_axe_tries`, `skill_dist`, `skill_dist_tries`, `skill_shielding`, `skill_shielding_tries`, `skill_fishing`, `skill_fishing_tries` FROM `players` WHERE `name` = " << db->escapeString(name);
return loadPlayer(player, db->storeQuery(query.str()));
}
@@ -296,6 +296,7 @@ bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result)
player->defaultOutfit.lookBody = result->getNumber("lookbody");
player->defaultOutfit.lookLegs = result->getNumber("looklegs");
player->defaultOutfit.lookFeet = result->getNumber("lookfeet");
+ player->defaultOutfit.lookAddons = result->getNumber("lookaddons");
player->currentOutfit = player->defaultOutfit;
if (g_game.getWorldType() != WORLD_TYPE_PVP_ENFORCED) {
@@ -331,6 +332,8 @@ bool IOLoginData::loadPlayer(Player* player, DBResult_ptr result)
player->loginPosition = player->getTemplePosition();
}
+ player->staminaMinutes = result->getNumber("stamina");
+
static const std::string skillNames[] = {"skill_fist", "skill_club", "skill_sword", "skill_axe", "skill_dist", "skill_shielding", "skill_fishing"};
static const std::string skillNameTries[] = {"skill_fist_tries", "skill_club_tries", "skill_sword_tries", "skill_axe_tries", "skill_dist_tries", "skill_shielding_tries", "skill_fishing_tries"};
static constexpr size_t size = sizeof(skillNames) / sizeof(std::string);
@@ -616,6 +619,7 @@ bool IOLoginData::savePlayer(Player* player)
query << "`lookhead` = " << static_cast(player->defaultOutfit.lookHead) << ',';
query << "`looklegs` = " << static_cast(player->defaultOutfit.lookLegs) << ',';
query << "`looktype` = " << player->defaultOutfit.lookType << ',';
+ query << "`lookaddons` = " << static_cast(player->defaultOutfit.lookAddons) << ',';
query << "`maglevel` = " << player->magLevel << ',';
query << "`mana` = " << player->mana << ',';
query << "`manamax` = " << player->manaMax << ',';
@@ -654,6 +658,7 @@ bool IOLoginData::savePlayer(Player* player)
query << "`lastlogout` = " << player->getLastLogout() << ',';
query << "`balance` = " << player->bankBalance << ',';
+ query << "`stamina` = " << player->getStaminaMinutes() << ',';
query << "`skill_fist` = " << player->skills[SKILL_FIST].level << ',';
query << "`skill_fist_tries` = " << player->skills[SKILL_FIST].tries << ',';
diff --git a/src/luascript.cpp b/src/luascript.cpp
index 8099d24..3401679 100644
--- a/src/luascript.cpp
+++ b/src/luascript.cpp
@@ -730,6 +730,8 @@ Position LuaScriptInterface::getPosition(lua_State* L, int32_t arg)
Outfit_t LuaScriptInterface::getOutfit(lua_State* L, int32_t arg)
{
Outfit_t outfit;
+ outfit.lookAddons = getField(L, arg, "lookAddons");
+
outfit.lookFeet = getField(L, arg, "lookFeet");
outfit.lookLegs = getField(L, arg, "lookLegs");
outfit.lookBody = getField(L, arg, "lookBody");
@@ -882,6 +884,7 @@ void LuaScriptInterface::pushOutfit(lua_State* L, const Outfit_t& outfit)
setField(L, "lookBody", outfit.lookBody);
setField(L, "lookLegs", outfit.lookLegs);
setField(L, "lookFeet", outfit.lookFeet);
+ setField(L, "lookAddons", outfit.lookAddons);
}
#define registerEnum(value) { std::string enumName = #value; registerGlobalVariable(enumName.substr(enumName.find_last_of(':') + 1), value); }
@@ -1607,6 +1610,7 @@ void LuaScriptInterface::registerFunctions()
registerEnumIn("configKeys", ConfigManager::ALLOW_CLONES)
registerEnumIn("configKeys", ConfigManager::BIND_ONLY_GLOBAL_ADDRESS)
registerEnumIn("configKeys", ConfigManager::OPTIMIZE_DATABASE)
+ registerEnumIn("configKeys", ConfigManager::STAMINA_SYSTEM)
registerEnumIn("configKeys", ConfigManager::WARN_UNSAFE_SCRIPTS)
registerEnumIn("configKeys", ConfigManager::CONVERT_UNSAFE_SCRIPTS)
registerEnumIn("configKeys", ConfigManager::TELEPORT_NEWBIES)
@@ -2008,6 +2012,9 @@ void LuaScriptInterface::registerFunctions()
registerMethod("Player", "getGroup", LuaScriptInterface::luaPlayerGetGroup);
registerMethod("Player", "setGroup", LuaScriptInterface::luaPlayerSetGroup);
+ registerMethod("Player", "getStamina", LuaScriptInterface::luaPlayerGetStamina);
+ registerMethod("Player", "setStamina", LuaScriptInterface::luaPlayerSetStamina);
+
registerMethod("Player", "getSoul", LuaScriptInterface::luaPlayerGetSoul);
registerMethod("Player", "addSoul", LuaScriptInterface::luaPlayerAddSoul);
registerMethod("Player", "getMaxSoul", LuaScriptInterface::luaPlayerGetMaxSoul);
@@ -7757,6 +7764,35 @@ int LuaScriptInterface::luaPlayerSetGroup(lua_State* L)
return 1;
}
+int LuaScriptInterface::luaPlayerGetStamina(lua_State* L)
+{
+ // player:getStamina()
+ Player* player = getUserdata(L, 1);
+ if (player) {
+ lua_pushnumber(L, player->getStaminaMinutes());
+ }
+ else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
+int LuaScriptInterface::luaPlayerSetStamina(lua_State* L)
+{
+ // player:setStamina(stamina)
+ uint16_t stamina = getNumber(L, 2);
+ Player* player = getUserdata(L, 1);
+ if (player) {
+ player->staminaMinutes = std::min(2520, stamina);
+ player->sendStats();
+ pushBoolean(L, true);
+ }
+ else {
+ lua_pushnil(L);
+ }
+ return 1;
+}
+
int LuaScriptInterface::luaPlayerGetSoul(lua_State* L)
{
// player:getSoul()
@@ -10616,11 +10652,12 @@ int LuaScriptInterface::luaConditionSetSpeedDelta(lua_State* L)
int LuaScriptInterface::luaConditionSetOutfit(lua_State* L)
{
// condition:setOutfit(outfit)
- // condition:setOutfit(lookTypeEx, lookType, lookHead, lookBody, lookLegs, lookFeet)
+ // condition:setOutfit(lookTypeEx, lookType, lookHead, lookBody, lookLegs, lookFeet[, lookAddons])
Outfit_t outfit;
if (isTable(L, 2)) {
outfit = getOutfit(L, 2);
} else {
+ outfit.lookAddons = getNumber(L, 8, outfit.lookAddons);
outfit.lookFeet = getNumber(L, 7);
outfit.lookLegs = getNumber(L, 6);
outfit.lookBody = getNumber(L, 5);
diff --git a/src/luascript.h b/src/luascript.h
index 8b90a48..90c2dd0 100644
--- a/src/luascript.h
+++ b/src/luascript.h
@@ -849,6 +849,9 @@ class LuaScriptInterface
static int luaPlayerGetGroup(lua_State* L);
static int luaPlayerSetGroup(lua_State* L);
+ static int luaPlayerGetStamina(lua_State* L);
+ static int luaPlayerSetStamina(lua_State* L);
+
static int luaPlayerGetSoul(lua_State* L);
static int luaPlayerAddSoul(lua_State* L);
static int luaPlayerGetMaxSoul(lua_State* L);
diff --git a/src/monsters.cpp b/src/monsters.cpp
index bf46bd1..9b5c467 100644
--- a/src/monsters.cpp
+++ b/src/monsters.cpp
@@ -759,6 +759,10 @@ bool Monsters::loadMonster(const std::string& file, const std::string& monsterNa
if ((attr = node.attribute("feet"))) {
mType->info.outfit.lookFeet = pugi::cast(attr.value());
}
+
+ if ((attr = node.attribute("addons"))) {
+ mType->info.outfit.lookAddons = pugi::cast(attr.value());
+ }
} else if ((attr = node.attribute("typeex"))) {
mType->info.outfit.lookTypeEx = pugi::cast(attr.value());
} else {
diff --git a/src/outputmessage.h b/src/outputmessage.h
index 92c690d..09f5435 100644
--- a/src/outputmessage.h
+++ b/src/outputmessage.h
@@ -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(bool addChecksum) {
+ 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;
+ }
- inline void append(const NetworkMessage& msg) {
- auto msgLen = msg.getLength();
- memcpy(buffer + info.position, msg.getBuffer() + 4, 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;
+ }
- 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;
- }
+protected:
+ template
+ 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);
+ }
- protected:
- template
- 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);
- }
-
- 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 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 bufferedProtocols;
};
diff --git a/src/protocolgame.cpp b/src/protocolgame.cpp
index f2536f0..3714984 100644
--- a/src/protocolgame.cpp
+++ b/src/protocolgame.cpp
@@ -242,8 +242,6 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg)
OperatingSystem_t operatingSystem = static_cast(msg.get());
version = msg.get();
- msg.skipBytes(7); // U32 client version, U8 client type, U16 dat revision
-
if (!Protocol::RSA_decrypt(msg)) {
disconnect();
return;
@@ -304,45 +302,24 @@ void ProtocolGame::onRecvFirstMessage(NetworkMessage& msg)
disconnectClient("Account number or password is not correct.");
return;
}
-
+
Account account;
if (!IOLoginData::loginserverAuthentication(accountNumber, password, account)) {
disconnectClient("Account number or password is not correct.");
return;
}
-
+
//Update premium days
Game::updatePremium(account);
g_dispatcher.addTask(createTask(std::bind(&ProtocolGame::login, getThis(), characterName, accountId, operatingSystem)));
+
}
void ProtocolGame::onConnect()
{
- auto output = OutputMessagePool::getOutputMessage();
- static std::random_device rd;
- static std::ranlux24 generator(rd());
- static std::uniform_int_distribution randNumber(0x00, 0xFF);
- // Skip checksum
- output->skipBytes(sizeof(uint32_t));
- // Packet length & type
- output->add(0x0006);
- output->addByte(0x1F);
-
- // Add timestamp & random number
- challengeTimestamp = static_cast(time(nullptr));
- output->add(challengeTimestamp);
-
- challengeRandom = randNumber(generator);
- output->addByte(challengeRandom);
-
- // Go back and write checksum
- output->skipBytes(-12);
- output->add(adlerChecksum(output->getOutputBuffer() + sizeof(uint32_t), 8));
-
- send(output);
}
void ProtocolGame::disconnectClient(const std::string& message) const
@@ -464,12 +441,15 @@ void ProtocolGame::parsePacket(NetworkMessage& msg)
void ProtocolGame::GetTileDescription(const Tile* tile, NetworkMessage& msg)
{
+ msg.add(0x00); //environmental effects
+
int32_t count;
Item* ground = tile->getGround();
if (ground) {
msg.addItem(ground);
count = 1;
- } else {
+ }
+ else {
count = 0;
}
@@ -478,7 +458,11 @@ void ProtocolGame::GetTileDescription(const Tile* tile, NetworkMessage& msg)
for (auto it = items->getBeginTopItem(), end = items->getEndTopItem(); it != end; ++it) {
msg.addItem(*it);
- if (++count == 10) {
+ count++;
+ if (count == 9 && tile->getPosition() == player->getPosition()) {
+ break;
+ }
+ else if (count == 10) {
return;
}
}
@@ -486,11 +470,20 @@ void ProtocolGame::GetTileDescription(const Tile* tile, NetworkMessage& msg)
const CreatureVector* creatures = tile->getCreatures();
if (creatures) {
+ bool playerAdded = false;
for (const Creature* creature : boost::adaptors::reverse(*creatures)) {
if (!player->canSeeCreature(creature)) {
continue;
}
+ if (tile->getPosition() == player->getPosition() && count == 9 && !playerAdded) {
+ creature = player;
+ }
+
+ if (creature->getID() == player->getID()) {
+ playerAdded = true;
+ }
+
bool known;
uint32_t removedKnown;
checkCreatureAsKnown(creature->getID(), known, removedKnown);
@@ -1864,12 +1857,18 @@ void ProtocolGame::AddPlayerStats(NetworkMessage& msg)
msg.add(std::min(player->getMaxMana(), std::numeric_limits::max()));
msg.addByte(std::min(player->getMagicLevel(), std::numeric_limits::max()));
+ msg.addByte(std::min(player->getBaseMagicLevel(), std::numeric_limits::max()));
msg.addByte(player->getMagicLevelPercent());
msg.addByte(player->getSoul());
msg.add(player->getStaminaMinutes());
+ msg.add(player->getBaseSpeed() / 2);
+
+ Condition* condition = player->getCondition(CONDITION_REGENERATION);
+ msg.add(condition ? condition->getTicks() / 1000 : 0x00);
+
msg.add(0); // xp boost time (seconds)
}
diff --git a/src/protocollogin.cpp b/src/protocollogin.cpp
index fad7a98..f32c17e 100644
--- a/src/protocollogin.cpp
+++ b/src/protocollogin.cpp
@@ -43,7 +43,7 @@ void ProtocolLogin::disconnectClient(const std::string& message, uint16_t versio
disconnect();
}
-void ProtocolLogin::getCharacterList(uint32_t accountNumber, const std::string& password, const std::string& token, uint16_t version)
+void ProtocolLogin::getCharacterList(uint32_t accountNumber, const std::string& password, uint16_t version)
{
Account account;
if (!IOLoginData::loginserverAuthentication(accountNumber, password, account)) {
@@ -51,20 +51,7 @@ void ProtocolLogin::getCharacterList(uint32_t accountNumber, const std::string&
return;
}
- uint32_t ticks = time(nullptr) / AUTHENTICATOR_PERIOD;
-
auto output = OutputMessagePool::getOutputMessage();
- if (!std::to_string(accountNumber).empty()) {
- if (token.empty() || !(token == generateToken(std::to_string(accountNumber), ticks) || token == generateToken(std::to_string(accountNumber), ticks - 1) || token == generateToken(std::to_string(accountNumber), ticks + 1))) {
- output->addByte(0x0D);
- output->addByte(0);
- send(output);
- disconnect();
- return;
- }
- output->addByte(0x0C);
- output->addByte(0);
- }
//Update premium days
Game::updatePremium(account);
@@ -79,38 +66,24 @@ void ProtocolLogin::getCharacterList(uint32_t accountNumber, const std::string&
output->addString(ss.str());
}
- //Add session key
- output->addByte(0x28);
- output->addString(std::to_string(accountNumber) + "\n" + password + "\n" + token + "\n" + std::to_string(ticks));
-
-
//Add char list
output->addByte(0x64);
- output->addByte(1); // number of worlds
-
- output->addByte(0); // world id
- output->addString(g_config.getString(ConfigManager::SERVER_NAME));
- output->addString(g_config.getString(ConfigManager::IP));
- output->add(g_config.getNumber(ConfigManager::GAME_PORT));
- output->addByte(0);
-
uint8_t size = std::min(std::numeric_limits::max(), account.characters.size());
output->addByte(size);
for (uint8_t i = 0; i < size; i++) {
- output->addByte(0);
output->addString(account.characters[i]);
+ output->addString(g_config.getString(ConfigManager::SERVER_NAME));
+ output->add(inet_addr(g_config.getString(ConfigManager::IP).c_str()));
+ output->add(g_config.getNumber(ConfigManager::GAME_PORT));
}
//Add premium days
- output->addByte(0);
if (g_config.getBoolean(ConfigManager::FREE_PREMIUM)) {
- output->addByte(1);
- output->add(0);
+ output->add(0xFFFF);
}
else {
- output->addByte(account.premiumDays > 0 ? 1 : 0);
- output->add(time(nullptr) + (account.premiumDays * 86400));
+ output->add(account.premiumDays);
}
send(output);
@@ -118,6 +91,7 @@ void ProtocolLogin::getCharacterList(uint32_t accountNumber, const std::string&
disconnect();
}
+
void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
{
if (g_game.getGameState() == GAME_STATE_SHUTDOWN) {
@@ -208,15 +182,6 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
return;
}
- // read authenticator token and stay logged in flag from last 128 bytes
- msg.skipBytes((msg.getLength() - 128) - msg.getBufferPosition());
- if (!Protocol::RSA_decrypt(msg)) {
- disconnectClient("Invalid authentification token.", version);
- return;
- }
-
- std::string authToken = msg.getString();
-
auto thisPtr = std::static_pointer_cast(shared_from_this());
- g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountNumber, password, authToken, version)));
+ g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountNumber, password, version)));
}
diff --git a/src/protocollogin.h b/src/protocollogin.h
index 4651b50..3b75851 100644
--- a/src/protocollogin.h
+++ b/src/protocollogin.h
@@ -43,7 +43,7 @@ class ProtocolLogin : public Protocol
private:
void disconnectClient(const std::string& message, uint16_t version);
- void getCharacterList(uint32_t accountNumber, const std::string& password, const std::string& token, uint16_t version);
+ void getCharacterList(uint32_t accountNumber, const std::string& password, uint16_t version);
};
#endif
diff --git a/src/server.cpp b/src/server.cpp
index 1b09123..d681456 100644
--- a/src/server.cpp
+++ b/src/server.cpp
@@ -56,7 +56,8 @@ void ServiceManager::stop()
for (auto& servicePortIt : acceptors) {
try {
io_service.post(std::bind(&ServicePort::onStopServer, servicePortIt.second));
- } catch (boost::system::system_error& e) {
+ }
+ catch (boost::system::system_error& e) {
std::cout << "[ServiceManager::stop] Network Error: " << e.what() << std::endl;
}
}
@@ -114,25 +115,28 @@ void ServicePort::onAccept(Connection_ptr connection, const boost::system::error
Service_ptr service = services.front();
if (service->is_single_socket()) {
connection->accept(service->make_protocol(connection));
- } else {
+ }
+ else {
connection->accept();
}
- } else {
+ }
+ else {
connection->close(Connection::FORCE_CLOSE);
}
accept();
- } else if (error != boost::asio::error::operation_aborted) {
+ }
+ else if (error != boost::asio::error::operation_aborted) {
if (!pendingStart) {
close();
pendingStart = true;
g_scheduler.addEvent(createSchedulerTask(15000,
- std::bind(&ServicePort::openAcceptor, std::weak_ptr(shared_from_this()), serverPort)));
+ std::bind(&ServicePort::openAcceptor, std::weak_ptr(shared_from_this()), serverPort)));
}
}
}
-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) {
@@ -140,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;
}
@@ -169,21 +171,23 @@ void ServicePort::open(uint16_t port)
try {
if (g_config.getBoolean(ConfigManager::BIND_ONLY_GLOBAL_ADDRESS)) {
acceptor.reset(new boost::asio::ip::tcp::acceptor(io_service, boost::asio::ip::tcp::endpoint(
- boost::asio::ip::address(boost::asio::ip::address_v4::from_string(g_config.getString(ConfigManager::IP))), serverPort)));
- } else {
+ boost::asio::ip::address(boost::asio::ip::address_v4::from_string(g_config.getString(ConfigManager::IP))), serverPort)));
+ }
+ else {
acceptor.reset(new boost::asio::ip::tcp::acceptor(io_service, boost::asio::ip::tcp::endpoint(
- boost::asio::ip::address(boost::asio::ip::address_v4(INADDR_ANY)), serverPort)));
+ boost::asio::ip::address(boost::asio::ip::address_v4(INADDR_ANY)), serverPort)));
}
acceptor->set_option(boost::asio::ip::tcp::no_delay(true));
accept();
- } catch (boost::system::system_error& e) {
+ }
+ catch (boost::system::system_error& e) {
std::cout << "[ServicePort::open] Error: " << e.what() << std::endl;
pendingStart = true;
g_scheduler.addEvent(createSchedulerTask(15000,
- std::bind(&ServicePort::openAcceptor, std::weak_ptr(shared_from_this()), port)));
+ std::bind(&ServicePort::openAcceptor, std::weak_ptr(shared_from_this()), port)));
}
}
@@ -197,7 +201,7 @@ void ServicePort::close()
bool ServicePort::add_service(const Service_ptr& new_svc)
{
- if (std::any_of(services.begin(), services.end(), [](const Service_ptr& svc) {return svc->is_single_socket();})) {
+ if (std::any_of(services.begin(), services.end(), [](const Service_ptr& svc) {return svc->is_single_socket(); })) {
return false;
}
diff --git a/src/server.h b/src/server.h
index 02e5278..e1d9aa2 100644
--- a/src/server.h
+++ b/src/server.h
@@ -27,98 +27,94 @@ class Protocol;
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;
+public:
+ virtual bool is_single_socket() const = 0;
+ virtual uint8_t get_protocol_identifier() const = 0;
+ virtual const char* get_protocol_name() const = 0;
- virtual Protocol_ptr make_protocol(const Connection_ptr& c) const = 0;
+ virtual Protocol_ptr make_protocol(const Connection_ptr& c) const = 0;
};
template
class Service final : public ServiceBase
{
- public:
- bool is_single_socket() const override {
- return ProtocolType::server_sends_first;
- }
- bool is_checksummed() const override {
- return ProtocolType::use_checksum;
- }
- uint8_t get_protocol_identifier() const override {
- return ProtocolType::protocol_identifier;
- }
- const char* get_protocol_name() const override {
- return ProtocolType::protocol_name();
- }
+public:
+ bool is_single_socket() const final {
+ return ProtocolType::server_sends_first;
+ }
+ uint8_t get_protocol_identifier() const final {
+ return ProtocolType::protocol_identifier;
+ }
+ const char* get_protocol_name() const final {
+ return ProtocolType::protocol_name();
+ }
- Protocol_ptr make_protocol(const Connection_ptr& c) const override {
- return std::make_shared(c);
- }
+ Protocol_ptr make_protocol(const Connection_ptr& c) const final {
+ return std::make_shared(c);
+ }
};
class ServicePort : public std::enable_shared_from_this
{
- public:
- explicit ServicePort(boost::asio::io_service& io_service) : io_service(io_service) {}
- ~ServicePort();
+public:
+ explicit ServicePort(boost::asio::io_service& io_service) : io_service(io_service) {}
+ ~ServicePort();
- // non-copyable
- ServicePort(const ServicePort&) = delete;
- ServicePort& operator=(const ServicePort&) = delete;
+ // non-copyable
+ ServicePort(const ServicePort&) = delete;
+ ServicePort& operator=(const ServicePort&) = delete;
- static void openAcceptor(std::weak_ptr weak_service, uint16_t port);
- void open(uint16_t port);
- void close();
- bool is_single_socket() const;
- std::string get_protocol_names() const;
+ static void openAcceptor(std::weak_ptr weak_service, uint16_t port);
+ void open(uint16_t port);
+ void close();
+ bool is_single_socket() const;
+ 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;
+ bool add_service(const Service_ptr& new_svc);
+ Protocol_ptr make_protocol(NetworkMessage& msg, const Connection_ptr& connection) const;
- void onStopServer();
- void onAccept(Connection_ptr connection, const boost::system::error_code& error);
+ void onStopServer();
+ void onAccept(Connection_ptr connection, const boost::system::error_code& error);
- protected:
- void accept();
+protected:
+ void accept();
- boost::asio::io_service& io_service;
- std::unique_ptr acceptor;
- std::vector services;
+ boost::asio::io_service& io_service;
+ std::unique_ptr acceptor;
+ std::vector services;
- uint16_t serverPort = 0;
- bool pendingStart = false;
+ uint16_t serverPort = 0;
+ bool pendingStart = false;
};
class ServiceManager
{
- public:
- ServiceManager() = default;
- ~ServiceManager();
+public:
+ ServiceManager() = default;
+ ~ServiceManager();
- // non-copyable
- ServiceManager(const ServiceManager&) = delete;
- ServiceManager& operator=(const ServiceManager&) = delete;
+ // non-copyable
+ ServiceManager(const ServiceManager&) = delete;
+ ServiceManager& operator=(const ServiceManager&) = delete;
- void run();
- void stop();
+ void run();
+ void stop();
- template
- bool add(uint16_t port);
+ template
+ bool add(uint16_t port);
- bool is_running() const {
- return acceptors.empty() == false;
- }
+ bool is_running() const {
+ return acceptors.empty() == false;
+ }
- protected:
- void die();
+protected:
+ void die();
- std::unordered_map acceptors;
+ std::unordered_map acceptors;
- boost::asio::io_service io_service;
- boost::asio::deadline_timer death_timer { io_service };
- bool running = false;
+ boost::asio::io_service io_service;
+ boost::asio::deadline_timer death_timer{ io_service };
+ bool running = false;
};
template
@@ -137,13 +133,14 @@ bool ServiceManager::add(uint16_t port)
service_port = std::make_shared(io_service);
service_port->open(port);
acceptors[port] = service_port;
- } else {
+ }
+ else {
service_port = foundServicePort->second;
if (service_port->is_single_socket() || ProtocolType::server_sends_first) {
std::cout << "ERROR: " << ProtocolType::protocol_name() <<
- " and " << service_port->get_protocol_names() <<
- " cannot use the same port " << port << '.' << std::endl;
+ " and " << service_port->get_protocol_names() <<
+ " cannot use the same port " << port << '.' << std::endl;
return false;
}
}