⚠️ Educational Purpose Disclaimer This project is created strictly for educational and research purposes to explore game client architecture, network protocols, and cross-platform development with .NET and MonoGame. This is a non-commercial, open-source learning project that demonstrates reverse engineering and game development concepts.
https://youtu.be/_ekXCQI2byE
| Component | Version | Download Link |
|---|---|---|
| .NET SDK | 10.0+ | Download |
| Git | Latest | Download |
| MuOnline Data | Season 20 (1.20.61) | Download |
| Data S6 Patch | Season 6 | Download |
git clone https://github.com/xulek/muonline.git
cd muonline
This client requires Season 20 (1.20.61) client data files for assets (models, textures, maps) but communicates using Season 6 protocol.
Data folderOpen Client.Main/Constants.cs and update line 25:
// Windows
public static string DataPath = @"C:\Games\MU_Red_1_20_61_Full\Data";
// Linux/macOS
public static string DataPath = "/home/user/Games/MU_Red_1_20_61_Full/Data";
Edit Client.Main/appsettings.json:
{
"MuOnlineSettings": {
"ConnectServerHost": "localhost",
"ConnectServerPort": 44405,
"ProtocolVersion": "Season6",
"ClientVersion": "1.04d",
"ClientSerial": "0123456789ABCDEF"
}
}
This client is designed to work with OpenMU, an open-source MuOnline server implementation.
Quick Start with Docker:
# Download and run OpenMU server
curl -o docker-compose.yml https://raw.githubusercontent.com/MUnique/OpenMU/master/deploy/all-in-one/docker-compose.yml
docker-compose up -d
The server will be available at localhost:44405 (matches default client configuration).
Alternative: You can also connect to any Season 6 compatible MuOnline server.
# Restore .NET tools
dotnet tool restore
# Build the solution
dotnet build
# Windows (DirectX 11 - Recommended)
dotnet run --project ./MuWinDX/MuWinDX.csproj -f net10.0-windows -c Debug -p:MonoGameFramework=MonoGame.Framework.WindowsDX
# Windows (OpenGL - For compatibility)
dotnet run --project ./MuWinGL/MuWinGL.csproj -f net10.0-windows -c Debug -p:MonoGameFramework=MonoGame.Framework.DesktopGL
# Linux
dotnet run --project ./MuLinux/MuLinux.csproj -f net10.0 -c Debug
# macOS
dotnet run --project ./MuMac/MuMac.csproj -f net10.0 -c Debug
# macOS (force prebuilt content fallback)
dotnet run --project ./MuMac/MuMac.csproj -f net10.0 -c Debug -p:UsePrebuiltContent=true
muonline/
├── Client.Data/ # Data file readers (BMD, ATT, MAP, OZB, etc.)
├── Client.Main/ # Core game engine, networking, UI, game logic
│ ├── Client.Main.Shared.props # shared settings
│ ├── Client.Main.*.csproj # platform variants: desktop/windows/android/ios
├── Client.Data/ # data processing (platform variants)
│ ├── Client.Data.Shared.props
│ ├── Client.Data.*.csproj
├── Client.Editor/ # Asset editor tool
├── MuWinGL/ # Windows OpenGL executable (MonoGame.Framework.DesktopGL)
├── MuWinDX/ # Windows DirectX 11 executable (MonoGame.Framework.WindowsDX)
├── MuAndroid/ # Android executable project
├── MuIos/ # iOS executable project
├── MuLinux/ # Linux executable project
└── MuMac/ # macOS executable project
For predictable restores and to avoid missing workloads, build/clean one head at a time.
# Windows DirectX (Recommended)
dotnet clean MuWinDX/MuWinDX.csproj && dotnet build MuWinDX/MuWinDX.csproj -c Debug -p:MonoGameFramework=MonoGame.Framework.WindowsDX
# Windows OpenGL
dotnet clean MuWinGL/MuWinGL.csproj && dotnet build MuWinGL/MuWinGL.csproj -c Debug -p:MonoGameFramework=MonoGame.Framework.DesktopGL
# Linux
dotnet clean MuLinux/MuLinux.csproj && dotnet build MuLinux/MuLinux.csproj -c Debug
# macOS
dotnet clean MuMac/MuMac.csproj && dotnet build MuMac/MuMac.csproj -c Debug
# macOS (force prebuilt content fallback)
dotnet clean MuMac/MuMac.csproj && dotnet build MuMac/MuMac.csproj -c Debug -p:UsePrebuiltContent=true
# Android (requires Android workload)
dotnet workload restore
dotnet clean MuAndroid/MuAndroid.csproj && dotnet build MuAndroid/MuAndroid.csproj -c Debug
# iOS (requires macOS + Xcode + iOS workload)
dotnet workload restore
dotnet clean MuIos/MuIos.csproj && dotnet build MuIos/MuIos.csproj -c Debug
Build outputs are placed in bin/Release/ directories.
For the maximum-performance DirectX build, use the validated publish script:
./scripts/publish/windows-performance.ps1
The script publishes a self-contained win-x64 folder build with ReadyToRun, tiered compilation, dynamic PGO, optimized shaders, disabled runtime diagnostics, and a SHA-256 manifest. It also validates the generated runtime configuration before creating the archive.
A diagnostic Release build can be produced without the compile-time performance profile:
dotnet publish ./MuWinDX/MuWinDX.csproj -c Release -r win-x64 -p:PerformanceRelease=false
OpenGL remains available as the compatibility backend:
dotnet publish ./MuWinGL/MuWinGL.csproj -c Release -r win-x64 -o publish-gl -p:MonoGameFramework=MonoGame.Framework.DesktopGL
The GitHub Actions workflow automatically builds both Windows versions (OpenGL and DirectX) on every push to main and publishes them to GitHub Pages.
dotnet publish ./MuLinux/MuLinux.csproj -f net10.0 -c Release -r linux-x64 --self-contained
dotnet publish ./MuMac/MuMac.csproj -f net10.0 -c Release
# Force prebuilt content fallback during publish
dotnet publish ./MuMac/MuMac.csproj -f net10.0 -c Release -p:UsePrebuiltContent=true
MuMac.csproj supports two content workflows:
Content.mgcb and builds content normally..xnb files from:
Client.Main/MGContent/PrebuiltContent/DesktopGL/ContentHow it works:
wine is available, build stays in default MGCB mode.wine is not available, build automatically switches to prebuilt mode.-p:UsePrebuiltContent=true.To prepare prebuilt content:
wine).DesktopGL .xnb files into:
Client.Main/MGContent/PrebuiltContent/DesktopGL/ContentClient.Main/MGContent/Content.mgcb.dotnet publish ./MuAndroid/MuAndroid.csproj -f net10.0-android -c Release \
-p:AndroidSdkDirectory="<path-to-android-sdk>" \
-p:JavaSdkDirectory="<path-to-jdk-11>" \
-p:AcceptAndroidSdkLicenses=True
# Requires macOS with Xcode and valid signing certificates
dotnet publish ./MuIos/MuIos.csproj -f net10.0-ios -c Release
This project implements a layered architecture with clear separation of concerns:
┌─────────────────────────────────────────────────────────┐
│ Platform Layer │
│ (MuWinGL/MuWinDX, MuLinux, MuMac, MuAndroid, MuIos) │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Client.Main (Core) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Scenes │ │ Networking │ │ Rendering │ │
│ │ (Login/Game) │ │ (S6 Proto) │ │ (MonoGame) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Game Objects │ │ UI System │ │ World System │ │
│ │(Player/NPC) │ │ (GameControl)│ │ (Terrain) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Client.Data (Data Readers) │
│ BMD • ATT • MAP • OZB • OZG • CWS • OBJS │
└─────────────────────────────────────────────────────────┘
BaseScene base class with LoginScene, LoadScene, GameSceneChangeWorldAsync<T>()PacketRouter - Dual-mode routing (ConnectServer/GameServer)[PacketHandler] - Attribute-based handler registrationLoginService, CharacterService, ConnectServerServiceWorldObject → PlayerObject, MonsterObject, NPCObject, DroppedItemObjectScopeManager handles object visibility and lifecycleGameControl with lifecycle methodsUiScalerMuGame.ScheduleOnMainThread(Action) for thread safety| Format | Description | Usage |
|---|---|---|
| BMD | 3D models and skeletal animations | Characters, monsters, items, NPCs |
| ATT | Terrain walkability attributes | Collision detection, pathfinding |
| MAP | Terrain heightmap data | 3D terrain rendering |
| OZB/OZG | Compressed texture formats | Textures for models and UI |
| CWS | Camera walk/pan scripts | Cinematic camera movements |
| OBJS | Object placement data | Map decorations and static objects |
Debug vs Release builds have different configurations:
Debug Settings:
SHOW_DEBUG_PANEL: true - Shows FPS, position, network statsUNLIMITED_FPS: true - Disables VSync for testingDataPath - Absolute path to data filesRelease Settings:
SHOW_DEBUG_PANEL: falseDataPath - Relative to executable locationRendering Options:
RENDER_SCALE: 2.0 - Supersampling multiplierENABLE_DYNAMIC_LIGHTING_SHADER: true - GPU-based lightingMSAA_ENABLED: false - Multi-sample anti-aliasing (performance impact){
"Logging": {
"LogLevel": {
"Default": "Information",
"Client.Main.Networking": "Trace"
}
},
"MuOnlineSettings": {
"ConnectServerHost": "localhost",
"ConnectServerPort": 44405,
"ProtocolVersion": "Season6",
"ClientVersion": "1.04d",
"ClientSerial": "0123456789ABCDEF",
"Graphics": {
"Width": 1280,
"Height": 720,
"IsFullScreen": false,
"UiVirtualWidth": 1280,
"UiVirtualHeight": 720
}
}
}
| Feature | OpenGL (MuWinGL) | DirectX 11 (MuWinDX) |
|---|---|---|
| Performance | Good | Excellent (modern GPUs) |
| Compatibility | Excellent (older hardware) | Windows 10/11 only |
| Shader Model | 3.0 (vs_3_0/ps_3_0) | 4.0 (vs_4_0/ps_4_0) |
| Visual Quality | Identical | Identical |
| Cross-Platform | Yes (same as Linux/macOS) | Windows-only |
| Stability | Very stable | Stable (fixed GPU sync issues) |
Both versions produce identical visual results but use different rendering paths:
Shader Compatibility:
#if OPENGL) to support both backendsKnown Fixed Issues (DirectX):
Contributions are welcome! This is an educational project, and we encourage learning and experimentation.
git checkout -b feature/amazing-feature)git commit -m 'Add amazing feature')git push origin feature/amazing-feature)async/await for networking operationsMuGame.ScheduleOnMainThread()Found a bug or have a question? Open an issue on GitHub.
This project is created for educational and research purposes only.
Protocol Implementation: The Season 6 network protocol implementation is based on publicly available information and reverse engineering for educational purposes.
Recommended Use Cases: