Skip to content

A total rewrite of the now-abandoned Richter Quake engine, splitting it up into Bevy components that can be independently used. Work-in-progress but is confirmed to be able to load and play demos from any level in Quake 1, as well as Hipnotic and Rogue.

License

Notifications You must be signed in to change notification settings

eira-fransham/seismon

 
 

Repository files navigation

Seismon

An extensible, modern Quake engine

Click here for a preview video:

Preview video

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.

Preview of demo playback

Goals

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.

Status

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:

Preview of running server

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.

Help needed

See issues for an up-to-date list of what needs help implementing.

Running

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

Feature checklist

  • 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)
  • 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
    • Alias model (.mdl) rendering
      • Keyframe animation
        • Static keyframes
        • Animated keyframes
      • Keyframe interpolation
      • Ambient lighting
      • Viewmodel rendering
    • 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
  • 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

Legal

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.

About

A total rewrite of the now-abandoned Richter Quake engine, splitting it up into Bevy components that can be independently used. Work-in-progress but is confirmed to be able to load and play demos from any level in Quake 1, as well as Hipnotic and Rogue.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • Rust 97.1%
  • WGSL 1.8%
  • GLSL 1.1%