From 3515c89f8216c420c6274633ad0731afdb62cf93 Mon Sep 17 00:00:00 2001 From: NotEvil Date: Wed, 15 Apr 2026 00:26:07 +0200 Subject: [PATCH] fix(D-01/C): missing sync + worldgen empty registry race (review) StruggleSessionManager: add V2EquipmentHelper.sync(player) after bind resistance update to prevent data loss on server restart during struggle HangingCagePiece: add fallback ResourceLocation arrays for worldgen when DataDrivenItemRegistry is empty (race with reload listener on initial world creation). Registry-first with hardcoded fallbacks. --- .../minigame/StruggleSessionManager.java | 1 + .../remake/worldgen/HangingCagePiece.java | 85 ++++++++++--------- 2 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/tiedup/remake/minigame/StruggleSessionManager.java b/src/main/java/com/tiedup/remake/minigame/StruggleSessionManager.java index eaaae08..258721f 100644 --- a/src/main/java/com/tiedup/remake/minigame/StruggleSessionManager.java +++ b/src/main/java/com/tiedup/remake/minigame/StruggleSessionManager.java @@ -647,6 +647,7 @@ public class StruggleSessionManager { } if (bindStack.getItem() instanceof IHasResistance resistanceItem) { resistanceItem.setCurrentResistance(bindStack, session.getCurrentResistance()); + V2EquipmentHelper.sync(player); } } diff --git a/src/main/java/com/tiedup/remake/worldgen/HangingCagePiece.java b/src/main/java/com/tiedup/remake/worldgen/HangingCagePiece.java index f09e2ad..06c8256 100644 --- a/src/main/java/com/tiedup/remake/worldgen/HangingCagePiece.java +++ b/src/main/java/com/tiedup/remake/worldgen/HangingCagePiece.java @@ -16,6 +16,7 @@ import javax.annotation.Nullable; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; import net.minecraft.nbt.DoubleTag; import net.minecraft.nbt.FloatTag; import net.minecraft.nbt.ListTag; @@ -543,38 +544,45 @@ public class HangingCagePiece extends StructurePiece { BlockEntity be = level.getBlockEntity(chestPos); if (be instanceof TrappedChestBlockEntity trappedChest) { // Random bind from data-driven ARMS items - List binds = DataDrivenItemRegistry.getAll().stream() - .filter(d -> d.occupiedRegions().contains(BodyRegionV2.ARMS)) - .collect(Collectors.toList()); - if (!binds.isEmpty()) { - DataDrivenItemDefinition chosenBind = binds.get(random.nextInt(binds.size())); - trappedChest.setBind(DataDrivenBondageItem.createStack(chosenBind.id())); - } + trappedChest.setBind(randomItemForRegion(random, BodyRegionV2.ARMS, FALLBACK_BINDS)); - // Random gag from data-driven MOUTH items (50% chance) + // Random gag (50% chance) if (random.nextFloat() < 0.50f) { - List gags = DataDrivenItemRegistry.getAll().stream() - .filter(d -> d.occupiedRegions().contains(BodyRegionV2.MOUTH)) - .collect(Collectors.toList()); - if (!gags.isEmpty()) { - DataDrivenItemDefinition chosenGag = gags.get(random.nextInt(gags.size())); - trappedChest.setGag(DataDrivenBondageItem.createStack(chosenGag.id())); - } + trappedChest.setGag(randomItemForRegion(random, BodyRegionV2.MOUTH, FALLBACK_GAGS)); } - // Random blindfold from data-driven EYES items (30% chance) + // Random blindfold (30% chance) if (random.nextFloat() < 0.30f) { - List blindfolds = DataDrivenItemRegistry.getAll().stream() - .filter(d -> d.occupiedRegions().contains(BodyRegionV2.EYES)) - .collect(Collectors.toList()); - if (!blindfolds.isEmpty()) { - DataDrivenItemDefinition chosenBf = blindfolds.get(random.nextInt(blindfolds.size())); - trappedChest.setBlindfold(DataDrivenBondageItem.createStack(chosenBf.id())); - } + trappedChest.setBlindfold(randomItemForRegion(random, BodyRegionV2.EYES, FALLBACK_BLINDFOLDS)); } } } + // Fallback item IDs for worldgen when DataDrivenItemRegistry is empty (race with reload) + private static final ResourceLocation[] FALLBACK_BINDS = { + new ResourceLocation("tiedup", "ropes"), + new ResourceLocation("tiedup", "chain"), + new ResourceLocation("tiedup", "armbinder") + }; + private static final ResourceLocation[] FALLBACK_GAGS = { + new ResourceLocation("tiedup", "cloth_gag"), + new ResourceLocation("tiedup", "ball_gag") + }; + private static final ResourceLocation[] FALLBACK_BLINDFOLDS = { + new ResourceLocation("tiedup", "classic_blindfold") + }; + + private static ItemStack randomItemForRegion(RandomSource random, BodyRegionV2 region, ResourceLocation[] fallbacks) { + List defs = DataDrivenItemRegistry.getAll().stream() + .filter(d -> d.occupiedRegions().contains(region)) + .collect(Collectors.toList()); + if (!defs.isEmpty()) { + return DataDrivenBondageItem.createStack(defs.get(random.nextInt(defs.size())).id()); + } + // Fallback for worldgen race condition (registry not loaded yet) + return DataDrivenBondageItem.createStack(fallbacks[random.nextInt(fallbacks.length)]); + } + static void safeSetBlock( WorldGenLevel level, BlockPos pos, @@ -632,26 +640,19 @@ public class HangingCagePiece extends StructurePiece { entityTag.putUUID("UUID", java.util.UUID.randomUUID()); // Random bind item — the damsel spawns already restrained - List bindDefs = DataDrivenItemRegistry.getAll().stream() - .filter(d -> d.occupiedRegions().contains(BodyRegionV2.ARMS)) - .collect(Collectors.toList()); - if (!bindDefs.isEmpty()) { - DataDrivenItemDefinition chosenBind = bindDefs.get(random.nextInt(bindDefs.size())); - ItemStack bindStack = DataDrivenBondageItem.createStack(chosenBind.id()); - bindStack.getOrCreateTag().putString("bindMode", "full"); - entityTag.put("Bind", bindStack.save(new CompoundTag())); + ItemStack bindStack = randomItemForRegion(random, BodyRegionV2.ARMS, FALLBACK_BINDS); + bindStack.getOrCreateTag().putString("bindMode", "full"); + entityTag.put("Bind", bindStack.save(new CompoundTag())); - // Add directly to chunk's pending entity list - ChunkAccess chunk = level.getChunk(masterPos); - if (chunk instanceof ProtoChunk protoChunk) { - protoChunk.addEntity(entityTag); - TiedUpMod.LOGGER.info( - "[HangingCage] Scheduled {} damsel with {} at {}", - shiny ? "shiny" : "regular", - chosenBind.id(), - masterPos.toShortString() - ); - } + // Add directly to chunk's pending entity list + ChunkAccess chunk = level.getChunk(masterPos); + if (chunk instanceof ProtoChunk protoChunk) { + protoChunk.addEntity(entityTag); + TiedUpMod.LOGGER.info( + "[HangingCage] Scheduled {} damsel at {}", + shiny ? "shiny" : "regular", + masterPos.toShortString() + ); } } }