From 2b23d87c805cc113812f9130f4b7d3ed36d84253 Mon Sep 17 00:00:00 2001 From: kayjaydee Date: Fri, 24 Apr 2026 18:11:02 +0200 Subject: [PATCH] docs: update README.md for clarity and structure - Simplified project description and improved readability. - Changed section titles for better organization (e.g., "Showcase" to "Demo"). - Reformatted screenshots into a markdown table for a cleaner layout. - Enhanced the "What Does It Do?" section to clearly outline features. - Streamlined the Quick Start and Commands sections for easier navigation. --- README.md | 363 +++++++++++++++++++----------------------------------- 1 file changed, 130 insertions(+), 233 deletions(-) diff --git a/README.md b/README.md index e3078cd..0fa6ebb 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,6 @@ -

Hytale Gravity Flip

+# 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.
-

+Gravity Flip lets you create anti-gravity regions on your Hytale server using a wand — no scripting, no file edits, no server restarts. Want to walk on the ceiling? Place two corners, name the region, and flip the world.

Java 25 @@ -15,7 +12,7 @@ --- -## Showcase +### Demo

@@ -23,291 +20,191 @@ Gravity Flip — video demo

+

Click to watch

-

Click to watch on YouTube

+#### Screenshots -### 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
+| ![](docs/screenshots/01-wand-selection.png) | ![](docs/screenshots/02-region-outline.png) | ![](docs/screenshots/03-walk-on-ceiling.png) | +| --- | --- | --- | +| ![](docs/screenshots/04-item-fountain.png) | ![](docs/screenshots/05-dense-particles.png) | ![](docs/screenshots/06-showcase-arena.png) | --- -## Features +## What Does It Do? -- **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. +- Mark a region in game with a wand tool. +- Instantly flips gravity *inside your box* for players, items, and/or mobs, depending on your config. +- Everything is persisted to disk, no fiddling with configs. +- Toggle regions, delete, teleport, etc., all via `/gravityflip` commands. +- Visualize with outlines or particles. Toggle between modes. +- Built for builders: no code, minimal ceremony. --- ## 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.** +1. Copy `hytale-gravity-flip-.jar` into your server's `mods` folder. +2. Run your server. +3. Use `/gravityflip wand` in-game to get the Gravity Flip Wand. +4. Left-click a block (corner 1), right-click another (corner 2). +5. Run `/gravityflip define ` — done. Gravity now flips inside that box. --- -## User Guide +## Commands -### Commands +All commands are subcommands of `/gravityflip`: -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). +| Command | What it does | +| ------------------------------- | --------------------------------------------------------- | +| `/gravityflip wand` | Gives you the wand. | +| `/gravityflip define ` | Defines a region from your selection. | +| `/gravityflip list` | Lists all registered regions and their info. | +| `/gravityflip delete ` | Removes a region. | +| `/gravityflip toggle ` | Enables/disables a region. | +| `/gravityflip tp ` | Teleports you to a region's center. | --- -## Showcase Regions +### How The Wand Works -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. | +- Left-click = set pos1 +- Right-click = set pos2 +- Each player gets their own selection — it sticks until changed/logged out. +- When both corners are set, run `/gravityflip define ` --- -## Installation +## Region Fields + +Gravity Flip regions are saved as JSON. Each region needs a `Name` and a `Box` (AABB). The rest have defaults. + +| Field | Type | Default | What it means | +|-------------------------|---------|-------------|-------------------------------------------------| +| Name | string | required | The name/id you use in commands. | +| Box | array | required | `{min: [x,y,z], max: [x,y,z]}` | +| Enabled | bool | true | If off, region does nothing. | +| FallDamage | bool | false | Keep vanilla fall damage? (usually off) | +| GracePeriodMs | int | 2500 | Smooths the gravity transition (ms). | +| VerticalForce | float | 0.1 | How strong the anti-grav is. | +| AffectPlayers | bool | true | Flip players? | +| AffectNpcs | bool | true | Flip mobs/NPCs? | +| AffectItems | bool | true | Flip dropped items? | +| VisualColor | string | #00FFFF | Outline/particle color. | +| VisualMode | string | Outline | Outline, Particles, or None. | +| VisualRefreshMs | int | 1000 | How often visuals are updated (ms). | +| VisualOpacity | float | 0.5 | Outline transparency (0–1) | +| VisualParticleId | string | Torch_Fire | Particle id for "Particles" mode. | +| VisualParticleDensity | float | 0.3 | Particle density along edges. | + +--- + +## Visualization + +- **Outline**: Wireframe box for editing and debugging. +- **Particles**: Edges emit particles. +- **None**: Go "invisible" for production/live use. + +--- + +## The Region File + +Sits at `Server/mods/Mythlane_GravityFlip/regions.json`. Changing regions via commands saves instantly. If you hand-edit, restart the server. First run always seeds a "demo" region. + +--- + +## Prebuilt Regions (for dev/testing) + +| Name | Min | Max | Purpose | +|----------------------|---------------|---------------|----------------------------------------| +| tutorial_walk_on_ceiling | (10,81,10) | (15,86,15) | Simple walk-on-ceiling, cyan outline | +| item_fountain | (20,80,10) | (23,100,13) | Items float up, for demos | +| mob_chamber | (30,81,10) | (40,89,20) | Mobs only, red outline | +| full_chaos | (-15,81,10) | (0,91,25) | Players, mobs, items — chaos, purple | +| gentle_lift | (-40,80,-20) | (-20,85,0) | Weak antigrav | +| strong_launch | (-15,80,-15) | (-10,83,-10) | Launch pad settings | +| grace_period_demo | (15,81,-20) | (23,87,-12) | Entry anim with grace period | +| no_grace | (25,81,-20) | (33,87,-12) | Instant flip, for comparison | +| fall_damage_off | (40,110,0) | (50,120,10) | Fall damage off, high up | +| disabled_example | (-30,81,0) | (-25,86,5) | Persisted but disabled | +| showcase_arena | (-80,81,-80) | (-50,96,-50) | 30x15x30 gold-outlined box | +| dense_particles | (50,81,50) | (58,89,58) | Ultra-dense particle effect | + +--- + +## Installing ```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. +./gradlew shadowJar +cp build/libs/hytale-gravity-flip-*.jar /Server/mods/ +# Restart your server ``` -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. +On first start, `/regions.json` is seeded with a demo region. Use the wand/commands to manage regions. --- ## Development -### Prerequisites +* Requires **JDK 25**, Gradle, Hytale Plugin API (from https://maven.hytale.com/release), and a dev server. +* Code lives in `src/main/java/com/mythlane/gravityflip/` +* Unit tests: pure-data logic is covered in `src/test/java/` -- **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 +### Building ```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 +./gradlew shadowJar # Build the fat jar with gson relocation +./gradlew test # Run unit tests ``` -### Extending the Plugin +For dev fast-deploy, see `copyJarToDevServer` gradle task. -Adding a new subcommand is three lines: +### Extending -```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). +- New subcommand? Add a class, register in `GravityFlipCommand`. +- New wand interaction? Register in the plugin `setup()` and hook it in assets. +- New region field? Add to the codec; existing JSON will keep defaults. --- -## Architecture +## How It Works ``` -+-----------------------+ +--------------------------+ -| 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 | - +-----------------+ +-------------------+ +Player/NPC/Item + | + v (checked every tick) + RegionTickLoop + | <---- Regions loaded from regions.json + GravityApplier + FallDamageGuard + | + region effect - 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() +Wand: + Player clicks -> WandSelectionStore -> define region -> registry saves to JSON ``` -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. +- Tightly integrated Hytale plugin — lifecycle hooks, asset registration, everything inside the jar. +- Tick loop: runs 10x/sec, checks if entities are in zones, flips gravity as needed. +- Threading: regions are snapshotted for fast concurrent reads. +- Plugin self-seeds demo region so you never boot to an empty world. --- -## Tech Stack +## 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). +- Java 25, modern features (records, sealed types, etc). +- Gradle 8 + shadowJar (Gson relocated out of the global space). +- Hytale Plugin API core (JavaPlugin, Config, Interaction.CODEC). +- JUnit 5 for testing data and codecs. --- ## 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). +Made by [Mythlane](https://mythlane.com). Plugin layout/modeling borrowed from our VotePipe and related plugins. --- ## License -License TBD. Contact **socials@mythlane.com** for usage inquiries. +License to be decided. Ping socials@mythlane.com for questions.