refactor: clean GSD references + shrink comments in wand/
This commit is contained in:
@@ -15,38 +15,7 @@ import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Gravity Flip wand interaction — reads Primary / Secondary clicks and pushes
|
||||
* the targeted block position into a {@link WandSelectionStore} keyed by the
|
||||
* clicker's player UUID.
|
||||
*
|
||||
* <p><b>Binding :</b> registered at {@code setup()} time via
|
||||
* {@code getCodecRegistry(Interaction.CODEC).register("GravityFlipWand", …)} —
|
||||
* same pattern as {@code ExitInstanceInteraction} (cf. 04-00 SPIKE-RESULT,
|
||||
* Finding 3). The matching {@code "Type": "GravityFlipWand"} reference in
|
||||
* {@code Items/gravityflip_wand.json} wires the click packet to this class.
|
||||
*
|
||||
* <p><b>One class for both click types :</b> {@link #firstRun} receives the
|
||||
* {@link InteractionType}. Primary → {@code setPos1}, Secondary → {@code setPos2}.
|
||||
* Centralising both in one class keeps a single registration entry and a
|
||||
* single CODEC — any other split would duplicate wiring for no gain.
|
||||
*
|
||||
* <p><b>Store injection :</b> the Hytale CODEC instantiates interactions via a
|
||||
* no-arg constructor, so we cannot inject the store through the constructor.
|
||||
* Instead, {@link #bindStore(WandSelectionStore)} installs a {@code volatile}
|
||||
* reference at plugin start. If the store is not bound (mis-wired plugin),
|
||||
* {@link #firstRun} is a safe no-op — fail-silent.
|
||||
*
|
||||
* <p><b>Threat surface :</b>
|
||||
* <ul>
|
||||
* <li>Chat feedback uses {@link PlayerRef#sendMessage} — directed to the
|
||||
* clicker only, no broadcast (T-04-01-03).</li>
|
||||
* <li>{@code TargetBlock} coordinates are stored raw as {@code int[]} — no
|
||||
* numeric processing in this plan; {@code /gravityflip define} (04-03)
|
||||
* is responsible for clamping / validating before region creation
|
||||
* (T-04-01-01).</li>
|
||||
* </ul>
|
||||
*/
|
||||
/** Wand interaction: Primary click sets pos1, Secondary click sets pos2 in the shared selection store. */
|
||||
public final class GravityFlipWandInteraction extends SimpleInstantInteraction {
|
||||
|
||||
@Nonnull
|
||||
@@ -60,19 +29,14 @@ public final class GravityFlipWandInteraction extends SimpleInstantInteraction {
|
||||
+ "Secondary click sets pos2, for the clicker's selection."))
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Store shared by every instance of this interaction — injected at plugin
|
||||
* start via {@link #bindStore}. Volatile so the writer thread ({@code setup()})
|
||||
* publishes a safe reference to the reader threads (interaction dispatch).
|
||||
*/
|
||||
// Volatile: writer (setup thread) must publish safely to reader threads (interaction dispatch).
|
||||
private static volatile WandSelectionStore STORE;
|
||||
|
||||
/** Wire the selection store before any click can be processed. Call once at {@code setup()}. */
|
||||
/** Wire the selection store before any click can be processed. */
|
||||
public static void bindStore(WandSelectionStore store) {
|
||||
STORE = store;
|
||||
}
|
||||
|
||||
/** Required no-arg constructor used by the CODEC factory. */
|
||||
public GravityFlipWandInteraction() {
|
||||
}
|
||||
|
||||
@@ -82,7 +46,6 @@ public final class GravityFlipWandInteraction extends SimpleInstantInteraction {
|
||||
@Nonnull CooldownHandler cooldownHandler) {
|
||||
WandSelectionStore store = STORE;
|
||||
if (store == null) {
|
||||
// Plugin mis-wired (bindStore never called). Silent no-op — don't crash the click.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -94,7 +57,6 @@ public final class GravityFlipWandInteraction extends SimpleInstantInteraction {
|
||||
|
||||
PlayerRef playerRef = commandBuffer.getComponent(entityRef, PlayerRef.getComponentType());
|
||||
if (playerRef == null) {
|
||||
// Clicker is not a player (mob, arrow, …) — ignore.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -114,6 +76,5 @@ public final class GravityFlipWandInteraction extends SimpleInstantInteraction {
|
||||
playerRef.sendMessage(Message.raw(
|
||||
"[gravityflip] pos2 set: (%d, %d, %d)".formatted(bp.x, bp.y, bp.z)));
|
||||
}
|
||||
// Any other InteractionType (Ability1, Pick, Equipped, …) is ignored.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,29 +3,12 @@ package com.mythlane.gravityflip.wand;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Thread-safe per-player wand selection store. Tracks the two corner positions
|
||||
* ({@code pos1} = Primary click, {@code pos2} = Secondary click) of each
|
||||
* builder's current selection, keyed by player {@link UUID}.
|
||||
*
|
||||
* <p><b>Pure-data :</b> no Hytale runtime dependency — same philosophy as
|
||||
* {@code FallDamageGuard}. Testable with JUnit alone, reusable by future
|
||||
* {@code /gravityflip define} command (Phase 04-02+) without runtime coupling.
|
||||
*
|
||||
* <p><b>Thread-safety :</b> backed by a {@link ConcurrentHashMap} whose
|
||||
* {@code compute(...)} mutations are atomic. Safe for concurrent
|
||||
* {@link #setPos1}/{@link #setPos2} calls on the same UUID (STRIDE T-04-01-04).
|
||||
*
|
||||
* <p><b>Lifecycle :</b> in-memory only — selections are discarded on plugin
|
||||
* shutdown. Conscious design : a builder will not quit mid-{@code define}.
|
||||
*/
|
||||
/** Thread-safe per-player wand selection store (pos1/pos2 keyed by player UUID). */
|
||||
public final class WandSelectionStore {
|
||||
|
||||
/** Immutable holder for a (possibly partial) selection. */
|
||||
public static final class Selection {
|
||||
/** {@code {x,y,z}} of the Primary click, or {@code null} if unset. */
|
||||
public final int[] pos1;
|
||||
/** {@code {x,y,z}} of the Secondary click, or {@code null} if unset. */
|
||||
public final int[] pos2;
|
||||
|
||||
Selection(int[] pos1, int[] pos2) {
|
||||
@@ -43,7 +26,7 @@ public final class WandSelectionStore {
|
||||
|
||||
private final ConcurrentHashMap<UUID, Selection> byUuid = new ConcurrentHashMap<>();
|
||||
|
||||
/** Record the Primary-click corner for {@code uuid}. Keeps any existing pos2. */
|
||||
/** Record the Primary-click corner for the given player. */
|
||||
public void setPos1(UUID uuid, int x, int y, int z) {
|
||||
if (uuid == null) return;
|
||||
byUuid.compute(uuid, (k, prev) -> new Selection(
|
||||
@@ -51,7 +34,7 @@ public final class WandSelectionStore {
|
||||
prev != null ? prev.pos2 : null));
|
||||
}
|
||||
|
||||
/** Record the Secondary-click corner for {@code uuid}. Keeps any existing pos1. */
|
||||
/** Record the Secondary-click corner for the given player. */
|
||||
public void setPos2(UUID uuid, int x, int y, int z) {
|
||||
if (uuid == null) return;
|
||||
byUuid.compute(uuid, (k, prev) -> new Selection(
|
||||
@@ -59,23 +42,20 @@ public final class WandSelectionStore {
|
||||
new int[]{x, y, z}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current selection for {@code uuid}. Never returns {@code null} :
|
||||
* an unknown UUID yields a {@link Selection} with both corners {@code null}.
|
||||
*/
|
||||
/** Return the current selection for the given player (never null). */
|
||||
public Selection get(UUID uuid) {
|
||||
if (uuid == null) return EMPTY;
|
||||
Selection s = byUuid.get(uuid);
|
||||
return s != null ? s : EMPTY;
|
||||
}
|
||||
|
||||
/** Forget the selection for {@code uuid} (e.g. after {@code /gravityflip define}). */
|
||||
/** Forget the selection for the given player. */
|
||||
public void clear(UUID uuid) {
|
||||
if (uuid == null) return;
|
||||
byUuid.remove(uuid);
|
||||
}
|
||||
|
||||
/** Diagnostic : number of players with an in-flight selection. */
|
||||
/** Number of players with an in-flight selection. */
|
||||
public int size() {
|
||||
return byUuid.size();
|
||||
}
|
||||
|
||||
@@ -12,11 +12,7 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* Pure-data tests for {@link WandSelectionStore} — no Hytale runtime dependency.
|
||||
* Covers set/get per UUID, overwrite semantics, unknown UUID default, clear,
|
||||
* and concurrent writes.
|
||||
*/
|
||||
/** Tests for {@link WandSelectionStore}: set/get per UUID, overwrite, clear, concurrency. */
|
||||
class WandSelectionStoreTest {
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user