Files
HeruEdhel 7394e8f874 feat: Add leaderboard and stats UI for minigames
- Implemented MinigameLeaderboardUIService to manage the leaderboard UI.
- Created MinigameLeaderboardUISystem to handle UI updates.
- Added methods in MinigameStatsService and MinigameStatsRepository for fetching top players and distinct dimension values.
- Introduced new commands for accessing minigame stats in the command language.
- Added tests for minigame interactions and ensured proper decoding of interaction fields.
- Refactored MinigameRuntimeEffect to utilize MinigameActionContext for better context handling.
2026-06-25 09:06:41 -07:00

7.5 KiB

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

gradlew.bat shadowJar

Run with the local Hytale server

gradlew.bat runServer

Create a minigame definition

Manually by adding a file under src/main/resources/Server/Minigames/: or via the asset editor.

{
  "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):

/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=<id>, MapId=<map>, optional VariantId=<variant>, and MapRole=MainArena on the primary arena volume. Team spawn volumes use SpawnRole=TeamSpawn and TeamId=<team>. MapSelectionMode controls whether a queued match uses votes or random selection.

To bootstrap common logic, spawn editable template volumes at your position:

/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:

{
  "Interactions": {
    "Secondary": {
      "Interactions": [
        {
          "Type": "MinigameJoinMinigameQueue",
          "MinigameId": "Skywars"
        }
      ],
      "Cooldown": {
        "Id": "join_skywars_queue",
        "Cooldown": 1.0
      }
    }
  }
}

Reusable assets:

Server/Item/Interactions/join_skywars_queue.json

{
  "Type": "MinigameJoinMinigameQueue",
  "MinigameId": "Skywars"
}

Server/Item/RootInteractions/join_skywars_queue_secondary.json

{
  "Interactions": [
    "join_skywars_queue"
  ],
  "Cooldown": {
    "Id": "join_skywars_queue",
    "Cooldown": 1.0
  }
}

Then reference the root interaction from an item:

{
  "Interactions": {
    "Secondary": "join_skywars_queue_secondary"
  }
}

Project Structure

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 How the Hytale-native pieces fit together
Minigame Definition MinigameDefinition JSON fields
Events, Conditions & Effects Current trigger condition/effect reference
Volumes How to use normal Hytale trigger volumes for minigames
Trigger Volume Tags Complete tag reference for maps, spawns, and signals
Commands /minigame command reference
Examples Small setup patterns

Build Commands

gradlew.bat compileJava
gradlew.bat processResources
gradlew.bat shadowJar