Skip to content

Game record

Game is the record one of these per minigame. It bundles the id, display name, accent colour, GameKind (singleton vs multi-lobby), LobbyConfig, StagingConfig, a PhaseFlow, and optional GameHooks. GameRegistry reads these fields and auto-builds the hub pad, the /conduit join <id> subcommand, and routes engine events into the hook callbacks.

  • You’re registering a new minigame and want the standard hub-lobby-arena wiring.
  • You want lifecycle hooks (onJoin, onDamage, onPhase, onButton) routed automatically.
  • You’re picking between the built-in phase flows or supplying your own.
package me.zlex.conduit.game;
public record Game(
String id,
Component displayName,
int accentColor,
GameKind kind,
LobbyConfig lobby,
StagingConfig staging,
PhaseFlow flow,
GameHooks hooks) {
public static Builder builder(String id, String displayName);
public static final class Builder {
public Builder accent(int argb);
public Builder kind(GameKind k);
public Builder lobby(LobbyConfig l);
public Builder staging(StagingConfig s);
public Builder flow(PhaseFlow f);
public Builder hooks(GameHooks h);
public Game build();
}
}

GameHooks is a 10-field record of nullable callbacks fired at well-defined moments — onZoneEntry, onPadEntry, onJoin, onLeave, onDamage, onEliminate, onPhase, onButton, onLobbyBuilt, onTearDown. Build via GameHooks.builder() and only wire what you need.

import me.zlex.conduit.game.Game;
import me.zlex.conduit.game.GameHooks;
import me.zlex.conduit.game.GameKind;
import me.zlex.conduit.game.GameRegistry;
import me.zlex.conduit.game.LobbyConfig;
import net.fabricmc.api.ModInitializer;
import net.minecraft.world.item.Items;
import java.util.List;
public final class SprintRaceMod implements ModInitializer {
@Override
public void onInitialize() {
Game game = Game.builder("sprint-race", "Sprint Race")
.accent(0xFFFFD700)
.kind(GameKind.MULTI_LOBBY)
.lobby(LobbyConfig.defaults("SPRINT RACE")
.withMaxPlayers(10)
.withPad(Items.YELLOW_WOOL)
.withType("Race")
.withTagline(List.of("First 3 to the finish line win.")))
.hooks(GameHooks.builder()
.onJoin((inst, p) -> SprintRound.onJoin(inst, p))
.onLeave((inst, p) -> SprintRound.onLeave(inst, p))
.onPhase((inst, prev, next) -> SprintRound.onPhase(inst, prev, next))
.build())
.build();
GameRegistry.register(game);
}
}
  • If you don’t supply a PhaseFlow, the builder picks PhaseFlow.defaultMulti() for MULTI_LOBBY and defaultSingleton() for SINGLETON.
  • GameHooks.none() is the safe empty-hooks value — easier than nullable-checking every field.
  • The accentColor field is reused for chat highlights, the pad’s particle ring, and the lobby header bar — pick a colour that reads well in all three.