Awesome
What is this sorcery?
Quake-style console is an in-game command-line interface with swappable command interpreters. It can be used during development to easily manipulate game objects at runtime or allow players to enter cheat codes, for example.
Note that this project is no longer in development. I do try to fix bugs though!
- https://www.youtube.com/watch?v=Is2m2oQ68Gc
- https://www.youtube.com/watch?v=oVWqy16W0ak
- https://www.youtube.com/watch?v=qJeCu-YB8Os
Getting Started
- Building source and samples
- Using QuakeConsole
- Setting up console to use PythonInterpreter
- Setting up console to use ManualInterpreter
- Setting up console to use RoslynInterpreter
The following is required to successfully compile the QuakeConsole MonoGame solution:
- Visual studio 2022+
- .NET 6.0+
- DirectX End-User Runtimes (June 2010)
- MonoGame 3.8.1+
Requirements
- MonoGame 3.8.1+
- .NET 6.0+
Setup
Install the console assembly through NuGet:
PM> Install-Package MonoGame.QuakeConsole.WindowsDX
The console itself is a typical DrawableGameComponent
. The following steps will go through setting it up in a game.
- In the
Game
constructor, create the console and add it to the components collection (console itself should be stored in a variable since it must be initialized and manually opened/closed later):
ConsoleComponent console;
public Game1()
{
// ...
console = new ConsoleComponent(this);
Components.Add(console);
}
- The console must be opened for it to accept user input. This is usually done in the update method by checking for a key press (the tilde key, for example):
protected override void Update(GameTime gameTime)
{
// ...
// manage previous and current keyboard states
if (previousKeyboardState.IsKeyUp(Keys.OemTilde) && currentKeyboardState.IsKeyDown(Keys.OemTilde))
console.ToggleOpenClose();
}
This has setup the console shell. For the console to actually do anything useful on user input, an interpreter must be configured (see below).
Sometimes it is desirable to prevent other game systems from accepting input while the console window is open. For this, it is required to know if the console is currently open (accepting input) or closed. This can be checked by the console.IsAcceptingInput
property.
Python interpreter can be used to interpret user input as Python code. It is extremely useful to, for example, manipulate game objects at runtime.
Requirements
- MonoGame 3.8.1+
- .NET 6.0+
Setup
Install the interpreter assembly through NuGet (this will also bring in the console if it hasn't been installed already):
PM> Install-Package MonoGame.QuakeConsole.PythonInterpreter.WindowsDX
- Create the interpreter and set it as the interpreter for the console:
var interpreter = new PythonInterpreter();
console.Interpreter = interpreter;
- To be able to modify game objects through the console, the objects must be added as variables to the IronPython engine (this creates the connection between the CLR and Python object):
interpreter.AddVariable("name", myVariable);
The object's public members can now be accessed from the console using the passed variable's name (press ctrl + space [by default] to autocomplete input to known variables/types/members).
<h2 id="setup4">Setting up console to use ManualInterpreter</h2>Manual interpreter can be used to define commands and their corresponding actions for the console manually. Useful to execute some behavior on command or provide players means to input cheat codes, for example.
Requirements
- MonoGame 3.8.1+
- .NET 6.0+
Setup
Install the interpreter assembly through NuGet (this will also bring in the console if it hasn't been installed already):
PM> Install-Package MonoGame.QuakeConsole.ManualInterpreter.WindowsDX
- Create the interpreter and set it as the interpreter for the console:
var interpreter = new ManualInterpreter();
console.Interpreter = interpreter;
A command is essentially a delegate that is invoked when user inputs the name of the command. The delegate provides an array of arguments separated by spaces (similar to arguments in a Windows console application) and optionally can return a string value that is output to the console.
- To register a command:
interpreter.RegisterCommand("name", action);
where action is of type Action<string[]>
or Func<string[], string>
.
Provides autocompletion for registered command names (ctrl + space by default).
<h2 id="setup5">Setting up console to use RoslynInterpreter</h2>Roslyn interpreter can be used to interpret user input as C# code using the Roslyn scripting API. It is useful to, for example, manipulate game objects at runtime.
Requirements
- MonoGame 3.8.1+
- .NET 6.0+
Setup
Install the interpreter assembly through NuGet (this will also bring in the console if it hasn't been installed already):
PM> Install-Package MonoGame.QuakeConsole.RoslynInterpreter.WindowsDX
- Create the interpreter and set it as the interpreter for the console:
var interpreter = new RoslynInterpreter();
console.Interpreter = interpreter;
- To be able to modify game objects through the console, the objects must be added as variables to the C# scripting context:
interpreter.AddVariable("name", myVariable);
The object's public members can now be accessed from the console using the passed variable's name.
Due to an issue at Roslyn side, global variables must be accessed through a 'globals' wrapper object:
globals.myVariable
RoslynInterpreter does not provide any autocompletion features.
Assemblies
- MonoGame.QuakeConsole: The core project for the console. Contains the behavior associated with handling user input and the visual side of the console's window.
Interpreters
- MonoGame.QuakeConsole.PythonInterpreter: IronPython interpreter for the console shell. Allows manipulating game objects using Python scripting language. Provides autocompletion for loaded .NET types.
- MonoGame.QuakeConsole.PythonInterpreter.Tests: Unit tests covering the expected execution and autocompletion behavior for Python interpreter.
- MonoGame.QuakeConsole.ManualInterpreter: Interpreter for manually defined commands. Provides autocompletion for command names.
- MonoGame.QuakeConsole.RoslynInterpreter: Interpreter using the Roslyn scripting API to execute console input as C# script.
Samples
- HelloPython: Simple sample which sets up the console with Python interpreter, allowing to execute Python code and manipulate a cube at runtime.
- Sandbox: Generic sandbox for testing out various parts of the project. Sets up the console tying together all the interpreters (Python, Roslyn, manual).
- Common: Supporting library providing common functionality for samples.
Development
Release a New Version
- Make sure version numbers are updated in .csproj files.
- Create packages:
dotnet pack -c Release MonoGame.QuakeConsole.DesktopGL.sln
dotnet pack -c Release MonoGame.QuakeConsole.WindowsDX.sln
- Publish packages (substitute
<version>
with version to be released):
VERSION=<version>
dotnet nuget push Source/bin/Release/MonoGame.QuakeConsole.DesktopGL.$VERSION.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json
dotnet nuget push Source/bin/Release/MonoGame.QuakeConsole.WindowsDX.$VERSION.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json
dotnet nuget push Interpreters/ManualInterpreter/bin/Release/MonoGame.QuakeConsole.ManualInterpreter.DesktopGL.$VERSION.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json
dotnet nuget push Interpreters/ManualInterpreter/bin/Release/MonoGame.QuakeConsole.ManualInterpreter.WindowsDX.$VERSION.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json
dotnet nuget push Interpreters/PythonInterpreter/bin/Release/MonoGame.QuakeConsole.PythonInterpreter.DesktopGL.$VERSION.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json
dotnet nuget push Interpreters/PythonInterpreter/bin/Release/MonoGame.QuakeConsole.PythonInterpreter.WindowsDX.$VERSION.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json
dotnet nuget push Interpreters/RoslynInterpreter/bin/Release/MonoGame.QuakeConsole.RoslynInterpreter.WindowsDX.$VERSION.nupkg --api-key $NUGET_API_KEY --source https://api.nuget.org/v3/index.json