Doomseeker

Doomseeker is a server browser application for multiple platforms with support for multiple different Doom game engines in mind. While the program provides the core functionality, it also serves as an engine for plugins that implement actual support for specific engines like Chocolate Doom, Odamex or Zandronum. This document is a reference manual for Doomseeker's Plugin API. If you're interested in developing a plugin for a new engine, we recommend to inspect plugins already available in Doomseeker's repository and use them as a base.

Following list orders plugins by subjective complexity:

  1. Chocolate Doom
  2. Odamex
  3. Zandronum

Each of these plugins provides examples for different implementations of game server clients, master server clients, execution of "join game" operation, game hosting, IRC channel definition, custom executable support per server basis, and so on.

Furthermore, we also have a so called "Fake Plugin" that is used for Doomseeker testing and development purposes and fakes both proper plugin implementation as well as the game master server and game servers.

So, where do I start?

A short startup guide can be found on this page:
https://doomseeker.drdteam.org/docs/plugins.php

Detailed help can be obtained by referring to Plugin API reference documentation.

What is [pure virtual] and how is it different from C++ virtual?

To understand why certain 'virtual' methods in Plugin API are exposed through a homebrew interface instead of C++'s standard 'virtual' keyword, we first need to understand what is Application Binary Interface (or ABI, for short), why it's important to keep it compatible between releases of Doomseeker, and how and when it breaks.

To keep things simple, ABI is how compiled Doomseeker executable and plugin's DLLs talk to each other. Nomenclature, such as 'DLL', differs a bit between OSes, but let's not digress. This section applies to all Operating Systems, be it Windows, Linux or other. Some changes to Doomseeker source code will maintain ABI compatibility, which means that old plugins can talk to new versions of Doomseeker. Some other changes, however, will break the ABI and when old plugin tries to talk to such build of Doomseeker, the whole program may crash. One of the ways to break ABI compatibility is to add a new 'virtual' method to a class that is already implemented by an old version of a plugin. The reason why this happens is excellently described on this page:

To allow us to extend existing classes in Doomseeker API with new virtual methods, we produced our own virtualization system. What plugin implementor needs to know is that this involves method pointers and setters for those pointers that need to be called from constructor. This is much simpler than it sounds. To override a [Pure Virtual] or [Virtual] method, just do the following:

  1. Declare and define method in your implementation as 'private'. It's signature needs to be the same as signature of the virtual method, so return value and all arguments must be the same.
  2. In constructor, call: set_method(&MyImplementation::method);
  3. If method is just [Virtual] (and not [Pure Virtual]) you can call the default behavior by calling method_default(). There's no need to specify the SuperClass:: prefix.

To see how to do this, inspect implementation of ZandronumRConProtocol. If you'd like to learn more, inspect implementation of its base class: RConProtocol.

In Doomseeker, you can encounter following types of virtual methods:

  • Standard C++ virtual and abstract methods. Override them as you'd override any other method.
  • Doomseeker's [Virtual] method that provides default implementation but can be overwritten.
  • Doomseeker's [Pure Virtual] method that provides no default implementation. Unfortunately, the code will compile even if you don't provide any implementation. Still, Doomseeker's debug builds will exit with assert() error if such method is called.

More reading on ABI compatibility: