Devlog: Behind the Scenes of Gradient MC
Hello, community! We continue to actively develop the server, and today we are excited to share the technical details of what our team has been working on lately.
🚀 Concept: Centralization
The main goal set for this summer is dividing the server’s tasks into “individual jobs”. In short: splitting the workload between services and plugins. You might ask why we are doing this at such an early stage, as it might seem like over-engineering. Let me explain: when developing a minigame server, we rely on performance and speed to give the servers exactly the processing power they need. But, if we leave the same set of plugins on every minigame, we will have unnecessary overhead, and scaling later will require a lot of resources to support the server. And nowadays, that’s expensive. Therefore, the decision was made to divide the workload. I will explain exactly how we are doing this below…
⚙️ “Connectors and Game Engines”
Most minigame plugins are built on a “one minigame - one server” system. At the same time, this minigame can contain several arenas for playing on a single server. This is called a multi-arena. The game plugin manages the worlds and has integrations with other plugins to transfer currency (for buying cosmetics and other “useful” things), experience (to increase the player’s level on the server), and technical metrics (number of players, wins, losses, etc.). It might seem like an ideal concept—less work for developers to maintain—but there are many hidden problems here that will eventually “backfire”…
I always adhere to the principle that everyone should be responsible for their own job. “All-in-one” is cool, but it’s hard to maintain. So, the idea came to mind to divide the minigame’s workload by creating a connector and a game engine.
Connector - a small plugin whose job is to send a player to an arena and receive them after they leave it. It displays how many arenas are available, connects you to a random one, or gives you the option to choose a specific one (only if the player has permission).
Game Engine - the minigame itself. The connection logic, statistics gathering, and display via placeholders have all been moved out of it. It strictly handles the gameplay process and nothing else.
Here the question arises: how does the connector know about available arenas, redirect to the game, and where does the game engine send the player after the match? This is where the proxy and Bungee communication channels come in. I will explain in more detail how it all works in future devlogs :>
👨💻 Services
So we have a connector and a game engine. Everything seems cool and great, but the functionality is missing: there are no statistics for players to compete with each other; no economy where they can earn experience and currency; no cosmetics to stand out among other players.
This is where services come in. They took over everything that the game engine used to do. Written in the Go programming language, they consume mere megabytes of RAM and tiny percentages of CPU, run blazingly fast, and serve as a “hub” for other plugins. For example: StatsService processes statistics from all minigames, freeing them from heavy database operations.
There can be many such services; they will quickly process any information received from the minigames and organize it for further use, such as displaying statistics on the website or leaderboards on the server.
🌐 Optimizations
- Dividing the work between connectors, game engines, and services allows us to make the server faster, stop worrying about TPS drops (when a world is regenerating), and get rid of unnecessary plugins for holograms, economy, lobby management, etc.
- Updating to new versions: we are updating our plugins to 26.1.2 to get new tools for development, content for players, and better security for the server.
- Transitioning to better world saving: the current implementation of vanilla worlds is only suitable for survival. Minigames do not need a lot of that core functionality: empty chunks, lighting engines, structure generation, etc. So, while looking for interesting solutions online, I stumbled upon Slime and Polar.
Slime - a world compression format that loads data directly into RAM, allowing for very fast deployment and deletion of temporary arenas for minigames. Polar - a more modern and even lighter In-Memory format, specifically designed for maximum performance and minimal resource consumption during frequent game session restarts.
The choice is obviously Polar.
Work is in full swing! We are grateful to everyone for your feedback and support.
Stay tuned for more posts, because we still have a lot to share.