Skip to content

Instantly share code, notes, and snippets.

@geospiza-fortis
Created November 2, 2020 07:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geospiza-fortis/e897aa6846b5f26573142d90da75724f to your computer and use it in GitHub Desktop.
Save geospiza-fortis/e897aa6846b5f26573142d90da75724f to your computer and use it in GitHub Desktop.

Private server development: The initial foray

So far, I've spent my time hacking on a maplestory private server from source that I could find on the internet. I want to try my hand at building a v62 server with some customized content because I'm curious about how everything fits together. There are three major components the the work that I've done over the last half a week. I created a server instance that I could run on my local machine, learned how to modify the client, and finally played around with the data.

I'm using argonms, which is an open-source server with some nice architectural enhancements over other odinms servers like HeavenMS. The service-based model could benefit from the use of docker and a container orchestration tool, so I decided this would be the base that I would use. Besides, I tried out a v83 client and didn't like all of the new features. In my first feature branch, I first started by building the Java project using Maven. There were a couple of jars included in the project that I eventually replaced using a POM.xml file fetching the dependencies from maven. The scripting engine uses Mozilla Rhino, which is a nice way to keep maintainable scripts for all of the events. I was suprised that everything worked as expected once I cleaned up the various launch scripts.

I added in a database and launched the center server so it could create all of the tables and start accepting connections from the other two services. This let me verify that the dns networking happening within the docker-compose group was working appropriately. From the center container, I could log into the argonms database using the db label pointing to the appropriate container. Once this was hooked in, I added in the game service and the login services. The first thing that needed to be done was to simplify the example properties files because they included extra channels and configuration that I didn't need. With the login server up, I tried to connect using a local client. At this point, I needed to connect a client so I could start testing.

I downloaded a clean version of the v62 client with the original setup so I could take a look through everything that was included. I downloaded a repacking tool which can read through the encrypted wz files that are included in the game setup. It turns out that these are deeply nested datastructures containing all of the information that the client simply parses. The server also needs an equivalent copy so that it can do everything to synchronize the clients. I used the repacker to dump all of the wz files into a separate folder using a classic XML scheme. When I tried to mount this into one of the containers on the server, I ran into some nullpointer issues. It turns out that argonms does not implement the xml format, and instead uses a custom KVJ format. I also containerized the data compiler, which was comparatively simple to the server. I could mount these files into the servers so that the servers could complete their boot.

When I tried using the original client to log in, it wouldn't work because it's pointing to the old official servers that are no longer online. When I tried prodding inside with a hexeditor, I couldn't seem to find the addresses necessary to redirect the client. Instead what I ended up doing was downloading a localhost modification of the client from ragezone. It seeemed a little sketchy because Windows defender went off, but it was one of the only clients that seemed to work appropriately. I installed ida and ollydbg, where I got to use them in practice. I edited the client so it used localhost instead of 127.0.0.1, since the latter is reserved for the system (or so I've heard). In any case, this solved the immediate failure when running the binary. After this, it wouldn't load because of some configuration issues on the server.

When I could actually start using the client with the servers, it was actually a very satisfying experience. I could see the client connect to the login server and see the login page myself. I wrote a little script to insert a tesing account that I could use to immediate create a character. But once I did this, I had to figure out why I kept disconnecing when making a character on the world. I tried setting the "external" ip to the dns resolved label, and to the actual IP found via hostname -I. It turned out that I needed to have this set to localhost, and to have forwarded the ports appropriately in the docker-file. I had stayed up late enough to see 1am loop over because of daylights saving, but in the morning after I was able to actually log into the game.

I spent the rest of the day trying to play with the outputs of the wz files in Spark. I thought it would be straighforward to read the XML files since they did seem to be structured, but the wz files that harepacker outputs are terrible for structured reading. Each of the row tags are all the same, and the type for each field is associated with an attribute inside of the tag. This is probably one of the worst formats to have to deal with, at least in spark, because it requires a lot of loops and recursion. I did manage to structify the maps and their portals, but plotting the data seems to be kind of a hit and miss.

So now with all of this, what is left to do? It turns out that this endevour will probably require a bit of time because of all of the different parts that are involved. On the client, I want to slim down the installer so it's only a few hundred megabytes. I want to create a small server that is limited to Sleepywood and implements most of the jump quests that have been rethemed. I'd like to add the necessary events on the server (so scripting) and add a leaderboard for jump quests. Eventually, I want to put the server in a kubernetes cluster so I can actually host it somewhere, although there is quite a bit of work that needs to be done.

I think the plan of action is to actually make this playable before I go down the rabbithole of trying to modify the client to be slim.

@geospiza-fortis
Copy link
Author

image

Plot of all of the maps in the wz file, generated using Gephi. This removes the most common node that keeps the graph fully connected. One idea is that keeping just the Sleepywood maps would be pruning all of the maps that are not connected to those maps by filtering on their location. Even easier, I can get rid of Ossyria and just keep Maple Island and Sleepywood.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment