Files
TiedUp-/src/test/java/com/tiedup/remake/v2/furniture/FurnitureSeatSyncCodecTest.java
NotEvil cc6a62a6e5 Polish V2 subsystem: lockpick kinds, package boundaries, client extractions
Architectural debt cleanup on top of the earlier V2 hardening pass.

Minigame:
  - LockpickMiniGameState splits the overloaded targetSlot int into a
    LockpickTargetKind enum + targetData int. Body-vs-furniture
    dispatch is now a simple enum check; the NBT-tag nonce it
    previously depended on is gone, along with the AIOOBE risk at
    BodyRegionV2.values()[targetSlot].
  - PacketLockpickAttempt.handleFurnitureLockpickSuccess takes the
    entity and seat id as explicit parameters. Caller pre-validates
    both before any side effect, so a corrupted ctx tag can no longer
    produce a "Lock picked!" UI with a used lockpick and nothing
    unlocked.

Package boundaries:
  - client.gltf no longer imports v2.bondage. Render-layer attachment,
    DataDrivenItemReloadListener, and GlbValidationReloadListener all
    live in v2.client.V2ClientSetup.
  - GlbValidationReloadListener moved to v2.bondage.client.diagnostic.
  - Reload-listener ordering is preserved via EventPriority (HIGH for
    the generic GLB cache clear in GltfClientSetup, LOW for bondage
    consumers in V2ClientSetup).
  - Removed the unused validateAgainstDefinition stub on GlbValidator.

Extractions from EntityFurniture:
  - FurnitureSeatSyncCodec (pipe/semicolon serialization for the
    SEAT_ASSIGNMENTS_SYNC entity data field), with 8 unit tests.
  - FurnitureClientAnimator (client-only seat-pose kickoff, moved out
    of the dual-side entity class).
  - EntityFurniture drops ~100 lines with no behavior change.

Interface docs:
  - ISeatProvider Javadoc narrowed to reflect that EntityFurniture is
    the only implementation; callers that need animation state or
    definition reference still downcast.
  - FurnitureAuthPredicate.findOccupant uses the interface only.
  - AnimationIdBuilder flagged as legacy JSON-era utility (NPC
    fallback + MCA mixin).

Artist guide: corrected the "Monster Seat System (Planned)" section
to match the ISeatProvider single-impl reality.
2026-04-19 02:06:02 +02:00

89 lines
2.7 KiB
Java

package com.tiedup.remake.v2.furniture;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.UUID;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
class FurnitureSeatSyncCodecTest {
private static final UUID U1 = UUID.fromString(
"00000000-0000-0000-0000-000000000001"
);
private static final UUID U2 = UUID.fromString(
"00000000-0000-0000-0000-000000000002"
);
@Test
@DisplayName("empty map encodes to empty string")
void empty() {
assertEquals("", FurnitureSeatSyncCodec.encode(Map.of()));
assertTrue(FurnitureSeatSyncCodec.decode("").isEmpty());
}
@Test
@DisplayName("single entry round-trip")
void single() {
Map<UUID, String> m = new LinkedHashMap<>();
m.put(U1, "left");
String wire = FurnitureSeatSyncCodec.encode(m);
assertEquals(U1 + ";left", wire);
assertEquals(m, FurnitureSeatSyncCodec.decode(wire));
}
@Test
@DisplayName("multi entry round-trip preserves insertion order")
void multi() {
Map<UUID, String> m = new LinkedHashMap<>();
m.put(U1, "left");
m.put(U2, "right");
String wire = FurnitureSeatSyncCodec.encode(m);
Map<UUID, String> back = FurnitureSeatSyncCodec.decode(wire);
assertEquals(m, back);
}
@Test
@DisplayName("decode skips corrupt UUIDs and preserves valid entries")
void skipsCorrupt() {
String wire = "not-a-uuid;left|" + U2 + ";right";
Map<UUID, String> back = FurnitureSeatSyncCodec.decode(wire);
assertEquals(1, back.size());
assertEquals("right", back.get(U2));
}
@Test
@DisplayName("decode rejects entries with missing seat id")
void rejectsEmptySeatId() {
String wire = U1 + ";";
assertTrue(FurnitureSeatSyncCodec.decode(wire).isEmpty());
}
@Test
@DisplayName("decode tolerates null input")
void nullInput() {
assertTrue(FurnitureSeatSyncCodec.decode(null).isEmpty());
}
@Test
@DisplayName("decode skips entries with no separator")
void skipsNoSeparator() {
String wire = "abc|" + U1 + ";right";
Map<UUID, String> back = FurnitureSeatSyncCodec.decode(wire);
assertEquals(1, back.size());
assertEquals("right", back.get(U1));
}
@Test
@DisplayName("decode skips entries starting with separator")
void skipsLeadingSeparator() {
String wire = ";seat|" + U1 + ";right";
Map<UUID, String> back = FurnitureSeatSyncCodec.decode(wire);
assertEquals(1, back.size());
assertEquals("right", back.get(U1));
}
}