Files
hytale-gravity-flip/README.md
T
kayjaydee 24ee43b3a3 docs: replace SHOWCASE.md with comprehensive README.md
- Replace portfolio-only SHOWCASE with unified README as sole project entry page
- Add full user guide: commands table, wand flow, region anatomy (all 15 config fields sourced from GravityFlipRegion.CODEC), visual modes, regions.json path
- Add developer section: prerequisites (JDK 25, Hytale API), project structure, build/test/deploy commands, extension snippets
- Add architecture overview with ASCII diagram (tick loop, wand flow, persistence)
- Correct subcommand list (wand/define/list/delete/toggle/tp) to match GravityFlipCommand source
- Preserve showcase content: video placeholder, screenshot grid (HTML table), 12 showcase regions table, feature list
- Add shields.io badges, tech-stack, roadmap, credits, license sections
2026-04-24 17:35:14 +02:00

18 KiB
Raw Blame History

Hytale Gravity Flip

Builder-friendly anti-gravity zones for Hytale servers.
Define a region with a wand, name it, walk on the ceiling — no code, no restarts.

Java 25 Gradle Shadow Hytale 2026.03.26 v1 shipped License


Showcase

Gravity Flip — video demo

Click to watch on YouTube

Screenshots

Wand selection on two corners Defined region with cyan outline overlay Player walking on the ceiling
Items rising inside the fountain zone Dense particle visualization Showcase arena, wide shot

Features

  • Builder-first workflow — define regions entirely in-game with a custom wand. No config editing required for the common case.
  • Six subcommandswand, define, list, delete, toggle, tp.
  • Per-UUID wand selection store — each builder owns their own pair of corners; survives rejoin.
  • Persistent regions — every zone serialised to regions.json, reloaded on boot via the Hytale Config<T> API.
  • Two visualization modesOutline (AABB wireframe) and Particles (volumetric emitters on edges) with configurable color, opacity, refresh rate, and density. None for production.
  • Per-entity affect toggles — target players only, items only, NPCs only, or any combination.
  • Configurable physicsVerticalForce (lift strength) and GracePeriodMs (smooth entry transition) per region.
  • Optional fall-damage immunity — suppress fall damage when leaving a zone so demos don't hurt.
  • Tick-loop detection — efficient AABB containment check each tick (~100 ms), scales to dozens of active regions.
  • First-run bootstrap — the plugin auto-seeds a demo region on first boot so the mechanic works out of the box.

Quick Start

  1. Install — drop hytale-gravity-flip-<version>.jar into <HytaleServer>/Server/mods/ and start the server.
  2. Get the wand — run /gravityflip wand in-game. You receive the Gravity Flip Wand item.
  3. Pick two corners — primary-click block A (pos1), secondary-click block B (pos2).
  4. Name the region/gravityflip define my_zone. Gravity inverts inside the box immediately.
  5. Fly up. Congratulations.

User Guide

Commands

All commands are sub-commands of /gravityflip.

Command Description Example
/gravityflip wand Gives the caller a Gravity Flip Wand item. /gravityflip wand
/gravityflip define <name> Creates a region from the caller's current wand selection (both corners required). /gravityflip define arena
/gravityflip list Prints every registered region with its AABB coordinates and enabled state. /gravityflip list
/gravityflip delete <name> Removes a region from disk and memory. /gravityflip delete arena
/gravityflip toggle <name> Enables or disables a region without deleting its config. /gravityflip toggle arena
/gravityflip tp <name> Teleports the caller to the center of a region (handy for large or hidden zones). /gravityflip tp arena

The Wand

The Gravity Flip Wand is a custom item registered through Hytale's item asset pack and Interaction.CODEC.

  • Primary click on a block → sets pos1 (min corner candidate).
  • Secondary click on a block → sets pos2 (max corner candidate).
  • Selection is stored per player UUID in an in-memory WandSelectionStore. Rejoining the server preserves the selection for the session.
  • Once both corners are set, /gravityflip define <name> normalizes them into an axis-aligned Box(min, max) and persists the region.

Region Anatomy

Every region is serialised to regions.json via GravityFlipRegion.CODEC. Only Name and Box are mandatory; every other field has a sensible default and can be omitted.

Field Type Default Description
Name string (required) Unique region identifier used by commands.
Box AABB (required) Axis-aligned box { "min": [x,y,z], "max": [x,y,z] }. Min must be component-wise ≤ Max.
Enabled boolean true If false, the region is persisted but dormant (no detection, no visualization).
FallDamage boolean false If true, vanilla fall damage is preserved. false suppresses fall damage on exit.
GracePeriodMs integer 2500 Smooth entry transition window (ms). 0 = instant flip.
VerticalForce double 0.1 Upward force applied per tick. Gentle lift ≈ 0.05. Launch pad ≈ 0.3.
AffectPlayers boolean true Flip players inside the region.
AffectNpcs boolean true Flip NPCs / mobs inside the region.
AffectItems boolean true Flip dropped items inside the region.
VisualColor string #00FFFF Hex color for the outline / particle tint.
VisualMode string Outline One of Outline, Particles, None.
VisualRefreshMs integer 1000 How often the visualization is re-emitted (ms). Lower = smoother, heavier.
VisualOpacity double 0.5 Overlay opacity, 0.01.0.
VisualParticleId string Torch_Fire Hytale particle asset id used in Particles mode. Dust_Sparkles_Fine is invisible in-world.
VisualParticleDensity double 0.3 Particles per edge unit. 1.0 saturates; 0.1 is sparse.

Visual Modes

  • Outline — colored AABB wireframe, refreshed every VisualRefreshMs. Best for builders and debugging.
  • Particles — particle emitters along the box edges, density and id configurable. Best for gameplay / showcase.
  • None — region is invisible. Use in production once builders are done.

Configuration File

The region file lives at <HytaleServer>/Server/mods/Mythlane_GravityFlip/regions.json and is written by the plugin whenever a command mutates the registry.

  • Hot-reload: not currently exposed as a subcommand — restart the server (or reload the plugin host) after hand-edits.
  • Auto-save contract: command handlers save immediately after mutations. External edits must restart.
  • First-run: if regions.json is empty/missing, the plugin seeds one showcase region (demo-gravity-flip, box (0,100,0)..(10,120,10), particles on).

Showcase Regions

A set of curated regions ships with the dev server's regions.json. They collectively exercise every plugin capability. Spawn is (0, 81, 0) on a superflat surface.

Region Min Max What it demonstrates
tutorial_walk_on_ceiling (10, 81, 10) (15, 86, 15) Baseline player-only flip with cyan outline.
item_fountain (20, 80, 10) (23, 100, 13) Tall vertical zone, items only — drop stuff and watch it rise.
mob_chamber (30, 81, 10) (40, 89, 20) NPC-only flip with red outline.
full_chaos (-15, 81, 10) (0, 91, 25) Players + NPCs + items, purple particles.
gentle_lift (-40, 80, -20) (-20, 85, 0) Soft VerticalForce=0.05 — slow drift.
strong_launch (-15, 80, -15) (-10, 83, -10) Aggressive VerticalForce=0.3 — launch pad.
grace_period_demo (15, 81, -20) (23, 87, -12) GracePeriodMs=5000 — smooth fade-in.
no_grace (25, 81, -20) (33, 87, -12) GracePeriodMs=0 — instant flip, side-by-side comparison.
fall_damage_off (40, 110, 0) (50, 120, 10) Elevated zone with FallDamage=false — safe exit.
disabled_example (-30, 81, 0) (-25, 86, 5) Enabled=false — persisted but inert, proves state handling.
showcase_arena (-80, 81, -80) (-50, 96, -50) 30×15×30 gold-outlined arena — hero shot for video.
dense_particles (50, 81, 50) (58, 89, 58) VisualParticleDensity=1.0 — maxed visual saturation.

Installation

# 1. Build the plugin jar
./gradlew clean shadowJar

# 2. Copy the fat-jar into your Hytale server's mods folder
cp build/libs/hytale-gravity-flip-*.jar "<HytaleServer>/Server/mods/"

# 3. (Re)start the server — the plugin auto-registers its item, interaction, and tick loop.

On first boot the plugin creates Server/mods/Mythlane_GravityFlip/regions.json and seeds a demo region. Edit in-game via commands, or hand-edit the file and restart.


Development

Prerequisites

  • JDK 25 (toolchain enforced by Gradle).
  • Hytale Plugin API — pulled from https://maven.hytale.com/release as com.hypixel.hytale:Server. Version pinned via hytaleServerVersion in gradle.properties.
  • A local Hytale dev server (for the optional copyJarToDevServer deploy task).

Project Structure

src/main/java/com/mythlane/gravityflip/
  GravityFlipPlugin.java          # Entry point (setup / start / shutdown lifecycle)
  command/                        # /gravityflip root + 6 sub-commands
  config/                         # GravityFlipConfig — persisted region list codec
  region/                         # GravityFlipRegion, RegionRegistry, RegionSnapshot
  wand/                           # WandSelectionStore + Interaction (CODEC-registered)
  tick/                           # RegionTickLoop — per-tick AABB detection
  physics/                        # GravityApplier, FallDamageGuard, FallDamageSuppressorSystem
  viz/                            # RegionVisualizer + ParticleEdgeEmitter
src/main/resources/
  manifest.json                   # Hytale plugin manifest (filtered by processResources)
  Server/Item/Items/
    gravityflip_wand.json         # Custom wand item asset
  Server/Interaction/RootInteractions/
    gravityflip_wand_root.json    # Wand root interaction definition
src/test/java/...                 # JUnit 5 unit tests (pure-data stores, codec round-trips)
docs/screenshots/                 # Portfolio assets

Build

# Fat-jar (shadow) with gson relocated to com.mythlane.gravityflip.libs.gson
./gradlew clean shadowJar

# Run tests
./gradlew test

# Build + auto-deploy to the configured dev server
./gradlew shadowJar
# The shadowJar task is finalized by copyJarToDevServer, which copies to:
#   C:/Users/minit/Desktop/HYTALE SERVER/Server/mods (default)
# Override with: -PdevServerMods=<path>   or set in gradle.properties
# Disable with:  -PdevServerMods=disabled

Extending the Plugin

Adding a new subcommand is three lines:

// In GravityFlipCommand.java
this.addSubCommand(new GravityFlipMySubCommand(plugin));

Adding a new wand-triggered interaction: register an additional Interaction.CODEC entry in GravityFlipPlugin#setup() and reference it from your item's Interactions block in src/main/resources/Server/Item/Items/<item>.json.

Adding a new region field: append a KeyedCodec<> entry to GravityFlipRegion.CODEC with a setter/getter pair. Absence in existing regions.json preserves the Java default (no migration needed).


Architecture

+-----------------------+       +--------------------------+
|  Player / NPC / Item  |       |  regions.json (Config<T>)|
+-----------+-----------+       +-------------+------------+
            |                                 |
            | per-tick AABB check             | loaded at start()
            v                                 v
    +-------+--------+               +--------+---------+
    | RegionTickLoop | <------------ | RegionRegistry   |
    +-------+--------+               +------------------+
            |
            | entity in enabled region?
            v
    +-------+---------+       +-------------------+
    | GravityApplier  | ----> | y-velocity invert |
    | + FallDamageGrd |       | + fall-dmg guard  |
    +-----------------+       +-------------------+

  Wand flow (independent, command-driven):

    Player primary/secondary click
           |
           v
    GravityFlipWandInteraction (Interaction.CODEC registered)
           |
           v
    WandSelectionStore (keyed by UUID)
           |
           v (on /gravityflip define <name>)
    RegionRegistry.add(...) -> configHolder.save()

Key technical notes:

  • Plugin entrypoint (GravityFlipPlugin) owns the lifecycle and all singletons. Wand interaction and item codec are registered in setup(); tick loop and command registry are wired in start().
  • Persistence uses Config<GravityFlipConfig> from the Hytale core API — typed JSON codec, atomic save semantics. The get() call is deferred past setup() because it blocks on preLoad().
  • Tick loop runs every ~100 ms with a 2 s startup delay to let Universe.get() settle. World is resolved lazily each tick, so the tick is a no-op until the world is ready.
  • Wand interaction is registered through Interaction.CODEC under the key "GravityFlipWand", matching the gravityflip_wand_root.json root interaction that the item references.
  • Asset pack is bundled inside the jar (IncludesAssetPack: true in manifest.json) and includes the wand model, icon, interaction root, and item definition.
  • ConcurrencyConfig<T>#get() returns a shared mutable reference; RegionRegistry snapshots it into an AtomicReference for lock-free tick-loop reads.

Tech Stack

  • Java 25 — modern records, pattern matching, sealed types.
  • Gradle 8 + com.gradleup.shadow 9.3.1 — fat-jar build with gson relocation.
  • Hytale Plugin API (com.hypixel.hytale:Server) — JavaPlugin, Config<T>, Interaction.CODEC, BuilderCodec, KeyedCodec, Universe / World access.
  • Gson 2.10.1 — relocated under com.mythlane.gravityflip.libs.gson to avoid classpath clashes.
  • JUnit 5.10 — pure-data unit tests for selection store and codec round-trips.

Roadmap

v1shipped — custom wand, 6 subcommands, outline + particle visualization, per-region physics tuning, per-entity affect toggles, JSON persistence, first-run bootstrap, dev-server auto-deploy task.

v2 — planned:

  • Hot-reload subcommand (/gravityflip reload) without restart.
  • HUD indicator when entering/leaving a zone.
  • Border visualization improvements (antialiased, beveled corners).
  • Multi-world support (regions keyed by world id).
  • Custom gravity profiles per region (horizontal push, directional gravity, zero-G).
  • Import / export region sets as shareable JSON bundles.
  • Permissions integration (who can create / edit / delete).

Credits

Built by the Mythlane team.

Plugin structure and conventions informed by the VotePipe and myth_* Hytale plugin family (Kotlin/Java scaffolding, CamelCase manifests, gradle.properties versioning).


License

License TBD. Contact socials@mythlane.com for usage inquiries.