Since the last post in which we presented the reason why we needed to heavily invest in upgrading our engine, the engine-upgrade branch has been slowly and steadily diverging from master.
After breaking and reassembling several subsystems we felt the need to stabilize a bit, and merge the changes in master. The reason is two-fold. First the extensive changes we made need real-world testing as we might not have thought of all the code paths. Second, we would like for the code to be able to be used by the other developers in their sub-projects. Also the merges with master were becoming increasingly difficult. Now, after about a month of polishing we are ready to land the first batch of engine-upgrade changes.
So since the beginning what has changed? Some stats: not including the source code from external libraries, 10,000 lines of code have been added, and 15,000 have been removed in more than 300 commits. We present two summaries of what has changed: a small one targeted players and a more extensive one targeted at developers.
What has changed for players?
Not much, and that's the whole point: it looks like the regular engine and quacks like the regular engine, although the internals have changed a lot.
- Some parts of the console can handle autocompletion and history better (irssi-style).
- There is support for cvar and command descriptions (most of the basic commands have one).
- The usage of the /if command to detect modifier keys has been deprecated in favor of /modcase. Likewise /wait has been removed, it can be replaced by /delay 1f.
What has changed for the developers?
We started directly be re-implementing the most basic subsystems of the engine: commands, cvars and logs as well as a few other minor ones. They were designed to have the same API in the engine and (eventually) in the PNaCl sandboxes while enforcing security for the latter. Likewise, we designed them with thread safety in mind although the engine is still single-threaded, only the logs are thread-safe for now so as to allow the SMP thread to print debug info.
Here are more details on the changes:
- Our cvars can now be defined statically and registered automatically to better preserve the locality of the code. The interface for using them is minimalist, while allowing type-checking ("aa" doesn't work for a bool while "on" does), range-checking, callbacks etc. The most basic example of a cvar is
static Cvar<int> maxfps("common.framerate.max", "int - the max framerate, 0 for unlimited", Cvar::ARCHIVE, 125);
next to the main loop of the engine. - Commands, likewise, are automatically registered and have a smaller interface.
- Since we are using C++11 we used the excellent tinyformat library to extend the logs to accept custom datatypes while keeping the C printf syntax. Yet again to preserve locality, subsystems can have loggers with a log level configurable at runtime. That way you can avoid being spammed with /set developer 1.
The build system has been completely rewritten to allow the building of the gamelogic in sandboxes or as shared libraries, using the old ABI or the future PNaCl ABI. Most external libraries have been moved out of the tree and you should use the system libraries. On mingw32/64 msvc32/64 macosx32/64 external dependencies will be automatically downloaded by the build script. Our usage of C++11 targets GCC 4.6, Clang 3.2 and MSVC 2013 or higher.
What next?
The new filesystem is almost finished, but it breaks the compatibility with the current one so we are delaying it. New exciting projects our developers want to work on include the OS abstraction layer, the core event pump, profiles and keybinds. The implemention of PNaCl for the other sandboxes is a work in progress, for example, we are toying with the idea of moving libRocket completely inside the sandboxes.
Even if this first merge is an important milestone for our upgrading project, I want to emphasize that this is a very long term project. There is still a huge amount of work to do, and then some more.
Are you ready for Alpha 22 with the engine changes?