Seismon is a Quake engine written in Rust, based on the Bevy framework. It is extensible, written in a modern ECS style, has a modern deferred and pipelined rendering system, and includes a modern audio framework. The engine is built as a set of plugins, and much of the work could be extracted to work in other games, particularly the console system. Work to extract these pieces out is ongoing (see #30).
Bevy has a lot of features related to rendering, audio and state management that in my previous Quake-related project
had to be implement manually - specifically, tonemapping/HDR and pipelined rendering. The audio system has also been completely
overhauled, originally with a custom-written Bevy module but now the system has been switched over to use
bevy_seedling
.
Based on Richter by Cormac O'Brien, and still shares a lot of its DNA. Seismon originally started as a quick weekend project to make Richter run on macOS, but I've now ended up spending months on it and the diff is something like +18,000, -11,000 LoC.
To my knowledge, this is the first full from-scratch rewrite of Quake 1, i.e. not forked from the Quake 1 source code release.
The ultimate goal is for the renderer, client-server interactions, server, input and console to be separate modules that can be mixed and matched without requiring all of them. As Quake already has a client-server model even in singleplayer games, once the client is its own separate system that only communicates with the server through regular networking methods it should be possible to write game logic in Rust (and therefore any scripting layer that integrates with Bevy, such as Lua) and still have regular Quake clients connect to it, instead of being restricted to QuakeC.
These goals are partially completed, as the audio, rendering and input handling are already separate plugins, although there are still some remaining interdependence issues.
The QuakeC interpreter is currently reasonably self-contained, but once the server is functional and all the relevant QuakeC functions
are implemented I hope to move it to use bevy_mod_scripting
and for the entity field storage to be done via the ECS. This
will make it far easier to write Quake mods in languages other than QuakeC, such as Lua. The Quake networking protocol is
fairly extensible and the client knows little about the server's game logic, so without the limitations of QuakeC it should
be possible to implement fairly complex games while still letting the DOS version of Quake connect to your server.
The console and post-processing are done using regular Bevy primitives, with the console being rendered using bevy-ui
.
The world and client updates are still handled with a centralised struct instead of components, making it impossible for
regular systems to interact with it. The console and keybinding system has been updated to be much more extensible, and
command implementations are just regular systems which can access any resource or component. All rendering is done through
the Bevy rendergraph, although the rendering code itself is still mostly written by hand using wgpu, albeit in a much more
extensible way than the original Richter implementation.
Audio is done using bevy_seedling
, a modern audiograph-based audio system replacing Bevy's default. This lets us apply
effects to the audio, and while it is relatively simple for now it should allow for some more advanced features later.
Hosting a server has preliminary support - the server can run all the initialisation code in QuakeC, and it can
load into any level from the original game. The server can correctly load entities, run the initialisation routines for
the player and entities, do basic physics, and send the resultant information to the client. The client can send input, which
is passed to QuakeC, but as player physics are not yet fully implemented the input can't actually move the player. The next
steps are to finish the physics and implement a couple of routines that are needed to make monsters move around. Basic collision
with the world and entities appears to work, but the best it can do right now is make the player awkwardly scoot around the level
when they spawn clipped into an entity (like on some levels where you start on an ammo/health pickup). Here is an example of the
client connected to the local Seismon server running e3m6
:
Networking is untested since beginning the rewrite, and I've been only using demos as a testcase. It is a priority to get this working again once the client update code is ported to use the ECS. I haven't touched most of the networking code, so in theory it should still work or only require minor changes. The main issue is that the very old version of the protocol implemented by Richter is not used by any servers I could find - hopefully soon I can implement protocol 666 (FitzQuake's protocol version) which will rectify this issue.
I've implemented mod support outside of the original id1
directory, and so far all the mods that are designed to work with the
original Quake release work. I have tried Hipnotic, Rogue, Soul of Evil, Xmen: Ravages of Apocalypse, MALICE (all the cutscenes
work but some of the regular levels have strange issues where entities are displayed with the wrong models), Omen, and Alien Quake.
Playing demos from all of these mods work.
A host of bugs and limitations from the original Richter were fixed. Inputs are no longer handled by an enum and you can
define your own arbitrary +action
/-action
commands which can be bound, and arbitrary cvars which can have a system
attached which will run when the cvar is changed. Commands are also implemented as systems, and so can have access to global
state.
There are still a couple of small pieces of code that use nightly Rust, but I hope to fix those eventually.
See issues for an up-to-date list of what needs help implementing.
cd /path/to/quake
# To run Quake 1 (id1 folder)
cargo +nightly run --release --manifest-path /path/to/seismon --bin quake-client
# To run other games
cargo +nightly run --release --manifest-path /path/to/seismon --bin quake-client -- --game [GAME_NAME]
# To run commands on startup (may require editing `quake.rc`, as `startdemos xxx` in the .rc
# may overwrite commands from `stuffcmds`)
cargo +nightly run --release --manifest-path /path/to/seismon --bin quake-client -- +map e1m1
- Networking
- NetQuake network protocol implementation (
sv_protocol 15
)- Connection protocol implemented
- All in-game server commands handled
- Carryover between levels
- FitzQuake extended protocol support (
sv_protocol 666
)
- NetQuake network protocol implementation (
- Server
- Initialisation routines
- All opcodes implemented
- Basic physics
- Complete physics
- All builtins implemented
- Input handling
- Basic client connection handling
- Full client connection
- Single-player clients
- External clients
- Diffing to prevent unnecessarily sending information
- Rendering
- Deferred dynamic lighting
- Particle effects
- Pipelined rendering
- Customizable UI
- Brush model (
.bsp
) rendering- Textures
- Static textures
- Animated textures
- Alternate animated textures
- Liquid texture warping
- Sky texture scrolling
- Lightmaps
- Occlusion culling
- Textures
- Alias model (
.mdl
) rendering- Keyframe animation
- Static keyframes
- Animated keyframes
- Keyframe interpolation
- Ambient lighting
- Viewmodel rendering
- Keyframe animation
- UI
- Console
- HUD
- Level intermissions
- On-screen messages
- Menus
- Use Bevy libraries instead of hand-rolling code
- Use
bevy_seedling
for audio - Use
hanabi
for particles - Use
bevy-ui
for UI - Use standard Bevy rendering for the world/models
- Support for rollback netcode using
matchbox
- Integrate an optional physics engine
- Use
- Sound
- Loading and playback
- Entity sound
- Ambient sound
- Spatial attenuation
- Stereo spatialization
- Music
- Global effects, particularly lookahead-enabled limiting to prevent audio clipping
- Console
- Line editing
- History browsing
- Cvar modification
- Shell-style completion
- Command execution
- Quake script file execution
- Demos
- Demo playback
- Demo recording
- File formats
- BSP loader
- MDL loader
- SPR loader
- PAK archive extraction
- WAD archive extraction
This software is released under the terms of the MIT License (see LICENSE.txt).
This project is in no way affiliated with id Software LLC, Bethesda Softworks LLC, or ZeniMax Media Inc. Information regarding the Quake trademark can be found at Bethesda's legal information page.
Due to licensing restrictions, the data files necessary to run Quake cannot be distributed with this
package. pak0.pak
, which contains the files for the first episode ("shareware Quake"), can be
retrieved from id's FTP server at ftp://ftp.idsoftware.com/idstuff/quake
. The full game can be
purchased from a number of retailers including Steam and GOG.