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

280 lines
7.5 KiB
Markdown

# 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=<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:
```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
```