package com.r3944realms.leashedplayer.content.commands; import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.arguments.FloatArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig; import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry; import com.r3944realms.leashedplayer.content.gamerules.Server.CreateLeashFenceKnotEntityIfAbsent; import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension; import com.r3944realms.leashedplayer.modInterface.PlayerLeashable; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; import net.minecraft.commands.arguments.EntityArgument; import net.minecraft.commands.arguments.coordinates.BlockPosArgument; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.BlockTags; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Leashable; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.Collection; import java.util.List; import static com.r3944realms.leashedplayer.content.commands.Command.SHOULD_USE_PREFIX; import static com.r3944realms.leashedplayer.content.commands.Command.getLiterArgumentBuilderOfCSS; public class LeashCommand { public static final Integer MIN_VALUE = LeashPlayerCommonConfig.MinimumLeashLengthCanBeSet.get(); public static final Integer MAX_VALUE = LeashPlayerCommonConfig.MaximumLeashLengthCanBeSet.get(); private final static String LEASHEDPLAYER_LEASH_MESSAGE_ = "leashedplayer.command.leash.message."; public final static String LEASH_FAILED = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.length.failed"; public final static String LEASH_LENGTH_SHOW = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.length.show", LEASH_LENGTH_SET = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.length.set", LEASH_DATA = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.data", LEASH_DATA_CLEAR = LEASH_DATA + ".clear" ; public final static String NO_LEASH_DATA = LEASH_DATA + ".null", LEASH_DATA_SHOW = LEASH_DATA + ".show", LEASH_DATA_SET = LEASH_DATA + ".set", LEASH_DATA_SET_FAILED_DIFF_LEVEL = LEASH_DATA_SET + ".failed.diff_level", LEASH_DATA_SET_FAILED_TOO_FAR = LEASH_DATA_SET + ".failed.too_far", LEASH_DATA_SET_FAILED_NO_KNOT_EXISTED_IN_THAT_POS = LEASH_DATA_SET + ".failed.no_knot_exist_in_that_pos", LEASH_DATA_SET_FAILED_FORBID_SAME_ENTITY = LEASH_DATA_SET + ".failed.forbid_same_entity", LEASH_DATA_CLEAR_FAILED_NO_DATA = LEASH_DATA_CLEAR + ".leash.clear.failed.no_data" ; public static void register(CommandDispatcher dispatcher) { @Nullable List> nodeList = SHOULD_USE_PREFIX ? null : new ArrayList<>(); LiteralArgumentBuilder literalArgumentBuilder = Commands.literal(com.r3944realms.leashedplayer.content.commands.Command.PREFIX); LiteralArgumentBuilder $$leashRoot = getLiterArgumentBuilderOfCSS("leash", !SHOULD_USE_PREFIX, nodeList); Command getSelfLeashLength = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = source.getPlayerOrException(); float leashLength = ((ILivingEntityExtension)player).getLeashLength(); source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SHOW, player.getDisplayName(), leashLength), true); } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command getRefPlayerLeashLength = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer"); float leashLength = ((ILivingEntityExtension)player).getLeashLength(); source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SHOW, player.getDisplayName(), leashLength), true); } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command getRefPlayersLeashLength = context -> { CommandSourceStack source = context.getSource(); try { Collection playerCol = EntityArgument.getPlayers(context, "targetPlayers"); playerCol.forEach(player -> { float leashLength = ((ILivingEntityExtension) player).getLeashLength(); source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SHOW, player.getDisplayName(), leashLength), true); }); } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command setSelfLengthLeashLength = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = source.getPlayerOrException(); float leashLength = context.getArgument("leashLength", Float.class); ((ILivingEntityExtension)player).setLeashLength(leashLength); source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SET, player.getDisplayName(), leashLength), true); } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command setRefPlayerLengthLeashLength = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer"); float leashLength = context.getArgument("leashLength", Float.class); ((ILivingEntityExtension)player).setLeashLength(leashLength); source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SET, player.getDisplayName(), leashLength), true); } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command setRefPlayersLengthLeashLength = context -> { CommandSourceStack source = context.getSource(); float leashLength = context.getArgument("leashLength", Float.class); try { Collection playerCol = EntityArgument.getPlayers(context, "targetPlayers"); playerCol.forEach(player -> { try { ((ILivingEntityExtension)player).setLeashLength(leashLength); source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SET, player.getDisplayName(), leashLength), true); } catch (Exception e) { throw new RuntimeException(e); } }); } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; //获取Data 构造一个MutableComponent显示数据 Command geSelfLeashData = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = source.getPlayerOrException(); Integer x = LeashLengthGetResultInt(player, source); if (x != null) return x; } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command getRefPlayerLeashData = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer"); Integer x = LeashLengthGetResultInt(player, source); if (x != null) return x; } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command getRefPlayersLeashData = context -> { CommandSourceStack source = context.getSource(); try { Collection playerCol = EntityArgument.getPlayers(context, "targetPlayers"); playerCol.forEach(player -> { try { LeashLengthGetResultInt(player, source); } catch (Exception e) { throw new RuntimeException(e); } }); } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; //设置前要判断其实体距离(同一维度,且距离不得大于其绳长的1.2倍(待定,也许可以设置在配置文件里) Command setSelfLeashDataEntity = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = source.getPlayerOrException(); Integer x = LeashDataEntitySetResultInt(context, player, source); if (x != null) return x; } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command setSelfLeashDataByBlockPos = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = source.getPlayerOrException(); Integer x = LeashDataBlockPosSetResultInt(context, source, player); if (x != null) return x; } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command setRefPlayerLeashDataEntity = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer"); Integer x = LeashDataEntitySetResultInt(context, player, source); if (x != null) return x; } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command setRefPlayersLeashDataEntity = context -> { CommandSourceStack source = context.getSource(); try { Collection playerCol = EntityArgument.getPlayers(context, "targetPlayers"); playerCol.forEach(player -> { try { LeashDataEntitySetResultInt(context, player, source); } catch (CommandSyntaxException e) { throw new RuntimeException(e); } }); } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command setRefPlayersLeashDataByBlockPos = context -> { CommandSourceStack source = context.getSource(); try { Collection playerCol = EntityArgument.getPlayers(context, "targetPlayers"); playerCol.forEach(player -> LeashDataBlockPosSetResultInt(context, source, player)); } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command setRefPlayerLeashDataByBlockPos = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer"); Integer x = LeashDataBlockPosSetResultInt(context, source, player); if (x != null) return x; } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command clearSelfLeashData = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = source.getPlayerOrException(); Integer x = LeashDataClearResultInt(source, PlayerLeashable.getLeashDataEntity(player, source.getLevel()), player); if (x != null) return x; } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command clearRefPlayerLeashData = context -> { CommandSourceStack source = context.getSource(); try { ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer"); Integer x = LeashDataClearResultInt(source, PlayerLeashable.getLeashDataEntity(player, source.getLevel()),player); if (x != null) return x; } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; Command clearRefPlayersLeashData = context -> { CommandSourceStack source = context.getSource(); try { Collection playerCol = EntityArgument.getPlayers(context, "targetPlayers"); playerCol.forEach(player -> { try { LeashDataClearResultInt(source, PlayerLeashable.getLeashDataEntity(player, source.getLevel()),player); } catch (Exception e) { throw new RuntimeException(e); } }); } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; LiteralArgumentBuilder SelfLeashLength = $$leashRoot.then(Commands.literal("length").executes(getSelfLeashLength) .then(Commands.literal("get").executes(getSelfLeashLength)) .then(Commands.literal("set").requires(cs -> cs.hasPermission(2)) .then(Commands.argument("leashLength", FloatArgumentType.floatArg(MIN_VALUE, MAX_VALUE)).executes(setSelfLengthLeashLength)) ) ); LiteralArgumentBuilder RefPlayerLeashLength = $$leashRoot.then( Commands.literal("length") .then(Commands.argument("targetPlayer", EntityArgument.player()).executes(getRefPlayerLeashLength) .then(Commands.literal("get").executes(getRefPlayerLeashLength)) .then(Commands.literal("set").requires(cs -> cs.hasPermission(2)) .then( Commands.argument("leashLength", FloatArgumentType.floatArg(MIN_VALUE, MAX_VALUE)).executes(setRefPlayerLengthLeashLength) ) ) ) .then(Commands.argument("targetPlayers", EntityArgument.players()).executes(getRefPlayersLeashLength) .then(Commands.literal("get").executes(getRefPlayersLeashLength)) .then(Commands.literal("set").requires(cs -> cs.hasPermission(2)) .then( Commands.argument("leashLength", FloatArgumentType.floatArg(MIN_VALUE, MAX_VALUE)).executes(setRefPlayersLengthLeashLength) ) ) ) ); LiteralArgumentBuilder RefPLayerData = $$leashRoot.then( Commands.literal("data") .then(Commands.argument("targetPlayer", EntityArgument.player()).executes(getRefPlayerLeashData) .then(Commands.literal("get") .executes(getRefPlayerLeashData) ) .then(Commands.literal("set").requires(cs -> cs.hasPermission(2)) .then(Commands.argument("holderEntity", EntityArgument.entity()) .executes(setRefPlayerLeashDataEntity) ) .then(Commands.argument("BlockPos", BlockPosArgument.blockPos()) .executes(setRefPlayerLeashDataByBlockPos) ) ) .then(Commands.literal("clear").requires(cs -> cs.hasPermission(2)).executes(clearRefPlayerLeashData)) ) .then(Commands.argument("targetPlayers", EntityArgument.players()).executes(getRefPlayersLeashData) .then(Commands.literal("get") .executes(getRefPlayersLeashData) ) .then(Commands.literal("set").requires(cs -> cs.hasPermission(2)) .then(Commands.argument("holderEntity", EntityArgument.entity()) .executes(setRefPlayersLeashDataEntity) ) .then(Commands.argument("BlockPos", BlockPosArgument.blockPos()) .executes(setRefPlayersLeashDataByBlockPos) ) ) .then(Commands.literal("clear").requires(cs -> cs.hasPermission(2)).executes(clearRefPlayersLeashData)) )); LiteralArgumentBuilder SelfData = $$leashRoot.then( Commands.literal("data") .then(Commands.literal("get") .executes(geSelfLeashData) ) .then(Commands.literal("set").requires(cs -> cs.hasPermission(2)) .then(Commands.argument("holderEntity", EntityArgument.entity()) .executes(setSelfLeashDataEntity) ) .then(Commands.argument("BlockPos", BlockPosArgument.blockPos()) .executes(setSelfLeashDataByBlockPos) ) ) .then(Commands.literal("clear").requires(cs -> cs.hasPermission(2)) .executes(clearSelfLeashData) ) ); if(SHOULD_USE_PREFIX) { literalArgumentBuilder .then(RefPlayerLeashLength) .then(SelfLeashLength) .then(RefPLayerData) .then(SelfData); dispatcher.register(literalArgumentBuilder); } else { nodeList.forEach(dispatcher::register); } } private static @Nullable Integer LeashLengthGetResultInt(ServerPlayer player, CommandSourceStack source) throws Exception { Leashable.LeashData leashDataFromEntityData = ((PlayerLeashable) player).getLeashDataFromEntityData(); if(leashDataFromEntityData == null) { source.sendSuccess(() -> Component.translatable(NO_LEASH_DATA, player.getDisplayName()), true); return 1; } else { Entity leashDataEntity = PlayerLeashable.getLeashDataEntityOrThrown(leashDataFromEntityData, source.getLevel()); source.sendSuccess(() -> Component.translatable(LEASH_DATA_SHOW, player.getDisplayName(), leashDataEntity.getDisplayName()), true); } return null; } private static @Nullable Integer LeashDataBlockPosSetResultInt(CommandContext context, CommandSourceStack source, ServerPlayer player) { BlockPos blockPos = BlockPosArgument.getBlockPos(context, "BlockPos"); Entity leashDataEntity = PlayerLeashable.getLeashFenceKnotEntity(source.getLevel(), blockPos); PlayerLeashable leashedPlayer = (PlayerLeashable) player; Component targetPlayerDisplayName = player.getDisplayName(); if(leashDataEntity == null) { ServerLevel level = context.getSource().getLevel(); if(GameruleRegistry.getGameruleBoolValue(level,CreateLeashFenceKnotEntityIfAbsent.ID)) { if(level.getBlockState(blockPos).is(BlockTags.FENCES)) { Entity leashKnotFence = PlayerLeashable.createLeashKnotFence(level, blockPos); leashedPlayer.setLeashedTo(leashKnotFence, true); source.sendSuccess(() -> Component.translatable(LEASH_DATA_SET, targetPlayerDisplayName, leashKnotFence.getDisplayName()), true); return null; } } source.sendFailure(Component.translatable(LEASH_DATA_SET_FAILED_NO_KNOT_EXISTED_IN_THAT_POS, blockPos.getX(), blockPos.getY(), blockPos.getZ())); return 1; } Component leashDataEntityDisplayName = leashDataEntity.getDisplayName(); return LeashDataCommonPartSetResultInt(source, player, leashDataEntity, leashedPlayer, targetPlayerDisplayName, leashDataEntityDisplayName); } private static @Nullable Integer LeashDataEntitySetResultInt(CommandContext context, ServerPlayer player, CommandSourceStack source) throws CommandSyntaxException { Entity leashDataEntity = EntityArgument.getEntity(context, "holderEntity"); PlayerLeashable leashedPlayer = (PlayerLeashable) player; Component targetPlayerDisplayName = player.getDisplayName(); Component leashDataEntityDisplayName = leashDataEntity.getDisplayName(); if(player.equals(leashDataEntity)) { source.sendFailure(Component.translatable(LEASH_DATA_SET_FAILED_FORBID_SAME_ENTITY)); return 1; } return LeashDataCommonPartSetResultInt(source, player, leashDataEntity, leashedPlayer, targetPlayerDisplayName, leashDataEntityDisplayName); } private static @Nullable Integer LeashDataCommonPartSetResultInt(CommandSourceStack source, ServerPlayer player, Entity leashDataEntity, PlayerLeashable leashedPlayer, Component targetPlayerDisplayName, Component leashDataEntityDisplayName) { if(player.level() != leashDataEntity.level()) { source.sendFailure(Component.translatable(LEASH_DATA_SET_FAILED_DIFF_LEVEL, targetPlayerDisplayName, leashDataEntityDisplayName)); return 2; } ILivingEntityExtension targetPlayerExtension = (ILivingEntityExtension) player; if (player.distanceTo(leashDataEntity) > targetPlayerExtension.getLeashLength() * 1.2f) { source.sendFailure(Component.translatable(LEASH_DATA_SET_FAILED_TOO_FAR, targetPlayerDisplayName, leashDataEntityDisplayName, targetPlayerExtension.getLeashLength())); return 3; } leashedPlayer.setLeashedTo(leashDataEntity, true); source.sendSuccess(() -> Component.translatable(LEASH_DATA_SET, targetPlayerDisplayName, leashDataEntityDisplayName), true); return null; } private static @Nullable Integer LeashDataClearResultInt(CommandSourceStack source, Entity leashDataEntity, ServerPlayer serverPlayer) { if(leashDataEntity == null) { source.sendFailure(Component.translatable(LEASH_DATA_CLEAR_FAILED_NO_DATA, serverPlayer.getDisplayName())); return 1; } ((PlayerLeashable)serverPlayer).dropLeash(true, false); source.sendSuccess(() -> Component.translatable(LEASH_DATA_CLEAR, serverPlayer.getDisplayName(), leashDataEntity.getDisplayName()), true); return null; } }