• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!
  • 2026 staff recruitment is open! Check it out and consider applying!

Tibia 7.7 Server Decompiled

That was already done as well. Thanks for the reply @Olddies, I actually found the issue...I didn't realize that using the SQLite browser I had to save after changing the "Host" field...now I get:


Code:
HandleLogin: Fehler beim Entschlüsseln.
error.log: HandleLogin: Fehler beim Entschlüsseln.

I understand this is something related to the RSA encryption, but I put the .pem file in the correct location, and it's the same .pem file in both the gameserver directory and the loginserver...

~~EDIT~~
It seems the problem is something to do with OTClient...if I use a regular 7.70 client and fusion's IP changer, it works just fine. Weird that OTClient will load the character list, but fails to join the gameserver? Of course I updated the RSA in the OTClient config
 
Last edited:
That was already done as well. Thanks for the reply @Olddies, I actually found the issue...I didn't realize that using the SQLite browser I had to save after changing the "Host" field...now I get:


Code:
HandleLogin: Fehler beim Entschlüsseln.
error.log: HandleLogin: Fehler beim Entschlüsseln.

I understand this is something related to the RSA encryption, but I put the .pem file in the correct location, and it's the same .pem file in both the gameserver directory and the loginserver...

~~EDIT~~
It seems the problem is something to do with OTClient...if I use a regular 7.70 client and fusion's IP changer, it works just fine. Weird that OTClient will load the character list, but fails to join the gameserver? Of course I updated the RSA in the OTClient config
otclient doesnt work with cip server unless you edit otc sources, cip engine sends different packets on login even if you manage to login with otc you will have few more problems, walking, fluids, and many other things
 
otclient doesnt work with cip server unless you edit otc sources, cip engine sends different packets on login even if you manage to login with otc you will have few more problems, walking, fluids, and many other things
Ahh OK good to know, I did not know that. Thank you! In that case, everything is working as expected.
 
Ahh OK good to know, I did not know that. Thank you! In that case, everything is working as expected.
There is a small incompatibility between 7.7 and 7.72 protocols and I think the one supported by OTC is 7.72. There is a definition that can be passed to the compiler in the makefile -DTIBIA772=1 to make it use the 7.72 protocol but I can't recall whether I was able to login with the OTC after it. I can tell you're able to use the 7.72 client which seems to be better documented so people like to use with along with custom DLLs.

Code:
CFLAGS = -m64 -fno-strict-aliasing -pedantic -Wall -Wextra -Wno-deprecated-declarations -Wno-unused-parameter -Wno-format-truncation -std=c++11 -pthread -DOS_LINUX=1 -DARCH_X64=1 -DTIBIA772=1
 
I cannot for the life of me figure out how to connect to this externally. You can't bind the gameserver to your public IP, it has to be internal, but then external users trying to login can't because the loginserver is forwarding their requests to the public IP, which the gameserver isn't listening on. What am I missing?
 
I cannot for the life of me figure out how to connect to this externally. You can't bind the gameserver to your public IP, it has to be internal, but then external users trying to login can't because the loginserver is forwarding their requests to the public IP, which the gameserver isn't listening on. What am I missing?
I'm not sure I understood the problem. It seems you're able to connect locally but not remotely? Without modifications the game server will bind to the address in the database, which is also used by the login server to redirect players. If you change the binding address to INADDR_ANY, as Olddies mentioned, it should listen to all available network interfaces and the address in the database doesn't matter, except that the login server will still need to properly redirect players.

If you're able to connect locally, it could be that you're using a local address in the database, that remote players aren't able to reach. I personally haven't had this kind of problem so I kept the original binding mechanism but if you're still having trouble, send me a DM and I'll try to figure what's going on.
 
does anybody has the map editor for this server ? for the item editor i can simply use ezzz tool right?
You need to change the RSA Key:

LUA:
121793809226659874120563434457378290680712961255388163335981998802810198001060741960884620303767165808945553490232384319640949111025960594429556046947046669780460678698731721332300359415965143790954689620894727453642602895794899765974634449445059302407051484378870077027957637912083504181824460210859132357393
server side or client side because in 7.70 it begins with 142... im having a similar issue running this dockerized
 
This is incredible! I've run the leaked files some months ago but this release is making me want to mess with this things all over again haha

Thank you Very Much fusion for your work and for sharing it with us!

Is it safe to assume this decompilation ended up being 1:1 with the leaked game or some details were "Lost in translation"?

Once again, Nice job!!
 
any instructions to run this dockerized im having issues trying to view char list, this does not need the necesry libraries used to run the game files? by libraries i mean the one that denis releawed when the leaked cipsoft files were released
 
any instructions to run this dockerized im having issues trying to view char list, this does not need the necesry libraries used to run the game files? by libraries i mean the one that denis releawed when the leaked cipsoft files were released
Use the rsa from otserv take the .pem file from nekiro downgrade, the one that start with “109…..” and edit the cip client with hex to change the rsa
 
This is incredible! I've run the leaked files some months ago but this release is making me want to mess with this things all over again haha

Thank you Very Much fusion for your work and for sharing it with us!

Is it safe to assume this decompilation ended up being 1:1 with the leaked game or some details were "Lost in translation"?

Once again, Nice job!!
I was finally able to make it run even tho I know little-to-nothing about linux, VMs and all this stuff... Playing on rookgaard yet but so far seems pretty good, pretty similar (actualy 1:1 so far) to the leaked game! What an absolutely amazin job @fusion32 ! Thank you once again very much! I'm really excited to make some modifications and see how the game reacts to them haha
 
Hello guys!


@fusion32 , I’d like to report something regarding the following TODO comment:

// TODO(fusion): This looks odd. The refreshing starts at (-1,-1) which means it might take a long time before the map is actually touched. Need to verify if this matches the original// behavior or if the compiler/decompiler messed it.

I’ve tested the leaked original game binary, and in that version the refreshable tiles do get refreshed at least once within the same day the server starts. I only found this TODO after noticing something strange: all the trash I left in Carlin was still there after several hours, even with nobody around the area.


I’m still not completely sure if the intended timing is this, but as far as I can tell, after launching the game, each refreshable tile in the original server gets refreshed after approximately four hours. Of course, each on their own time:

(Reference screenshot from tibiantis.info.)

EDIT: I think I've "fixed it" (still not sure if was broken tho haha)... Now the map tries to refresh only one ".sec line" on x axis before entering the map for real, I think this way is more in line with the intended behaviour of the game. Can I upload here the updated operate.cc? I've tested it and now folda boat is refreshed only a few minutes after the server starts (the way I think is correct)... Before this "fix" the game binary would iterate through more than 40,000 non-existent sectors before reaching the actual map region...
 

Attachments

Last edited:
Hello guys!


@fusion32 , I’d like to report something regarding the following TODO comment:



I’ve tested the leaked original game binary, and in that version the refreshable tiles do get refreshed at least once within the same day the server starts. I only found this TODO after noticing something strange: all the trash I left in Carlin was still there after several hours, even with nobody around the area.


I’m still not completely sure if the intended timing is this, but as far as I can tell, after launching the game, each refreshable tile in the original server gets refreshed after approximately four hours. Of course, each on their own time:

(Reference screenshot from tibiantis.info.)
Woops... I've just checked the binary and I actually misread the initial values of RefreshX and RefreshY. They're set to 0x7FFFFFFF => INT_MAX rather than 0xFFFFFFFF => -1. This makes it wrap to SectorXMin and SectorYMin respectively right from the first call. Thanks for catching that. You can also submit any weird behaviors you find to the issue tracker on github, but anything works really.

The weird thing is that I remember checking this a few times before actually taking the time to write that comment, but I guess sometimes you miss stuff when you're tired.
 
Woops... I've just checked the binary and I actually misread the initial values of RefreshX and RefreshY. They're set to 0x7FFFFFFF => INT_MAX rather than 0xFFFFFFFF => -1. This makes it wrap to SectorXMin and SectorYMin respectively right from the first call. Thanks for catching that. You can also submit any weird behaviors you find to the issue tracker on github, but anything works really.

The weird thing is that I remember checking this a few times before actually taking the time to write that comment, but I guess sometimes you miss stuff when you're tired.

Oh sorry man, I've edited my message before seeing yours haha, I've "fixed it" by myself, still don't know if I did it the right way tho... Have you seen my edit? Sorry again...

PS: I'm SUPER happy to be able to help, even if only a little bit, with this magnificient project of yours.
 
I actually went ahead and did a back of the envelope calculation, and if the numbers are mildly correct, it would have taken ~100 hours for it to start refreshing sectors. I'm not entirely sure I've seen any sectors refresh while testing but I wasn't actively looking for it either. Anyway this means that sector refreshing wasn't happening so it's not actually tested. I'd expect other bugs to show up from this change but it might as well just work.

For a config similar to the one from the leaked tarball, you'd have something like this (roughly):
Code:
SectorXMin =  996
SectorXMax = 1043
SectorYMin =  984
SectorYMax = 1031
RefreshedCylinders = 8

EmptySectors = SectorXMin + SectorYMin x (SectorXMax - SectorXMin + 1)
             = 996        + 984        x 48
             = 48228

RefreshInterval = ~1min

TimeToFirstRefresh = (EmptySectors / RefreshedCylinders) * RefreshInterval
                   = (48228 / 8) * 1min
                   = ~6000min
                   = ~100hr
 
SectorXMin = 996 SectorXMax = 1043 SectorYMin = 984 SectorYMax = 1031 RefreshedCylinders = 8 EmptySectors = SectorXMin + SectorYMin x (SectorXMax - SectorXMin + 1) = 996 + 984 x 48 = 48228 RefreshInterval = ~1min TimeToFirstRefresh = (EmptySectors / RefreshedCylinders) * RefreshInterval = (48228 / 8) * 1min = ~6000min = ~100hr
Yeah, I came to that conclusion too fusion...

I've changed:

static int RefreshX = -1;
static int RefreshY = -1;

To:
static int RefreshX;
static int RefreshY;
static bool initialized = false;

if (!initialized) {
RefreshX = SectorXMin - 1;
RefreshY = SectorYMin;
initialized = true;
}

And it seems to be working fine now, as I said earlier, Folda ferry was refreshed after some minutes while some other areas of the map were still "dirty"... I’ll test it more thoroughly, but in my initial tests this fix seems to be working correctly... I'll keep testing it and will report anything unusual that may happen :D
 
UPDATE ON MAP REFRESH:

This morning I noticed that Fusion had updated the /srcs on GitHub, so I downloaded the latest tibia-game-master, compiled it, and started running some tests. Everything seems to be working well so far.


The Folda ferry was cleaned up a few minutes after the server booted, while other refreshable locations still hadn’t been refreshed yet (since their timers hadn’t come up). That’s a good sign.


Before leaving for work, I left the server running on my PC and deliberately littered several refreshable areas. I’ll check everything again when I get back home and will update this post accordingly.


Thanks for the quick action on this, Fusion!
 
UPDATE ON MAP REFRESH (2):

First of all, I'm sorry I'm late, my VM went nuts yesterday for whatever reason and decided to change IP two times (power failure maybe?), so I was not able to login anymore on the server that was running, thus, not able to finish the tests.

Well, today I'm working from home so I was able to take a closer look on how everything's going with the server, and...just good news so far:

The refresh sysetms seems to working flawlessly.

Starting by the northwest corner "driving" trought all the x axys sectors, finishing at southeast after some hours.

The Fresh Prince Of Bel Air Reaction GIF

So far, so good!
PS: I wasn't able to edit my last comment so I've made this new one, feel free to merge both of them in case you guys think it's necessary.
 
Last edited:
First of all, Thank you very much for making this public!

I feel a bit rusty and also unsure about some of these things as ive been away from the OT scene for at least 5 years now.
And before that I mainly dabbled in pre-compiled distros and on Windows.

Ive managed to get everything up and "running(?)".

Its all hosted on the same machine as the client under Garuda(Arch) Linux OS

My first issue was when trying to load the game it was complaining about not finding 'Zanera'.
Checking the Worlds tables in sqlite showed that it was empty
so I added it into the tibia.db via sqlite
LUA:
INSERT INTO worlds (name, ip, port, password) VALUES ('Zanera', '127.0.0.1', 7173, 'nXE?/>j`');
INSERT INTO worlds (name, ip, port, password) VALUES ('Zanera', '127.0.0.1', 7174, 'nXE?/>j`');
INSERT INTO worlds (name, ip, port, password) VALUES ('Zanera', '127.0.0.1', 7175, 'nXE?/>j`');
INSERT INTO worlds (name, ip, port, password) VALUES ('Zanera', '127.0.0.1', 7176, 'nXE?/>j`');
Perhaps this is an issue?

Then I got it to successfully boot.
Got the WebUI running and created an account
Sorted out the RSA by patching my client with the forked IP-Changer by minhkey. (Awesome)
Managed to login into account and upon selecting character I was greeted with the lack of premium account.
So I went back to tibia.db with sqlite and updated my account with
Code:
UPDATE Accounts
SET PremiumEnd = strftime('%s','now','+365 days')
WHERE AccountID = 12345;
Now I got past the Premium needed to access Zanera
But once again blocked by a login queue. And that is where I am currently stuck 😅

Any help that enables me to login and re-live some nostalgia is very much appreciated! ❤️
 
First of all, Thank you very much for making this public!

I feel a bit rusty and also unsure about some of these things as ive been away from the OT scene for at least 5 years now.
And before that I mainly dabbled in pre-compiled distros and on Windows.

Ive managed to get everything up and "running(?)".

Its all hosted on the same machine as the client under Garuda(Arch) Linux OS

My first issue was when trying to load the game it was complaining about not finding 'Zanera'.
Checking the Worlds tables in sqlite showed that it was empty
so I added it into the tibia.db via sqlite
LUA:
INSERT INTO worlds (name, ip, port, password) VALUES ('Zanera', '127.0.0.1', 7173, 'nXE?/>j`');
INSERT INTO worlds (name, ip, port, password) VALUES ('Zanera', '127.0.0.1', 7174, 'nXE?/>j`');
INSERT INTO worlds (name, ip, port, password) VALUES ('Zanera', '127.0.0.1', 7175, 'nXE?/>j`');
INSERT INTO worlds (name, ip, port, password) VALUES ('Zanera', '127.0.0.1', 7176, 'nXE?/>j`');
Perhaps this is an issue?

Then I got it to successfully boot.
Got the WebUI running and created an account
Sorted out the RSA by patching my client with the forked IP-Changer by minhkey. (Awesome)
Managed to login into account and upon selecting character I was greeted with the lack of premium account.
So I went back to tibia.db with sqlite and updated my account with
Code:
UPDATE Accounts
SET PremiumEnd = strftime('%s','now','+365 days')
WHERE AccountID = 12345;
Now I got past the Premium needed to access Zanera
But once again blocked by a login queue. And that is where I am currently stuck 😅

Any help that enables me to login and re-live some nostalgia is very much appreciated! ❤️
Hello, you've probably missed an important step of the process, that was creating the "default profile" on the db by using the patch inside mslqite, there's a file there which name starts with 999... All you have to do is to place this file inside the patch folder and start the query again...

You're probably stuck in a queue because the world has not defined the online max players, so (I believe) its locked to 0 hehe

PS: You might need to delete the world entry "Zanera" you've created first before running the patch ;)
 
Back
Top