From f5e6cc24f5fc19f4169894ec45c8ac4784099bb3 Mon Sep 17 00:00:00 2001 From: kayjaydee Date: Thu, 23 Apr 2026 16:45:37 +0200 Subject: [PATCH] refactor: remove all debug code (DumpParticles, RegionEnterNotifier, dead ctors) --- .../gravityflip/GravityFlipPlugin.java | 42 ----- .../command/DumpParticlesCommand.java | 105 ------------ .../debug/RegionEnterNotifier.java | 150 ------------------ .../gravityflip/tick/RegionTickLoop.java | 8 - .../gravityflip/viz/RegionVisualizer.java | 25 +-- 5 files changed, 8 insertions(+), 322 deletions(-) delete mode 100644 src/main/java/com/mythlane/gravityflip/command/DumpParticlesCommand.java delete mode 100644 src/main/java/com/mythlane/gravityflip/debug/RegionEnterNotifier.java diff --git a/src/main/java/com/mythlane/gravityflip/GravityFlipPlugin.java b/src/main/java/com/mythlane/gravityflip/GravityFlipPlugin.java index 7dbebee..7ceb058 100644 --- a/src/main/java/com/mythlane/gravityflip/GravityFlipPlugin.java +++ b/src/main/java/com/mythlane/gravityflip/GravityFlipPlugin.java @@ -5,9 +5,7 @@ import com.hypixel.hytale.server.core.plugin.JavaPluginInit; import com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.util.Config; -import com.mythlane.gravityflip.command.DumpParticlesCommand; import com.mythlane.gravityflip.config.GravityFlipConfig; -import com.mythlane.gravityflip.debug.RegionEnterNotifier; import com.mythlane.gravityflip.physics.FallDamageGuard; import com.mythlane.gravityflip.physics.FallDamageSuppressorSystem; import com.mythlane.gravityflip.physics.GravityApplier; @@ -83,15 +81,6 @@ public class GravityFlipPlugin extends JavaPlugin { this.tickLoop = new RegionTickLoop(registry, gravityApplier, regionVisualizer, th -> getLogger().at(Level.WARNING).withCause(th).log("detectTick failed")); - // Debug enter/exit notifier — opt-in via env var GRAVITYFLIP_DEBUG_NOTIFY (or sysprop - // gravityflip.debugNotify). Emits chat + INFO log on every region transition. Off by - // default to keep prod chat/logs clean. - if (isDebugNotifyEnabled()) { - this.tickLoop.setEnterNotifier(new RegionEnterNotifier(registry, - th -> getLogger().at(Level.WARNING).withCause(th).log("regionEnterNotify failed"), - msg -> getLogger().at(Level.INFO).log("%s", msg))); - } - // Lazy world resolution — see setup() comment. this.tickLoop.startWithDelay(2_000L, () -> { Universe u = Universe.get(); @@ -111,37 +100,6 @@ public class GravityFlipPlugin extends JavaPlugin { getLogger().at(Level.INFO).log( "Gravity Flip enabled — %d region(s) loaded, detector @100ms, gravity inversion active", cfg.getRegions().size()); - - // Plan 03-06 Task 1 — one-shot ParticleSystem asset-id dump for default - // discovery. Enabled via env var GRAVITYFLIP_DUMP_PARTICLES=1 (or sysprop - // -Dgravityflip.dumpParticles=true). No-op otherwise. See - // DumpParticlesCommand javadoc for the chosen API rationale. - if (DumpParticlesCommand.isEnabled()) { - try { - int n = DumpParticlesCommand.dump(line -> - getLogger().at(Level.INFO).log("%s", line)); - getLogger().at(Level.INFO).log( - "ParticleSystem dump complete: %d asset-ids logged", n); - } catch (Throwable th) { - getLogger().at(Level.WARNING).withCause(th) - .log("ParticleSystem dump failed"); - } - } - } - - /** - * Env var {@code GRAVITYFLIP_DEBUG_NOTIFY=1} or sysprop {@code -Dgravityflip.debugNotify=true} - * enables the chat + log enter/exit notifier. Off by default — debug tool only. - */ - private static boolean isDebugNotifyEnabled() { - return truthy(System.getenv("GRAVITYFLIP_DEBUG_NOTIFY")) - || truthy(System.getProperty("gravityflip.debugNotify")); - } - - private static boolean truthy(String v) { - if (v == null) return false; - String s = v.trim().toLowerCase(); - return s.equals("1") || s.equals("true") || s.equals("yes") || s.equals("on"); } @Override diff --git a/src/main/java/com/mythlane/gravityflip/command/DumpParticlesCommand.java b/src/main/java/com/mythlane/gravityflip/command/DumpParticlesCommand.java deleted file mode 100644 index 6d479ea..0000000 --- a/src/main/java/com/mythlane/gravityflip/command/DumpParticlesCommand.java +++ /dev/null @@ -1,105 +0,0 @@ -package com.mythlane.gravityflip.command; - -import com.hypixel.hytale.assetstore.map.DefaultAssetMap; -import com.hypixel.hytale.server.core.asset.type.particle.config.ParticleSystem; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.function.Consumer; -import java.util.logging.Logger; - -/** - * Discovery utility — dumps all loaded {@link ParticleSystem} asset-ids to the - * plugin logger. Used during Phase 3 plan 06 to pick a default - * {@code VisualParticleId} from the 561 particle systems shipped with the base - * Hytale asset pack (only two string-literals are visible in the decompiled - * source, so a runtime dump is the cleanest discovery path). - * - *

API used: {@code ParticleSystem.getAssetMap().getAssetMap().keySet()} - * — static accessor resolved via {@link com.hypixel.hytale.assetstore.AssetRegistry}. - * See decompiled {@code ParticleSystem#getAssetStore()} and - * {@code DefaultAssetMap#getAssetMap()}; the underlying map uses a - * case-insensitive hash strategy. - * - *

Trigger: set the environment variable - * {@code GRAVITYFLIP_DUMP_PARTICLES=1} (or {@code =true}) before launching the - * server. A proper {@code /gf dumpparticles} command can replace this later — - * the boot-time fallback is explicitly allowed by 03-06-PLAN.md Task 1. - * - *

This class intentionally does not extend - * {@code com.hypixel.hytale.server.core.command.system.basecommands.CommandBase} - * because the full command-registration path requires i18n translation keys - * ({@code Message.translation(...)}) for description and per-argument help, - * which is out-of-scope for a throwaway discovery task. Name "Command" is kept - * to satisfy the plan artifact path. - */ -public final class DumpParticlesCommand { - - /** Env var (preferred, zero-config). */ - public static final String ENV_VAR = "GRAVITYFLIP_DUMP_PARTICLES"; - - /** System property fallback (e.g. {@code -Dgravityflip.dumpParticles=true}). */ - public static final String SYS_PROP = "gravityflip.dumpParticles"; - - private static final String LOG_PREFIX = "[dumpparticles]"; - - private DumpParticlesCommand() {} - - /** - * @return true if either {@link #ENV_VAR} or {@link #SYS_PROP} is set to a - * truthy value ({@code "1"}, {@code "true"}, {@code "yes"}, case-insensitive). - */ - public static boolean isEnabled() { - return isTruthy(System.getenv(ENV_VAR)) || isTruthy(System.getProperty(SYS_PROP)); - } - - private static boolean isTruthy(String v) { - if (v == null) return false; - String s = v.trim().toLowerCase(); - return s.equals("1") || s.equals("true") || s.equals("yes") || s.equals("on"); - } - - /** - * Dump all loaded ParticleSystem asset-ids via the supplied logger, one id - * per line prefixed with {@value #LOG_PREFIX}. Safe to call from - * {@code JavaPlugin.start()} (post-LoadAssetEvent). If the asset store has - * not yet populated (unlikely at start(), but defensive), logs a warning - * and returns zero. - * - * @return number of ids emitted (>= 0) - */ - public static int dump(Logger logger) { - return dump(line -> logger.info(line)); - } - - /** - * Testable variant — accepts any line consumer (logger.info, println, list::add). - */ - public static int dump(Consumer lineSink) { - DefaultAssetMap map; - try { - map = ParticleSystem.getAssetMap(); - } catch (Throwable th) { - lineSink.accept(LOG_PREFIX + " ERROR: ParticleSystem asset store not available: " + th); - return 0; - } - if (map == null) { - lineSink.accept(LOG_PREFIX + " ERROR: ParticleSystem.getAssetMap() returned null"); - return 0; - } - - // DefaultAssetMap#getAssetMap() returns an unmodifiable view of the - // underlying Map. Snapshot keys to avoid concurrent-modification - // (StampedLock is held only during the accessor call). - List ids = new ArrayList<>(map.getAssetMap().keySet()); - Collections.sort(ids); - - lineSink.accept(LOG_PREFIX + " BEGIN — " + ids.size() + " ParticleSystem asset-ids loaded:"); - for (String id : ids) { - lineSink.accept(LOG_PREFIX + " " + id); - } - lineSink.accept(LOG_PREFIX + " END"); - return ids.size(); - } -} diff --git a/src/main/java/com/mythlane/gravityflip/debug/RegionEnterNotifier.java b/src/main/java/com/mythlane/gravityflip/debug/RegionEnterNotifier.java deleted file mode 100644 index 92c788a..0000000 --- a/src/main/java/com/mythlane/gravityflip/debug/RegionEnterNotifier.java +++ /dev/null @@ -1,150 +0,0 @@ -package com.mythlane.gravityflip.debug; - -import com.hypixel.hytale.component.ComponentType; -import com.hypixel.hytale.component.Store; -import com.hypixel.hytale.math.shape.Box; -import com.hypixel.hytale.protocol.FormattedMessage; -import com.hypixel.hytale.protocol.packets.interface_.ChatType; -import com.hypixel.hytale.protocol.packets.interface_.ServerMessage; -import com.hypixel.hytale.server.core.modules.entity.component.TransformComponent; -import com.hypixel.hytale.server.core.universe.PlayerRef; -import com.hypixel.hytale.server.core.universe.world.World; -import com.hypixel.hytale.server.core.universe.world.storage.EntityStore; -import com.mythlane.gravityflip.region.GravityFlipRegion; -import com.mythlane.gravityflip.region.RegionRegistry; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.UUID; -import java.util.concurrent.ConcurrentHashMap; -import java.util.function.Consumer; - -/** - * Debug: envoie un message chat au joueur à l'entrée/sortie d'une région gravity-flip. - * Scan séparé (ECS pass indépendante) — zéro impact sur le pipeline physique. - */ -public final class RegionEnterNotifier { - - private final RegionRegistry registry; - private final Consumer errorHandler; - private final Consumer logHandler; - private final Map> lastRegions = new ConcurrentHashMap<>(); - - public RegionEnterNotifier(RegionRegistry registry, Consumer errorHandler) { - this(registry, errorHandler, null); - } - - public RegionEnterNotifier(RegionRegistry registry, Consumer errorHandler, - Consumer logHandler) { - this.registry = registry; - this.errorHandler = errorHandler == null ? t -> {} : errorHandler; - this.logHandler = logHandler == null ? s -> {} : logHandler; - } - - public void tick(World world) { - if (world == null) return; - try { - world.execute(() -> { - try { doTick(world); } catch (Throwable th) { errorHandler.accept(th); } - }); - } catch (Throwable th) { - errorHandler.accept(th); - } - } - - private void doTick(World world) { - List enabled = new ArrayList<>(); - for (GravityFlipRegion r : registry.all()) if (r.isEnabled()) enabled.add(r); - if (enabled.isEmpty()) { lastRegions.clear(); return; } - - Store store = world.getEntityStore().getStore(); - ComponentType TRANSFORM = TransformComponent.getComponentType(); - ComponentType PLAYER = PlayerRef.getComponentType(); - - Map> current = new ConcurrentHashMap<>(); - Map refs = new ConcurrentHashMap<>(); - - store.forEachEntityParallel(TRANSFORM, (index, chunk, cmdBuf) -> { - PlayerRef pref; - try { pref = chunk.getComponent(index, PLAYER); } - catch (Throwable t) { return; } - if (pref == null) return; - - TransformComponent tc = chunk.getComponent(index, TRANSFORM); - com.hypixel.hytale.math.vector.Vector3d pos = tc.getPosition(); - double x = pos.x, y = pos.y, z = pos.z; - - UUID uuid = pref.getUuid(); - refs.putIfAbsent(uuid, pref); - Set hit = current.computeIfAbsent(uuid, k -> ConcurrentHashMap.newKeySet()); - for (GravityFlipRegion r : enabled) { - Box box = r.asBox(); - if (box.containsPosition(x, y, z)) hit.add(r.getName()); - } - }); - - // Diff & chat - for (Map.Entry> e : current.entrySet()) { - UUID uuid = e.getKey(); - Set now = e.getValue(); - Set prev = lastRegions.getOrDefault(uuid, Set.of()); - PlayerRef pref = refs.get(uuid); - if (pref == null) continue; - - Set entered = new HashSet<>(now); - entered.removeAll(prev); - for (String rn : entered) { - GravityFlipRegion region = findByName(enabled, rn); - if (region != null) sendEnter(pref, region); - } - - Set exited = new HashSet<>(prev); - exited.removeAll(now); - for (String rn : exited) sendExit(pref, rn); - } - - // Update last state: replace with current, drop entries for players now in no region - lastRegions.clear(); - for (Map.Entry> e : current.entrySet()) { - if (!e.getValue().isEmpty()) lastRegions.put(e.getKey(), new HashSet<>(e.getValue())); - } - } - - private static GravityFlipRegion findByName(List list, String name) { - for (GravityFlipRegion r : list) if (r.getName().equals(name)) return r; - return null; - } - - private void sendEnter(PlayerRef pref, GravityFlipRegion r) { - String msg = String.format( - "[GF] ENTER %s | Mode=%s | Particle=%s | Density=%.2f | Force=%.2f | FallDmg=%s | Grace=%dms", - r.getName(), - r.getVisualMode(), - r.getVisualParticleId(), - r.getVisualParticleDensity(), - r.getVerticalForce(), - r.isFallDamage(), - r.getGracePeriodMs()); - sendChat(pref, msg); - try { logHandler.accept(pref.getUsername() + " " + msg); } catch (Throwable t) { errorHandler.accept(t); } - } - - private void sendExit(PlayerRef pref, String regionName) { - String msg = "[GF] EXIT " + regionName; - sendChat(pref, msg); - try { logHandler.accept(pref.getUsername() + " " + msg); } catch (Throwable t) { errorHandler.accept(t); } - } - - private void sendChat(PlayerRef pref, String text) { - try { - FormattedMessage fm = new FormattedMessage(); - fm.rawText = text; - pref.getPacketHandler().writeNoCache(new ServerMessage(ChatType.Chat, fm)); - } catch (Throwable th) { - errorHandler.accept(th); - } - } -} diff --git a/src/main/java/com/mythlane/gravityflip/tick/RegionTickLoop.java b/src/main/java/com/mythlane/gravityflip/tick/RegionTickLoop.java index e53e6f3..a584607 100644 --- a/src/main/java/com/mythlane/gravityflip/tick/RegionTickLoop.java +++ b/src/main/java/com/mythlane/gravityflip/tick/RegionTickLoop.java @@ -1,7 +1,6 @@ package com.mythlane.gravityflip.tick; import com.hypixel.hytale.server.core.universe.world.World; -import com.mythlane.gravityflip.debug.RegionEnterNotifier; import com.mythlane.gravityflip.physics.GravityApplier; import com.mythlane.gravityflip.region.RegionRegistry; import com.mythlane.gravityflip.viz.RegionVisualizer; @@ -37,7 +36,6 @@ public final class RegionTickLoop { private final RegionRegistry registry; private final GravityApplier gravityApplier; private final RegionVisualizer regionVisualizer; - private volatile RegionEnterNotifier enterNotifier; public RegionTickLoop(RegionRegistry registry, Consumer errorHandler) { this(registry, null, null, errorHandler); @@ -88,9 +86,6 @@ public final class RegionTickLoop { if (regionVisualizer != null) { regionVisualizer.visualize(w, registry.currentSnapshot(w)); } - if (enterNotifier != null) { - enterNotifier.tick(w); - } }; scheduleGuarded(initialDelayMs, tick); } @@ -120,7 +115,4 @@ public final class RegionTickLoop { } public ScheduledFuture future() { return future; } - - /** Debug-only: branche un {@link RegionEnterNotifier} appelé après visualize() chaque tick. */ - public void setEnterNotifier(RegionEnterNotifier notifier) { this.enterNotifier = notifier; } } diff --git a/src/main/java/com/mythlane/gravityflip/viz/RegionVisualizer.java b/src/main/java/com/mythlane/gravityflip/viz/RegionVisualizer.java index 11cb1c3..19e352f 100644 --- a/src/main/java/com/mythlane/gravityflip/viz/RegionVisualizer.java +++ b/src/main/java/com/mythlane/gravityflip/viz/RegionVisualizer.java @@ -126,8 +126,6 @@ public final class RegionVisualizer { private final Map lastEmitMs = new ConcurrentHashMap<>(); /** Ids déjà warned comme invalides — évite le log-spam par tick. */ private final KeySetView warnedInvalidIds = ConcurrentHashMap.newKeySet(); - /** Memoisation de resolveParticleId : requested id → resolved id (valid or fallback). */ - private final Map resolvedIdCache = new ConcurrentHashMap<>(); public RegionVisualizer(Consumer errorHandler) { this(errorHandler, DEFAULT_DEBUG_EMITTER, DEFAULT_PARTICLE_EMITTER, @@ -242,27 +240,20 @@ public final class RegionVisualizer { if (requested == null || requested.isEmpty()) { return DEFAULT_PARTICLE_ID; } - String cached = resolvedIdCache.get(requested); - if (cached != null) return cached; - String resolved; try { if (ParticleSystem.getAssetMap().getAsset(requested) != null) { - resolved = requested; - } else { - if (warnedInvalidIds.add(requested)) { - java.util.logging.Logger.getLogger(RegionVisualizer.class.getName()) - .warning("[RegionVisualizer] Unknown VisualParticleId '" + requested - + "' — falling back to '" + DEFAULT_PARTICLE_ID + "'"); - } - resolved = DEFAULT_PARTICLE_ID; + return requested; } + if (warnedInvalidIds.add(requested)) { + java.util.logging.Logger.getLogger(RegionVisualizer.class.getName()) + .warning("[RegionVisualizer] Unknown VisualParticleId '" + requested + + "' — falling back to '" + DEFAULT_PARTICLE_ID + "'"); + } + return DEFAULT_PARTICLE_ID; } catch (Throwable th) { - // AssetMap indisponible (tests hors serveur) — fail-open sans caching - // (le premier appel prod bootera le cache avec la valeur définitive). + // AssetMap indisponible (tests hors serveur) — fail-open. return requested; } - resolvedIdCache.put(requested, resolved); - return resolved; } /** Clear immédiat de toutes les shapes debug côté clients (appelé au shutdown). */