Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: compatibility with 13.16 #538

Merged
merged 1 commit into from
May 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion data/setup.otml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
game
sprite-size: 32
last-supported-version: 1291
last-supported-version: 1316

map
viewport: 8 6
Expand Down
14 changes: 7 additions & 7 deletions modules/client_entergame/entergame.lua
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,9 @@ end
function EnterGame.init()
enterGame = g_ui.displayUI('entergame')
enterGameButton = modules.client_topmenu.addLeftButton('enterGameButton', tr('Login') .. ' (Ctrl + G)',
'/images/topbuttons/login', EnterGame.openWindow)
'/images/topbuttons/login', EnterGame.openWindow)
motdButton = modules.client_topmenu.addLeftButton('motdButton', tr('Message of the day'), '/images/topbuttons/motd',
EnterGame.displayMotd)
EnterGame.displayMotd)
motdButton:hide()
g_keyboard.bindKeyDown('Ctrl+G', EnterGame.openWindow)

Expand Down Expand Up @@ -338,7 +338,7 @@ function EnterGame.tryHttpLogin(clientVersion)
local onRecv = function(message, err)
if err then
onError(nil, 'Bad Request.', 400)
return
return
end

local _, bodyStart = message:find('{')
Expand Down Expand Up @@ -390,13 +390,13 @@ function EnterGame.tryHttpLogin(clientVersion)
onCharacterList(nil, characters, account)
end

HTTP.post(G.host .. "/login.php",
HTTP.post(G.host .. "/login.php",
json.encode({
email = G.account,
password = G.password,
type = 'login'
}),
onRecv
onRecv, false
)

loadBox = displayCancelBox(tr('Please wait'), tr('Connecting to login server...'))
Expand All @@ -409,7 +409,7 @@ function EnterGame.tryHttpLogin(clientVersion)

g_game.setClientVersion(clientVersion)
g_game.setProtocolVersion(g_game.getClientProtocolVersion(clientVersion))
g_game.chooseRsa(G.host)
g_game.chooseRsa(G.host)
if modules.game_things.isLoaded() then
else
loadBox:destroy()
Expand Down Expand Up @@ -560,4 +560,4 @@ end
function EnterGame.disableMotd()
motdEnabled = false
motdButton:hide()
end
end
18 changes: 14 additions & 4 deletions modules/corelib/http.lua
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function HTTP.getJSON(url, callback)
return operation
end

function HTTP.post(url, data, callback)
function HTTP.post(url, data, callback, checkContentLength)
if not g_http or not g_http.post then
return error("HTTP.post is not supported")
end
Expand All @@ -35,7 +35,12 @@ function HTTP.post(url, data, callback)
data = json.encode(data)
is_json = true
end
local operation = g_http.post(url, data, HTTP.timeout, is_json)

if checkContentLength == nil then
checkContentLength = true
end

local operation = g_http.post(url, data, HTTP.timeout, is_json, checkContentLength)
HTTP.operations[operation] = { type = "post", url = url, callback = callback }
return operation
end
Expand All @@ -57,8 +62,13 @@ function HTTP.download(url, file, callback, progressCallback)
return error("HTTP.download is not supported")
end
local operation = g_http.download(url, file, HTTP.timeout)
HTTP.operations[operation] = { type = "download", url = url, file = file, callback = callback,
progressCallback = progressCallback }
HTTP.operations[operation] = {
type = "download",
url = url,
file = file,
callback = callback,
progressCallback = progressCallback
}
return operation
end

Expand Down
1 change: 1 addition & 0 deletions modules/game_features/features.lua
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ controller:registerEvents(g_game, {

if version >= 1290 then
g_game.enableFeature(GameSequencedPackets);
g_game.enableFeature(GameBosstiary);
g_game.enableFeature(GameThingClock);
g_game.enableFeature(GameThingCounter);
g_game.enableFeature(GameThingPodiumItemType);
Expand Down
1 change: 1 addition & 0 deletions modules/gamelib/const.lua
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ GameDynamicForgeVariables = 93
GameConcotions = 94
GameAnthem = 95
GameVipGroups = 96
GameBosstiary = 97
GameLoadSprInsteadProtobuf = 100
GameItemShader = 101
GameCreatureShader = 102
Expand Down
14 changes: 7 additions & 7 deletions modules/gamelib/game.lua
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ function g_game.isOfficialTibia()
end

function g_game.getSupportedClients()
return {740, 741, 750, 755, 760, 770, 772, 780, 781, 782, 790, 792, 800, 810, 811, 820, 821, 822, 830, 831, 840,
842, 850, 853, 854, 855, 857, 860, 861, 862, 870, 871, 900, 910, 920, 931, 940, 943, 944, 951, 952, 953,
954, 960, 961, 963, 970, 971, 972, 973, 980, 981, 982, 983, 984, 985, 986, 1000, 1001, 1002, 1010, 1011,
1012, 1013, 1020, 1021, 1022, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1050,
1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1070, 1071, 1072, 1073,
1074, 1075, 1076, 1080, 1081, 1082, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1281, 1285,
1286, 1287, 1291, 1300, 1314}
return { 740, 741, 750, 755, 760, 770, 772, 780, 781, 782, 790, 792, 800, 810, 811, 820, 821, 822, 830, 831, 840,
842, 850, 853, 854, 855, 857, 860, 861, 862, 870, 871, 900, 910, 920, 931, 940, 943, 944, 951, 952, 953,
954, 960, 961, 963, 970, 971, 972, 973, 980, 981, 982, 983, 984, 985, 986, 1000, 1001, 1002, 1010, 1011,
1012, 1013, 1020, 1021, 1022, 1030, 1031, 1032, 1033, 1034, 1035, 1036, 1037, 1038, 1039, 1040, 1041, 1050,
1051, 1052, 1053, 1054, 1055, 1056, 1057, 1058, 1059, 1060, 1061, 1062, 1063, 1064, 1070, 1071, 1072, 1073,
1074, 1075, 1076, 1080, 1081, 1082, 1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099, 1281, 1285,
1286, 1287, 1291, 1300, 1314, 1316 }
end

-- The client version and protocol version where
Expand Down
1 change: 1 addition & 0 deletions src/client/const.h
Original file line number Diff line number Diff line change
Expand Up @@ -524,6 +524,7 @@ namespace Otc
GameConcotions = 94,
GameAnthem = 95,
GameVipGroups = 96,
GameBosstiary = 97,

// others
GameLoadSprInsteadProtobuf = 100,
Expand Down
4 changes: 4 additions & 0 deletions src/client/protocolcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,8 @@ namespace Proto

// original tibia ONLY
GameServerPassiveCooldown = 94,
GameServerBosstiaryData = 97,
GameServerBosstiarySlots = 98,
GameServerSendClientCheck = 99,
GameServerFullMap = 100,
GameServerMapTopRow = 101,
Expand Down Expand Up @@ -155,6 +157,7 @@ namespace Proto
GameServerRefreshBestiaryTracker = 185,
GameServerTaskHuntingBasicData = 186,
GameServerTaskHuntingData = 187,
GameServerBosstiaryCooldownTimer = 189,
GameServerFloorChangeUp = 190,
GameServerFloorChangeDown = 191,
GameServerLootContainers = 192,
Expand All @@ -178,6 +181,7 @@ namespace Proto
GameServerSendDailyReward = 228,
GameServerSendRewardHistory = 229,
GameServerSendPreyFreeRerolls = 230,
GameServerSendBosstiaryEntryChanged = 230,
GameServerSendPreyTimeLeft = 231,
GameServerSendPreyData = 232,
GameServerSendPreyRerollPrice = 233,
Expand Down
6 changes: 6 additions & 0 deletions src/client/protocolgame.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,12 @@ class ProtocolGame : public Protocol
void parseMarketDetail(const InputMessagePtr& msg);
void parseMarketBrowse(const InputMessagePtr& msg);

// 13x
void parseBosstiaryData(const InputMessagePtr& msg);
void parseBosstiarySlots(const InputMessagePtr& msg);
void parseBosstiaryCooldownTimer(const InputMessagePtr& msg);
void parseBosstiaryEntryChanged(const InputMessagePtr& msg);

void parseAttachedEffect(const InputMessagePtr& msg);
void parseDetachEffect(const InputMessagePtr& msg);
void parseCreatureShader(const InputMessagePtr& msg);
Expand Down
104 changes: 102 additions & 2 deletions src/client/protocolgameparse.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -488,9 +488,13 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
case Proto::GameServerSendRewardHistory:
parseRewardHistory(msg);
break;
case Proto::GameServerSendPreyFreeRerolls:
parsePreyFreeRerolls(msg);

case Proto::GameServerSendPreyFreeRerolls: // || Proto::GameServerSendBosstiaryEntryChanged
if (g_game.getFeature(Otc::GameBosstiary))
parseBosstiaryEntryChanged(msg);
else parsePreyFreeRerolls(msg);
break;

case Proto::GameServerSendPreyTimeLeft:
parsePreyTimeLeft(msg);
break;
Expand Down Expand Up @@ -522,6 +526,17 @@ void ProtocolGame::parseMessage(const InputMessagePtr& msg)
parseMarketBrowse(msg);
break;

// 13xx
case Proto::GameServerBosstiaryData:
parseBosstiaryData(msg);
break;
case Proto::GameServerBosstiarySlots:
parseBosstiarySlots(msg);
break;
case Proto::GameServerBosstiaryCooldownTimer:
parseBosstiaryCooldownTimer(msg);
break;

case Proto::GameServerAttchedEffect:
parseAttachedEffect(msg);
break;
Expand Down Expand Up @@ -3722,6 +3737,91 @@ void ProtocolGame::parseMarketBrowse(const InputMessagePtr& msg)
g_lua.callGlobalField("g_game", "onMarketBrowse", intOffers, nameOffers);
}

// 13x
void ProtocolGame::parseBosstiaryData(const InputMessagePtr& msg)
{
msg->getU16(); // Number of kills to achieve 'Bane Prowess'
msg->getU16(); // Number of kills to achieve 'Bane expertise'
msg->getU16(); // Number of kills to achieve 'Base Mastery'

msg->getU16(); // Number of kills to achieve 'Archfoe Prowess'
msg->getU16(); // Number of kills to achieve 'Archfoe Expertise'
msg->getU16(); // Number of kills to achieve 'Archfoe Mastery'

msg->getU16(); // Number of kills to achieve 'Nemesis Prowess'
msg->getU16(); // Number of kills to achieve 'Nemesis Expertise'
msg->getU16(); // Number of kills to achieve 'Nemesis Mastery'

msg->getU16(); // Points will receive when reach 'Bane Prowess'
msg->getU16(); // Points will receive when reach 'Bane Expertise'
msg->getU16(); // Points will receive when reach 'Base Mastery'

msg->getU16(); // Points will receive when reach 'Archfoe Prowess'
msg->getU16(); // Points will receive when reach 'Archfoe Expertise'
msg->getU16(); // Points will receive when reach 'Archfoe Mastery'

msg->getU16(); // Points will receive when reach 'Nemesis Prowess'
msg->getU16(); // Points will receive when reach 'Nemesis Expertise'
msg->getU16(); // Points will receive when reach 'Nemesis Mastery'
}

void ProtocolGame::parseBosstiarySlots(const InputMessagePtr& msg) {
const auto& getBosstiarySlot = [&]() {
msg->getU8(); // Boss Race
msg->getU32(); // Kill Count
msg->getU16(); // Loot Bonus
msg->getU8(); // Kill Bonus
msg->getU8(); // Boss Race
msg->getU32(); // Remove Price
msg->getU8(); // Inactive? (Only true if equal to Boosted Boss)
};

msg->getU32(); // Player Points
msg->getU32(); // Total Points next bonus
msg->getU16(); // Current Bonus
msg->getU16(); // Next Bonus

const bool isSlotOneUnlocked = msg->getU8();
const uint32_t bossIdSlotOne = msg->getU32();
if (isSlotOneUnlocked && bossIdSlotOne != 0) {
getBosstiarySlot();
}

const bool isSlotTwoUnlocked = msg->getU8();
const uint32_t bossIdSlotTwo = msg->getU32();
if (isSlotTwoUnlocked && bossIdSlotTwo != 0) {
getBosstiarySlot();
}

const bool isTodaySlotUnlocked = msg->getU8();
const uint32_t boostedBossId = msg->getU32();
if (isTodaySlotUnlocked && boostedBossId != 0) {
getBosstiarySlot();
}

const bool bossesUnlocked = msg->getU8();
if (bossesUnlocked) {
const uint16_t bossesUnlockedSize = msg->getU16();

for (uint_fast16_t i = 0; i < bossesUnlockedSize; ++i) {
msg->getU32(); // bossId
msg->getU8(); // bossRace
}
}
}

void ProtocolGame::parseBosstiaryCooldownTimer(const InputMessagePtr& msg) {
const uint16_t bossesOnTrackerSize = msg->getU16();
for (uint_fast16_t i = 0; i < bossesOnTrackerSize; ++i) {
msg->getU32(); // bossRaceId
msg->getU64(); // Boss cooldown in seconds
}
}

void ProtocolGame::parseBosstiaryEntryChanged(const InputMessagePtr& msg) {
msg->getU32(); // bossId
}

void ProtocolGame::parseAttachedEffect(const InputMessagePtr& msg) {
const uint32_t id = msg->getU32();
const uint16_t attachedEffectId = msg->getU16();
Expand Down
13 changes: 8 additions & 5 deletions src/framework/net/protocolhttp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ int Http::get(const std::string& url, int timeout)
result->operationId = operationId;
m_operations[operationId] = result;
const auto& session = std::make_shared<HttpSession>(m_ios, url, m_userAgent, m_enable_time_out_on_read_write, m_custom_header, timeout,
false, result, [&](HttpResult_ptr result) {
false, true, result, [&](HttpResult_ptr result) {
bool finished = result->finished;
g_dispatcher.addEvent([result, finished] {
if (!finished) {
Expand All @@ -87,7 +87,7 @@ int Http::get(const std::string& url, int timeout)
return operationId;
}

int Http::post(const std::string& url, const std::string& data, int timeout, bool isJson)
int Http::post(const std::string& url, const std::string& data, int timeout, bool isJson, bool checkContentLength)
{
if (!timeout) // lua is not working with default values
timeout = 5;
Expand All @@ -97,14 +97,14 @@ int Http::post(const std::string& url, const std::string& data, int timeout, boo
}

int operationId = m_operationId++;
asio::post(m_ios, [&, url, data, timeout, isJson, operationId] {
asio::post(m_ios, [&, url, data, timeout, isJson, checkContentLength, operationId] {
auto result = std::make_shared<HttpResult>();
result->url = url;
result->operationId = operationId;
result->postData = data;
m_operations[operationId] = result;
const auto& session = std::make_shared<HttpSession>(m_ios, url, m_userAgent, m_enable_time_out_on_read_write, m_custom_header, timeout,
isJson, result, [&](HttpResult_ptr result) {
isJson, checkContentLength, result, [&](HttpResult_ptr result) {
bool finished = result->finished;
g_dispatcher.addEvent([result, finished] {
if (!finished) {
Expand Down Expand Up @@ -135,7 +135,7 @@ int Http::download(const std::string& url, const std::string& path, int timeout)
result->operationId = operationId;
m_operations[operationId] = result;
const auto& session = std::make_shared<HttpSession>(m_ios, url, m_userAgent, m_enable_time_out_on_read_write, m_custom_header, timeout,
false, result, [&, path](HttpResult_ptr result) {
false, true, result, [&, path](HttpResult_ptr result) {
if (!result->finished) {
g_dispatcher.addEvent([result] {
g_lua.callGlobalField("g_http", "onDownloadProgress", result->operationId, result->url, result->progress, result->speed);
Expand Down Expand Up @@ -416,6 +416,9 @@ void HttpSession::on_request_sent(const std::error_code& ec, size_t /*bytes_tran
header.c_str() + pos + sizeof("Content-Length: ") - 1,
nullptr, 10);
m_result->size = len - m_response.size();
} else if (m_checkContentLength) {
onError("HttpSession error receiving header " + m_url + ": " + "Content-Length not found");
return;
}

asio::async_read(m_socket, m_response,
Expand Down
6 changes: 4 additions & 2 deletions src/framework/net/protocolhttp.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,14 +66,15 @@ class HttpSession : public std::enable_shared_from_this<HttpSession>
HttpSession(asio::io_service& service, const std::string& url, const std::string& agent,
const bool& enable_time_out_on_read_write,
const stdext::map<std::string, std::string>& custom_header,
int timeout, bool isJson, const HttpResult_ptr& result, HttpResult_cb callback) :
int timeout, bool isJson, bool checkContentLength, const HttpResult_ptr& result, HttpResult_cb callback) :
m_service(service),
m_url(url),
m_agent(agent),
m_enable_time_out_on_read_write(enable_time_out_on_read_write),
m_custom_header(custom_header),
m_timeout(timeout),
m_isJson(isJson),
m_checkContentLength(checkContentLength),
m_result(result),
m_callback(std::move(callback)),
m_socket(service),
Expand All @@ -95,6 +96,7 @@ class HttpSession : public std::enable_shared_from_this<HttpSession>
stdext::map<std::string, std::string> m_custom_header;
int m_timeout;
bool m_isJson;
bool m_checkContentLength;
HttpResult_ptr m_result;
HttpResult_cb m_callback;
asio::ip::tcp::socket m_socket;
Expand Down Expand Up @@ -195,7 +197,7 @@ class Http
void terminate();

int get(const std::string& url, int timeout = 5);
int post(const std::string& url, const std::string& data, int timeout = 5, bool isJson = false);
int post(const std::string& url, const std::string& data, int timeout = 5, bool isJson = false, bool checkContentLength = true);
int download(const std::string& url, const std::string& path, int timeout = 5);
int ws(const std::string& url, int timeout = 5);
bool wsSend(int operationId, const std::string& message);
Expand Down