So… Yeah, I mean, I just straight up dove in.
I broke up a bunch of components that were closely tied together and now I have separate scenes for all the stuff that’s the same from zone-to-zone, like the UIs, the player’s avatar, the server connection, and then for the zones themselves. This allows a player character to be transplanted from zone-to-zone without reinitializing everything all over again, we can just reuse the stuff that was loaded at the start.
Transitioning from zone-to-zone is still a challenge though. In fact a lot of the transition from the login server to the actual world server is still handled by the client. Which is fundamentally flawed because it means the client could alter the data being sent to the server, which we absolutely don’t want.
When is a server a client and when is a server a server?
I meantioned yesterday that
Godot will absolutely not allow that. A server is a server and cannot be a client to another server.
So that’s where a lot of today’s efforts were focused. I tried out about 10 different approaches, some of which were very similar and some of which were pretty radical, but here’s what I ended up with…
Each area (including the login screen) has its own server. That server is directly responsible for handling interaction with the player. It figured out if you’re allowed to interact with NPCs, use items, enter combat, craft an item, etc. Those are going to use Godot’s built-in RPC.
But they also need to talk to the Central Server, which will be used at key inflection points: login, logout, zone transfers, periodic heartbeats to keep sessions alive, etc.
But since Godot’s built-in RPC won’t let me use the servers as clients – and won’t allow a server and a client to exist in the same scene …..
Fuck it, we’ll do it live
Yeah, I wrote it myself. I wrote up a Central Relay, which is meant to act as a bridge between an Area (or Login) server and the Central Server.
The central server and relay don’t use Godot’s built-in RPC (because they can’t). Instead, I’m doing all of the serialization and packet handling my damn self. I still get a little bit of usage of Godot’s library, but honestly, not a whole lot.
It ended up not being so difficult when I wrapped my head around it. There were a lot of problems to solve – like having the Area Server register with the Central Server so the two can continuously communicate. That handshake process was rough.
Figuring out how to properly serialize and deserialize packets in a performant way ate up probably a full hour of today’s stream just trying to go “EAT THIS DATA YOU PUNK ASS BITCH.”
But in the end, I got there. And I even abstracted it out into a very generic form so that when it comes time to write the behaviours that are actually different between the Area Servers and the Login Servers, it should be relatively easy to do.
I’m not making full use of the Central Server yet… the client is still handling far too much of the login process, but I’m almost there. The Central Server runs, the Login Server’s relay runs, they communicate….
The next step is making the Login Server use the relay instead of doing the work itself.