MHServerEmu Progress Report - December 2025

Merry Christmas and happy holidays, everyone! I have one last Progress Report to share this year.

0.8.0 and Beyond

With the release of version 0.8.0, MHServerEmu has officially reached a feature-complete state. This means that all major gameplay and social systems that existed when the game was shut down in 2017 have been restored, and I am now shifting my focus towards various minor tasks on my laundry list.

The next release is going to be version 0.8.1. The plan for this minor release is for it to include the vast majority of changes that will be done before 1.0.0, but keep it compatible with existing account data for players who want to keep playing without losing their progress. 1.0.0 will follow shortly after and will not be compatible with existing account data, enforcing a fresh start if you choose to update. This is the only planned “wipe” we are going to have.

I am currently aiming to release version 1.0.0 in the first quarter of 2026, meaning March 31st is the final deadline. I am optimistic that it will be ready before that date, but I still want to allow us some leeway just in case something takes longer than expected. A more concrete release date will be announced when it is set in stone.

The changes I will be working on until then fit into three broad categories: polish, bug fixes, and optimization.

Polish primarily covers various minor features that did not make it into one of the major releases for one reason or another. For example, did you know that when Gazillion developers were removing stat and power point bonuses from the campaign, they missed a +150 Health bonus for completing the invaded version of Xavier’s School in Chapter 10? For this one remaining mission reward to work as it is defined in the game data, we are going to need to implement stat rewards that were supposedly a pre-BUE feature. There are not that many features like this left, and I would prefer to take care of them before 1.0.

When it comes to bug fixes, we are aware of a pretty significant number of issues that existed in the game in 2017, which we dub “Gazillion issues”. We are not going to be fixing many of these issues, because resolving many of them would require doing client-side patches, and in some cases the fixes could have unexpected side effects on the game’s balance. We will be focusing primarily on issues with our own server code, as well as potentially game-breaking Gazillion issues that can be mitigated completely server-side. One good example of an issue with our code that needs to be resolved before 1.0 is how new accounts can get stuck in a soft-locked mission state in The Raft if a disconnect happens at the wrong moment, requiring an account wipe to proceed.

As for optimization, the server is in a relatively decent state on this front if you are playing on a self-hosted local server, but we still need to do some work for popular public servers to be able to handle larger player counts and longer uptimes we expect for 1.0. A lot of this is going to involve minimizing unnecessary memory allocations to reduce the work the garbage collector needs to do and mitigate some of the memory fragmentation issues that have been emerging on the more popular public servers over longer periods of uptime.

One last thing to note is that because we do not have any major features left to talk about, I will no longer be writing these Progress Reports on a monthly cadence. Instead, future Progress Reports will be coming out when I actually have something to share. There may also be other forms of content posted on this blog, so stay tuned!

Matchmaking

Looking back at what I worked on in December, the most time and effort went into restoring the matchmaking system. Let’s take a look at how it works.

Each region in Marvel Heroes can be flagged in game data with one or more RegionQueueMethod flags. Regions flagged this way use a separate instance management system that is designed to work with matchmaking. Gazillion engineers set up region prototypes in a way where RegionQueueMethod flags could be applied by game designers only in two predefined sets: PvPQueue and DailyQueue. The main difference between them is that DailyQueue allows you to bypass the matchmaking process and enter the match region by yourself or with just your party members, which is not possible for PvPQueue.

When a player initiates a transfer to a match region (e.g. by selecting it in the Waypoint menu), this transfer request is converted to a RegionRequestQueueCommandVar and sent to the Player Manager service, which handles matchmaking.

The matchmaking system is rather complex and consists of three major components:

  • RegionRequestQueue - manages matchmaking for a particular region.

  • RegionRequestGroup - represents an atomic group of 1-10 players queued for a match together.

  • Match - represents a collection of RegionRequestGroup instances divided into one or more MatchTeam instances.

When players queue up for a region, a RegionRequestGroup is created for them and registered in the RegionRequestQueue corresponding to the region. Every time a new group is registered, the queue attempts to fill up the current pending Match instance. When all MatchTeam instances in a Match are fully filled up, a region is created and the players are transferred to it.

While it sounds relatively straightforward on paper, there is a lot of complexity in managing states of individual members in groups and how they interact with other systems. Here is a diagram of possible states for a queued player:

These member states are replicated from the Player Manager to game instances the queued players are currently in, and they are then further relayed to connected clients. Most of these state changes end up being represented client-side as various notification popups you see when you queue up for a region.

When players choose to bypass the matchmaking process, a RegionRequestGroup is still created for them and they go through the same system, but the RegionRequestQueue immediately starts a Match without waiting for it to be completely filled up.

The main reason we needed to get matchmaking working is because the game’s one and only PvP mode, Fire & Ice, is designed with it in mind. While it is possible to force a PvP match to start without matchmaking with some server-side hackery, there is no player-friendly way to do it in-game. Right now it functions exactly like it did back in Gazillion days, requiring two teams of five players each in the same level bracket (20-29, 30-39, 40-49, 50-59, or 60). With the lower player counts and lesser PvP engagement than Gazillion developers expected when they put these restrictions in place, we are considering doing various tweaks to make PvP matches easier to start, but the specifics have not been decided yet.

Supergroups

Another social system that received a significant amount of my attention this month is supergroups, also referred to internally as “guilds”. Supergroups are effectively Parties 2: Electric Boogaloo, so I strongly recommend you to read the September 2025 report where we covered parties in detail.

Supergroups use a replication system very similar to parties, where there are authoritative MasterGuild instances handled by the Player Manager. Data from them is replicated to game instances to be used in game-side Guild and GuildMember representations, as well as the Community system. However, there are some additional bells and whistles that make supergroups more involved.

The most crucial difference is the fact that supergroups are persistent, and supergroup members can be modified while they are offline. This means membership data needs to also be replicated to the database and be kept separate from regular player data. Taking into account the relatively small number of players and supergroups that servers are going to have, I opted to load all supergroups from the database at server startup and keep them in memory to avoid the complexity of potentially having to wait for database responses when handling requests. This means that the only thing we need to do to keep everything in sync is send updates to the database when we make changes to MasterGuild instances.

Supergroups also have some additional customization options compared to parties. In particular, you can name your supergroup, set its Message of the Day (MotD), and give specific members elevated priviliges by promoting them to officers. All of these changes need to be validated, applied, communicated to members across different game instances, and saved to the database.

There is extra functionality needed on the side of the Community system to be able to display last online time for members in the Supergroup tab of the Social panel. Last online time needs to be tracked, saved to the database, and queried for players who have not logged in since the last server restart. One advantage of having all guilds loaded at all times is that here we can skip querying last online time for players who are not members of supergroups, because it is not needed for Friend and Ignore lists.

Some rethinking was also needed for how we handle chat. Supergroups can have up to 600 members in version 1.52, and if we continued to resolve message receivers game-side like we used to, this would require including up to 600 player ids with each supergroup chat message sent to the Grouping Manager. This is not a good idea for all sorts of reasons, so I implemented a proper chat room system. The Grouping Manager now keeps track of supergroups for online players, which allows it to resolve receivers on its own by knowing just the id of the player who sent the message, which is always included anyway. I have also applied this more optimized system to local region and party chat rooms.

With all of this, supergroups are now functional, and the last major piece of the puzzle is put in place. The game is now in a feature-complete state, and I can focus on the final polish.


Thank you for following the development of MHServerEmu. I hope to see you all again next year for the official launch of version 1.0!