diff --git a/README.md b/README.md index 4c8fc16..397da02 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,4 @@ +# 版本 0.0.2.2 【注意:本解釋簡繁混寫,因爲趕時間,所以並不怎麽規範,請諒解】 ## 简介 现在开始你可以用拴绳栓住玩家,也可以栓住自己了,不如尝试栓住彼此来通关我的世界吧( @@ -11,10 +12,16 @@ ## 指令 -* `/lp leash length [<玩家>] setLength <长度> ` - 设置该玩家的拴绳长度 [ 如果<玩家>为空则代表执行对象是自己 ,<长度> 为在 5 ~ 1024之间的浮点数 ] +* `/lp leash length [<玩家>] set <长度> ` - 设置该玩家的拴绳长度 [ 如果<玩家>为空则代表执行对象是自己 ,<长度> 为在 5 ~ 1024之间的浮点数 ] -* `/lp leash length [<玩家>] [getLength]` - 获取该玩家的拴绳长度 [ 如果<玩家>为空则代表执行对象是自己 , [getLength] 可不写] +* `/lp leash length [<玩家>] [get]` - 顯示该玩家的拴绳长度 [ 如果<玩家>为空则代表执行对象是自己 , [get] 可不写] + +* `/lp leash data [<玩家>] set <實體>/<方塊坐標>` - 設置該玩家的的拴繩數據實體設置為<實體>/位於<方塊坐標>處的柵欄上的拴繩結實體 + +* `/lp leash data [<玩家>] [get]` - 顯示该玩家的拴绳數據 [ 如果<玩家>为空则代表执行对象是自己 , [get] 可不写] ## 游戏规则 -* `LP.TeleportWithLeashedPlayers` - 来决定被栓玩家是否在传送时能随拴绳持有者一起传送 [默认值: True] \ No newline at end of file +* `LP.TeleportWithLeashedPlayers` - 此規則啓用后, 被栓玩家將會随玩家拴绳持有者一起传送 [默认值: True] + +* `LP.CreateLeashFenceKnotEntityIfAbsent` - 此規則啓用后, 在設置 leashData 時,如果對應方塊坐標上的柵欄沒有拴繩結則會自動創建這個實體並綁定 [默认值: True] \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index be81186..b97bba6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -32,7 +32,7 @@ mod_name=Leashed Player # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=All Rights Reserved # The mod version. See https://semver.org/ -mod_version=0.0.1 +mod_version=0.0.2.2 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html diff --git a/src/generated/resources/.cache/211976637bfb5e111401ad2bfb58570ef2fb3dff b/src/generated/resources/.cache/211976637bfb5e111401ad2bfb58570ef2fb3dff index a655a10..d39d5c3 100644 --- a/src/generated/resources/.cache/211976637bfb5e111401ad2bfb58570ef2fb3dff +++ b/src/generated/resources/.cache/211976637bfb5e111401ad2bfb58570ef2fb3dff @@ -1,2 +1,2 @@ -// 1.21 2024-09-03T17:46:39.9837977 Languages: en_us for mod: leashedplayer -d770cde6d74b269e8a0447edeb0a65668dda07d3 assets/leashedplayer/lang/en_us.json +// 1.21 2024-09-04T14:54:14.4635752 Languages: en_us for mod: leashedplayer +3e231f3b588ab61d2990c49bf1f1deca5593dbbf assets/leashedplayer/lang/en_us.json diff --git a/src/generated/resources/.cache/a1129211d3ad6d65c101bb152ae8c66c8256bccb b/src/generated/resources/.cache/a1129211d3ad6d65c101bb152ae8c66c8256bccb index 931b7fa..a8ab8f3 100644 --- a/src/generated/resources/.cache/a1129211d3ad6d65c101bb152ae8c66c8256bccb +++ b/src/generated/resources/.cache/a1129211d3ad6d65c101bb152ae8c66c8256bccb @@ -1,2 +1,2 @@ -// 1.21 2024-09-03T17:46:39.9827933 Languages: zh_cn for mod: leashedplayer -eb4dc9fdfece3e001d0f32abcad5de6b926b0a4d assets/leashedplayer/lang/zh_cn.json +// 1.21 2024-09-04T14:54:14.4585471 Languages: zh_cn for mod: leashedplayer +6db8ccbbd7d3bf13e819c2ae1762f37e2c332043 assets/leashedplayer/lang/zh_cn.json diff --git a/src/generated/resources/.cache/ed628fd843215c1bf29a07b9cbd1b26a6af0636d b/src/generated/resources/.cache/ed628fd843215c1bf29a07b9cbd1b26a6af0636d index d90dea0..77191da 100644 --- a/src/generated/resources/.cache/ed628fd843215c1bf29a07b9cbd1b26a6af0636d +++ b/src/generated/resources/.cache/ed628fd843215c1bf29a07b9cbd1b26a6af0636d @@ -1,2 +1,2 @@ -// 1.21 2024-09-03T17:46:39.9817953 Languages: zh_tw for mod: leashedplayer -0f4c1499f9241f8d8c33033dbcad397c4f3df5fa assets/leashedplayer/lang/zh_tw.json +// 1.21 2024-09-04T14:54:14.4535174 Languages: zh_tw for mod: leashedplayer +86fa3a80c53a50ad5af47129384e506cddda79aa assets/leashedplayer/lang/zh_tw.json diff --git a/src/generated/resources/assets/leashedplayer/lang/en_us.json b/src/generated/resources/assets/leashedplayer/lang/en_us.json index 0d4184c..f629b5b 100644 --- a/src/generated/resources/assets/leashedplayer/lang/en_us.json +++ b/src/generated/resources/assets/leashedplayer/lang/en_us.json @@ -1,7 +1,16 @@ { - "gamerule.RWN.TeleportWithLeashedPlayers": "Teleport with leashed player", - "gamerule.RWN.TeleportWithLeashedPlayers.description": "You will teleport with your leashed players ", - "leashedplayer.command.leash.message.leash.length.fail": "Failed (Internal Error)", - "leashedplayer.command.leash.message.leash.length.set": "The Leash length of %s is set to %f blocks", - "leashedplayer.command.leash.message.leash.length.show": "The Leash Length of %s is %f blocks" + "gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "Create Leash Fence Knot Entity if absent", + "gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "Create LeashKnot Entity if it's absent on fence", + "gamerule.LP.TeleportWithLeashedPlayers": "Teleport leashed player with player holder", + "gamerule.LP.TeleportWithLeashedPlayers.description": "Holder will teleport with their leashed players ", + "leashedplayer.command.leash.message.leash.data.null": "%1$s has no LeashDataEntity", + "leashedplayer.command.leash.message.leash.data.show": "%1$s's LeashDataEntity is %2$s", + "leashedplayer.command.leash.message.leash.leash_data.set": "%1$s LeashDataEntity now is set as %2$s", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.diff_level": "%1$s and %2$s are not at a same level", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.forbid_same_entity": "Prohibit setting the same entity", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.no_knot_exist_in_that_pos": "No knot found at (X:%f,Y:%f,Z:%f)", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.too_far": "The distance between %1$s and %2$s is larger than the 1.2 times of LeashLength, LeashLength is %3$s blocks", + "leashedplayer.command.leash.message.leash.length.failed": "Failed (Internal Error, maybe your command is incorrect)", + "leashedplayer.command.leash.message.leash.length.set": "The Leash length of %1$s is set to %2$s blocks", + "leashedplayer.command.leash.message.leash.length.show": "The Leash Length of %1$s is %2$s blocks" } \ No newline at end of file diff --git a/src/generated/resources/assets/leashedplayer/lang/zh_cn.json b/src/generated/resources/assets/leashedplayer/lang/zh_cn.json index 35f62a5..c0a6909 100644 --- a/src/generated/resources/assets/leashedplayer/lang/zh_cn.json +++ b/src/generated/resources/assets/leashedplayer/lang/zh_cn.json @@ -1,7 +1,16 @@ { - "gamerule.RWN.TeleportWithLeashedPlayers": "传送被栓玩家", - "gamerule.RWN.TeleportWithLeashedPlayers.description": "传送时将被栓玩家与自己一起传送", - "leashedplayer.command.leash.message.leash.length.fail": "失败(内部错误)", - "leashedplayer.command.leash.message.leash.length.set": "%s的拴绳长度被设置为%f格", - "leashedplayer.command.leash.message.leash.length.show": "%s的拴绳长度为%f格" + "gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "如果缺失则创建栓绳结", + "gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "如果在栅栏处缺失栓绳结,则创建它", + "gamerule.LP.TeleportWithLeashedPlayers": "被栓玩家随玩家持有者传送", + "gamerule.LP.TeleportWithLeashedPlayers.description": "传送时将被栓玩家与持有者一起传送", + "leashedplayer.command.leash.message.leash.data.null": "%1$s沒有拴绳数据实体", + "leashedplayer.command.leash.message.leash.data.show": "%1$s的拴绳数据实体为%2$s", + "leashedplayer.command.leash.message.leash.leash_data.set": "%1$s拴绳数据实体被设置为%2$s", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.diff_level": "%1$s和%2$s不在同一维度上", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.forbid_same_entity": "禁止设置同一实体", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.no_knot_exist_in_that_pos": "未找到栓绳结在(X:%f, Y:%f, Z:%f)处", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.too_far": "%1$s到%2$s的距离超过了1.2倍 栓绳长度,原长:%3$s 格", + "leashedplayer.command.leash.message.leash.length.failed": "失败(内部错误,可能是你输的指令有误)", + "leashedplayer.command.leash.message.leash.length.set": "%1$s的拴绳长度被设置为%2$s格", + "leashedplayer.command.leash.message.leash.length.show": "%1$s的拴绳长度为%2$s格" } \ No newline at end of file diff --git a/src/generated/resources/assets/leashedplayer/lang/zh_tw.json b/src/generated/resources/assets/leashedplayer/lang/zh_tw.json index 1cc33af..567eba9 100644 --- a/src/generated/resources/assets/leashedplayer/lang/zh_tw.json +++ b/src/generated/resources/assets/leashedplayer/lang/zh_tw.json @@ -1,7 +1,16 @@ { - "gamerule.RWN.TeleportWithLeashedPlayers": "傳送被栓玩家", - "gamerule.RWN.TeleportWithLeashedPlayers.description": "傳送時將被栓玩家與隨自己一起傳送", - "leashedplayer.command.leash.message.leash.length.fail": "失敗(内部錯誤)", - "leashedplayer.command.leash.message.leash.length.set": "%s的栓繩長度被設置為%f格", - "leashedplayer.command.leash.message.leash.length.show": "%s的栓繩長度為%f格" + "gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "如果缺失則創建栓繩結", + "gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "如果在柵欄処缺失拴繩結,則創建它", + "gamerule.LP.TeleportWithLeashedPlayers": "被栓玩家随玩家持有者傳送", + "gamerule.LP.TeleportWithLeashedPlayers.description": "將被栓玩家將隨持有者一起傳送", + "leashedplayer.command.leash.message.leash.data.null": "%1$s沒有栓繩數據實體", + "leashedplayer.command.leash.message.leash.data.show": "%1$s栓繩數據實體為%2$s", + "leashedplayer.command.leash.message.leash.leash_data.set": "%1$s栓繩數據實體設置為%2$s", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.diff_level": "%1$s和%2$s不在同一緯度上", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.forbid_same_entity": "禁止設置同一實體", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.no_knot_exist_in_that_pos": "未找到栓繩結在(X:%f, Y:%f, Z:%f)処", + "leashedplayer.command.leash.message.leash.leash_data.set.failed.too_far": "%1$s到%2$s的距離超過了1.2倍栓繩長度,原長:%3$s 格", + "leashedplayer.command.leash.message.leash.length.failed": "失敗(内部錯誤,,可能你輸入的指令有誤)", + "leashedplayer.command.leash.message.leash.length.set": "%1$s的栓繩長度被設置為%2$s格", + "leashedplayer.command.leash.message.leash.length.show": "%1$s的栓繩長度為%2$s格" } \ No newline at end of file diff --git a/src/main/java/com/r3944realms/leashedplayer/LeashedPlayer.java b/src/main/java/com/r3944realms/leashedplayer/LeashedPlayer.java index 17bea37..c23c73b 100644 --- a/src/main/java/com/r3944realms/leashedplayer/LeashedPlayer.java +++ b/src/main/java/com/r3944realms/leashedplayer/LeashedPlayer.java @@ -1,7 +1,7 @@ package com.r3944realms.leashedplayer; import net.neoforged.fml.common.Mod; -//TODO: 13:40 + @Mod(LeashedPlayer.MOD_ID) public class LeashedPlayer { public static final String MOD_ID = "leashedplayer"; diff --git a/src/main/java/com/r3944realms/leashedplayer/content/commands/LeashCommand.java b/src/main/java/com/r3944realms/leashedplayer/content/commands/LeashCommand.java index 93477eb..412d302 100644 --- a/src/main/java/com/r3944realms/leashedplayer/content/commands/LeashCommand.java +++ b/src/main/java/com/r3944realms/leashedplayer/content/commands/LeashCommand.java @@ -5,19 +5,40 @@ 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.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 net.minecraft.world.entity.decoration.LeashFenceKnotEntity; +import org.jetbrains.annotations.Nullable; public class LeashCommand { private final static String LEASHEDPLAYER_LEASH_MESSAGE_ = "leashedplayer.command.leash.message."; - public final static String LEASH_LENGTH_SHOW = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.length.show", - LEASH_LENGTH_FAIL = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.length.fail", - LEASH_LENGTH_SET = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.length.set"; + public final static String LEASH_FAILED = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.length.failed", + LEASH_LENGTH_SHOW = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.length.show", + LEASH_LENGTH_SET = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.length.set", + NO_LEASH_DATA = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.data.null", + LEASH_DATA_SHOW = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.data.show", + LEASH_DATA_SET = LEASHEDPLAYER_LEASH_MESSAGE_ + "leash.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"; + public static void register(CommandDispatcher dispatcher) { LiteralArgumentBuilder literalArgumentBuilder = Commands.literal(com.r3944realms.leashedplayer.content.commands.Command.PREFIX); Command getSelfLeashLength = context -> { @@ -25,9 +46,9 @@ public class LeashCommand { try { ServerPlayer player = source.getPlayerOrException(); float leashLength = ((ILivingEntityExtension)player).getLeashLength(); - source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SHOW, player.getName(), leashLength), true); + source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SHOW, player.getDisplayName(), leashLength), true); } catch (Exception e) { - source.sendFailure(Component.translatable(LEASH_LENGTH_FAIL)); + source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; @@ -37,9 +58,9 @@ public class LeashCommand { try { ServerPlayer player = EntityArgument.getPlayer(context, "player"); float leashLength = ((ILivingEntityExtension)player).getLeashLength(); - source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SHOW, player.getName(), leashLength), true); + source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SHOW, player.getDisplayName(), leashLength), true); } catch (Exception e) { - source.sendFailure(Component.translatable(LEASH_LENGTH_FAIL)); + source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; @@ -50,9 +71,9 @@ public class LeashCommand { ServerPlayer player = source.getPlayerOrException(); float leashLength = context.getArgument("leashLength", Float.class); ((ILivingEntityExtension)player).setLeashLength(leashLength); - source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SET, player.getName(), leashLength), true); + source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SET, player.getDisplayName(), leashLength), true); } catch (Exception e) { - source.sendFailure(Component.translatable(LEASH_LENGTH_FAIL)); + source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; @@ -60,22 +81,102 @@ public class LeashCommand { Command setLengthLeashLength = context -> { CommandSourceStack source = context.getSource(); try { -// Player player = context.getArgument("player", Player.class); ServerPlayer player = EntityArgument.getPlayer(context, "player"); float leashLength = context.getArgument("leashLength", Float.class); ((ILivingEntityExtension)player).setLeashLength(leashLength); - source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SET, player.getName(), leashLength), true); + source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SET, player.getDisplayName(), leashLength), true); } catch (Exception e) { - source.sendFailure(Component.translatable(LEASH_LENGTH_FAIL)); + source.sendFailure(Component.translatable(LEASH_FAILED)); return -1; } return 0; }; - LiteralArgumentBuilder $$leashRoot = Commands.literal("leash").requires(cs -> cs.hasPermission(2)); + //获取Data 构造一个MutableComponent显示数据 + Command geSelfLeashData = context -> { + CommandSourceStack source = context.getSource(); + try { + ServerPlayer player = source.getPlayerOrException(); + Integer x = LeashLengthResultInt(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 = LeashLengthResultInt(player, source); + if (x != null) return x; + } 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 = LeashDataEntityResultInt(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 = LeashDataBlockPosResultInt(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 = LeashDataEntityResultInt(context, player, source); + if (x != null) return x; + + } 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 = LeashDataBlockPosResultInt(context, source, player); + if (x != null) return x; + + } catch (Exception e) { + source.sendFailure(Component.translatable(LEASH_FAILED)); + return -1; + } + return 0; + }; + LiteralArgumentBuilder $$leashRoot = Commands.literal("leash"); literalArgumentBuilder.then( $$leashRoot.then(Commands.literal("length").executes(getSelfLeashLength) - .then(Commands.literal("getLength").executes(getSelfLeashLength)) - .then(Commands.literal("setLength") + .then(Commands.literal("get").executes(getSelfLeashLength)) + .then(Commands.literal("set").requires(cs -> cs.hasPermission(2)) .then(Commands.argument("leashLength", FloatArgumentType.floatArg(5, 1024)).executes(setSelfLengthLeashLength) ) ) @@ -85,8 +186,8 @@ public class LeashCommand { $$leashRoot.then( Commands.literal("length") .then(Commands.argument("player", EntityArgument.player()).executes(getRefPlayerLeashLength) - .then(Commands.literal("getLength").executes(getRefPlayerLeashLength)) - .then(Commands.literal("setLength") + .then(Commands.literal("get").executes(getRefPlayerLeashLength)) + .then(Commands.literal("set").requires(cs -> cs.hasPermission(2)) .then( Commands.argument("leashLength", FloatArgumentType.floatArg(5, 1024)).executes(setLengthLeashLength) ) @@ -95,7 +196,106 @@ public class LeashCommand { ) + ); + literalArgumentBuilder.then( + $$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) + ) + ) + ) + ) + ); + literalArgumentBuilder.then( + $$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) + ) + ) + ) ); dispatcher.register(literalArgumentBuilder); } + + private static @Nullable Integer LeashLengthResultInt(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 LeashDataBlockPosResultInt(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 LeashDataCommonPartResultInt(source, player, leashDataEntity, leashedPlayer, targetPlayerDisplayName, leashDataEntityDisplayName); + } + + private static @Nullable Integer LeashDataEntityResultInt(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 LeashDataCommonPartResultInt(source, player, leashDataEntity, leashedPlayer, targetPlayerDisplayName, leashDataEntityDisplayName); + } + + private static @Nullable Integer LeashDataCommonPartResultInt(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; + } + + } diff --git a/src/main/java/com/r3944realms/leashedplayer/content/gamerules/Server/CreateLeashFenceKnotEntityIfAbsent.java b/src/main/java/com/r3944realms/leashedplayer/content/gamerules/Server/CreateLeashFenceKnotEntityIfAbsent.java new file mode 100644 index 0000000..cd1a8a6 --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/content/gamerules/Server/CreateLeashFenceKnotEntityIfAbsent.java @@ -0,0 +1,25 @@ +package com.r3944realms.leashedplayer.content.gamerules.Server; + +import com.r3944realms.leashedplayer.LeashedPlayer; +import com.r3944realms.leashedplayer.content.gamerules.Gamerules; +import com.r3944realms.leashedplayer.utils.Util; +import net.minecraft.world.level.GameRules; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; + +import static com.r3944realms.leashedplayer.content.gamerules.Gamerules.GAMERULE_REGISTRY; + +@EventBusSubscriber(modid = LeashedPlayer.MOD_ID, bus = EventBusSubscriber.Bus.MOD) +public class CreateLeashFenceKnotEntityIfAbsent { + public static final boolean DEFAULT_VALUE = true; + public static final String ID = Util.getGameruleName(CreateLeashFenceKnotEntityIfAbsent.class); + public static final String DESCRIPTION_KEY = Gamerules.getDescriptionKey(CreateLeashFenceKnotEntityIfAbsent.class); + public static final String NAME_KEY = Gamerules.getNameKey(CreateLeashFenceKnotEntityIfAbsent.class); + public static final GameRules.Category CATEGORY = GameRules.Category.PLAYER; + + @SubscribeEvent + public static void onCommonSetup(final FMLCommonSetupEvent event) { + GAMERULE_REGISTRY.registerGamerule(ID, CATEGORY, DEFAULT_VALUE); + } +} diff --git a/src/main/java/com/r3944realms/leashedplayer/datagen/LanguageAndOtherData/ModLangKeyValue.java b/src/main/java/com/r3944realms/leashedplayer/datagen/LanguageAndOtherData/ModLangKeyValue.java index 9e44c44..da8b418 100644 --- a/src/main/java/com/r3944realms/leashedplayer/datagen/LanguageAndOtherData/ModLangKeyValue.java +++ b/src/main/java/com/r3944realms/leashedplayer/datagen/LanguageAndOtherData/ModLangKeyValue.java @@ -1,6 +1,7 @@ package com.r3944realms.leashedplayer.datagen.LanguageAndOtherData; import com.r3944realms.leashedplayer.content.commands.LeashCommand; +import com.r3944realms.leashedplayer.content.gamerules.Server.CreateLeashFenceKnotEntityIfAbsent; import com.r3944realms.leashedplayer.content.gamerules.Server.TeleportWithLeashedPlayers; import com.r3944realms.leashedplayer.utils.Enum.LanguageEnum; import com.r3944realms.leashedplayer.utils.Enum.ModPartEnum; @@ -13,13 +14,23 @@ import java.util.function.Supplier; public enum ModLangKeyValue { //COMMAND_MESSAGE - MESSAGE_LEASH_LENGTH_FAIL(LeashCommand.LEASH_LENGTH_FAIL, ModPartEnum.COMMAND, "Failed (Internal Error)", "失败(内部错误)", "失敗(内部錯誤)", false), - MESSAGE_LEASH_LENGTH_SHOW(LeashCommand.LEASH_LENGTH_SHOW, ModPartEnum.COMMAND, "The Leash Length of %s is %f blocks", "%s的拴绳长度为%f格", "%s的栓繩長度為%f格" , false), - MESSAGE_LEASH_LENGTH_SET(LeashCommand.LEASH_LENGTH_SET, ModPartEnum.COMMAND, "The Leash length of %s is set to %f blocks", "%s的拴绳长度被设置为%f格", "%s的栓繩長度被設置為%f格" , false), + MESSAGE_LEASH_LENGTH_FAILED(LeashCommand.LEASH_FAILED, ModPartEnum.COMMAND, "Failed (Internal Error, maybe your command is incorrect)", "失败(内部错误,可能是你输的指令有误)", "失敗(内部錯誤,,可能你輸入的指令有誤)", false), + MESSAGE_LEASH_LENGTH_SHOW(LeashCommand.LEASH_LENGTH_SHOW, ModPartEnum.COMMAND, "The Leash Length of %1$s is %2$s blocks", "%1$s的拴绳长度为%2$s格", "%1$s的栓繩長度為%2$s格" , false), + MESSAGE_LEASH_LENGTH_SET(LeashCommand.LEASH_LENGTH_SET, ModPartEnum.COMMAND, "The Leash length of %1$s is set to %2$s blocks", "%1$s的拴绳长度被设置为%2$s格", "%1$s的栓繩長度被設置為%2$s格" , false), + MESSAGE_LEASH_GET_LEASH_DATA(LeashCommand.LEASH_DATA_SHOW, ModPartEnum.COMMAND, "%1$s's LeashDataEntity is %2$s", "%1$s的拴绳数据实体为%2$s", "%1$s栓繩數據實體為%2$s",false), + MESSAGE_LEASH_NO_LEASH_DATA(LeashCommand.NO_LEASH_DATA, ModPartEnum.COMMAND, "%1$s has no LeashDataEntity", "%1$s沒有拴绳数据实体", "%1$s沒有栓繩數據實體", false), + MESSAGE_LEASH_SET_LEASH_DATA(LeashCommand.LEASH_DATA_SET, ModPartEnum.COMMAND, "%1$s LeashDataEntity now is set as %2$s", "%1$s拴绳数据实体被设置为%2$s", "%1$s栓繩數據實體設置為%2$s", false), + MESSAGE_LEASH_SET_FAILED_DIFF_LEVEL(LeashCommand.LEASH_DATA_SET_FAILED_DIFF_LEVEL, ModPartEnum.COMMAND,"%1$s and %2$s are not at a same level", "%1$s和%2$s不在同一维度上", "%1$s和%2$s不在同一緯度上", false), + MESSAGE_LEASH_SET_FAILED_TOO_FAR(LeashCommand.LEASH_DATA_SET_FAILED_TOO_FAR, ModPartEnum.COMMAND,"The distance between %1$s and %2$s is larger than the 1.2 times of LeashLength, LeashLength is %3$s blocks", "%1$s到%2$s的距离超过了1.2倍 栓绳长度,原长:%3$s 格", "%1$s到%2$s的距離超過了1.2倍栓繩長度,原長:%3$s 格", false), + MESSAGE_LEASH_SET_FAILED_NO_KNOT_EXIST_IN_THAT_POS(LeashCommand.LEASH_DATA_SET_FAILED_NO_KNOT_EXISTED_IN_THAT_POS, ModPartEnum.COMMAND, "No knot found at (X:%f,Y:%f,Z:%f)", "未找到栓绳结在(X:%f, Y:%f, Z:%f)处", "未找到栓繩結在(X:%f, Y:%f, Z:%f)処", false), + MESSAGE_LEASH_SET_FAILED_FORBID_SAME_ENTITY(LeashCommand.LEASH_DATA_SET_FAILED_FORBID_SAME_ENTITY, ModPartEnum.COMMAND, "Prohibit setting the same entity","禁止设置同一实体", "禁止設置同一實體", false), //GAME_RULE_NAME - TELEPORT_WITH_LEASHED_PLAYERS(TeleportWithLeashedPlayers.NAME_KEY, ModPartEnum.NAME, "Teleport with leashed player", "传送被栓玩家", "傳送被栓玩家" ,false), + TELEPORT_WITH_LEASHED_PLAYERS(TeleportWithLeashedPlayers.NAME_KEY, ModPartEnum.NAME, "Teleport leashed player with player holder", "被栓玩家随玩家持有者传送", "被栓玩家随玩家持有者傳送" ,false), + CREATE_LEASH_FENCE_KNOT_ENTITY_IF_ABSENT(CreateLeashFenceKnotEntityIfAbsent.NAME_KEY, ModPartEnum.NAME, "Create Leash Fence Knot Entity if absent", "如果缺失则创建栓绳结", "如果缺失則創建栓繩結", false), //GAME_RULE_DESCRIPTION - TELEPORT_WITH_LEASHED_DESCRIPTION(TeleportWithLeashedPlayers.DESCRIPTION_KEY, ModPartEnum.DESCRIPTION, "You will teleport with your leashed players ", "传送时将被栓玩家与自己一起传送", "傳送時將被栓玩家與隨自己一起傳送" ,false), + TELEPORT_WITH_LEASHED_DESCRIPTION(TeleportWithLeashedPlayers.DESCRIPTION_KEY, ModPartEnum.DESCRIPTION, "Holder will teleport with their leashed players ", "传送时将被栓玩家与持有者一起传送", "將被栓玩家將隨持有者一起傳送" ,false), + CREATE_LEASH_FENCE_KNOT_ENTITY_IF_ABSENT_DESCRIPTION(CreateLeashFenceKnotEntityIfAbsent.DESCRIPTION_KEY, ModPartEnum.DESCRIPTION, "Create LeashKnot Entity if it's absent on fence", "如果在栅栏处缺失栓绳结,则创建它", "如果在柵欄処缺失拴繩結,則創建它",false), + ; private final Supplier supplier; private String key; diff --git a/src/main/java/com/r3944realms/leashedplayer/mixin/both/MixinPlayer.java b/src/main/java/com/r3944realms/leashedplayer/mixin/both/MixinPlayer.java index f514510..c55faa0 100644 --- a/src/main/java/com/r3944realms/leashedplayer/mixin/both/MixinPlayer.java +++ b/src/main/java/com/r3944realms/leashedplayer/mixin/both/MixinPlayer.java @@ -213,6 +213,7 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl private void saveLeashData(@org.jetbrains.annotations.Nullable LeashData pLeashData) { CompoundTag compoundTag = new CompoundTag(); this.writeLeashData(compoundTag, pLeashData); + this.entityData.set(Pl$LEASH_DATA, compoundTag); } @SuppressWarnings("AddedMixinMembersNamePattern") diff --git a/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinLevelRenderer.java b/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinLevelRenderer.java index 294b058..1badcb3 100644 --- a/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinLevelRenderer.java +++ b/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinLevelRenderer.java @@ -2,6 +2,7 @@ package com.r3944realms.leashedplayer.mixin.client; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.datafixers.util.Either; +import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension; import com.r3944realms.leashedplayer.modInterface.IPlayerRendererExtension; import com.r3944realms.leashedplayer.modInterface.PlayerLeashable; import net.minecraft.client.Camera; @@ -12,11 +13,13 @@ import net.minecraft.client.player.AbstractClientPlayer; import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.entity.player.PlayerRenderer; import net.minecraft.core.BlockPos; +import net.minecraft.core.Holder; import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Leashable; import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; @@ -27,6 +30,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import javax.annotation.Nullable; +import java.util.List; import java.util.UUID; @Mixin(LevelRenderer.class) @@ -83,9 +87,33 @@ public abstract class MixinLevelRenderer { playerRendererExtension.renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, LeashFenceKnotEntity.getOrCreateKnot(level, delayedLeashInfo.right().get())); } else if (delayedLeashInfo.right().isEmpty() && delayedLeashInfo.left().isPresent()) { assert level != null; + Player playerByUUID = level.getPlayerByUUID(delayedLeashInfo.left().get()); if (playerByUUID != null) { playerRendererExtension.renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, playerByUUID); + } else { + float MaxLeashLength = ((ILivingEntityExtension) abstractClientPlayer).getLeashLength() * 2f; + List entities = level.getEntities( + null, + new AABB( + abstractClientPlayer.getX() - MaxLeashLength, + abstractClientPlayer.getY() - MaxLeashLength, + abstractClientPlayer.getZ() - MaxLeashLength, + abstractClientPlayer.getX() + MaxLeashLength, + abstractClientPlayer.getY() + MaxLeashLength, + abstractClientPlayer.getZ() + MaxLeashLength + ) + ); + Entity holder = null; + for (Entity entity_ : entities) { + if(entity_.getUUID().equals(delayedLeashInfo.left().get())) { + holder = entity_; + break; + } + } + if (holder != null) { + playerRendererExtension.renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, holder); + } } } } diff --git a/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinPlayerRenderer.java b/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinPlayerRenderer.java index 2783caf..a5ba5bc 100644 --- a/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinPlayerRenderer.java +++ b/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinPlayerRenderer.java @@ -3,6 +3,7 @@ package com.r3944realms.leashedplayer.mixin.client; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.datafixers.util.Either; +import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension; import com.r3944realms.leashedplayer.modInterface.IPlayerRendererExtension; import com.r3944realms.leashedplayer.modInterface.PlayerLeashable; import net.minecraft.client.Camera; @@ -22,6 +23,7 @@ import net.minecraft.world.entity.Leashable; import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.LightLayer; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Mixin; @@ -30,6 +32,7 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.List; import java.util.UUID; @Mixin(PlayerRenderer.class) @@ -57,6 +60,29 @@ public abstract class MixinPlayerRenderer extends LivingEntityRenderer entities = level.getEntities( + null, + new AABB( + pEntity.getX() - MaxLeashLength, + pEntity.getY() - MaxLeashLength, + pEntity.getZ() - MaxLeashLength, + pEntity.getX() + MaxLeashLength, + pEntity.getY() + MaxLeashLength, + pEntity.getZ() + MaxLeashLength + ) + ); + Entity holder = null; + for (Entity entity_ : entities) { + if(entity_.getUUID().equals(delayedLeashInfo.left().get())) { + holder = entity_; + break; + } + } + if (holder != null) { + renderLeash(pEntity, pPartialTicks, pPoseStack, pBuffer, holder); + } } } } diff --git a/src/main/java/com/r3944realms/leashedplayer/mixin/server/MixinServerGamePacketListenerImpl.java b/src/main/java/com/r3944realms/leashedplayer/mixin/server/MixinServerGamePacketListenerImpl.java index 5dac58c..44fc5bf 100644 --- a/src/main/java/com/r3944realms/leashedplayer/mixin/server/MixinServerGamePacketListenerImpl.java +++ b/src/main/java/com/r3944realms/leashedplayer/mixin/server/MixinServerGamePacketListenerImpl.java @@ -24,12 +24,12 @@ public class MixinServerGamePacketListenerImpl { @Shadow public ServerPlayer player; @Unique - private List Whimsy$LeashPlayers = new ArrayList<>(); + private List Pl$LeashPlayers = new ArrayList<>(); @Inject(method = {"teleport(DDDFFLjava/util/Set;)V"}, at = {@At("HEAD")}) private void teleportHead(double pX, double pY, double pZ, float pYaw, float pPitch, Set pRelativeSet, CallbackInfo ci) { try { //獲取Holder - this.Whimsy$LeashPlayers = ((PlayerLeashable)this.player).getLeashHolder() != null ? Collections.emptyList() : Objects.requireNonNull(this.player.getServer()).getPlayerList().getPlayers().stream().filter(serverPlayer -> (serverPlayer instanceof PlayerLeashable) && ((PlayerLeashable)serverPlayer).getLeashHolder() == this.player && player != serverPlayer).collect(Collectors.toList()); + this.Pl$LeashPlayers = ((PlayerLeashable)this.player).getLeashHolder() != null ? Collections.emptyList() : Objects.requireNonNull(this.player.getServer()).getPlayerList().getPlayers().stream().filter(serverPlayer -> (serverPlayer instanceof PlayerLeashable) && ((PlayerLeashable)serverPlayer).getLeashHolder() == this.player && player != serverPlayer).collect(Collectors.toList()); } catch (Exception e) { logger.error("Internal Error:",e); } @@ -37,9 +37,9 @@ public class MixinServerGamePacketListenerImpl { @Inject(method = {"teleport(DDDFFLjava/util/Set;)V"}, at = {@At("TAIL")}) private void teleportTail(double pX, double pY, double pZ, float pYaw, float pPitch, Set pRelativeSet, CallbackInfo ci) { if(GameruleRegistry.getGameruleBoolValue(this.player.serverLevel(), TeleportWithLeashedPlayers.ID)) { - for (Entity whimsy$LeashPlayer : this.Whimsy$LeashPlayers) { - if(whimsy$LeashPlayer instanceof ServerPlayer) { - if(whimsy$LeashPlayer instanceof PlayerLeashable playerLeashable) { + for (Entity Pl$LeashPlayer : this.Pl$LeashPlayers) { + if(Pl$LeashPlayer instanceof ServerPlayer) { + if(Pl$LeashPlayer instanceof PlayerLeashable playerLeashable) { playerLeashable.dropLeash(false,false); if(((ServerPlayer) playerLeashable).serverLevel() == this.player.serverLevel()) { ((ServerPlayer) playerLeashable).connection.teleport(pX, pY, pZ, pYaw, pPitch, pRelativeSet); diff --git a/src/main/java/com/r3944realms/leashedplayer/modInterface/PlayerLeashable.java b/src/main/java/com/r3944realms/leashedplayer/modInterface/PlayerLeashable.java index 15f0830..0d21fad 100644 --- a/src/main/java/com/r3944realms/leashedplayer/modInterface/PlayerLeashable.java +++ b/src/main/java/com/r3944realms/leashedplayer/modInterface/PlayerLeashable.java @@ -1,13 +1,18 @@ package com.r3944realms.leashedplayer.modInterface; +import net.minecraft.core.BlockPos; import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Leashable; +import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.phys.AABB; import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; +import java.util.Optional; +import java.util.UUID; public interface PlayerLeashable extends Leashable { @@ -51,4 +56,64 @@ public interface PlayerLeashable extends Leashable { //这边覆写去掉了乘坐相关的逻辑,即乘坐状态下也可以正常被栓住,不影响其乘坐状态 } + static Entity getLeashDataEntityOrThrown(@NotNull Leashable.LeashData leashDataFromEntityData, @NotNull ServerLevel level) throws Exception { + if(leashDataFromEntityData.delayedLeashInfo != null) { + Optional UUID = leashDataFromEntityData.delayedLeashInfo.left(); + Optional BlockPos = leashDataFromEntityData.delayedLeashInfo.right(); + if (UUID.isPresent()) { + return level.getEntity(UUID.get()); + } else if(BlockPos.isPresent()) { + return LeashFenceKnotEntity.getOrCreateKnot(level, BlockPos.get()); + } else { + throw new Exception("invalid delayedLeashInfo"); + } + } + else if(leashDataFromEntityData.leashHolder != null) { + return leashDataFromEntityData.leashHolder; + } + else if(leashDataFromEntityData.delayedLeashHolderId != 0) { + Entity entity = level.getEntity(leashDataFromEntityData.delayedLeashHolderId); + if(entity == null) { + throw new Exception("Not found Entity. maybe the pId is invalid"); + } + return entity; + } + else { + throw new Exception("invalid leash data"); + } + } + static boolean isLeashFenceKnotEntityExisted(ServerLevel pLevel, BlockPos pPos) { + int i = pPos.getX(); + int j = pPos.getY(); + int k = pPos.getZ(); + + for (LeashFenceKnotEntity leashfenceknotentity : pLevel.getEntitiesOfClass( + LeashFenceKnotEntity.class, new AABB((double)i - 1.0, (double)j - 1.0, (double)k - 1.0, (double)i + 1.0, (double)j + 1.0, (double)k + 1.0) + )) { + if (leashfenceknotentity.getPos().equals(pPos)) { + return true; + } + } + return false; + } + @Nullable + static Entity getLeashFenceKnotEntity(ServerLevel pLevel, BlockPos pPos) { + int i = pPos.getX(); + int j = pPos.getY(); + int k = pPos.getZ(); + + for (LeashFenceKnotEntity leashfenceknotentity : pLevel.getEntitiesOfClass( + LeashFenceKnotEntity.class, new AABB((double)i - 1.0, (double)j - 1.0, (double)k - 1.0, (double)i + 1.0, (double)j + 1.0, (double)k + 1.0) + )) { + if (leashfenceknotentity.getPos().equals(pPos)) { + return leashfenceknotentity; + } + } + return null; + } + static Entity createLeashKnotFence(ServerLevel pLevel, BlockPos pPos) { + LeashFenceKnotEntity leashfenceknotentity = new LeashFenceKnotEntity(pLevel, pPos); + pLevel.addFreshEntity(leashfenceknotentity); + return leashfenceknotentity; + } } diff --git a/src/main/resources/META-INF/neoforge.mods.toml b/src/main/resources/META-INF/neoforge.mods.toml index a7fedad..db4e426 100644 --- a/src/main/resources/META-INF/neoforge.mods.toml +++ b/src/main/resources/META-INF/neoforge.mods.toml @@ -14,7 +14,7 @@ loaderVersion="${loader_version_range}" #mandatory license="${mod_license}" # A URL to refer people to when problems occur with this mod -#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional +issueTrackerURL="https://github.com/3944Realms/R39_Whimsy_NeoForgeModProject_Sub/issues" #optional # A list of mods - how many allowed here is determined by the individual mod loader [[mods]] #mandatory @@ -32,10 +32,10 @@ displayName="${mod_name}" #mandatory #updateJSONURL="https://change.me.example.invalid/updates.json" #optional # A URL for the "homepage" for this mod, displayed in the mod UI -#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional +displayURL="https://github.com/3944Realms/R39_Whimsy_NeoForgeModProject_Sub" #optional # A file name (in the root of the mod JAR) containing a logo for display -#logoFile="examplemod.png" #optional +logoFile= "leashedplayerlogo.png" #optional # A text field displayed in the mod UI #credits="" #optional diff --git a/src/main/resources/leashedplayerlogo.png b/src/main/resources/leashedplayerlogo.png new file mode 100644 index 0000000..7756ae2 Binary files /dev/null and b/src/main/resources/leashedplayerlogo.png differ