# core-minigames A Hytale-native minigame extension for server-side minigame definitions, runtime state, and trigger-volume logic. The mod mirrors Hytale's own asset, trigger, and interaction systems instead of maintaining a separate minigame-only registry layer. Minigames are `MinigameDefinition` assets, trigger logic is registered as real `TriggerEffect` and `TriggerCondition` codec entries, item/entity/NPC actions can use real `Interaction` entries, and runtime events are dispatched on Hytale's event bus. ## Features - Asset-driven minigame definitions in `Server/Minigames/` - Hytale Asset Editor support through `MinigameDefinition.CODEC` - Hytale trigger-volume integration through native `TriggerEffect` and `TriggerCondition` types - Hytale interaction integration through native `Interaction` types for item/entity/NPC use actions - Asset-backed `MinigameId` picker fields in the trigger-volume editor - Asset-backed minigame trigger-volume templates in `Server/MinigameVolumeTemplates/` - Runtime lifecycle commands for creating, enabling, starting, stopping, and resetting minigames - Multi-map runtime support using Hytale trigger-volume tags - Player, team, score, lives, counter, status, and phase runtime state - Hytale event-bus dispatch through `MinigameEvent` ## Quick Start ### Build ```bash gradlew.bat shadowJar ``` ### Run with the local Hytale server ```bash gradlew.bat runServer ``` ### Create a minigame definition Manually by adding a file under `src/main/resources/Server/Minigames/`: or via the asset editor. ```json { "Id": "My_Minigame", "Name": "My Minigame", "Description": "A short description shown in menus.", "Enabled": true, "MinPlayers": 2, "MaxPlayers": 8, "TeamMode": "SOLO", "WinCondition": "HIGHEST_SCORE", "RoundLengthSeconds": 180, "CountdownSeconds": 10 } ``` Or create one from the server (saved into the named asset pack, so it survives restarts): ```text /minigame create MyAssetPack My_Minigame "My Minigame" /minigame enable My_Minigame /minigame start My_Minigame ``` Note: a game can only start once a trigger volume with a `SetMinigamePhase(ACTIVE)` effect exists for it — see `docs/architecture.md` (Lifecycle Contract). ## Trigger Volume Logic Use normal Hytale trigger volumes for the area shape and interaction point, then attach the minigame trigger conditions and effects. For multi-map minigames, tag volumes with `MinigameId=`, `MapId=`, optional `VariantId=`, and `MapRole=MainArena` on the primary arena volume. Team spawn volumes use `SpawnRole=TeamSpawn` and `TeamId=`. `MapSelectionMode` controls whether a queued match uses votes or random selection. To bootstrap common logic, spawn editable template volumes at your position: ```text /triggervolume minigametemplates /triggervolume minigametemplate core_lifecycle --MinigameId=My_Minigame --MapId=Arena01 /triggervolume minigametemplate team_arena --MinigameId=Battle --MapId=Castle --VariantId=Night ``` The UI remembers each builder's minigame/map variables. Both paths create normal Hytale trigger volumes with template tags replaced by the provided IDs. Available condition types: - `MinigamePhase` - `PlayerInMinigame` - `PlayerStatus` - `PlayerScore` - `TeamScore` - `Counter` - `CurrentRound` - `PlayerLives` - `TeamCondition` - `TimerElapsed` - `ObjectiveStatus` - `WinConditionMet` Available effect types: - `StartMinigame` - `EndMinigame` - `ResetMinigame` - `SetMinigamePhase` - `ResetScores` - `ModifyScore` - `ModifyCounter` - `ModifyLives` - `SetPlayerStatus` - `SetPlayerLoadout` - `JoinMinigameQueue` - `LeaveMinigameQueue` - `VoteForMap` - `StartQueuedMinigame` - `SpawnItem` - `SpawnNpc` - `MountPlayer` - `DismountPlayer` - `SetRound` - `StartTimer` - `StopTimer` - `SetSpawnPoint` - `RespawnPlayer` - `RespawnAllPlayers` - `SwapTeams` - `SendMinigameMessage` - `AssignTeam` - `SaveInventory` - `RestoreInventory` - `ClearInventory` - `SetObjectiveStatus` - `ModifyObjectiveProgress` - `AwardKillScore` - `PlaceBlocks` - `OpenMinigameQueueUI` - `StartPlayerTimer` - `StopPlayerTimer` Fields named `MinigameId` use an editor dropdown backed by registered `MinigameDefinition` assets. ## Interaction Logic Many minigame effects also have Hytale interaction counterparts. Interaction type IDs use the `Minigame` prefix plus the trigger effect ID, for example `MinigameJoinMinigameQueue`, `MinigameModifyScore`, and `MinigameOpenMinigameQueueUI`. Interaction-backed minigame actions use Hytale root interaction cooldown and chaining fields instead of trigger-volume `Event`, `Interval`, and `Delay`. Common routing fields are `MinigameId`, optional `MapId`, optional `VariantId`, and optional `TeamId`. Available interaction types: - `MinigameStartMinigame` - `MinigameEndMinigame` - `MinigameResetMinigame` - `MinigameSetMinigamePhase` - `MinigameResetScores` - `MinigameModifyScore` - `MinigameModifyCounter` - `MinigameModifyLives` - `MinigameSetPlayerStatus` - `MinigameSetPlayerLoadout` - `MinigameJoinMinigameQueue` - `MinigameLeaveMinigameQueue` - `MinigameVoteForMap` - `MinigameStartQueuedMinigame` - `MinigameSetRound` - `MinigameStartTimer` - `MinigameStopTimer` - `MinigameSetSpawnPoint` - `MinigameRespawnPlayer` - `MinigameRespawnAllPlayers` - `MinigameSwapTeams` - `MinigameSendMinigameMessage` - `MinigameAssignTeam` - `MinigameSaveInventory` - `MinigameRestoreInventory` - `MinigameClearInventory` - `MinigameSetObjectiveStatus` - `MinigameModifyObjectiveProgress` - `MinigameOpenMinigameQueueUI` - `MinigameStartPlayerTimer` - `MinigameStopPlayerTimer` Volume-only for now: `AwardKillScore`, `SpawnItem`, `SpawnNpc`, `MountPlayer`, `DismountPlayer`, and `PlaceBlocks`. Inline item secondary-use example: ```json { "Interactions": { "Secondary": { "Interactions": [ { "Type": "MinigameJoinMinigameQueue", "MinigameId": "Skywars" } ], "Cooldown": { "Id": "join_skywars_queue", "Cooldown": 1.0 } } } } ``` Reusable assets: `Server/Item/Interactions/join_skywars_queue.json` ```json { "Type": "MinigameJoinMinigameQueue", "MinigameId": "Skywars" } ``` `Server/Item/RootInteractions/join_skywars_queue_secondary.json` ```json { "Interactions": [ "join_skywars_queue" ], "Cooldown": { "Id": "join_skywars_queue", "Cooldown": 1.0 } } ``` Then reference the root interaction from an item: ```json { "Interactions": { "Secondary": "join_skywars_queue_secondary" } } ``` ## Project Structure ```text core-minigames/ |-- src/main/java/net/kewwbec/minigames/ | |-- MinigameCorePlugin.java | |-- action/ | |-- command/ | |-- event/ | |-- interaction/ | |-- model/ | |-- runtime/ | |-- service/ | `-- volume/ | |-- condition/ | `-- effect/ |-- src/main/resources/Server/ | |-- Languages/en-US/ | `-- Minigames/ |-- docs/ `-- wiki/ ``` ## Documentation | Doc | Description | |-----|-------------| | [Architecture](docs/architecture.md) | How the Hytale-native pieces fit together | | [Minigame Definition](docs/minigame-definition.md) | `MinigameDefinition` JSON fields | | [Events, Conditions & Effects](docs/events-conditions-effects.md) | Current trigger condition/effect reference | | [Volumes](docs/volumes.md) | How to use normal Hytale trigger volumes for minigames | | [Trigger Volume Tags](docs/tags.md) | Complete tag reference for maps, spawns, and signals | | [Commands](docs/commands.md) | `/minigame` command reference | | [Examples](docs/examples.md) | Small setup patterns | ## Build Commands ```bash gradlew.bat compileJava gradlew.bat processResources gradlew.bat shadowJar ```