From 24ee43b3a3ee2efe3083483ff7365b04c8e2b28c Mon Sep 17 00:00:00 2001 From: kayjaydee Date: Fri, 24 Apr 2026 17:35:14 +0200 Subject: [PATCH] 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 --- README.md | 313 ++++++++++++++++++++++++++++++++++++++++++++++++++++ SHOWCASE.md | 144 ------------------------ 2 files changed, 313 insertions(+), 144 deletions(-) create mode 100644 README.md delete mode 100644 SHOWCASE.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..e3078cd --- /dev/null +++ b/README.md @@ -0,0 +1,313 @@ +

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 cornersDefined region with cyan outline overlayPlayer walking on the ceiling
Items rising inside the fountain zoneDense particle visualizationShowcase 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 subcommands** — `wand`, `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` API. +- **Two visualization modes** — `Outline` (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 physics** — `VerticalForce` (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-.jar` into `/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 ` | 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 ` | Removes a region from disk and memory. | `/gravityflip delete arena` | +| `/gravityflip toggle ` | Enables or disables a region without deleting its config. | `/gravityflip toggle arena` | +| `/gravityflip tp ` | 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 ` 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.0`–`1.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 `/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 + +```bash +# 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 "/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 + +```bash +# 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= or set in gradle.properties +# Disable with: -PdevServerMods=disabled +``` + +### Extending the Plugin + +Adding a new subcommand is three lines: + +```java +// 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/.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)| ++-----------+-----------+ +-------------+------------+ + | | + | 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 ) + 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` 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. +- **Concurrency** — `Config#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`, `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 + +**v1** — **shipped** — 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](https://mythlane.com)** 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. diff --git a/SHOWCASE.md b/SHOWCASE.md deleted file mode 100644 index 17dbf11..0000000 --- a/SHOWCASE.md +++ /dev/null @@ -1,144 +0,0 @@ -# Hytale Gravity Flip - -![Java 25](https://img.shields.io/badge/Java-25-orange) -![Gradle](https://img.shields.io/badge/Gradle-Shadow-green) -![Hytale](https://img.shields.io/badge/Hytale-2026.03.26-blueviolet) -![Status](https://img.shields.io/badge/v1-shipped-brightgreen) - -> A Hytale server plugin that lets builders create **inverted-gravity zones** entirely in-game — no code, no restarts. Define a region with a wand, name it, and every player, NPC, or item inside immediately flips upward. - ---- - -## Video Showcase - -[![Gravity Flip Demo](https://img.youtube.com/vi/VIDEO_ID/maxresdefault.jpg)](https://www.youtube.com/watch?v=VIDEO_ID) - -*Click to watch on YouTube* - ---- - -## Screenshots - - - -![Wand selection on two corners](docs/screenshots/01-wand-selection.png) -![Defined region with cyan outline overlay](docs/screenshots/02-region-outline.png) -![Player walking on the ceiling](docs/screenshots/03-walk-on-ceiling.png) -![Items rising inside the fountain zone](docs/screenshots/04-item-fountain.png) -![Dense particle visualization](docs/screenshots/05-dense-particles.png) -![Showcase arena, wide shot](docs/screenshots/06-showcase-arena.png) - ---- - -## Features - -- **Six in-game subcommands** — `wand`, `define`, `list`, `show`, `remove`, `reload`. Full workflow without touching config files. -- **Per-UUID wand selection store** — each builder has their own pair of corners, survives rejoin. -- **Persistent regions** — all zones saved to `regions.json`, reloaded at boot. -- **Two visualization modes** — `Outline` (box wireframe) and `Particles` (volumetric fill) with configurable color, opacity, refresh rate, density. -- **Per-entity affect toggles** — target players only, items only, NPCs only, or any combination. -- **Configurable physics** — `VerticalForce` (lift strength) and `GracePeriodMs` (smooth entry transition) per region. -- **Optional fall-damage immunity** — turn off fall damage when leaving a zone so demos don't hurt. -- **Hot reload** — `/gravityflip reload` re-reads `regions.json` without restarting the server. -- **Tick-loop detection** — efficient AABB containment check each tick, scales to dozens of active regions. - ---- - -## Quick Start - -1. **Install** — drop `MythlaneGravityFlip--all.jar` into `Server/mods/` and start the server. -2. **Get the wand** — in-game, run `/gravityflip wand`. You receive the custom *Gravity Flip Wand* item. -3. **Pick two corners** — left-click block A (min corner), right-click block B (max corner). -4. **Name the region** — `/gravityflip define my_zone`. Gravity inverts inside the box immediately. - ---- - -## Command Reference - -| Command | Effect | -| ------------------------------- | ---------------------------------------------------------------------- | -| `/gravityflip wand` | Grants the *Gravity Flip Wand* item to the caller. | -| `/gravityflip define ` | Creates a region from the caller's current wand selection. | -| `/gravityflip list` | Prints every registered region with coords and enabled state. | -| `/gravityflip show ` | Highlights a region's outline for quick visual lookup. | -| `/gravityflip remove ` | Deletes a region from disk and memory. | -| `/gravityflip reload` | Re-reads `regions.json` without restarting the server. | - ---- - -## Technical Highlights - -- **Java 25** — modern pattern matching, records, sealed types. -- **Gradle Shadow** — single fat-jar output (`./gradlew shadowJar`). -- **Hytale plugin API** — integrates with `Config` for typed persistence, `Interaction.CODEC` for the custom wand behavior, and a custom item asset pack for the wand visual. -- **Pure-data selection store** — `WandSelectionStore` keyed by player UUID, testable without a live server. -- **Tick-driven detection** — per-tick AABB containment, entity-type gating, grace-period smoothing. -- **Codec-registered interactions** — wand left/right-click registered through `Interaction.CODEC` so the item reacts natively. - ---- - -## Showcase Regions - -These ship in the `regions.json` bundled with the dev server and cover every plugin capability. Spawn is at `(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 - -```bash -# Build the plugin jar -./gradlew shadowJar - -# Copy to your Hytale server -cp build/libs/MythlaneGravityFlip-*-all.jar "/Server/mods/" - -# Restart the server — the plugin auto-registers its item, interactions, and tick listener. -``` - -On first boot the plugin creates `Server/mods/Mythlane_GravityFlip/regions.json`. Edit in-game via commands, or hand-edit the file and `/gravityflip reload`. - ---- - -## Development - -```bash -# Run the dev server (auto-deploys the shadow jar into the configured HYTALE_SERVER_DIR) -./gradlew devServer -``` - -Repository layout: - -``` -src/main/java/com/mythlane/gravityflip/ - plugin/ # Entry point, interaction + item registration - regions/ # Region model, store, JSON persistence - wand/ # Wand item, selection store, interaction handlers - command/ # /gravityflip subcommand implementations - tick/ # Per-tick AABB detection and physics application - visual/ # Outline + particle renderers -src/test/java/... # Pure-data unit tests (selection store, region codec, etc.) -docs/screenshots/ # Portfolio assets -``` - ---- - -## License / Credits - -Built by **[Mythlane](https://mythlane.com)**. - -Plugin references: inspired by the structure of VotePipe and the `myth_*` Hytale plugin family (Kotlin DSL scaffolding, CamelCase manifests, `gradle.properties` conventions).