Clean repo for open source release
Remove build artifacts, dev tool configs, unused dependencies, and third-party source dumps. Add proper README, update .gitignore, clean up Makefile.
This commit is contained in:
313
src/main/java/com/tiedup/remake/items/ItemKey.java
Normal file
313
src/main/java/com/tiedup/remake/items/ItemKey.java
Normal file
@@ -0,0 +1,313 @@
|
||||
package com.tiedup.remake.items;
|
||||
|
||||
import com.tiedup.remake.core.SystemMessageManager;
|
||||
import com.tiedup.remake.v2.BodyRegionV2;
|
||||
import com.tiedup.remake.items.base.ItemOwnerTarget;
|
||||
import com.tiedup.remake.state.IBondageState;
|
||||
import com.tiedup.remake.util.KidnappedHelper;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Collar Key - Used to lock/unlock bondage items via the Slave Management GUI.
|
||||
*
|
||||
* <p>Phase 20: Key-Lock System</p>
|
||||
* <ul>
|
||||
* <li><b>Linking:</b> Right-click a player wearing a collar to link (claim) the key to them.</li>
|
||||
* <li><b>Management:</b> Opens SlaveItemManagementScreen to lock/unlock individual items.</li>
|
||||
* <li><b>Key UUID:</b> Each key has a unique UUID used to identify which locks it created.</li>
|
||||
* <li><b>Security:</b> Only items locked with this key can be unlocked by it.</li>
|
||||
* </ul>
|
||||
*/
|
||||
public class ItemKey extends ItemOwnerTarget {
|
||||
|
||||
private static final String NBT_KEY_UUID = "keyUUID";
|
||||
|
||||
public ItemKey() {
|
||||
super(new net.minecraft.world.item.Item.Properties().durability(64));
|
||||
}
|
||||
|
||||
// ========== Phase 20: Key UUID System ==========
|
||||
|
||||
/**
|
||||
* Get the unique UUID for this key.
|
||||
* Generates one if it doesn't exist yet.
|
||||
* This UUID is used to identify locks created by this specific key.
|
||||
*
|
||||
* @param stack The key ItemStack
|
||||
* @return The key's unique UUID
|
||||
*/
|
||||
public UUID getKeyUUID(ItemStack stack) {
|
||||
CompoundTag tag = stack.getOrCreateTag();
|
||||
if (!tag.hasUUID(NBT_KEY_UUID)) {
|
||||
// Generate a new UUID for this key
|
||||
tag.putUUID(NBT_KEY_UUID, UUID.randomUUID());
|
||||
}
|
||||
return tag.getUUID(NBT_KEY_UUID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this key matches the given UUID.
|
||||
*
|
||||
* @param stack The key ItemStack
|
||||
* @param lockUUID The lock's UUID to check against
|
||||
* @return true if this key matches the lock
|
||||
*/
|
||||
public boolean matchesLock(ItemStack stack, UUID lockUUID) {
|
||||
if (lockUUID == null) return false;
|
||||
return lockUUID.equals(getKeyUUID(stack));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows ownership and target information when hovering over the item in inventory.
|
||||
*/
|
||||
@Override
|
||||
public void appendHoverText(
|
||||
ItemStack stack,
|
||||
@Nullable Level level,
|
||||
List<Component> tooltip,
|
||||
TooltipFlag flag
|
||||
) {
|
||||
super.appendHoverText(stack, level, tooltip, flag);
|
||||
|
||||
if (hasOwner(stack)) {
|
||||
tooltip.add(
|
||||
Component.literal("Owner: ")
|
||||
.withStyle(ChatFormatting.GOLD)
|
||||
.append(
|
||||
Component.literal(getOwnerName(stack)).withStyle(
|
||||
ChatFormatting.WHITE
|
||||
)
|
||||
)
|
||||
);
|
||||
} else {
|
||||
tooltip.add(
|
||||
Component.literal(
|
||||
"Unclaimed (Right-click a collar wearer to claim)"
|
||||
).withStyle(ChatFormatting.GRAY)
|
||||
);
|
||||
}
|
||||
|
||||
if (hasTarget(stack)) {
|
||||
tooltip.add(
|
||||
Component.literal("Target: ")
|
||||
.withStyle(ChatFormatting.BLUE)
|
||||
.append(
|
||||
Component.literal(getTargetName(stack)).withStyle(
|
||||
ChatFormatting.WHITE
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
tooltip.add(
|
||||
Component.literal("Right-click a collared player to toggle LOCK")
|
||||
.withStyle(ChatFormatting.DARK_GRAY)
|
||||
.withStyle(ChatFormatting.ITALIC)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logic for interacting with entities wearing collars.
|
||||
* Opens the Slave Item Management GUI to lock/unlock individual items.
|
||||
*
|
||||
* Phase 14.1.5: Refactored to support IBondageState (LivingEntity + NPCs)
|
||||
* Phase 20: Opens GUI instead of direct toggle
|
||||
*/
|
||||
@Override
|
||||
public InteractionResult interactLivingEntity(
|
||||
ItemStack stack,
|
||||
Player player,
|
||||
LivingEntity target,
|
||||
InteractionHand hand
|
||||
) {
|
||||
// Check if target can wear collars (Player, EntityDamsel, EntityKidnapper)
|
||||
IBondageState targetState = KidnappedHelper.getKidnappedState(target);
|
||||
|
||||
// Target must be wearing a collar
|
||||
if (targetState == null || !targetState.hasCollar()) {
|
||||
if (!player.level().isClientSide) {
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.ERROR,
|
||||
"Target is not wearing a collar!"
|
||||
);
|
||||
}
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
// Server-side: Handle claiming and validation
|
||||
if (!player.level().isClientSide) {
|
||||
// 1. Claim logic - first interaction with a collar wearer links the key
|
||||
if (!hasOwner(stack)) {
|
||||
setOwner(stack, player);
|
||||
setTarget(stack, target);
|
||||
// Ensure key UUID is generated
|
||||
getKeyUUID(stack);
|
||||
|
||||
// Also link the player to the collar (become collar owner)
|
||||
linkPlayerToCollar(player, target, targetState);
|
||||
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.KEY_CLAIMED,
|
||||
target
|
||||
);
|
||||
player.setItemInHand(hand, stack); // Sync NBT to client
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
// 2. Ownership check - only the person who claimed the key can use it
|
||||
if (!isOwner(stack, player)) {
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.KEY_NOT_OWNER
|
||||
);
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
// 3. Target check - this key only fits the entity it was first linked to
|
||||
if (
|
||||
target instanceof Player targetPlayer &&
|
||||
!isTarget(stack, targetPlayer)
|
||||
) {
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.KEY_WRONG_TARGET
|
||||
);
|
||||
return InteractionResult.FAIL;
|
||||
} else if (
|
||||
!(target instanceof Player) &&
|
||||
!target.getUUID().equals(getTargetId(stack))
|
||||
) {
|
||||
SystemMessageManager.sendToPlayer(
|
||||
player,
|
||||
SystemMessageManager.MessageCategory.KEY_WRONG_TARGET
|
||||
);
|
||||
return InteractionResult.FAIL;
|
||||
}
|
||||
|
||||
// Server validation passed - client will open GUI
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
// Client-side: Open the Slave Item Management GUI
|
||||
// Only open if key is already claimed and we're the owner (client trusts server validation)
|
||||
if (hasOwner(stack) && isOwner(stack, player)) {
|
||||
// Verify target matches (client-side check for responsiveness)
|
||||
boolean targetMatches = false;
|
||||
if (target instanceof Player targetPlayer) {
|
||||
targetMatches = isTarget(stack, targetPlayer);
|
||||
} else {
|
||||
targetMatches = target.getUUID().equals(getTargetId(stack));
|
||||
}
|
||||
|
||||
if (targetMatches) {
|
||||
openUnifiedBondageScreen(target);
|
||||
}
|
||||
}
|
||||
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens the UnifiedBondageScreen in master mode targeting a specific entity.
|
||||
* Called from client-side code only.
|
||||
*
|
||||
* @param target The living entity to manage bondage for
|
||||
*/
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
private void openUnifiedBondageScreen(
|
||||
net.minecraft.world.entity.LivingEntity target
|
||||
) {
|
||||
net.minecraft.client.Minecraft.getInstance().setScreen(
|
||||
new com.tiedup.remake.client.gui.screens.UnifiedBondageScreen(target)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Link a player to a collar - make them an owner.
|
||||
*
|
||||
* <p>When a key is claimed on a collared entity:
|
||||
* <ul>
|
||||
* <li>Add player as owner to the collar item</li>
|
||||
* <li>Register the relationship in CollarRegistry</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param player The player claiming the key
|
||||
* @param target The collared entity
|
||||
* @param targetState The target's IBondageState state
|
||||
*/
|
||||
private void linkPlayerToCollar(
|
||||
Player player,
|
||||
LivingEntity target,
|
||||
IBondageState targetState
|
||||
) {
|
||||
ItemStack collarStack = targetState.getEquipment(BodyRegionV2.NECK);
|
||||
if (collarStack.isEmpty()) return;
|
||||
|
||||
if (
|
||||
collarStack.getItem() instanceof
|
||||
com.tiedup.remake.items.base.ItemCollar collar
|
||||
) {
|
||||
// Add player as owner to the collar (if not already)
|
||||
if (!collar.getOwners(collarStack).contains(player.getUUID())) {
|
||||
collar.addOwner(collarStack, player);
|
||||
|
||||
// Update the collar in the target's inventory
|
||||
targetState.equip(BodyRegionV2.NECK, collarStack);
|
||||
}
|
||||
|
||||
// Register in CollarRegistry (if on server)
|
||||
if (
|
||||
player.level() instanceof
|
||||
net.minecraft.server.level.ServerLevel serverLevel
|
||||
) {
|
||||
com.tiedup.remake.state.CollarRegistry registry =
|
||||
com.tiedup.remake.state.CollarRegistry.get(serverLevel);
|
||||
if (registry != null) {
|
||||
registry.registerCollar(target.getUUID(), player.getUUID());
|
||||
|
||||
// Sync the registry to the new owner
|
||||
if (
|
||||
player instanceof
|
||||
net.minecraft.server.level.ServerPlayer serverPlayer
|
||||
) {
|
||||
java.util.Set<UUID> slaves = registry.getSlaves(
|
||||
player.getUUID()
|
||||
);
|
||||
com.tiedup.remake.network.ModNetwork.sendToPlayer(
|
||||
new com.tiedup.remake.network.sync.PacketSyncCollarRegistry(
|
||||
slaves
|
||||
),
|
||||
serverPlayer
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Sync the target's inventory (collar was modified)
|
||||
if (
|
||||
target instanceof
|
||||
net.minecraft.server.level.ServerPlayer targetPlayer
|
||||
) {
|
||||
com.tiedup.remake.network.sync.SyncManager.syncInventory(
|
||||
targetPlayer
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user