mirror of
https://github.com/ErikasKontenis/SabrehavenServer.git
synced 2025-05-02 10:39:20 +02:00
introduce multiple client version support in config.lua and NPCs
This commit is contained in:
parent
ff7636b945
commit
0cd1af211e
@ -37,6 +37,7 @@ replaceKickOnLogin = true
|
||||
maxPacketsPerSecond = -1
|
||||
autoStackCumulatives = false
|
||||
moneyRate = 1
|
||||
clientVersion = 780
|
||||
|
||||
-- Deaths
|
||||
-- NOTE: Leave deathLosePercent as -1 if you want to use the default
|
||||
|
@ -123,6 +123,7 @@ bool ConfigManager::load()
|
||||
integer[NEWBIE_TOWN] = getGlobalNumber(L, "newbieTownId", 1);
|
||||
integer[NEWBIE_LEVEL_THRESHOLD] = getGlobalNumber(L, "newbieLevelThreshold", 5);
|
||||
integer[MONEY_RATE] = getGlobalNumber(L, "moneyRate", 1);
|
||||
integer[CLIENT_VERSION] = getGlobalNumber(L, "clientVersion");
|
||||
|
||||
loaded = true;
|
||||
lua_close(L);
|
||||
|
@ -111,6 +111,7 @@ class ConfigManager
|
||||
NEWBIE_TOWN,
|
||||
NEWBIE_LEVEL_THRESHOLD,
|
||||
MONEY_RATE,
|
||||
CLIENT_VERSION,
|
||||
|
||||
LAST_INTEGER_CONFIG /* this must be the last one */
|
||||
};
|
||||
|
@ -351,6 +351,13 @@ enum ReloadTypes_t : uint8_t {
|
||||
RELOAD_TYPE_WEAPONS,
|
||||
};
|
||||
|
||||
enum ClientVersion_t : uint16_t {
|
||||
CLIENT_VERSION_780 = 780,
|
||||
CLIENT_VERSION_781 = 781,
|
||||
CLIENT_VERSION_790 = 790,
|
||||
CLIENT_VERSION_792 = 792,
|
||||
};
|
||||
|
||||
static constexpr int32_t CHANNEL_GUILD = 0x00;
|
||||
static constexpr int32_t CHANNEL_PARTY = 0x01;
|
||||
static constexpr int32_t CHANNEL_RULE_REP = 0x02;
|
||||
|
@ -24,10 +24,6 @@ static constexpr auto STATUS_SERVER_NAME = "Sabrehaven";
|
||||
static constexpr auto STATUS_SERVER_VERSION = "1.0";
|
||||
static constexpr auto STATUS_SERVER_DEVELOPERS = "OTLand community & Sabrehaven Developers Team";
|
||||
|
||||
static constexpr auto CLIENT_VERSION_MIN = 780;
|
||||
static constexpr auto CLIENT_VERSION_MAX = 781;
|
||||
static constexpr auto CLIENT_VERSION_STR = "7.81";
|
||||
|
||||
static constexpr auto AUTHENTICATOR_DIGITS = 6U;
|
||||
static constexpr auto AUTHENTICATOR_PERIOD = 30U;
|
||||
|
||||
|
@ -76,6 +76,11 @@ void Game::setWorldType(WorldType_t type)
|
||||
worldType = type;
|
||||
}
|
||||
|
||||
void Game::setClientVersion(ClientVersion_t version)
|
||||
{
|
||||
clientVersion = version;
|
||||
}
|
||||
|
||||
void Game::setGameState(GameState_t newState)
|
||||
{
|
||||
if (gameState == GAME_STATE_SHUTDOWN) {
|
||||
|
@ -127,6 +127,11 @@ class Game
|
||||
return worldType;
|
||||
}
|
||||
|
||||
void setClientVersion(ClientVersion_t version);
|
||||
ClientVersion_t getClientVersion() const {
|
||||
return clientVersion;
|
||||
}
|
||||
|
||||
Cylinder* internalGetCylinder(Player* player, const Position& pos) const;
|
||||
Thing* internalGetThing(Player* player, const Position& pos, int32_t index,
|
||||
uint32_t spriteId, stackPosType_t type) const;
|
||||
@ -533,6 +538,7 @@ class Game
|
||||
|
||||
GameState_t gameState = GAME_STATE_NORMAL;
|
||||
WorldType_t worldType = WORLD_TYPE_PVP;
|
||||
ClientVersion_t clientVersion;
|
||||
|
||||
LightState_t lightState = LIGHT_STATE_DAY;
|
||||
uint8_t lightLevel = LIGHT_LEVEL_DAY;
|
||||
|
@ -1676,6 +1676,7 @@ void LuaScriptInterface::registerFunctions()
|
||||
registerEnumIn("configKeys", ConfigManager::NEWBIE_LEVEL_THRESHOLD)
|
||||
registerEnumIn("configKeys", ConfigManager::BLOCK_HEIGHT)
|
||||
registerEnumIn("configKeys", ConfigManager::DROP_ITEMS)
|
||||
registerEnumIn("configKeys", ConfigManager::CLIENT_VERSION)
|
||||
|
||||
// os
|
||||
registerMethod("os", "mtime", LuaScriptInterface::luaSystemTime);
|
||||
|
@ -51,7 +51,9 @@ void Npcs::loadNpcs()
|
||||
return;
|
||||
}
|
||||
|
||||
g_game.placeCreature(npc, npc->getMasterPos(), false, true);
|
||||
if (npc->getClientVersion() <= g_game.getClientVersion()) {
|
||||
g_game.placeCreature(npc, npc->getMasterPos(), false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,6 +154,8 @@ bool Npc::load()
|
||||
script.readCoordinate(masterPos.x, masterPos.y, masterPos.z);
|
||||
} else if (ident == "radius") {
|
||||
masterRadius = script.readNumber();
|
||||
} else if (ident == "clientversion") {
|
||||
clientVersion = script.readNumber();
|
||||
} else if (ident == "behaviour") {
|
||||
if (behaviourDatabase) {
|
||||
script.error("behaviour database already defined");
|
||||
|
@ -85,6 +85,9 @@ class Npc final : public Creature
|
||||
int32_t getMasterRadius() const {
|
||||
return masterRadius;
|
||||
}
|
||||
int32_t getClientVersion() const {
|
||||
return clientVersion;
|
||||
}
|
||||
const Position& getMasterPos() const {
|
||||
return masterPos;
|
||||
}
|
||||
@ -141,6 +144,7 @@ class Npc final : public Creature
|
||||
uint32_t lastTalkCreature;
|
||||
uint32_t focusCreature;
|
||||
uint32_t masterRadius;
|
||||
uint16_t clientVersion = 0;
|
||||
|
||||
int64_t conversationStartTime;
|
||||
int64_t conversationEndTime;
|
||||
|
@ -245,6 +245,27 @@ void mainLoader(int, char*[], ServiceManager* services)
|
||||
}
|
||||
std::cout << asUpperCaseString(worldType) << std::endl;
|
||||
|
||||
std::cout << ">> Checking client version... " << std::flush;
|
||||
int32_t clientVersion = g_config.getNumber(ConfigManager::CLIENT_VERSION);
|
||||
if (clientVersion == 780) {
|
||||
g_game.setClientVersion(CLIENT_VERSION_780);
|
||||
} else if (clientVersion == 781) {
|
||||
g_game.setClientVersion(CLIENT_VERSION_781);
|
||||
} else if (clientVersion == 790) {
|
||||
g_game.setClientVersion(CLIENT_VERSION_790);
|
||||
} else if (clientVersion == 792) {
|
||||
g_game.setClientVersion(CLIENT_VERSION_792);
|
||||
}
|
||||
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.";
|
||||
startupErrorMessage(ss.str());
|
||||
return;
|
||||
}
|
||||
std::cout << clientVersion << std::endl;
|
||||
|
||||
std::cout << ">> Loading map" << std::endl;
|
||||
if (!g_game.loadMainMap(g_config.getString(ConfigManager::MAP_NAME))) {
|
||||
startupErrorMessage("Failed to load map");
|
||||
|
@ -1775,6 +1775,7 @@ void ProtocolGame::sendOutfitWindow()
|
||||
Outfit_t currentOutfit = player->getDefaultOutfit();
|
||||
AddOutfit(msg, currentOutfit);
|
||||
|
||||
const ClientVersion_t clientVersion = g_game.getClientVersion();
|
||||
std::vector<ProtocolOutfit> protocolOutfits;
|
||||
if (player->isAccessPlayer()) {
|
||||
static const std::string gamemasterOutfitName = "Gamemaster";
|
||||
@ -1790,14 +1791,19 @@ void ProtocolGame::sendOutfitWindow()
|
||||
}
|
||||
|
||||
protocolOutfits.emplace_back(outfit.name, outfit.lookType, addons);
|
||||
if (protocolOutfits.size() == 15) { // Game client doesn't allow more than 15 outfits
|
||||
break;
|
||||
if (CLIENT_VERSION_780 <= clientVersion && clientVersion <= CLIENT_VERSION_792) {
|
||||
if (protocolOutfits.size() == 15) { // Game client doesn't allow more than 15 outfits in 780-792
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
msg.addByte(protocolOutfits.size());
|
||||
for (const ProtocolOutfit& outfit : protocolOutfits) {
|
||||
msg.add<uint16_t>(outfit.lookType);
|
||||
if (clientVersion > CLIENT_VERSION_781) {
|
||||
msg.addString(outfit.name);
|
||||
}
|
||||
msg.addByte(outfit.addons);
|
||||
}
|
||||
|
||||
|
@ -262,7 +262,7 @@ class ProtocolGame final : public Protocol
|
||||
|
||||
uint32_t eventConnect = 0;
|
||||
uint32_t challengeTimestamp = 0;
|
||||
uint16_t version = CLIENT_VERSION_MIN;
|
||||
uint16_t version;
|
||||
|
||||
uint8_t challengeRandom = 0;
|
||||
|
||||
|
@ -118,7 +118,7 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
|
||||
|
||||
if (version <= 760) {
|
||||
std::ostringstream ss;
|
||||
ss << "Only clients with protocol " << CLIENT_VERSION_STR << " allowed!";
|
||||
ss << "Only clients with protocol " << getClientVersionString(g_game.getClientVersion()) << " allowed!";
|
||||
disconnectClient(ss.str(), version);
|
||||
return;
|
||||
}
|
||||
@ -136,9 +136,9 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
|
||||
enableXTEAEncryption();
|
||||
setXTEAKey(key);
|
||||
|
||||
if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) {
|
||||
if (!isProtocolAllowed(version)) {
|
||||
std::ostringstream ss;
|
||||
ss << "Only clients with protocol " << CLIENT_VERSION_STR << " allowed!";
|
||||
ss << "Only clients with protocol " << getClientVersionString(g_game.getClientVersion()) << " allowed!";
|
||||
disconnectClient(ss.str(), version);
|
||||
return;
|
||||
}
|
||||
@ -185,3 +185,19 @@ void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
|
||||
auto thisPtr = std::static_pointer_cast<ProtocolLogin>(shared_from_this());
|
||||
g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, thisPtr, accountNumber, password, version)));
|
||||
}
|
||||
|
||||
|
||||
bool ProtocolLogin::isProtocolAllowed(uint16_t version)
|
||||
{
|
||||
ClientVersion_t allowedClientVersion = g_game.getClientVersion();
|
||||
|
||||
if (allowedClientVersion == version)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (version == 781 && allowedClientVersion == CLIENT_VERSION_780) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -21,6 +21,7 @@
|
||||
#define FS_PROTOCOLLOGIN_H_1238F4B473074DF2ABC595C29E81C46D
|
||||
|
||||
#include "protocol.h"
|
||||
#include "tools.h"
|
||||
|
||||
class NetworkMessage;
|
||||
class OutputMessage;
|
||||
@ -38,6 +39,7 @@ class ProtocolLogin : public Protocol
|
||||
explicit ProtocolLogin(Connection_ptr connection) : Protocol(connection) {}
|
||||
|
||||
void onRecvFirstMessage(NetworkMessage& msg) override;
|
||||
bool isProtocolAllowed(uint16_t version);
|
||||
|
||||
private:
|
||||
void disconnectClient(const std::string& message, uint16_t version);
|
||||
|
@ -110,7 +110,7 @@ void ProtocolStatus::sendStatusString()
|
||||
serverinfo.append_attribute("url") = g_config.getString(ConfigManager::URL).c_str();
|
||||
serverinfo.append_attribute("server") = STATUS_SERVER_NAME;
|
||||
serverinfo.append_attribute("version") = STATUS_SERVER_VERSION;
|
||||
serverinfo.append_attribute("client") = CLIENT_VERSION_STR;
|
||||
serverinfo.append_attribute("client") = getClientVersionString(g_game.getClientVersion()).c_str();
|
||||
|
||||
pugi::xml_node owner = tsqp.append_child("owner");
|
||||
owner.append_attribute("name") = g_config.getString(ConfigManager::OWNER_NAME).c_str();
|
||||
@ -240,7 +240,7 @@ void ProtocolStatus::sendInfo(uint16_t requestedInfo, const std::string& charact
|
||||
output->addByte(0x23); // server software info
|
||||
output->addString(STATUS_SERVER_NAME);
|
||||
output->addString(STATUS_SERVER_VERSION);
|
||||
output->addString(CLIENT_VERSION_STR);
|
||||
output->addString(getClientVersionString(g_game.getClientVersion()));
|
||||
}
|
||||
send(output);
|
||||
disconnect();
|
||||
|
@ -1230,3 +1230,33 @@ void getFilesInDirectory(const boost::filesystem::path& root, const std::string&
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string getClientVersionString(uint32_t version)
|
||||
{
|
||||
return getClientVersionString(static_cast<ClientVersion_t>(version));
|
||||
}
|
||||
|
||||
std::string getClientVersionString(ClientVersion_t version)
|
||||
{
|
||||
std::string result;
|
||||
switch (version)
|
||||
{
|
||||
case CLIENT_VERSION_780:
|
||||
result = "7.80";
|
||||
break;
|
||||
case CLIENT_VERSION_781:
|
||||
result = "7.81";
|
||||
break;
|
||||
case CLIENT_VERSION_790:
|
||||
result = "7.90";
|
||||
break;
|
||||
case CLIENT_VERSION_792:
|
||||
result = "7.92";
|
||||
break;
|
||||
default:
|
||||
result = "Unknown";
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -100,6 +100,9 @@ const char* getReturnMessage(ReturnValue value);
|
||||
|
||||
void getFilesInDirectory(const boost::filesystem::path& root, const std::string& ext, std::vector<boost::filesystem::path>& ret);
|
||||
|
||||
std::string getClientVersionString(uint32_t version);
|
||||
std::string getClientVersionString(ClientVersion_t version);
|
||||
|
||||
inline int64_t OTSYS_TIME()
|
||||
{
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
Loading…
x
Reference in New Issue
Block a user