- Reduce javadocs to one-liners across config/region/physics/tick/viz/plugin root
- Translate residual French comments; no behavioural change
- Tests adjusted where assertions referenced French strings
- Removed a comment regarding the rejection of quoted arguments with spaces, as the validation logic is already covered by existing tests. This helps to keep the test code clean and focused.
Log cleanup:
- Drop redundant INFO "Gravity Flip enabled" in setup() (substantive version at
start() remains as the single startup line).
- Drop INFO "debug enter/exit notifier ENABLED" (the notifier itself emits per
region transition; extra startup noise not needed).
- Remove dead back-compat GravityApplier ctors that accepted an infoHandler
Consumer (no callers post-03-06; debug logs already stripped).
- Clean stale javadoc referencing removed [DBG npc.woken]/[DBG npc.ctrlNull]
one-shot logs.
- Also ship the pre-staged cleanup work: RegionEnterNotifier gated behind
GRAVITYFLIP_DEBUG_NOTIFY env var, GravityApplier infoHandler field removed,
tick logs stripped.
Efficiency:
- RegionVisualizer.resolveParticleId now memoises the requested->resolved
mapping in a ConcurrentHashMap, eliminating the ParticleSystem.getAssetMap()
lookup on every tick emission per region. Warn-once semantics preserved via
warnedInvalidIds. Fail-open path (AssetMap unavailable in tests) intentionally
does not populate the cache.
- Document in GravityApplier javadoc why Pass 1 + Pass 2 cannot be fused:
restore requires the complete currentlyInRegion set before diffing against
previouslyInverted.
Considered but not applied:
- ParticleEdgeEmitter.edgePoints caching per (box, density): throttled to
>=100ms refresh and typical <20 regions => alloc pressure negligible;
premature without measurement.
- Reusing RegionRegistry snapshot in RegionEnterNotifier: notifier is
opt-in/off-by-default, so its independent ECS scan has zero prod cost.
Tests: ./gradlew clean build green, no test changes required.
- Service GravityApplier qui toggle PhysicsValues.invertedGravity via CommandBuffer.replaceComponent
- Thread-safe tracker ConcurrentHashMap.newKeySet<UUID> pour dedup entre ticks
- Second pass O(N) pour restaurer la gravité à la sortie de région (trade-off v1 documenté)
- Pure diff static helper + hooks package-private pour tests unitaires sans runtime Hytale
- 6 tests verts (diff + tracker semantics)
- RegionTickLoop: single-thread daemon scheduler @100ms, 2s initial delay,
shutdown -> awaitTermination(5s) -> shutdownNow lifecycle.
Three start overloads: (World), (Supplier<World>), (Runnable). Errors are
routed to a Consumer<Throwable> so an exception in one tick never kills
the scheduler.
- GravityFlipPlugin.start():
* builds RegionRegistry from configHolder.get() + holder for save()
* starts the tick loop with a Supplier<World> that lazily resolves
Universe.get().getDefaultWorld() (deviation: PrepareUniverseEvent in the
pinned API only carries WorldConfigProvider — no Universe/World access,
so we use the lazy-supplier pattern from MythWorld instead)
* registers the ScheduledFuture with TaskRegistry (raw cast, try/catch fallback)
- GravityFlipPlugin.shutdown(): tickLoop.stop() BEFORE super.shutdown()
- RegionTickLoopTest: 3 timing tests pass (>=8 ticks/sec, stop within 5s,
exception resilience).
- gradle build green; fat jar contains both region/ and tick/ class dirs.
- GravityFlipConfig wraps List<GravityFlipRegion> via ArrayCodec under the
KeyedCodec("Regions", ...) entry. Decoded list is a mutable ArrayList
(NOT List.of(arr)) so Phase 4 commands can mutate at runtime.
- GravityFlipPlugin.configHolder uses the named overload
withConfig("regions", GravityFlipConfig.CODEC) — produces
<dataDirectory>/regions.json. The 1-arg overload would hardcode config.json.
- configHolder() javadoc documents the save contract (no auto-save on
shutdown; mutators must call configHolder.save() explicitly) and the shared
mutable reference caveat that 02-02's RegionRegistry will resolve.
- 4 round-trip tests cover: empty default, two-region order preservation,
empty list, and list mutability (regression guard against List.of).
- GravityFlipRegion holds Name (String) + Box (Hytale AABB) + Enabled (boolean),
serialised through a BuilderCodec keyed on "Name"/"Box"/"Enabled".
- Validators.nonNull() applied to Name and Box (correct package is
com.hypixel.hytale.codec.validation.Validators, not codec.builder).
- Server jar 2026.03.26 uses com.hypixel.hytale.math.vector.Vector3d for Box.min/max
(NOT org.joml.Vector3d, which only appeared in newer builds).
- 3 JUnit 5 round-trip tests cover name/box/enabled, enabled=false, and empty name.
- testImplementation added for the Server artifact so codec encode/decode is
reachable from unit tests.