New architecture for the server software

Chuk

Member
Hello,

Got a couple of ideas on reworking the PSOBB server.

First of all, keeping these goals in mind :


  • Stability
    Simplicity
    Customizability
    Anti-cheat prevention

Target platforms (cross platform is always better but can make stability an issue)

Operation systems
  • Windows
    Linux

Database
  • PostgreSQL
    MySQL

Now for the software itself, I came up with a basic but solid class system on how to tackle this in a more object oriented way. Here is a brief and simple description about how the classes could be organized :

Classes

Login
This class will handle the login of the clients and make the different ships selectable. It will also keep track of the number of players logged in, the logouts and create the initial character packets that need to be sent to the client when they join the game.

Patcher
To update new content or small changes to the game like skins or lobby music we will need this class to update all changes to the different installed clients. We must make sure the patcher forces all clients to update.

PacketHandler
This class sends/receives the packets, encrypts/decrypts, filters them and sends them to the right subclass. ItÔÇÖs possible to turn on or off logging of packets in this class and it also checks for malformed packets. It also has an option to visualize packets in a human readable way. I would like to reduce the amount of dealing with raw packets in other classes to a minimum. This could cost us a bit of performance BUT will keep the code a lot cleaner. Packets could also easily be formed using enums to make working with them much easier.

DatabaseHandler
This class loads and stores everything the server needs. It needs simple functions that can be used by the other classes to quickly store and load data. It will also check the data before it saves it to prevent storing corrupted data.

ConfigurationLoader
This class should handle the various configurations the server needs, like the drops, rare monster settings, etc. Preferably store the configurations with xml or another clear human readable format. The configurations must be read on ship startup but also reloadable when the ship is already running.

CommandHandler
This class will include all commands users and GMs can use. It also checks the permissions and logs the used commands in a both raw format and human readable way. I suggest this class passes on the ÔÇÿworkÔÇÖ to the other classes but just handles the command invocation and throughput.

ServerView
This is an optional class that will wrap up the interface visually for easy managing and configuration of the server. Any option that is available here should also be available through command line. Perhaps this could even work remotely but this is also optional.

Player
This class holds all the information of the currently logged on player. When the login is successful, the login creates an instance of this class to easily store and pass data to other classes. This class contains ALL information the player needs to play as well as extra information that is useful for the server.

Ship
This class contains the configurations/settings that were loaded by the ConfigurationLoader and contains basic data like the ÔÇÿplayers onlineÔÇÖ on the ship, the rooms that are up etc. Unlike in the tethalla project, this class holds more functional data than actual methods to process packets. (there can be a few though). It would be good if a list of online players could be pulled in xml and updated frequently so we could display it on a webpage.

Item
This is more a class that stores the information of the item but itÔÇÖs not a struct because there can be methods in this class that alter the item. For example a method to change the special or stats of the weapon. Perhaps make a few subclasses depending on the item type, following the liskov substitution principle.

Sublcasses

DamageManager
This will handle the damage dealt to the objects. Between players and other players, players and enemies, enemies and enemies, etc. This also handles the kills, negative statuses and anything related to this. Perhaps also interaction between players like Resta, buffs, etc. or we can make another class for those.

ItemManager
This class will manage the item transactions and will make following subclasses work together (this could eventually be replaced if we do the managing in the ship class after all )

TradeManager
The tradewindow gets managed by this class. Trading items between player in a safe way to prevent corruption, ghosting or item scamming.

BankManager
This handles anything related to bank transactions, storing / withdrawing items and meseta.

ShopManager
Anything related to selling and buying things in the shop are handled here. Who knows we could some nifty options to the shop later on like selling rare items for PDs.

InventoryManager
Picking up an item, dropping an item, sorting your inventory, equipping an item must be regulated in this class. ( Also combining items. )

GameManager
This class handles joining rooms, setting passwords, keeping an eye on the difficulty, locking rooms with a quest, changing lobbies, etc.

QuestManager
Loading the quests, sending them to the players, keep an eye on the reward system. Perhaps we could also somehow keep track of the quest progress to let the users join a quest in progress, with some limitations ofcourse.

ChallengeManager
Everything that is needed in challenge mode will be handled here.

BattleManager
Everything that is needed in battle mode will be handled here.

EventManager
Setting a specific event and applying all changes that come with this will be handled here, it would be nice if we can somehow create and store event configurations and load them in this class.

CommunicationManager
Sending messages, chatting in the lobby, announcements, logging messages on the client side, all this must be regulated here. Perhaps we could also add a function to support chatting from outside the game.

Open for any feedback and remarks.
 

No One

Member
So, I've already started taking a crack at rewriting code -- originally it was intended to be an Eden-specific thing, mainly for a highly-experimental test server, but college ate up my time and work eats it up occasionally too. Now that the ability to make it actually is serious, I'm psyched to be a part of doing it.

Now, none of the things below are "official," but were things I had in mind when I was working on the revisions I've made thus far. They do not speak on the behalf of what we will end up doing, as we're still discussing that, but they are things I strongly wish to see.


A) The codebase will be migrated to C++. C++2011 will be utilized due to the plethora of features within the standard library, such as native thread library, smart pointers, containers, chrono, streams, "auto," templates, and many other things. There is every intention on seeing it simple, stable, and flexible. It might use more memory and CPU, as Teth is ultra-lightweight, but it shouldn't be anything unreasonable.

B) Cross-platform support is something I've been wanting to see myself. Mind you it still will require a 32bit environment -- at least at the start -- as we don't want to break structs that rely on sizeof(x) being 4 bytes instead of 8. Packing binary buffers isn't the worst thing to do, buuuut reinventing the wheel isn't useful when you want to first get the car engine working :p

Regardless, I do want to see Teth cross-platform, at least between GCC and Visual Studio (Clang too, perhaps, but I have yet to use it as I mainly use VS), all of which are free and support C++2011. This will mean that some #ifdefs will have to exist in some locations to bridge the compiler / OS gaps, but it shouldn't really be a problem when done in a logical manner.

C) Customization is definitely a goal. I have had some wild ideas of a highly experimental Eden build, and want to see the flexibility of ... numerous things that cannot be accomplished without major functional rewrites to the current Teth. Flexibility is something that we want to see...that's not to say you can get away with not knowing how to code, but changing it should not require people to understand the memory layout of everything to make basic changes to various parts of the server. In fact, the prevalence of hex in the code is one of the first things I wanted to abstract away!

Additionally, customization needs to extend to the data files themselves. I don't think that there's a need to maintain data in the binary-locked structs, especially when the overhead of parsing human-readable data into a binary form is not super time-consuming, and can be accomplished when the server initially loads. Extra flexibility would allow items to be added to the server without needing to worry about how they're added (and letting the ship do it automatically), allow for drop charts to be changed without restarting the ship, allow quests to be added or removed without restarting it, and a variety of things that would make management and development much more enjoyable.

D) Anti-cheating measures will, of course, be present in the ship. There's obviously no way to perfectly prevent cheating or stop users who have malicious intent, but security is definitely something that will be addressed. I've already come up with a few ideas on how to help verify both player and item legitimacy, as well as just provide the admins more information about everything in general, to accomplish some of this.

E) While I'm far from an expert at working with SQL, I do want to keep data a bit more organized than "here's your 14kb character data struct saved in one field!" To me, that seems prone to fail horrendously if a write fails, and extra redundancy in the database is desirable.


As for all of your classes, I am entirely in agreement with the need to consolidate various units. It's much easier to change and maintain code that is as consolidated and centralized as possible -- fixing code in one location will fix it in all the locations it was being used. We both are in agreement on much of the functionality that we'd like to see implemented, although my list has been discussed over numerous Skype conversations with multiple people rather than being in one, consolidated post like what you have XD

Item
This is more a class that stores the information of the item but itÔÇÖs not a struct because there can be methods in this class that alter the item. For example a method to change the special or stats of the weapon. Perhaps make a few subclasses depending on the item type, following the liskov substitution principle.

I've already implemented all the item types and some basic character data stuff, so here's a preview of how they can be worked with:

//...'cause a lawnchair is phonetically similar to launcher.
unique_ptr<normalWeapon> custom_lawnchair(new normalWeapon(0x000903));
custom_lawnchair->setGrind(25);
custom_lawnchair->setSpecial(normalWeapon::NormalSpecials::CHAOS);
custom_lawnchair->setPercent(normalWeapon::percentages::HIT, 35);
custom_lawnchair->setPercent(normalWeapon::percentages::ABEAST, 75);
c.addToInventory(std::move(custom_lawnchair));

//------------------------------------------------------------------------------------
// bool charData::addToInventory(std::unique_ptr<item> i) { ... }
//
// ...addToInventory takes an "item" as a parameter -- all of the item types
// { normalWeapon, srankWeapon, unitItem, magItem, consumableItem, armorShieldItem }
// are subclasses of it, and "item" itself is an uninstantiable abstract class.
//
// Ownership of items is also enforced, so once you "give" an item to someone,
// the previous owner of the item loses possession of it.

//------------------------------------------------------------------------------------
 

Sodaboy

Administrator
Staff member
I'm all about making the software as good as it can be. You guys seem to have some pretty good ideas and a method in your head on executing them. This time around, I think I am going to let you guys lead the project and study what you do. I will still be contributing what I can, but won't really get to be active until I return on the 29th from my trip to Japan.
 

Chuk

Member
Glad you both like my suggestions. I don't have extremely much time to code a lot but I'd be more than glad to help out wherever I can.

@No one, is there a public repository you are working with on the new server or is it internal to Eden?
 

legit nyck

Member
one thing that should be corrected with urgency is that the exe virus alarm
find some way to remove it permanently.
 

No One

Member
@Chuk: Currently the code is local to my own computer and not implemented in any server; the code that you see is just part of a modular test I used to verify that it was able to spit out character data and handle item manipulation (killcounters, etc) in a correct way that I've confirmed with a simple parser. I have not set up a public repository for it yet, and would prefer cleaning up a bit of it before releasing it to the public, as well as compress and simplify the item history system first...

I'm not super familiar with .NET environment and do most of my coding in C++ at the moment. The rewriting I have done with the server already is in C++, and Teth itself is already written in C (and thus directly portable to C++). Don't get me wrong -- I'd love to work on it in C#, and would be more than willing to help move it to C#, but I'd also like to get the experience of using C++ in a serious, large-scale application...both for job experience, and because I've been doing a lot of reading into C++ functionality and features recently. Plus, if done in a clean manner, the C++ code should be easy to translate to .NET, at least moreso than pure C, and should be faster than .NET when compiled for the system it runs on.


@legit nyck: Changing client architecture is not critical in this step of the design. At the moment, coding the server and allowing it to perform required functions is critical. Additionally, not all antivirus software considers PSOBB a virus, and modifying the EXE (because we lack source code for it) to subvert this could be incredibly tricky, so that is not likely something that will be addressed as known workarounds exist.
 

Chuk

Member
Anyone thinks it's worthwhile to design a UML diagram of the new software layout? It would offer some guidance during the programming process + we could notice and think about problems way ahead.

Drawing a complete UML diagram is a time consuming process though, so if nobody sees the added value, I won't make one.
 

Lee

Member
there's 2 very simple reasons why pso is flagged as a virus, both of which could be fixed yourself nyck.

1. the packer you use for the exe, just don't pack it if you need to
2. pso exe contains some self executing overwrite code to work with the loader, the pat system, you program your own loader and don't use the self overwriting code.
 

Xenon

Member
I've actually been working on a tethealla port (mostly rewrite) for a little while now and one thing I'd really like to see addressed is the reliance on global state. PSO's command-based architecture allows for a pretty modular implementation for the packet handlers and it maps well to a pipeline model for processing data on a per-client basis. It also paves the way for multi threading if you're particularly ambitious and after a more scalable and theoretically all-around faster server.

I'm all for object oriented design where appropriate, but after toying with the idea for a bit in the early phases of my own design I think it's kind of an unnecessary abstraction - the classes are going to end up being monolithic and thus more difficult to work with for all sorts of reasons. You could argue that Fuzziqer's newserv architecture is rather close to what Chuk described despite his having basically written it in C with a C++ compiler, and it ends up being pretty hard to follow. Not saying it's a bad idea or that it can't be done, but worth bearing in mind.

I doubt I'll get any traction on this but I'll put it out there - I've actually been toying with using Golang instead of C++ (though like Fuzziqer I'm basically just using C) given that it's more memory safe, still compiled to native code, enables struct alignment (convenient for packets), has a pretty solid type system, and is cross platform. For this particular project I don't know that the extra control C++ offers is really all that useful, but that's just my 2 cents; I just personally tend to avoid it :).
 

Chuk

Member
So far been working on the overall server structure and the patcher

granular_server.png


The idea is to really split up the functionalities in their respective classes. I want to stress out the simplicity of this approach so that the code could be picked up by delevopers of a any skill level. Complicated parts of the code (like the networking part, concurrency and encryption) should be left out of the logic as much as possible.

Started by breaking down the main methods of tetealla and start with pseudo code and empty methods that will be filled in step by step.
 
Top