Skip to content

Platform Model

Extension

Your game logic and assets, packaged into an mmx file

API

Everything you need to interact with Minecraft using MiniModes

Platform

MiniModes automatically translates your game to run on ANY platform, like a Paper server or a Fabric mod

An extension is a loadable game pack. The engine scans extension artifacts for @Game classes, creates game instances, binds a GameRuntime, and registers declared resources.

Extension artifacts conventionally build with Shadow and use the .mmx extension:

plugins {
kotlin("jvm")
id("com.gradleup.shadow")
}
dependencies {
compileOnly(project(":miniModes-api"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
}
tasks.shadowJar {
archiveClassifier.set("")
archiveBaseName.set(project.name)
archiveVersion.set(project.version.toString())
archiveExtension.set("mmx")
}

The important dependency choice is compileOnly(project(":miniModes-api")). The server supplies MiniModes. The extension compiles against the API and packages only its own helper code and required libraries.

The API layer gives you stable, platform-neutral handles:

  • GameTemplate and SettingsGameTemplate for lifecycle and game state.
  • GamePlayer, GameWorld, GameInventory, GameEntity, and GameVehicle for server objects.
  • EventsScope for normalized game events.
  • GameCommandsScope and GameInputTypes for typed local commands and prompts.
  • DSLs such as ItemDSL, sidebar, doubleJump, entity, projectile, vehicle, areas, and route.

The API does not force a single game structure. A tiny Spleef game can stay in one class; a larger mode can split arena generation, settings config, weapons, and scoring into separate files.

Core services own shared behavior:

  • Extension discovery and resource registration.
  • Game selection and pre-game sessions.
  • Party, rematch, and Mashup flow.
  • Settings voting and runtime settings.
  • Interactive item dispatch.
  • Sidebar binding and scoreboards.
  • Runtime disposal.

The Platform interface is the port surface implemented by server adapters:

interface Platform {
val scheduler: PlatformScheduler
val worlds: PlatformWorlds
val players: PlatformPlayers
val events: PlatformEvents
val entities: PlatformEntities
val projectiles: PlatformProjectiles
val vehicles: PlatformVehicles
val doubleJump: DoubleJumpService
}

Paper and Fabric adapters translate those calls into native server behavior. Extension code should stay above this layer unless it is intentionally doing adapter-specific work.

Every match has a gameId. The runtime uses it to scope:

  • Event subscriptions.
  • Scheduled tasks.
  • Player wrapper cache.
  • Worlds and world slots.
  • Projectiles and projectile metadata.
  • Vehicles.
  • Spawned entities and death handlers.

When a game ends through endGame, endGame(outcome), or manager cancellation, GameRuntime.dispose() unsubscribes events, cancels tasks, cleans platform registries for entities/projectiles/vehicles, clears player handles, and runs finalization hooks. World cleanup is performed by the game shutdown path.

That scoping is the core ergonomic promise of MiniModes: a game can create runtime objects liberally without hand-rolling cleanup lists for every feature.