Commit Graph

21 Commits

Author SHA1 Message Date
kayjaydee 0069d4c47e feat(03-05): ajoute 4 champs Visual* optionnels + round-trip tests (Task 1)
- GravityFlipRegion: VisualColor/VisualMode/VisualRefreshMs/VisualOpacity
  avec defaults (#00FFFF, Outline, 1000, 0.5), getters/setters, javadoc.
- CODEC: 4 KeyedCodec optionnels (pas de validator nonNull) => back-compat
  legacy regions.json.
- 2 tests round-trip (custom + defaults quand champs absents).
2026-04-23 14:52:42 +02:00
kayjaydee d43aa4a98c feat(03-04): FallDamageSuppressorSystem + wiring + cleanup [DBG throttle] (Task 3)
- FallDamageSuppressorSystem: subclass DamageEventSystem, cancel Damage
  cause=Fall quand guard.shouldSuppressFallDamage; FALL_INDEX lazy via
  DamageCause.getAssetMap().getIndex; groupe inspectDamageGroup
- GravityApplier: 3-arg constructor avec FallDamageGuard; first-match
  region, filtres AffectPlayers/Npcs/Items avant wake, seed addForce
  paramétré par VerticalForce (remplace hardcode 0.1); notifie
  guard.markInRegion / markExit (via lastKnownRegion map pour Pass 2)
- Cleanup: retire les AtomicInteger counters + log [DBG tick=...]
  throttle 1s; conserve logs one-shot [DBG npc.woken]/[DBG npc.ctrlNull]
- GravityFlipPlugin.setup(): instancie FallDamageGuard, registerSystem
  sur entityStoreRegistry; start() passe guard au GravityApplier
- Imports Query + CommandBuffer alignés sur FlockMembershipSystems
2026-04-23 14:03:58 +02:00
kayjaydee f9d5595837 feat(03-04): ajoute FallDamageGuard tracker thread-safe (Task 2)
- ConcurrentHashMap<UUID, region> current + exit + regionAtExit
- shouldSuppressFallDamage: in-region FallDamage=false OU grace window
- Pas de static mutable, injecté via constructeur
- 7 tests pure-data couvrant entry/in-region/exit/grace/re-entry/override
2026-04-23 14:00:56 +02:00
kayjaydee a834c59b66 feat(03-04): ajoute 6 champs optionnels sur GravityFlipRegion (Task 1)
- POJO: FallDamage (false), GracePeriodMs (2500), VerticalForce (0.1),
  AffectPlayers/Npcs/Items (true) avec getters/setters
- CODEC: 6 .append sans nonNull validator (sémantique optionnelle)
- Tests: 6 round-trip + back-compat defaults (9 tests total)
2026-04-23 14:00:12 +02:00
kayjaydee ffb716ca1c build: auto-copy shadowJar vers le dossier mods du serveur dev Hytale
Ajoute une tâche Gradle `copyJarToDevServer` finalisant shadowJar :
le fat JAR est copié dans C:/Users/minit/Desktop/HYTALE SERVER/Server/mods
par défaut. Overridable via -PdevServerMods=... et désactivable avec
-PdevServerMods=disabled.
2026-04-23 12:35:37 +02:00
kayjaydee 210c93aee7 feat(03-02): wake-up MovementManager + MotionController on region flip
- GravityApplier: branches player (setDefaultSettings + applyDefaultSettings + update) et NPC (Role.getActiveMotionController().updatePhysicsValues) dans les 2 pass
- wakePlayerOrNpc() helper appelé depuis forEachEntityParallel (sous world.execute — WorldThread assert OK)
- PhysicsValues construit localement via buildPhysicsValuesWithFlag (évite relookup ECS pre-commit cmdBuf)
- Seam pure FlaggedDecision extraite pour tests unitaires hors runtime Hytale (Rule 3 — static init PhysicsValues nécessite PluginBase)
- 8 tests verts (6 existants + 2 nouveaux sur buildFlaggedDecision)
2026-04-23 12:29:00 +02:00
kayjaydee 4a02ceaa82 fix(region): wrap refreshFor(World) dans world.execute (WorldThread assert)
- RegionRegistry.refreshFor dispatche scan ECS + publishSnapshot via world.execute
- Publication devient asynchrone (1-tick staleness max, borne par tick loop @100ms)
- Null-path enabled.isEmpty publie directement (pas de travail ECS requis)
- Amendement D-04 du plan 03-01 : world.execute requis côté initiation de forEachEntityParallel
2026-04-23 11:49:00 +02:00
kayjaydee af02e19685 fix(gravity): wrap forEachEntityParallel dans world.execute (WorldThread assert)
- GravityApplier.apply dispatche via world.execute(Runnable) pour satisfaire assertThread de Store.forEachEntityParallel
- PASS 1, PASS 2 et update tracker exécutés dans le même Runnable (cohérence intra-tick)
- Null-guards conservés avant le dispatch
- Amendement D-04 du plan 03-01 : world.execute requis côté initiation
2026-04-23 11:48:29 +02:00
kayjaydee f7dcc7d59a feat(03-01): wire GravityApplier into RegionTickLoop + plugin (Task 2)
- RegionTickLoop gagne un constructeur 3-args (registry, gravityApplier, errorHandler)
- Ancien constructeur 2-args conservé pour rétrocompat des tests Phase 02
- Tick body appelle gravityApplier.apply(w, registry.currentSnapshot(w)) après refreshFor
- GravityFlipPlugin.start() construit l'applier et l'injecte dans le tickLoop
- Log de démarrage mis à jour: 'gravity inversion active'
2026-04-23 10:32:28 +02:00
kayjaydee ef3f398c55 feat(03-01): add GravityApplier with native PhysicsValues.invertedGravity toggle (Task 1)
- 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)
2026-04-23 10:31:43 +02:00
kayjaydee 562f60d343 chore: update .gitignore to include local tooling and decompiled sources 2026-04-23 10:06:09 +02:00
kayjaydee 53b43d83c7 feat(02-02): add RegionTickLoop + plugin wiring (Task 3)
- 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.
2026-04-23 00:56:12 +02:00
kayjaydee 6574c05128 feat(02-02): add RegionRegistry + RegionSnapshot with ECS refreshFor (Tasks 1+2)
- RegionSnapshot: immutable per-world occupancy view (byRegion/tickId/world)
- RegionRegistry:
  * AtomicReference<List<GravityFlipRegion>> for tick-loop-safe region reads
  * CRUD (add/remove/setEnabled) under mutationLock + atomic snapshot republish
  * refreshFromConfig(cfg) hook for Phase 4 command handlers
  * refreshFor(World) iterates ECS via forEachEntityParallel +
    TransformComponent.getComponentType() (ComponentType IS-A Query, no builder) +
    Box.containsPosition(x,y,z); publishes per-world snapshot via AtomicReference.
  * Lazy ComponentType init (avoids Hytale PluginBase static init in tests)
  * Snapshots map keyed by Object (not World) so JDK 25 tests don't need Mockito
- 7/7 RegionRegistryTest pass: CRUD, snapshot read/publish, cross-thread visibility,
  refreshFromConfig atomic swap.

Probe results (recorded for SUMMARY):
- ArchetypeChunk.getRef(int) NOT present; actual method is getReferenceTo(int)
- TransformComponent.getPosition() returns com.hypixel.hytale.math.vector.Vector3d
  in pinned 2026.03.26 (Phase 02-01 deviation pattern recurs)
2026-04-23 00:54:32 +02:00
kayjaydee 216f544d9b feat(02-01): wire GravityFlipConfig to regions.json via named withConfig
- 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).
2026-04-23 00:43:26 +02:00
kayjaydee b046f44ab5 feat(02-01): add GravityFlipRegion POJO + BuilderCodec with round-trip tests
- 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.
2026-04-23 00:41:36 +02:00
kayjaydee 59b33615df refactor(01): align scaffold with Mythlane conventions (Kotlin DSL, CamelCase manifest, pinned server version)
- Convert build.gradle/settings.gradle to Kotlin DSL matching VotePipe + myth_*
- Manifest keys: lowercase -> CamelCase (Group/Name/Version/Main/ServerVersion/...)
  matching production Mythlane plugins (empirical authority)
- gradle.properties adopts pluginGroup/pluginVersion/pluginDescription/hytaleServerVersion
- Template manifest via processResources.expand(${version}, ${description}, ${hytaleServerVersion})
- Add baseline deps: gson (relocated), jetbrains annotations, JUnit 5
- shadowJar archiveBaseName=hytale-gravity-flip

Rebuild: BUILD SUCCESSFUL, fat JAR regenerated with CamelCase manifest.
2026-04-22 23:32:25 +02:00
kayjaydee 2e26f8a10f feat(01): plugin manifest and entry class 2026-04-22 23:28:13 +02:00
kayjaydee 628c26aff2 feat(01): gradle scaffold (settings, properties, build, wrapper) 2026-04-22 23:23:52 +02:00
kayjaydee f9d8f71f0d chore: ignore .planning/ alongside .claude/ 2026-04-22 23:13:48 +02:00
kayjaydee 4252c8d07f chore: untrack .planning and .claude (local only) 2026-04-22 23:13:43 +02:00
kayjaydee 266b9b3f04 docs: initialize GSD project (Hytale Gravity Flip) — PROJECT, research, REQUIREMENTS, ROADMAP, STATE, config, CLAUDE.md 2026-04-22 23:12:11 +02:00