Doctacosa

gamedev

As you might have seen in the Creeper's Lab news this weekend, I released three more plugins to the public: kicks and bans management, Race Away and Grindatron. I first distributed five plugins last summer, which I wrote about in this space. I explained how an extra layer of polish was necessary before others could really use these tools properly, but you might be wondering what type of work that involves. Let's take a look!

A first important step is to ensure that the plugins can run on their own. It might seem simple, but some of these need me to do manual corrections once in a while, or handle some tasks by working directly on the database's records to complete them. This isn't something I want others to have to handle, so I usually need to complete and automate some processes. The bonus of doing this is that I no longer need to do these steps by mistake afterwards, so that's a win-win scenario!

On a similar topic of automation, the initial setup is important: something that I added when necessary is for each plugin to automatically create its database tables and/or configuration files when it first runs, so that everything is ready to go. I didn't include this step on the first versions I used on the Creeper's Lab because I didn't know what would be needed, plus needs grew over time!

Something important that many developers don't like to do is documentation. “Why should I be writing text when I could be writing code?”, many seem to think. In this case, it's important as any other server owners wanting to use these plugins need to know how to set them up and use them! A full documentation involves what each plugin does, how to install it, setting permissions, any in-game commands available, and possibly more. This gives people the feeling they can trust the thing to do what it's meant to, and hopefully reduces the amount of questions I have to deal with.

Another element is the branding: how to name them, and what logo to give them. I usually prefer a descriptive name so you can get a vague idea of each plugin's purpose from the start, with the IO prefix for Interordi. For example, the plugin used to synchronize player inventories across multiple servers is named IOSync. A logo isn't strictly required, of course, but it adds a way to quickly identify something and make it stand out. I developed a basic visual identity for all my server tools, so you can tell they're from the same family!

These are the main steps! Most of that work only needs to be done once, and I usually do it close to release. This way, I know exactly what's necessary and don't need multiple do-overs.

#gamedev #projects

– Doctacosa

Recently, I reorganized the entire support system of the game servers as I described in this news post. The servers are now able to turn themselves off when empty, then wake back up whenever a player tries to access them. The main result is the empty ones no longer use any RAM or CPU, letting the other worlds have more resources to themselves.

The results were clear: we have had some instability for the past several weeks, including crashes every few days, and that cleared up pretty much instantly. I'm satisfied to see that it was all worth the effort!

This is something that I had been thinking about for a while and then spent most of the past month developing. The dedicated server was getting full, especially on RAM usage, causing instability. Plus, this meant that I couldn't run any more servers in parallel: bringing Seasonal and Tasmantis online for some weeks already increased the rate of issues, which is no fun for the player base, so something had to be done.

Sure, I could have opted to rent a dedicated server with higher specs, or outright get a second one, but I like to maximize what I have before getting more. Plus, this keeps the entire operation running at a lower budget, freeing money for other ventures.

Another feature that I introduced helps me keep the game servers up to date: whenever the servers wake up, they also pull the latest versions of the game itself, selected plugins and their configuration. If, say, Rodinia wakes up 10 times in a given day? That's 10 opportunities to update its files and get the latest improvements and corrections! Before, that was only possible when I did manual restarts, which could be as rare as once every few weeks.

This replaces the Python script that I mentioned back in 2017.

To summarize, this work had three main results: * An immediate, positive effect on game stability. * Easier server updates by fetching files on every wake up. * New opportunities for special projects by freeing resources.

I'm proud of the result. This required several weeks of development but will definitely pay off in the future!

#gamedev #projects #minecraft

– Doctacosa

I'm a big fan of the concept of online player profiles. It's a fun way for you to see your current progression, or look at other players to see who's active and how they're doing. Plus, if you're in a competitive spirit, you can compare yourself to others!

Right now, we have player profiles for everyone who's registered to play Minecraft on the Creeper's Lab. As an example, here's my own profile. It tells you quickly when I registered, was last online, my level of activity and a whole lot of gameplay statistics. Hopefully, people will agree with me that it's a clean layout that allows you to find some good information quickly.

This month's poll is about these profiles (answer now if you haven't already!) as I'm looking at the next steps.

One of the most recent additions has been the skulltulas tracker. There are 100 of these scattered across the Lost Woods, pushing people to explore and try to find the whole set. It's a relatively simple addition, yet adds an extra layer of an existing activity. I want to do more work like this in the future.

This doesn't have to be only about Minecraft either! Interordi has communities in other games, and there are some fun integrations that could be done. Notably, we've got many who play RuneScape; I've done a proof-of-concept that shows the progression of a given player within the game. This is interactive – enter a player name to view their data! This is something that could be integrated in a centralized Interordi profile alongside other info.

Something that I discovered earlier this year was RetroAchievements, which adds achievements to older emulated games. Here's my (rather slim) profile at this moment. After a preliminary check, this is something that could also be imported into an Interordi profile. Is this something that you would like to see? If so, please speak up!

Once the data is available, new options open up. Leaderboards? Possible! Comparison with a friend? Sure thing! A summary across all games? Yep!

My idea is to have a single stop for the community's players to view some data about their online games. Do you have any ideas on what should be added, or integrations that would make this worthwhile? Please add your comments below!

#gamedev #projects

– Doctacosa

Well, this wasn't what I planned to write about this month, but an incident that took place earlier today is worth a mention.

Some players noticed this morning that the forums and website were unusually slow, or outright unresponsive. I assumed at first that this was a random issue that would resolve itself (Internet issues, perhaps?), but after contacting my web host, it turned out that the website was undergoing a Distributed Denial of Service (DDoS) attack!

Someone was using several connections to try to load forum pages, while adding a database query payload in the URLs. The goal of that might have been to try and find a security flaw to exploit, but the sheer amount of page requests being done completely overloaded the website's capacity to answer. In the roughly 4 hours that this lasted, the server recorded 367,570 page loads. As you can imagine, that goes way beyond the usual amount of traffic! The solution turned out to be as simple as pulling the forums temporarily offline: with no vector of attack available, the DDoS hit automatically stopped after a while.

Unfortunately, things like these will happen once in a while when dealing with online communities and it can be especially common in gaming circles. While it's difficult to say who caused this one, it could have been a previous player that was banned, or someone who didn't like the answers we gave them. The game servers get hit once in a while too, but the datacentre where those reside has a built-in protection against these type of attacks, so whoever is online at the time won't even notice that something is going on. I get notified so I can keep track of the situation as needed.

There's no perfect way to prevent this, as angry people might go to any length to try to act out of revenge. On this specific case, the forums could be migrated to our dedicated server; they would then be covered by the datacentre's protective shield. Beyond that, every situation has to be dealt with on its own!

#gamedev #projects

– Doctacosa

The latest major feature for the Creeper's Lab landed two days ago: full support for Bedrock players on all servers! This includes Windows 10 and mobile, plus consoles with some workarounds.

Then, new advertisements were posted last night to make people aware of this. The reception has been... interesting. Actual quotes:

  • “Impossible”
  • “That’s literally not how the game works”
  • “yea that's literally not possible”
  • “How is that possible”

There's some convincing to be done, but several others have tried it successfully already!

I take no credit for allowing Bedrock players to play on our Java servers, that goes to the talented team at Geyser. My efforts were focused on updating my code backend to properly support these new players, and I had plenty of challenges to face.

First and obvious, the whitelist. Java users get whitelisted by entering their player name on their forum profile, but Bedrock uses Xbox Live Gamertag accounts, with the identifier being a XUID instead of the usual Java UUID. Finding a way to fetch that information and properly update player accounts as they log in took some time. Behind the scenes, the flow is different, but from the players point of view it works the same.

Later came the player statistics. This might seem irrelevant, but player statistics are used for more than vanity purposes: they power a lot of systems, from the web profiles to the achievements, plus my internal activity tracking tools. This was relatively straightforward to do, only requiring time to adjust everything properly!

Finally, a key part was to allow players to be on both Java and Bedrock at the same time. Many people have both versions since the Windows 10 Edition used to be given away for free with Java Edition purchases, and it's reasonable to expect people to want to play on either account whenever. Until now, I had a strict 1:1 relationship between forum IDs and player UUIDs, and this couldn't be the case anymore. I've restructured data processing so that each person can have multiple player accounts attached to their names, solving this issue.

And here we are. The tech issues are mostly dealt with, now it's time to advertise and attract these new players that used to be out of reach!

#gamedev #projects #minecraft

– Doctacosa

I spent a good chunk of the past two weeks or so doing improvements to the backend that powers the Creeper's Lab. While you're familiar with the game servers (of course!), the website and the forums, there's more hidden behind the scenes to help run the show. This includes among others the tools that allows the staff to write news posts, see player statistics, review bans and more. While these aren't visible, they're important to ensure that everything can be done properly and efficiently, so I decided to spend some time on them.

Among these changes comes a new structure to the module I use to launch each game server. I've decoupled the launch of that program from the launch of a server itself, so that it can be controlled separately. While this doesn't have any short-term purpose, it'll allow me to do some improvements that will be described in a future post.

I've done extensive changes to how the servers themselves and their base data (name, address, directory, etc.) are stored. From this, I've designed a script that allows me to select some files and copy them to any servers. This comes in handy when I want to apply a new server setting, for example: I can do the change once, place the edited file in a central location, then copy it directly to all servers. This is much less tedious than editing 5+ files one by one, and less error-prone too!

Building on that, the whitelisting system was streamlined to be faster. When a new player registered, under the previous version, the whitelist was pushed from the forums to each individual server. This could take about 15 seconds, the long wait potentially giving the new player the impression that something was wrong. Under the new design, the whitelist is uploaded once, then automatically copied to all game servers. This is at least three times as fast, offering a better experience.

Along the way, I've also given myself the ability to fully control the minigame servers like Parkour and PvP. Due to the previously limited integration, if these encountered a problem, I had to manually open a connection to run commands directly. Now, they work the same as all other game servers, so part of the maintenance can be done from a web browser, or even directly from my phone!

These updates fall into the category of less interesting work that nobody sees the results of directly, but it pays off through easier maintenance and updates. With Minecraft 1.15 being mostly stable, 1.16 not expected any time soon and no other high priority project in the way, this was a good time to take care of this and get better tools in place.

#gamedev #projects

– Doctacosa

In previous Game Dev entries, I've talked about my reasoning behind the introduction of the chat server and how I managed to apply improved formatting on the messages. The whole system has been extremely reliable since the beginning, with a solid design and self-repair capabilities when the connection between the core and one of the channels (game server, IRC or Discord) is lost. Still, there's always room for improvements.

The majority of my development time in the past week or so has been dedicated to adding an extra layer of polish and functionality to the chat system. This notably includes:

  • Deaths, kicks and bans are now visible network-wide to all, helping to explain what's going on.
  • An annoying display bug introduced a few weeks ago where newly registered players would still appear as visitors in-game has been squashed.
  • The minigames (currently Parkour and PvP) now use the chat core as well. While their chat remains limited to the players in each location, without a global link, they benefit from the richer display formatting and custom titles. As a bonus, private messages can now be sent and received from the rest of the network!
  • After erratic reports of the quick private reply, /r, sometimes sending messages to the wrong person, I decided to investigate once it happened to me and I had a small test case to study. It turns out that, if a private message was first sent without capitalizing the receiving player's name properly, later /r would go to the person contacted before then. This was rare as most players use tab-completion, which takes care of the capitalization on its own! I've now fixed this.
  • Players who bounce off servers as they're denied entry (dead in UHC, or using the wrong game version) would emit annoying network-wide notifications whenever that happened. Clueless players liked to punch the buttons again and again, creating chat noise. Now, if the player's transfer to another server is denied, no message is sent.
  • A small but tricky issue when using the .players command to get the list of online players sometimes caused the chat to delink, later messages being lost until someone talked on the server itself. This turned out to be an issue on how HTTP calls weren't firing from the correct thread. Let's stay light on the technical details of multi-threading...!

None of these were critical, but they're part of some of the first impression that new players get from the Creeper's Lab and its community. I think a layer of polish is important to help people understand that the various systems are stable and reliable, and so I took the initiative of getting some long-time targets and annoyances out of the way.

#gamedev #projects

– Doctacosa

Last time, I explained the path I took when it comes to player stats, and what the next challenges were. Due to our previous plugin no longer being able to work under 1.14, I had to replace it with another option. Rather than try and find something suitable, I chose to expand my own stats plugin to cover everything that'd be needed.

This was completed last weekend, as the Minecraft servers got updated to 1.14 and the new plugin took over. The way I see it, there were three critical parts to this project: track everything that we need, keep the data of the previous plugin, and make it efficient. There were some challenges along the way, so here's how that played out.

Track everything that we need I replicated everything already tracked, which is used for the display of the player profiles and the achievements, among other things, In the future, when new achievements get added, it'll only be a matter of tracking more gameplay events and save them to the database. The framework to do this is already in place now, as the saving methods are shared for all stats, making new additions relatively simple.

Keep the data of the previous plugin The great aspect of doing everything on your own is that you have full control over it, and it's designed the way that works best for you. The worst aspect of doing everything on your own is that you need to do everything on your own. And that takes time. In this case, I needed to bring in pre-1.13 item names to the post-1.13 format. For example, a “bed” of type 15 is now known as a “black_bed”. Thankfully, Mojang provided a file with the list of naming changes between the two game versions, so I could use that directly as a reference to write a converter. I had accounted for most of the challenges related to this, except for one that I didn't foresee...

The plugin in place hadn't been updated in quite a while, and its data was stored using old item names, from several game versions ago. There was no crafting table to be found, it was a “workbench”. Slabs were absents, I had “step”s. The spelling of various names was different. And so on. This meant that I had to create a whole additional conversion layer to bring items to their 1.12 format before I could bring those over to post-1.13. Not an impossible task by any means, but it took more time than I wanted it to!

Make it efficient Stats tracking involves running constant checks on all players to know what they're doing. Things like emptying buckets or changing worlds happen once in a while and are easy to do. Tracking movement is a continuous job; counting the amount of blocks broken goes quick if you've got Efficiency V and beacons to help you! You don't want to save every single individual action, as it would drag the performance of the entire server down very quickly.

What I did instead was batch all actions in groups (for example, player Doctacosa has broken 25 stone blocks and 20 dirt blocks in the Laurasia overworld so far), then push these to the database every minute. This minimises the number of calls done to the database, as we save the total values created in a minute instead of every individual action. Additionally, the saving process is done in a separate thread, so the server's activity isn't on hold while it happens. The end result is super efficient, as a sample analysis revealed that the plugin is accounting for only 0.0019% of Laurasia's workload!

The work on that is completed, the player profiles have been adjusted to pull from the new source, and so have the achievements. Time to move onward!

#gamedev #projects

– Doctacosa

My work on updating the Creeper's Lab to Minecraft 1.14 is underway right now. One of the big (bad) surprises I encountered quickly is that our stats-tracking plugin is breaking in the new game version, and there's no clear upgrade path available. The stats tracking is critical to our setup: it's part of the player profiles on the forums, the achievements targets, griefing tracking, and more. There is no easy way out of this one, and this unfortunately isn't the first time this happens either. Here's a recap of all the gameplay stats solutions I've used in the past.

Stats/TNO-Stats Our first stats plugin, selected because it had a wide range of values being tracked, in a simple format, and was easy enough to use. Initially, nothing relied on this, but I integrated it early on so we could record as many gameplay events as possible.

BeardStats Quickly after that initial setup, the first Stats plugin went abandoned. Someone else made a follow-up that was compatible with the same structure, so I migrated to this. The initial version of key features like the achievements were made using this one.

Vanilla When Minecraft 1.8 rolled around, a lot of functionality was rewritten, breaking a lot of compatibility. Unfortunately, BeardStats stopped getting updated around that time, so I had to look for another option. The Mojang team had implemented their own vanilla statistics, tracked server-side and viewable through your game menu. I rewrote everything to support this. However, at the next game update, I realized that Mojang's implementation caused any stat with an ID change (for example, roses becoming poppies) to completely ERASE the old values and start counting anew, which wasn't acceptable for our uses. Another change was needed.

Stats2 At the time, Stats2 was the leading plugin to track player events, so I once again rewrote all my logic to be based on this. A negative effect was that all stats had to be counted from 0, but it seemed like a necessary evil to get a stable base to work with.

Stats3 The author of Stats2 created a new version, Stats3, with a different data structure and better performance. Thankfully, this one properly converted the values already stored to the new format. While I had to do some updates to the processing of achievements to account for the new format, this was a rather smooth change.

IOBattleStats Stats3 didn't count everything I wanted for the sake of some achievements, like the famous “Sailor Scout – Defeat an enemy with the power of Love”. To complement it, I wrote my own plugin, focused on a more detailed tracking of any damage taken or dealt (to both mobs and other players), along with death causes on all sides. This took care of PvP and PvE events, while everything else still relied on Stats3.

And that's where we stood, up until 1.14 showed up. My initial tests revealed that Stats3 was completely incompatible with the new game version, as it was still trying to use numerical item IDs instead of names. Its author stopped updating it, and instead chose to start building Stats5, once again incompatible with the previous versions, and this time with no data converter available. That'd have meant restarting counting the values from 0 all over again, and that's where I decided to draw the line. No more!

I figured that, if everyone on this front is going to let me down every few years, I might as well do it myself, so that's what I'm doing now. IOBattleStats is being expanded on to track all relevant gameplay values, from block breaking to minecart distance passing by portal uses. I'll also write a converter from Stats3 to IOBattleStats' own data format, so that everyone working toward specific achievements don't need to restart from zero. Then, everything based on these stats (see above: player profiles, achievements, griefing tracking) will be updated to the new data format, and this time should finally be the one.

This takes more time to do upfront, but will save me from having to rewrite significant parts of the existing systems every year or two, so I see it as very much worthwhile!

#gamedev #projects #plugins

– Doctacosa

With the bulk of the Minecraft 1.13 update behind us, let's look back at an unexpected issue I faced while moving between the two dedicated servers.

I used the opportunity of migrating the software on a new server to optimize the various config files a bit. One of the changes I did for the Minecraft servers is to have them running on localhost only, as they don't need to be visible to the outside world: only Bungee, the point that ties it all together and is used by the players to connect, needs to be accessible. As such, instead of having the game servers use a public IP address, they only run on a private one. An added benefit is that this matches what I'm using on my PC to run tests, so I can move config files back and forth without editing anything!

A problem I discovered, however, is that this only exposed the related services to the local environment as well. It's possible to use special calls to do things like get the list of players online, the maximum amount of players allowed, or even run commands remotely. However, if the ports for the services aren't opened to the outside world, it's impossible to use them! Things as simple as displaying the list of connected players on the website would no longer work.

To work around this, I ended up writing a simple PHP page on the dedicated server itself that waits for requests. Whenever one is received, it translates it into a game server command and runs it before returning the result. It's able to make the connection as this page is visible both internally and externally, acting as a bridge between the two worlds while keeping the security model intact!

With this new setup, no game ports are visible to the outside. Once in a while, I'll notice that random people (script kiddies?) try to scan the dedicated server for weaknesses. As of now, nothing is opened or accessible without the proper authorization, so these attempts won't even connect!

#gamedev #projects

– Doctacosa