Build your first game
Zero to a running SkyWars in five steps. Every file shown whole, then build, run and join.
This walks the whole path: an empty folder to a SkyWars you can join. It targets Hytale, so you write one module and never think about engines. Total: three files and a manifest.
1. Scaffold the module
A game is an ordinary Gradle module that produces a shadow jar. Two dependencies: the SDK and the engine adapter.
skywars/
build.gradle.kts
src/main/
java/net/example/
SkyWars.java
SkyWarsConfig.java
resources/
hive-game.json plugins {
java
id("com.gradleup.shadow") version "8.3.0"
}
dependencies {
// the SDK + the Hytale adapter; nothing else to wire
implementation("dev.hivescale:hive-sdk:1.0.0")
implementation("dev.hivescale:minigame-hytale:1.0.0")
} 2. Declare it: hive-game.json
This sits in resources/ and is the only thing the network needs to register,
size and route your game. minPlayers / maxPlayers / countdownSeconds drive
the lobby; arena tells the genre which world to load and which markers are
spawns. Full field list in Manifest & config.
{
"id": "skywars",
"name": "SkyWars",
"genre": "match",
"engine": "hytale",
"main": "net.example.SkyWars",
"minPlayers": 2,
"maxPlayers": 12,
"countdownSeconds": 20,
"arena": {
"world": "skywars-map-1",
"spawns": "Player_Spawnpoint"
}
} 3. Type your settings
Per-network knobs are a plain class. The network loads it, validates it, and
hands it to your instance as ctx.config(). Operators tune these from the
dashboard without a rebuild.
package net.example;
public final class SkyWarsConfig {
public int chestRefillSeconds = 120;
public boolean doubleJump = true;
} 4. Write the game
The whole game is three overrides. You describe what happens at start, on death, and at the end; the genre runs everything else around them, the countdown, the win check, scoring, and sending the winner home.
package net.example;
import dev.hivescale.minigame.match.MatchLifecycle;
import dev.hivescale.minigame.match.MatchContext;
import dev.hivescale.minigame.match.MatchResult;
import dev.hivescale.minigame.PlayerHandle;
public final class SkyWars extends MatchLifecycle<SkyWarsConfig> {
// The lobby filled and the countdown hit zero. Drop everyone
// onto their island. ctx.spawn(p) reads the arena's
// "Player_Spawnpoint" markers for you.
@Override
public void onStart(MatchContext ctx) {
ctx.players().forEach(p -> p.teleport(ctx.spawn(p)));
ctx.broadcast("Last one standing wins. Go!");
}
// A player died. Eliminate them; the genre checks the win
// condition and ends the match when one player is left.
@Override
public void onDeath(PlayerHandle p, MatchContext ctx) {
ctx.eliminate(p);
ctx.broadcast(p.name() + " is out. " + ctx.alive().size() + " left.");
}
// The match ended. The winner is already paid out and sent
// home; this is just the closing line.
@Override
public void onEnd(MatchResult result, MatchContext ctx) {
result.winner().ifPresent(w -> ctx.broadcast(w.name() + " won!"));
}
} That is the complete game. There is no game loop, no tick handler, no thread management, no server registration code.
Coming from raw Hytale? That last paragraph is the whole point. A hand-written Hytale party game has to stand up its own 30 Hz tick loop and hop every callback onto the world thread before it can do anything:
The part you no longer write// What a hand-rolled Hytale party game does for the loop alone // (GINCo's Byte Crashers, paraphrased): Timer timer = new Timer("GameTick", true); timer.scheduleAtFixedRate(new TimerTask() { public void run() { World w = gameStateManager.getBoardWorld(); if (w != null && w.isAlive()) w.execute(() -> gameStateManager.tick()); } }, 0L, 33L); // 30 Hz, by hand, plus thread-hopping into the worldThe genre owns that loop. You only fill in the verbs.
5. Build, run, join
# Build the jar
$ ./gradlew shadowJar
# Drop it on a Hytale server and point it at your network
$ cp build/libs/skywars-all.jar myserver/mods/
$ export HIVE_API_KEY=hv_live_••••••••••••••••
$ java -jar HytaleServer.jarThe jar self-registers on startup, so the server shows up as a skywars host in
matchmaking immediately. Now join from a lobby (or a second
client) and watch the flow:
- You land in the waiting lobby. Matchmaking keeps routing players in.
- At
minPlayersthe countdown starts, announced for you. - At zero,
onStartfires, everyone is teleported to a spawn, and the match begins. - As players die,
onDeatheliminates them and broadcasts the count. - One left, the genre pays out,
onEndruns, and the winner is sent home.
You wrote three methods and got all of that.
Where to go next
- Add a Hytale-only flourish (a particle burst on elimination) with the native escape hatch. It is one line and stays clearly marked.
- Match games covers the full lifecycle, teams and custom win conditions.
- Building a Mario-Party-style host instead? Party games.