A cross-platform re-implementation of O2Jam game server in C#.
This project is inspired by the Mozart Project 0.028.
Supported client version: v5.89* (O2JamO2 Final)
* Non-beta client that has 3K Mode. Compatible with O2Solista v0.3, v0.5 and v0.6
| Build | Supported client version |
|---|---|
| Mozart.Encore | v3.10 (O2Jam Original) |
| Amadeus.Encore | v3.82 (O2Jam NX) |
| CrossTime.Encore | v2.33 (O2Jam X2) |
| Identity.Encore | v5.89 (O2JamO2 Beta) |
Important
This project is free from copyrighted materials. All codes are original work written from scratch.
No copyrighted game assets, binaries, or master data are distributed in this repository.
You will have to provide metadata files in order to enable all functionalities. See Metadata files to learn more.
- Zero-Configuration for quick start.
- Full online and local network multiplayer support.
- Complete packet op-code coverage.
- Compatible with multiple SQL database systems.
- Support multi planet and channels deployment.
- Highly customizable with high-level network protocol implementation.
* FTP and In-game web server features are not included.
| Project | Description |
|---|---|
| Encore | Custom TCP server framework |
| Mozart.Server | Core O2Jam server implementation |
| Mozart.Data | Data persistent implementation |
| Mozart.Migrations | Database migrations with various drivers |
| Identity.Web | Lightweight HTTP Web server |
| Identity | Game server implementation for O2Jam client v5.89 |
The server can be configured either with config.ini or command-line arguments.
See Command-line configuration provider to set up command-line config.
Server deployment mode and TCP connection setting.
Use --Server:<Option> to configure these settings via command-line arguments (e.g, --Server:Port=15010)
| Option | Description |
|---|---|
Mode |
Server deployment mode. Supported values:
Full |
Address |
127.0.0.1 |
Port |
15010 |
MaxConnections |
The maximum number of clients connecting to the server. Default: 10000 |
PacketBufferSize |
The maximum number of bytes per message frame that can be processed by the server. Default: 4096 bytes |
Lightweight HTTP web server settings.
| Option | Description |
|---|---|
Enabled |
Determine whether the web server is enabled. Default: false |
Address |
Web server address to listen incoming requests. Using 0.0.0.0 may require admin privilege. Default: 127.0.0.1 |
Port |
HTTP port to listen incoming requests. Default: 15010 |
Database connection setting.
Use --Db:<Option> to configure these settings via command-line arguments
| Option | Description |
|---|---|
Driver |
Specify database provider. Supported drivers:
Sqlite |
Name |
Database name. Default: O2JAM |
Url |
Database Url, also known as Connection String. Default: Data Source=O2JAM.db |
MinBatchSize |
Minimum number of statements that are needed for a multi-statement command sent to the database. Default: (not configured) |
MaxBatchSize |
Maximum number of statements that are needed for a multi-statement command sent to the database. Default: (not configured) |
CommandTimeout |
The wait time (in seconds) before terminating the attempt to execute a command and generating an error. Default: (not configured) |
Determine auth behavior
Use --Auth:<Option> to configure these settings via command-line arguments.
| Option | Description |
|---|---|
Mode |
Determine the authentication scheme. Both Default and Foreign read from member table.
9you and GAMANIA are aliases for Foreign. |
SessionExpiry |
Determine the number of minutes before the session gets deleted from t_o2jam_login after the connection terminated.Set 0 to never expired which is recommended for single player or online server with custom session implementation. Otherwise, It is recommended to set between 2-5 minutes.Default: 5 minutes |
RevokeOnStartup |
Clear login tables on start-up. Recommended to disable for local server. Default: true |
Gateway & Channels network and economy rating configuration. There must be at least one channel for the server to work properly.
Use --Gateway:<Option> & --Gateway:Channels:<N>:<Option> to configure these settings via command-line arguments (e.g, --Gateway:Channels:0:Id=0).
<N> is the index of channel table (not to be confused with channel id!).
The index (<N>) represents an array index and must always start from 0, ordered and with no gap in-between. The Id however, can be un-ordered and with gaps in-between.
These options can be configured under Gateway section.
Tip
This configuration is ignored in the Full deployment mode.
| Option | Description |
|---|---|
Address |
127.0.0.1 |
Port |
15047 |
Timeout |
The maximum wait time (in seconds) for establishing connection between the gateway and the channel. Default: 30 seconds |
These options can be configured under Gateway:Channels:<N> section as explained above.
Tip
This configuration is ignored in the Gateway deployment mode.
Important
You can only have exactly one channel in the Channel deployment mode.
| Option | Description |
|---|---|
Id |
The channel id (required) |
Capacity |
Channel maximum capacity. Default: 100 |
Gem |
GEM reward rate. Default: 1.0 |
Exp |
EXP reward rate. Default: 1.0 |
MusicList |
Path of OJNList.dat exclusive for this channel. Format must compatible with client v5.89 (O2JamO2 Final). Default: (Empty) using global Metadata |
ItemData |
Path of Itemdata.dat exclusive for this channel. Format must compatible with client v5.89 (O2JamO2 Final). Default: (Empty) using global Metadata |
Metadata files that act as source of truth of particular game data outside the database. They are optional for running the server, but features such as play reward, ranking and the equipment system will not function without them.
Metadata can be usually overriden per channel.
Important
You must supply the metadata files that are compatible with the client version supported by this build.
Use --Metadata:<Option> to configure these settings via command-line arguments.
| Option | Description |
|---|---|
MusicList |
Relative or absolute path of OJNList.dat. Format must compatible with client v5.89 (O2JamO2 Final). |
ItemData |
Relative or absolute path of Itemdata.dat. Format must compatible with client v5.89 (O2JamO2 Final). |
Gameplay-specific settings.
Use --Game:<Option> to configure these settings via command-line arguments.
| Option | Description |
|---|---|
AllowSoloInVersus |
Specify whether playing solo is eligible in VS Mode. Default: true |
SingleModeRewardLevelLimit |
The maximum level limit of gaining reward in Single mode. Default: Level 10 |
FreeMusic |
Unlock all premium music based on the provided MusicList. Default: true |
MusicLoadTimeout |
The maximum wait time (in seconds) before terminating unresponsive client sessions when loading the game music. Note: when one or more clients are timed out, the remaining clients will still likely stuck for a certain amount of time regardless of this setting. Default: 60 seconds |
Use Entity Framework tools to run the database migration. See Entity Framework Core CLI tools to learn more about the CLI installation.
Important
You may notice that the database schema look funky with premature normalizations here and there.
This is intentional because the app need to support the existing official database schema.
The table structure represents a best-effort attempt to follow the e-Games database distribution. Structures that are known exclusive to the foreign database distribution are omitted.
However, unlike official server app, Mozart will not interact with database via Stored Procedure and will execute DML directly.
The migration files are divided by projects based on provider. Use the following command to create a new migration:
# Replace "MySql" with your preferred database driver
dotnet ef migrations add --project Source\Mozart.Migrations\MySql\Mozart.Migrations.MySql.csproj \
--startup-project Source\Identity\Identity.csproj \
--context Mozart.Data.Contexts.MainDbContext \
<migration name>
-- Auth:Mode=<auth mode> \
Db:Driver=<driver> \
Db:Url="<connection string>"Important
Database migration is automatically executed every start-up as long as the Auth:Mode equals to Default.
This is because Auth:Mode=Foreign is a compatibility mode that enables Mozart to continue to work with an existing foreign database that has different auth schema than the original e-Games clients (such as 9you or GAMANIA).
Database migration will never be officially supported in Foreign mode*.
* The server will likely raise an exception with PendingModelChangesWarning when running database migration with Foreign mode.
The errors can be suppressed, but there's no guarantee that migration will continue to work using foreign auth schema for the future releases.
Tip
The -- token directs dotnet ef to treat everything that follows as an argument and not try to parse them as options.
Any extra arguments not used by dotnet ef are forwarded to the Mozart.
Tip
You can place the configured config.ini in your working directory to configure the database configuration
instead of passing them via CLI.
Run the following command to execute the migration:
dotnet ef database update --project Source\Mozart.Migrations\MySql\Mozart.Migrations.MySql.csproj \
--startup-project Source\Identity\Identity.csproj \
--context Mozart.Data.Contexts.MainDbContext \
-- Auth:Mode=<auth mode> \
Db:Driver=<driver> \
Db:Url="<connection string>"By default, the server exposes user registration and login APIs used to generate the authentication tokens required to run the game.
The original web server files (ASP Classic) are not included and cannot be hosted within this project. This functionality considered out-of-scope, and unlikely to be added in the future.
Warning
Official NOWCOM clients does not allow custom web server url by default. The game simply does not respect the web server address in the launch argument.
Therefore, even if the original web server is ported into this Web Server module, enabling in-game shop functionality still requires either modifying the game client or configuring client-side host settings.
Warning
Scaling is a feature that 99% users won’t ever need.
It’s intended for niche scenarios—such as replicating the original server’s scaling infrastructure—or for deployments across constrained hardware (e.g., deploying servers into multiple microcontrollers).
Like many traditional MMOs, O2Jam shards its network traffic across multiple servers known as Planets, each of which hosts several Channels.
To support this design, you must run Mozart.Encore in separate instances:
-
Gateway
- One instance per
Planet - Listens for all incoming end-user client connections
- Keeps track of its Planet’s Channel instances
- One instance per
-
Channel
- One instance per
Channel - Handles persistent and non-persistent in-game states for its assigned Channel
- One instance per
There can only be one "node" of Gateway or Channel instance at a time, and it cannot be horizontally scaled.
You cannot run multiple instances to represent a single Gateway or Channel, because each instance is the scaling unit of the horizontal scaling itself.
See Server and Gateway & Channels configuration section above to configure the Gateway and Channel instances.
Clients specify all available Gateways when launching O2Jam via OTwo.exe. The syntax is:
OTwo.exe <encrypted_parameters> \
|test|??|<gateway_address_1>|<gateway_port_1>\
|test|??|<gateway_address_2>|<gateway_port_2>\
…\
|test|??|<gateway_address_n>|<gateway_port_n>Caution
If you are using batch or terminal directly, make sure that the pipe (|) are escaped using ^.
For example: ^|test^|??^|127.0.0.1^|15010
Note
The number of servers are not explicitly specified.
See AuthParameters and AuthParameterRsaChiper to view the details on how encode or decode the encrypted_parameters works.
Use user:authorize command to generate the session and the encrypted parameters.
For example, if you have three Planets (three Gateways), you might use:
OTwo.exe 00C70200E85000DF8E00E..... \
|test|??|192.168.10.1|15010\
|test|??|192.168.10.2|15011\
|test|??|192.168.10.3|15012\Tip
You may mirror one gateway instance for multiple planets by reusing the same IP and port multiple times. For example:
OTwo.exe 00C70200E85000DF8E00E..... \
|test|??|192.168.10.1|15010\
|test|??|192.168.10.1|15010\
|test|??|192.168.10.1|15010\Upon start-up, the Channel instances will register themselves to the configured Gateway instance via TCP network.
Therefore, the Gateway need to be available first. This will allow the Gateway instances to discover Channels that available for user to select.
When the Channel lost its connection to its Gateway, it will automatically shut down itself.
It might be possible to host and scale Mozart.Encore in kubernetes via agones. However, it may require code changes.
Please refer to their documentation and third-party examples to learn more.
The server application has built-in utilities to help local player usage or server maintenance.
db:migrate: Execute database migration within the configured database.user:register: Register a new user.user:authorize: Authorize user credential. Display encoded auth parameters that can be used to launch the game.ranking:upsert: Generates or updates user rankings. This command is intended to be executed periodically using a scheduled cron job.
Run the CLI with --help flag for more details.