package com.tiedup.remake.commands; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.IntegerArgumentType; import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.tiedup.remake.cells.CellDataV2; import com.tiedup.remake.cells.CellRegistryV2; import com.tiedup.remake.state.PlayerBindState; import com.tiedup.remake.v2.bondage.CollarHelper; import com.tiedup.remake.util.teleport.Position; import com.tiedup.remake.util.teleport.TeleportHelper; import com.tiedup.remake.v2.BodyRegionV2; import net.minecraft.ChatFormatting; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.EntityArgument; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.item.ItemStack; /** * Collar management commands. * * Commands: * /collar claim - Claim ownership of a player's collar * /collar unclaim - Remove your ownership * /collar rename - Set alias for collar * /collar addowner - Add another owner * /collar removeowner - Remove an owner * /collar sethome - Set home location * /collar setprison - Set prison location (legacy) * /collar setcell - Assign cell to collar (preferred) * /collar prisonradius - Set prison fence radius (legacy) * /collar prisonfence [on/off] - Toggle prison fence (legacy) * /collar backhome - Teleport slave back home * /collar info - Show collar info * * Requires OP level 2. */ public class CollarCommand { public static void register( CommandDispatcher dispatcher ) { dispatcher.register(createCollarCommand()); } /** * Create the collar command builder (for use as subcommand of /tiedup). * @return The command builder */ public static com.mojang.brigadier.builder.LiteralArgumentBuilder< CommandSourceStack > createCollarCommand() { return Commands.literal("collar") .requires(CommandHelper.REQUIRES_OP) // /collar claim .then( Commands.literal("claim").then( Commands.argument( "player", EntityArgument.player() ).executes(CollarCommand::claim) ) ) // /collar unclaim .then( Commands.literal("unclaim").then( Commands.argument( "player", EntityArgument.player() ).executes(CollarCommand::unclaim) ) ) // /collar rename .then( Commands.literal("rename").then( Commands.argument("player", EntityArgument.player()).then( Commands.argument( "name", StringArgumentType.greedyString() ).executes(CollarCommand::rename) ) ) ) // /collar addowner .then( Commands.literal("addowner").then( Commands.argument("target", EntityArgument.player()).then( Commands.argument( "owner", EntityArgument.player() ).executes(CollarCommand::addOwner) ) ) ) // /collar removeowner .then( Commands.literal("removeowner").then( Commands.argument("target", EntityArgument.player()).then( Commands.argument( "owner", EntityArgument.player() ).executes(CollarCommand::removeOwner) ) ) ) // /collar setcell (assigns cell) .then( Commands.literal("setcell").then( Commands.argument("player", EntityArgument.player()).then( Commands.argument( "cellname", StringArgumentType.word() ).executes(CollarCommand::setCell) ) ) ) // /collar tocell (teleport to assigned cell) .then( Commands.literal("tocell").then( Commands.argument( "player", EntityArgument.player() ).executes(CollarCommand::teleportToCell) ) ) // /collar info .then( Commands.literal("info").then( Commands.argument( "player", EntityArgument.player() ).executes(CollarCommand::info) ) ); } private static ItemStack getPlayerCollar(ServerPlayer player) { PlayerBindState state = PlayerBindState.getInstance(player); if (state == null || !state.hasCollar()) return ItemStack.EMPTY; return state.getEquipment(BodyRegionV2.NECK); } private static int claim(CommandContext context) throws CommandSyntaxException { CommandSourceStack source = context.getSource(); ServerPlayer target = EntityArgument.getPlayer(context, "player"); ItemStack collar = getPlayerCollar(target); if (collar.isEmpty()) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString()) ); return 0; } if (source.getEntity() instanceof ServerPlayer executor) { if (CollarHelper.isCollar(collar)) { CollarHelper.addOwner(collar, executor); source.sendSuccess( () -> Component.translatable( "command.tiedup.collar_cmd.claimed", target.getName().getString() ).withStyle(ChatFormatting.GREEN), true ); return 1; } } source.sendFailure(Component.translatable("command.tiedup.collar_cmd.claim_failed")); return 0; } private static int unclaim(CommandContext context) throws CommandSyntaxException { CommandSourceStack source = context.getSource(); ServerPlayer target = EntityArgument.getPlayer(context, "player"); ItemStack collar = getPlayerCollar(target); if (collar.isEmpty()) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString()) ); return 0; } if (source.getEntity() instanceof ServerPlayer executor) { if (CollarHelper.isCollar(collar)) { CollarHelper.removeOwner(collar, executor.getUUID()); source.sendSuccess( () -> Component.translatable( "command.tiedup.collar_cmd.unclaimed", target.getName().getString() ).withStyle(ChatFormatting.GREEN), true ); return 1; } } source.sendFailure(Component.translatable("command.tiedup.collar_cmd.unclaim_failed")); return 0; } private static int rename(CommandContext context) throws CommandSyntaxException { CommandSourceStack source = context.getSource(); ServerPlayer target = EntityArgument.getPlayer(context, "player"); String name = StringArgumentType.getString(context, "name"); ItemStack collar = getPlayerCollar(target); if (collar.isEmpty()) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString()) ); return 0; } if (CollarHelper.isCollar(collar)) { CollarHelper.setNickname(collar, name); source.sendSuccess( () -> Component.translatable( "command.tiedup.collar_cmd.renamed", name ).withStyle(ChatFormatting.GREEN), true ); return 1; } return 0; } private static int addOwner(CommandContext context) throws CommandSyntaxException { CommandSourceStack source = context.getSource(); ServerPlayer target = EntityArgument.getPlayer(context, "target"); ServerPlayer owner = EntityArgument.getPlayer(context, "owner"); ItemStack collar = getPlayerCollar(target); if (collar.isEmpty()) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString()) ); return 0; } if (CollarHelper.isCollar(collar)) { CollarHelper.addOwner(collar, owner); source.sendSuccess( () -> Component.translatable( "command.tiedup.collar_cmd.owner_added", owner.getName().getString(), target.getName().getString() ).withStyle(ChatFormatting.GREEN), true ); return 1; } return 0; } private static int removeOwner(CommandContext context) throws CommandSyntaxException { CommandSourceStack source = context.getSource(); ServerPlayer target = EntityArgument.getPlayer(context, "target"); ServerPlayer owner = EntityArgument.getPlayer(context, "owner"); ItemStack collar = getPlayerCollar(target); if (collar.isEmpty()) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString()) ); return 0; } if (CollarHelper.isCollar(collar)) { CollarHelper.removeOwner(collar, owner.getUUID()); source.sendSuccess( () -> Component.translatable( "command.tiedup.collar_cmd.owner_removed", owner.getName().getString(), target.getName().getString() ).withStyle(ChatFormatting.GREEN), true ); return 1; } return 0; } /** * /collar setcell * * Assign a named cell to a player's collar. */ private static int setCell(CommandContext context) throws CommandSyntaxException { CommandSourceStack source = context.getSource(); ServerPlayer target = EntityArgument.getPlayer(context, "player"); String cellName = StringArgumentType.getString(context, "cellname"); ItemStack collar = getPlayerCollar(target); if (collar.isEmpty()) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString()) ); return 0; } // Get the cell by name ServerLevel serverLevel = source.getLevel(); CellRegistryV2 registry = CellRegistryV2.get(serverLevel); CellDataV2 cell = registry.getCellByName(cellName); if (cell == null) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.cell_not_found", cellName) ); return 0; } if (CollarHelper.isCollar(collar)) { CollarHelper.setCellId(collar, cell.getId()); source.sendSuccess( () -> Component.translatable( "command.tiedup.collar_cmd.cell_assigned", cellName, target.getName().getString() ).withStyle(ChatFormatting.GREEN), true ); return 1; } return 0; } /** * /collar tocell * * Teleport player to their assigned cell. */ private static int teleportToCell( CommandContext context ) throws CommandSyntaxException { CommandSourceStack source = context.getSource(); ServerPlayer target = EntityArgument.getPlayer(context, "player"); ItemStack collar = getPlayerCollar(target); if (collar.isEmpty()) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString()) ); return 0; } if (CollarHelper.isCollar(collar)) { if (!CollarHelper.hasCellAssigned(collar)) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.no_cell_assigned") ); return 0; } // Get cell position and teleport java.util.UUID cellId = CollarHelper.getCellId(collar); ServerLevel serverLevel = source.getLevel(); CellDataV2 cell = CellRegistryV2.get(serverLevel).getCell(cellId); if (cell == null) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.cell_deleted") ); return 0; } net.minecraft.core.BlockPos teleportTarget = cell.getSpawnPoint() != null ? cell.getSpawnPoint() : cell.getCorePos().above(); Position cellPos = new Position( teleportTarget, serverLevel.dimension() ); TeleportHelper.teleportEntity(target, cellPos); source.sendSuccess( () -> Component.translatable( "command.tiedup.collar_cmd.teleported", target.getName().getString(), cell.getCorePos().toShortString() ).withStyle(ChatFormatting.GREEN), true ); return 1; } return 0; } private static int info(CommandContext context) throws CommandSyntaxException { CommandSourceStack source = context.getSource(); ServerPlayer target = EntityArgument.getPlayer(context, "player"); ItemStack collar = getPlayerCollar(target); if (collar.isEmpty()) { source.sendFailure( Component.translatable("command.tiedup.collar_cmd.no_collar", target.getName().getString()) ); return 0; } if (CollarHelper.isCollar(collar)) { source.sendSuccess( () -> Component.translatable( "command.tiedup.collar_cmd.info_header", target.getName().getString() ).withStyle(ChatFormatting.GOLD), false ); String nickname = CollarHelper.getNickname(collar); String nicknameDisplay = (nickname == null || nickname.isEmpty()) ? "None" : nickname; source.sendSuccess( () -> Component.translatable("command.tiedup.collar_cmd.info_nickname", nicknameDisplay).withStyle(ChatFormatting.GRAY), false ); source.sendSuccess( () -> Component.translatable("command.tiedup.collar_cmd.info_has_owner", String.valueOf(CollarHelper.hasOwner(collar))).withStyle(ChatFormatting.GRAY), false ); // Cell assignment java.util.UUID cellId = CollarHelper.getCellId(collar); if (cellId != null) { ServerLevel serverLevel = source.getLevel(); CellRegistryV2 registry = CellRegistryV2.get(serverLevel); CellDataV2 cell = registry.getCell(cellId); if (cell != null) { String cellDisplay = cell.getName() != null ? cell.getName() : cellId.toString().substring(0, 8) + "..."; source.sendSuccess( () -> Component.translatable( "command.tiedup.collar_cmd.info_cell", cellDisplay, cell.getCorePos().toShortString() ).withStyle(ChatFormatting.GRAY), false ); } else { source.sendSuccess( () -> Component.translatable("command.tiedup.collar_cmd.info_cell_deleted").withStyle(ChatFormatting.RED), false ); } } else { source.sendSuccess( () -> Component.translatable("command.tiedup.collar_cmd.info_cell_none").withStyle(ChatFormatting.GRAY), false ); } boolean locked = collar.getItem() instanceof com.tiedup.remake.items.base.ILockable lockable && lockable.isLocked(collar); source.sendSuccess( () -> Component.translatable( "command.tiedup.collar_cmd.info_locked", String.valueOf(locked) ).withStyle(ChatFormatting.GRAY), false ); return 1; } return 0; } }