Hosting infrastructure, service registration, and lifecycle helpers for Minecraftonia applications.
$ dotnet add package Minecraftonia.HostingMinecraftonia is a work-in-progress voxel sandbox built with C# 13/.NET 9 and Avalonia. The project experiments with custom voxel ray tracing, procedural terrain, and responsive desktop UI while staying fully cross-platform.
Minecraftonia.sln organizes the modular libraries, the desktop client, and supporting samples.
.
├── src/
│ ├── Minecraftonia/ # Avalonia desktop client and launcher
│ ├── Minecraftonia.Core/ # Core domain primitives (BlockType, configs, enums)
│ ├── Minecraftonia.Content/ # Procedural block textures and material providers
│ ├── Minecraftonia.VoxelEngine/ # Chunk streaming, voxel storage, and player math
│ ├── Minecraftonia.Rendering.Core/ # Frame buffers, camera math, and material sampling
│ ├── Minecraftonia.Rendering.Pipelines/ # CPU ray tracer, FXAA, GI, and renderer factories
│ ├── Minecraftonia.Rendering.Avalonia/ # Avalonia render control and frame presenters
│ ├── Minecraftonia.Hosting/ # Game loop host abstractions shared across frontends
│ ├── Minecraftonia.Hosting.Avalonia/ # Avalonia keyboard/pointer capture utilities
│ ├── Minecraftonia.Game/ # Gameplay orchestration, saves, and world bootstrap
│ ├── Minecraftonia.MarkovJunior/ # MarkovJunior-inspired rule engine
│ ├── Minecraftonia.MarkovJunior.Architecture/ # Procedural settlement layout helpers
│ ├── Minecraftonia.OpenStreetMap/ # Overpass-powered blueprint importer
│ └── Minecraftonia.WaveFunctionCollapse/ # 3D WFC solver and pattern library
├── samples/ # Minimal frontends demonstrating the libraries
│ ├── Minecraftonia.Sample.BasicBlock/
│ ├── Minecraftonia.Sample.Doom.Core/
│ ├── Minecraftonia.Sample.Doom/
│ └── Minecraftonia.Sample.Doom.Avalonia/
├── docs/ # Reference docs and smoke-test guides
├── tools/ # Utility scripts
└── publish/ # Local publish output
src/ maps 1:1 to a published NuGet package (or the desktop app) so you can pull in only what you need.docs/smoke-tests.md.Each package ships with XML docs and guards, but the snippets below show a quick integration recipe. Install the packages with dotnet add package <Name>.
Install: dotnet add package Minecraftonia.Core
using Minecraftonia.Core;
var config = MinecraftoniaWorldConfig.FromDimensions(
width: 256,
height: 96,
depth: 256,
waterLevel: 48,
seed: 0xC0FFEE);
Console.WriteLine($"World size: {config.Width}×{config.Height}×{config.Depth}");
Install: dotnet add package Minecraftonia.Content
using System.Numerics;
using Minecraftonia.Content;
using Minecraftonia.Core;
using Minecraftonia.VoxelEngine;
var textures = new BlockTextures();
var sample = textures.Sample(BlockType.Grass, BlockFace.PositiveY, 0.5f, 0.5f);
Console.WriteLine($"Grass RGB: {sample.Color}, opacity: {sample.Opacity:0.00}");
Install: dotnet add package Minecraftonia.VoxelEngine
using System.Numerics;
using Minecraftonia.Core;
using Minecraftonia.VoxelEngine;
public sealed class FlatWorld : VoxelWorld<BlockType>
{
public FlatWorld()
: base(new ChunkDimensions(16, 16, 16), chunkCountX: 4, chunkCountY: 1, chunkCountZ: 4)
{
}
protected override void PopulateChunk(VoxelChunk<BlockType> chunk)
{
for (int x = 0; x < chunk.Dimensions.SizeX; x++)
{
for (int z = 0; z < chunk.Dimensions.SizeZ; z++)
{
chunk.SetBlock(x, 0, z, BlockType.Grass, markDirty: false);
chunk.SetBlock(x, 1, z, BlockType.Dirt, markDirty: false);
}
}
}
}
var world = new FlatWorld();
world.EnsureChunksAround(new Vector3(8f, 0f, 8f), radius: 1);
Install: dotnet add package Minecraftonia.Rendering.Core
using System;
using Minecraftonia.Rendering.Core;
using var framebuffer = new VoxelFrameBuffer(new VoxelSize(320, 180));
Span<byte> pixels = framebuffer.Span;
for (int i = 0; i < pixels.Length; i += 4)
{
pixels[i + 0] = 0x40; // B
pixels[i + 1] = 0x90; // G
pixels[i + 2] = 0xE0; // R
pixels[i + 3] = 0xFF; // A
}
Install: dotnet add package Minecraftonia.Rendering.Pipelines
using Minecraftonia.Core;
using Minecraftonia.Game;
using Minecraftonia.Rendering.Core;
using Minecraftonia.Rendering.Pipelines;
var game = new MinecraftoniaGame();
var options = new VoxelRendererOptions<BlockType>(
renderSize: new VoxelSize(640, 360),
fieldOfViewDegrees: 75f,
isSolid: block => block.IsSolid(),
isEmpty: block => block == BlockType.Air);
var renderer = new VoxelRayTracerFactory<BlockType>().Create(options);
var result = renderer.Render(game.World, game.Player, game.Textures);
Install: dotnet add package Minecraftonia.Rendering.Avalonia
using Avalonia.Controls;
using Minecraftonia.Core;
using Minecraftonia.Game;
using Minecraftonia.Rendering.Avalonia.Controls;
using Minecraftonia.Rendering.Core;
using Minecraftonia.Rendering.Pipelines;
public sealed class GameView : UserControl
{
public GameView()
{
var game = new MinecraftoniaGame();
var renderer = new VoxelRayTracerFactory<BlockType>().Create(
new VoxelRendererOptions<BlockType>(
renderSize: new VoxelSize(640, 360),
fieldOfViewDegrees: 75f,
isSolid: block => block.IsSolid(),
isEmpty: block => block == BlockType.Air));
Content = new VoxelRenderControl<BlockType>
{
Renderer = renderer,
Materials = game.Textures,
World = game.World,
Player = game.Player,
RenderContinuously = true
};
}
}
Install: dotnet add package Minecraftonia.Hosting
using System;
using Minecraftonia.Core;
using Minecraftonia.Game;
using Minecraftonia.Hosting;
using Minecraftonia.Rendering.Core;
using Minecraftonia.Rendering.Pipelines;
using Minecraftonia.VoxelEngine;
var game = new MinecraftoniaGame();
var renderer = new VoxelRayTracerFactory<BlockType>().Create(
new VoxelRendererOptions<BlockType>(
renderSize: new VoxelSize(320, 180),
fieldOfViewDegrees: 70f,
isSolid: block => block.IsSolid(),
isEmpty: block => block == BlockType.Air));
var host = new GameHost<BlockType>(new Session(game), new Pipeline(renderer));
var frame = host.Step(TimeSpan.FromMilliseconds(16));
sealed class Session : IGameSession<BlockType>
{
private readonly MinecraftoniaGame _game;
public Session(MinecraftoniaGame game) => _game = game;
public IVoxelWorld<BlockType> World => _game.World;
public Player Player => _game.Player;
public IVoxelMaterialProvider<BlockType> Materials => _game.Textures;
public void Update(GameTime time) =>
_game.Update(
new GameInputState(
MoveForward: false,
MoveBackward: false,
MoveLeft: false,
MoveRight: false,
Sprint: false,
Jump: false,
KeyboardYaw: 0f,
KeyboardPitch: 0f,
MouseYawDelta: 0f,
MousePitchDelta: 0f,
BreakBlock: false,
PlaceBlock: false,
HotbarSelection: null,
HotbarScrollDelta: 0),
deltaTime: (float)time.Elapsed.TotalSeconds);
}
sealed class Pipeline : IRenderPipeline<BlockType>
{
private readonly IVoxelRenderer<BlockType> _renderer;
public Pipeline(IVoxelRenderer<BlockType> renderer) => _renderer = renderer;
public IVoxelRenderResult<BlockType> Render(IGameSession<BlockType> session, IVoxelFrameBuffer? framebuffer = null) =>
_renderer.Render(session.World, session.Player, session.Materials, framebuffer);
}
Install: dotnet add package Minecraftonia.Hosting.Avalonia
Assumes renderControl is the Avalonia control you want to capture.
using System;
using Avalonia;
using Avalonia.Controls;
using Minecraftonia.Hosting.Avalonia;
var topLevel = TopLevel.GetTopLevel(renderControl) ?? throw new InvalidOperationException("Control is not attached.");
var pointer = new PointerInputSource(topLevel, renderControl);
var keyboard = new KeyboardInputSource(topLevel);
pointer.EnableMouseLook();
void ProcessInput()
{
var deltaYaw = pointer.DeltaX;
var deltaPitch = pointer.DeltaY;
pointer.NextFrame();
keyboard.NextFrame();
}
Install: dotnet add package Minecraftonia.Game
using Minecraftonia.Game;
var game = new MinecraftoniaGame();
var input = new GameInputState(
MoveForward: false,
MoveBackward: false,
MoveLeft: false,
MoveRight: false,
Sprint: false,
Jump: false,
KeyboardYaw: 0f,
KeyboardPitch: 0f,
MouseYawDelta: 0f,
MousePitchDelta: 0f,
BreakBlock: false,
PlaceBlock: false,
HotbarSelection: null,
HotbarScrollDelta: 0);
game.Update(input, deltaTime: 1f / 60f);
Console.WriteLine($"Player position: {game.Player.Position}");
Install: dotnet add package Minecraftonia.MarkovJunior
using Minecraftonia.MarkovJunior;
using Minecraftonia.MarkovJunior.Rules;
var empty = new MarkovSymbol("Empty", paletteIndex: 0);
var wall = new MarkovSymbol("Wall", paletteIndex: 1);
var state = new MarkovJuniorState(16, 4, 16, empty);
var layer = new MarkovLayer("Scatter")
.AddRule(new NoiseFillRule("Walls", wall, threshold: 0.35, salt: 0x42));
var engine = new MarkovJuniorEngine(seed: 1234)
.AddLayer(layer);
engine.Execute(state);
Install: dotnet add package Minecraftonia.MarkovJunior.Architecture
using Minecraftonia.MarkovJunior.Architecture;
using Minecraftonia.WaveFunctionCollapse;
using Minecraftonia.WaveFunctionCollapse.Architecture;
var cluster = new SettlementCluster(
id: 1,
moduleType: ArchitectureModuleType.Market,
cells: new[] { (0, 0), (1, 0), (0, 1), (1, 1) });
var context = new ArchitectureClusterContext(cluster, tileSizeX: 8, tileSizeZ: 8);
var layout = ArchitectureRuleSet.GenerateLayout(
moduleType: ArchitectureModuleType.Market,
context,
seed: 2025);
Install: dotnet add package Minecraftonia.OpenStreetMap
using System;
using Minecraftonia.OpenStreetMap;
if (OpenStreetMapBlueprintGenerator.TryCreate(
width: 64,
depth: 64,
seed: Environment.TickCount,
out var blueprint,
out var source,
out var link))
{
Console.WriteLine($"Fetched blueprint for {source} ({link}) with {blueprint.Clusters.Count} clusters.");
}
else
{
Console.WriteLine("No blueprint available this time. Try a different seed.");
}
Install: dotnet add package Minecraftonia.WaveFunctionCollapse
using System;
using Minecraftonia.Core;
using Minecraftonia.WaveFunctionCollapse;
var library = VoxelPatternLibraryFactory.CreateDefault(worldHeight: 64, waterLevel: 32);
var generator = new WaveFunctionCollapseGenerator3D(
library,
gridSizeX: 4,
gridSizeZ: 4,
random: new Random(1337));
BlockType[,,] blocks = generator.Generate();
Console.WriteLine($"Generated pattern volume: {blocks.GetLength(0)}×{blocks.GetLength(1)}×{blocks.GetLength(2)}");
WriteableBitmap path or uploaded to a Skia GRContext-backed texture for crisp scaling without traditional GPU shaders.Minecraftonia.Hosting and .Hosting.Avalonia drive the update/render loop and pointer/keyboard capture used by the full game and sample apps alike.dotnet --info to confirm)git clone https://github.com/<your-account>/Minecraftonia.git
cd Minecraftonia
dotnet build Minecraftonia.sln
dotnet run --project Minecraftonia
The application launches directly into the main menu. Use the pointer to navigate or the keyboard (Enter/Space) to activate focused buttons.
The repo also ships with a lightweight sample that demonstrates the reusable rendering stack without the full game shell:
dotnet run --project samples/Minecraftonia.Sample.BasicBlock
The window now hosts SampleGameControl, which composes Minecraftonia.Hosting and .Hosting.Avalonia to reuse the same render/input loop as the main game. Click or press Tab to capture the pointer, then fly around the sample block column with WASD, Space, and Shift.
Render a classic-inspired hanger to a Portable Pixmap image using only the shared rendering pipelines:
dotnet run --project samples/Minecraftonia.Sample.Doom
This produces doom-frame.ppm in the working directory. Open the file with any PPM-compatible image viewer to inspect the voxel scene.
Launch an interactive Avalonia window orbiting the same voxel hall with mouse-look controls:
dotnet run --project samples/Minecraftonia.Sample.Doom.Avalonia
Use Tab/click to capture the mouse, move with the mouse, and press Esc to release the pointer.
Minecraftonia ships as a self-contained desktop app for each OS. To publish locally:
# Linux x64
dotnet publish src/Minecraftonia/Minecraftonia.csproj -c Release -r linux-x64 --self-contained true -o publish/linux-x64
# macOS Apple Silicon
dotnet publish src/Minecraftonia/Minecraftonia.csproj -c Release -r osx-arm64 --self-contained true -o publish/osx-arm64
# Windows x64
dotnet publish src/Minecraftonia/Minecraftonia.csproj -c Release -r win-x64 --self-contained true -o publish/win-x64
Each command creates an OS-specific directory under publish/ ready to zip and distribute.
The repository provides a cross-platform CI/CD pipeline in .github/workflows/build-and-release.yml:
main, pull requests, and tags prefixed with v.linux-x64, osx-arm64, and win-x64 self-contained binaries using .NET 9 (dotnet publish ... --self-contained true).zip/Compress-Archive).To cut a release, create and push a semver tag (e.g., git tag v0.3.0 && git push origin v0.3.0). The action produces ready-to-download archives under the new release.
| Action | Default | Notes |
|---|---|---|
| Move | W A S D | Arrow keys rotate the camera; Q/E nudge yaw without the mouse |
| Sprint | Shift | Hold while moving to increase travel speed |
| Jump | Space | Requires ground contact |
| Look | Mouse | F1 toggles pointer capture; Esc releases capture |
| Break Block | Left mouse button | Uses the current ray-traced hit |
| Place Block | Right mouse button | Places the selected hotbar block |
| Pause/Menu | Esc | Opens the in-game menu overlay |
| Invert X / Y | F2 / F3 | Toggles independently |
| Sensitivity | + / - | Adjusts mouse-look multiplier |
| Hotbar | 1-7, Tab, scroll wheel | Scroll cycles palette |
| Re-roll world | F5 | Swaps in a real-world inspired terrain snapshot with remapped materials |
Pause the game with Esc, then resume, save/exit, or return to the main menu.
Minecraftonia now ships with a voxel-aware Wave Function Collapse (WFC) generator tuned for Minecraft-like landscapes. Patterns are defined as 8×HEIGHT×8 voxel tiles with annotated edges (grass, shore, water, cliff, forest). The solver collapses a grid of these 3D patterns, honouring edge tags in all directions so terrain transitions stay coherent.
F5 to rebuild the world with a fresh WFC seed.VoxelPatternLibraryFactory.CreateDefault and can be extended or tweaked without touching the solver.BlockType[,,] payload plus sets of edge tags. Two edges are compatible when they share at least one tag, mirroring MarkovJunior-style rules.In addition to terrain WFC, Minecraftonia includes a rule-driven architectural generator built on a MarkovJunior-inspired engine. The pipeline creates layered passes:
Rules live in MarkovJunior/Architecture, and settlements are placed automatically wherever the macro blueprint tags regions as biome_settlement. Export additional debug maps by setting MINECRAFTONIA_ARCH_DEBUG=1 before launching; the engine will dump blueprint/layout snapshots under docs/debug/.
To add a new biome tile:
VoxelPattern3D with the desired block arrangement.WithEdgeTags) to describe how it should connect (for example "grass", "water", "cliff").The generator automatically retries when contradictions appear and falls back to the legacy noise terrain only if all attempts fail, keeping worlds playable.
Minecraftonia.sln
├── src/Minecraftonia/ # Avalonia desktop front-end
├── src/Minecraftonia.Game/ # Game orchestration, rendering bridge, save system
├── src/Minecraftonia.VoxelEngine/ # Core voxel world data structures & physics
├── src/Minecraftonia.Rendering.Pipelines/ # CPU ray tracer, GI/FXAA helpers, renderer interfaces
└── publish/ # Optional self-contained publish output
src/Minecraftonia (Desktop UI frontend)GameControl custom control and overlays menus rendered via XAML. Menu state is driven from MainWindow.axaml.cs, which responds to pause events and manages new/load/save flows.GameControl APIs to toggle raw mouse capture, warp the pointer to the window center, and react to Esc/F1 toggles, keeping UI and camera motion in sync.GameControl now advances simulation via TopLevel.RequestAnimationFrame. The loop self-reschedules only while attached to the visual tree, keeping update cadence tightly coupled to Avalonia’s compositor and avoiding timer drift.System.Numerics.Vector<T> operations, so we structure pixel buffers and deltas to maximise contiguous memory access for vectorised stages downstream.src/Minecraftonia.GameMinecraftoniaGame orchestration – Central façade coordinating player input, movement integration, voxel manipulation, and save/load. Capsule-vs-voxel sweeps handle collisions while the interaction system retains the closest ray hit for block breaking/placing. Chunk ranges are warmed before spawn to avoid hitching.MinecraftoniaVoxelWorld provides both legacy layered-noise terrain and a 3D-pattern WFC pipeline. Patterns encode voxel microstructures with edge tags, letting the solver assemble rivers, shores, cliffs, plains, and forests while respecting block-level adjacency.GameSaveData/PlayerSaveData capture world dimensions, chunk parameters, flattened block arrays, palette index, and player kinematics. Loading reconstructs chunks via span hydration to minimise allocations.GameControl converts keyboard/mouse/pointer events into GameInputState per frame and forwards it to _game.Update.src/Minecraftonia.VoxelEngineVoxelWorld<TBlock> maintains chunk dictionaries, but each chunk owns a contiguous block span. BlockAccessCache caches the current chunk/raw array so hot loops (ray tracing, serialisation) avoid repeated dictionary lookups.MoveWithCollisions performs axis-separated sweeps with step-up logic, delivering responsive first-person motion.Minecraftonia.Rendering.PipelinesVoxelRayTracer casts one centre ray per pixel, then conditionally adds stratified jitter samples when colour/alpha variance signals edge detail. DDA traversal caches chunk/local coordinates and runs per-scanline in parallel.Vector4 maths, letting .NET emit SSE/AVX instructions. The FXAA/sharpen pass copies the render buffer once and processes rows in parallel, preserving alpha while smoothing edges without supersampling cost.System.Numerics.Vector4 dot products and lerps for luma detection, blending, and sharpening, automatically mapping to hardware SIMD instructions on supported CPUs.GameControl.Render draws crosshair, FPS counter, hotbar selection, and block outlines over the framebuffer via Avalonia drawing primitives.GameControl gathers input (keyboard, mouse, pointer delta) each frame, marshals it into GameInputState, and calls _game.Update.MinecraftoniaGame applies look, movement, interactions, and updates the MinecraftoniaVoxelWorld accordingly.VoxelRayTracer fills a reusable CPU framebuffer; GameControl then presents it using either the legacy WriteableBitmap pathway or the Skia texture-backed presenter, depending on the configured mode.StartNewGame, LoadGame, CreateSaveData, or pointer capture toggles, coordinating via dispatcher calls to maintain smooth focus changes.Saves are stored under the user Application Data folder:
~/.config/Minecraftonia/Saves/latest.json%APPDATA%\Minecraftonia\Saves\latest.jsonFiles are JSON encoded GameSaveData objects. Corrupt or mismatched versions are rejected with clear error messaging in the UI.
main (e.g., feature/improve-water)dotnet build Minecraftonia.slnMinecraftonia is released under the MIT.
Have fun exploring! Contributions, bug reports, and feature suggestions are always welcome.