From 987ec866c38f74e2517ae34b3a8e436d62dcd496 Mon Sep 17 00:00:00 2001 From: 3944Realms Date: Thu, 5 Sep 2024 23:15:06 +0800 Subject: [PATCH] =?UTF-8?q?2024-09-05=20=E7=89=88=E6=9C=AC0.0.3.0-Beta.0.1?= =?UTF-8?q?=20=E5=A2=9E=E5=8A=A0:=201.=20=E5=A2=9E=E5=8A=A0=E4=BA=86?= =?UTF-8?q?=E6=96=B0=E7=9A=84=E6=8C=87=E4=BB=A4=20data=20clear=202.=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E4=BA=86=E9=85=8D=E7=BD=AE=E6=96=87=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E6=96=B9=E4=BE=BF=E4=BF=AE=E6=94=B9=E6=9C=AC=E6=A8=A1?= =?UTF-8?q?=E7=BB=84=E7=9A=84=E9=83=A8=E5=88=86=E8=A1=8C=E4=B8=BA=203.=20?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E6=96=B0=E7=9A=84=E5=86=85=E5=AE=B9=EF=BC=8C?= =?UTF-8?q?=E5=A6=82=E6=8B=B4=E7=BB=B3=E7=AE=AD=EF=BC=88=E4=BD=86=E6=98=AF?= =?UTF-8?q?=E6=9C=89=E7=82=B9BUG=20=E4=BF=AE=E6=94=B9=E4=B8=8E=E8=B0=83?= =?UTF-8?q?=E6=95=B4=EF=BC=9A=201.=E8=B0=83=E6=95=B4=E4=BA=86=E5=8E=9F?= =?UTF-8?q?=E8=AF=AD=E8=A8=80=E9=83=A8=E5=88=86=E9=94=99=E5=88=AB=E5=AD=97?= =?UTF-8?q?=202.=E6=9B=B4=E6=94=B9=E4=BA=86=E4=B9=8B=E5=89=8D=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E3=80=90=E6=A0=93=E7=BB=B3=E8=BF=90=E5=8A=A8?= =?UTF-8?q?=E9=80=BB=E8=BE=91=E3=80=91=20=E5=85=B7=E9=AB=94=E6=96=B0?= =?UTF-8?q?=E5=86=85=E5=AE=B9=E8=AB=8B=E8=A6=8B=20README.md=20=E4=BB=8B?= =?UTF-8?q?=E7=B4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 18 +- Resource/leashed_rope_arrow.png | Bin 0 -> 268 bytes gradle.properties | 10 +- gradle/wrapper/gradle-wrapper.properties | 2 +- .../0aef4464247e697f9a7226f384437b478152c21c | 2 + .../1749bb0c3e8c52cfb2d8ed2140e4678c71e770f5 | 2 + .../211976637bfb5e111401ad2bfb58570ef2fb3dff | 4 +- .../456392f19d2beac1e6e71432fcc2128b993c47e1 | 1 + .../853329c6e706e45295e80307b8a95a5709025422 | 2 +- .../9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e | 3 + .../a1129211d3ad6d65c101bb152ae8c66c8256bccb | 4 +- .../ed628fd843215c1bf29a07b9cbd1b26a6af0636d | 4 +- .../assets/leashedplayer/lang/en_us.json | 16 +- .../assets/leashedplayer/lang/zh_cn.json | 24 ++- .../assets/leashedplayer/lang/zh_tw.json | 30 +-- .../models/item/leash_rope_arrow.json | 6 + .../recipes/misc/leash_rope_arrow.json | 32 +++ .../recipe/leash_rope_arrow.json | 16 ++ .../data/minecraft/tags/item/arrows.json | 5 + .../leashedplayer/ClientEventHandler.java | 16 ++ .../leashedplayer/LeashedPlayer.java | 37 ++++ .../renders/LeashRopeArrowRenderer.java | 23 +++ .../config/LeashPlayerCommonConfig.java | 41 ++++ .../content/commands/Command.java | 4 +- .../content/commands/LeashCommand.java | 194 ++++++++++++------ .../content/entities/LeashRopeArrow.java | 115 +++++++++++ .../content/entities/ModEntityRegister.java | 28 +++ .../content/items/LeashRopeArrowItem.java | 29 +++ .../content/items/ModCreativeTab.java | 37 ++++ .../content/items/ModItemRegister.java | 33 +++ .../LanguageAndOtherData/ModLangKeyValue.java | 39 +++- .../datagen/ModDataGeneratorHandler.java | 29 ++- .../datagen/provider/ModBlockTagProvider.java | 21 ++ .../provider/ModItemModelProvider.java | 43 ++++ .../datagen/provider/ModItemTagProvider.java | 26 +++ .../datagen/provider/ModRecipeProvider.java | 29 +++ .../leashedplayer/mixin/both/MixinEntity.java | 6 +- .../leashedplayer/mixin/both/MixinPlayer.java | 118 +++++++---- .../mixin/client/MixinEntityRenderer.java | 7 +- .../mixin/client/MixinLevelRenderer.java | 14 +- .../mixin/client/MixinPlayerRenderer.java | 55 ++++- .../IPlayerRendererExtension.java | 13 +- .../modInterface/PlayerLeashable.java | 34 +++ .../r3944realms/leashedplayer/utils/Util.java | 27 +++ .../resources/META-INF/accesstransformer.cfg | 4 +- .../entity/projectiles/leash_rope_arrow.png | Bin 0 -> 260 bytes .../textures/item/leash_rope_arrow.png | Bin 0 -> 268 bytes 47 files changed, 1024 insertions(+), 179 deletions(-) create mode 100644 Resource/leashed_rope_arrow.png create mode 100644 src/generated/resources/.cache/0aef4464247e697f9a7226f384437b478152c21c create mode 100644 src/generated/resources/.cache/1749bb0c3e8c52cfb2d8ed2140e4678c71e770f5 create mode 100644 src/generated/resources/.cache/456392f19d2beac1e6e71432fcc2128b993c47e1 create mode 100644 src/generated/resources/.cache/9fb1092f32d4fcbf9e061ffd718d4ec689c6c95e create mode 100644 src/generated/resources/assets/leashedplayer/models/item/leash_rope_arrow.json create mode 100644 src/generated/resources/data/leashedplayer/advancement/recipes/misc/leash_rope_arrow.json create mode 100644 src/generated/resources/data/leashedplayer/recipe/leash_rope_arrow.json create mode 100644 src/generated/resources/data/minecraft/tags/item/arrows.json create mode 100644 src/main/java/com/r3944realms/leashedplayer/ClientEventHandler.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/client/renders/LeashRopeArrowRenderer.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/config/LeashPlayerCommonConfig.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/content/entities/LeashRopeArrow.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/content/entities/ModEntityRegister.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/content/items/LeashRopeArrowItem.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/content/items/ModCreativeTab.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/content/items/ModItemRegister.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModBlockTagProvider.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModItemModelProvider.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModItemTagProvider.java create mode 100644 src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModRecipeProvider.java create mode 100644 src/main/resources/assets/leashedplayer/textures/entity/projectiles/leash_rope_arrow.png create mode 100644 src/main/resources/assets/leashedplayer/textures/item/leash_rope_arrow.png diff --git a/README.md b/README.md index 397da02..0af5304 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,23 @@ -# 版本 0.0.2.2 【注意:本解釋簡繁混寫,因爲趕時間,所以並不怎麽規範,請諒解】 +# 版本 0.0.3.0-Beta.0.1 提前介绍 【注意:本解釋簡繁混寫,因爲趕時間,所以並不怎麽規範,請諒解】 ## 简介 -现在开始你可以用拴绳栓住玩家,也可以栓住自己了,不如尝试栓住彼此来通关我的世界吧( +现在开始你可以用拴绳拴住玩家,也可以拴住自己了,不如尝试拴住彼此来通关我的世界吧( 你可以: 1. 拴绳可以拴住玩家 -2. 在无任何栓住实体的情况下用拴绳对准栅栏可以拴住自己 -3. 可以用指令来获取和调整玩家实体的拴绳的长度 +2. 在无任何拴住实体的情况下用拴绳对准栅栏可以拴住自己 +3. 可以用指令来获取和调整玩家实体的拴绳的长度和设置拴绳数据实体 4. 目前有游戏规则来决定被栓玩家是否在传送时能随拴绳持有者一起传送 +## 配置文件 +1. 可改变指令前命名空间和关闭命名空间 +2. 修改命令拴绳的可设置的长度范围 +3. 设置拴绳在达到多少倍的拴绳长度后掉落 - +## 新物品 和 实体 +### 拴绳箭 + 获得飞一样的感觉(操作不当可能会摔死 +#### 射中实体时,会将射击者拴绳绑定在改实体上(该实体父类必须是有LivingEntity类型),同时拴绳箭会以普通的箭矢掉落 +#### 射中栅栏时,会自动将玩家拴在上面 ,同时拴绳箭会以普通的箭矢掉落 ## 指令 * `/lp leash length [<玩家>] set <长度> ` - 设置该玩家的拴绳长度 [ 如果<玩家>为空则代表执行对象是自己 ,<长度> 为在 5 ~ 1024之间的浮点数 ] diff --git a/Resource/leashed_rope_arrow.png b/Resource/leashed_rope_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..771bb730f54cfaa9fa2ebe543b108979a3a96d54 GIT binary patch literal 268 zcmV+n0rUQeP)C#>A5DeEPJ$TZ7?02u#C>=S{wa# z&ow#jw^?jbo;B(q$1*sV6YOsXETc2BWB&GU^AjA#2}Ye^E&NtchRt3ZVVrzCuVQ|N zcb6Qi?X|Z3B}yqemcjL6M#nPv1yY66G-V;tf&oAXL8TOh5WfiuN%8(!qMJL)uVnQW S;U=R10000 { + public static final ResourceLocation LEASH_ROPE_ARROW = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "textures/entity/projectiles/leash_rope_arrow.png"); + public LeashRopeArrowRenderer(EntityRendererProvider.Context pContext) { + super(pContext); + } + + @Override + public @NotNull ResourceLocation getTextureLocation(@NotNull LeashRopeArrow pEntity) { + return LEASH_ROPE_ARROW; + } +} diff --git a/src/main/java/com/r3944realms/leashedplayer/config/LeashPlayerCommonConfig.java b/src/main/java/com/r3944realms/leashedplayer/config/LeashPlayerCommonConfig.java new file mode 100644 index 0000000..f152bde --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/config/LeashPlayerCommonConfig.java @@ -0,0 +1,41 @@ +package com.r3944realms.leashedplayer.config; + +import net.neoforged.neoforge.common.ModConfigSpec; + +import java.util.function.Predicate; + +public class LeashPlayerCommonConfig { + public static ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder(); + public static final ModConfigSpec SPEC; + public static final ModConfigSpec.ConfigValue LeashedPlayerModCommandPrefix; + public static final ModConfigSpec.BooleanValue EnableLeashPlayerCommandPrefix; + public static ModConfigSpec.IntValue MinimumLeashLengthCanBeSet, MaximumLeashLengthCanBeSet; + public static ModConfigSpec.ConfigValue TheMultipleThatLeashRopeArrowBreakLength, TheLeashBreakLengthTimesBase; + static { + BUILDER.comment("Leash Player Config"); + + + BUILDER.push("Command"); + EnableLeashPlayerCommandPrefix = BUILDER.comment("The prefix of this mod's commands"," [ Default: true] ").define("Enable Leash Player Command", true); + LeashedPlayerModCommandPrefix = BUILDER.comment("The prefix of this mod's commands"," [ Default:'lp'] ").define("LeashedPlayerModCommandPrefix", "lp"); + + BUILDER.pop(); + + BUILDER.push("Leash Rope Arrow"); + TheMultipleThatLeashRopeArrowBreakLength = BUILDER.comment("How many times is the length of the arrow rope based on BreakLength TimeBase", "[ Default : 5.0f, Invalid Range:[1.0f, 10.0f] ]").define("TheMultipleArrowBreak", 5.0f, o -> (o instanceof Float f) && f >= 2.0f && f <= 10.0f); + + BUILDER.pop(); + + BUILDER.push("Misc"); + + BUILDER.push("LeashLength"); + TheLeashBreakLengthTimesBase = BUILDER.comment("When it exceeds how many times, the leash will drop","[ Default:2.0f, Invalid Range:[2.0f, 5.0f] ]").define("BreakLengthTimeBase", 2.0f, o -> (o instanceof Float f) && f >= 2.0f && f <= 5.0f); + MinimumLeashLengthCanBeSet = BUILDER.comment("The minimum integer's length of Leash", "[ Default:5, Invalid Range:[2,10] ]").defineInRange("MinLeashLength", 5, 2, 10); + MaximumLeashLengthCanBeSet = BUILDER.comment("The maximum integer's length of Leash", "[ Default:1024, Invalid Range:[32, 1024] ]").defineInRange("MaxLeashLength", 1024, 32, 1024); + + + + + SPEC = BUILDER.build(); + } +} diff --git a/src/main/java/com/r3944realms/leashedplayer/content/commands/Command.java b/src/main/java/com/r3944realms/leashedplayer/content/commands/Command.java index 2ac3362..4d75cfe 100644 --- a/src/main/java/com/r3944realms/leashedplayer/content/commands/Command.java +++ b/src/main/java/com/r3944realms/leashedplayer/content/commands/Command.java @@ -1,5 +1,7 @@ package com.r3944realms.leashedplayer.content.commands; +import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig; + public class Command { - public static final String PREFIX = "lp"; + public static final String PREFIX = LeashPlayerCommonConfig.LeashedPlayerModCommandPrefix.get(); } 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 412d302..90d225b 100644 --- a/src/main/java/com/r3944realms/leashedplayer/content/commands/LeashCommand.java +++ b/src/main/java/com/r3944realms/leashedplayer/content/commands/LeashCommand.java @@ -7,6 +7,7 @@ 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; @@ -22,25 +23,47 @@ 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; +import java.util.ArrayList; +import java.util.List; + 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", - 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 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" + ; + private static LiteralArgumentBuilder getLiterArgumentBuilderOfCSS(String name, boolean shouldAddToList, @Nullable List> list) { + LiteralArgumentBuilder literal = Commands.literal(name); + if (shouldAddToList) { + assert list != null; + list.add(literal); + } + return literal; + } public static void register(CommandDispatcher dispatcher) { + boolean shouldUsePrefix = LeashPlayerCommonConfig.EnableLeashPlayerCommandPrefix.get(); + @Nullable List> nodeList = shouldUsePrefix ? null : new ArrayList<>(); LiteralArgumentBuilder literalArgumentBuilder = Commands.literal(com.r3944realms.leashedplayer.content.commands.Command.PREFIX); + LiteralArgumentBuilder $$leashRoot = getLiterArgumentBuilderOfCSS("leash", !shouldUsePrefix, nodeList); + Command getSelfLeashLength = context -> { CommandSourceStack source = context.getSource(); try { @@ -96,7 +119,7 @@ public class LeashCommand { CommandSourceStack source = context.getSource(); try { ServerPlayer player = source.getPlayerOrException(); - Integer x = LeashLengthResultInt(player, source); + Integer x = LeashLengthGetResultInt(player, source); if (x != null) return x; } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); @@ -109,7 +132,7 @@ public class LeashCommand { CommandSourceStack source = context.getSource(); try { ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer"); - Integer x = LeashLengthResultInt(player, source); + Integer x = LeashLengthGetResultInt(player, source); if (x != null) return x; } catch (Exception e) { source.sendFailure(Component.translatable(LEASH_FAILED)); @@ -122,7 +145,7 @@ public class LeashCommand { CommandSourceStack source = context.getSource(); try { ServerPlayer player = source.getPlayerOrException(); - Integer x = LeashDataEntityResultInt(context, player, source); + Integer x = LeashDataEntitySetResultInt(context, player, source); if (x != null) return x; } catch (Exception e) { @@ -135,7 +158,7 @@ public class LeashCommand { CommandSourceStack source = context.getSource(); try { ServerPlayer player = source.getPlayerOrException(); - Integer x = LeashDataBlockPosResultInt(context, source, player); + Integer x = LeashDataBlockPosSetResultInt(context, source, player); if (x != null) return x; @@ -150,7 +173,7 @@ public class LeashCommand { CommandSourceStack source = context.getSource(); try { ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer"); - Integer x = LeashDataEntityResultInt(context, player, source); + Integer x = LeashDataEntitySetResultInt(context, player, source); if (x != null) return x; } catch (Exception e) { @@ -163,7 +186,7 @@ public class LeashCommand { CommandSourceStack source = context.getSource(); try { ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer"); - Integer x = LeashDataBlockPosResultInt(context, source, player); + Integer x = LeashDataBlockPosSetResultInt(context, source, player); if (x != null) return x; } catch (Exception e) { @@ -172,52 +195,73 @@ public class LeashCommand { } return 0; }; - LiteralArgumentBuilder $$leashRoot = Commands.literal("leash"); - literalArgumentBuilder.then( - $$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(5, 1024)).executes(setSelfLengthLeashLength) + 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.getLeashDataEntityOrThrown(player, source.getLevel()),player); + if (x != null) return x; + + } 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("player", 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(setLengthLeashLength) + ) ) ) - ) ); - literalArgumentBuilder.then( - $$leashRoot.then( - Commands.literal("length") - .then(Commands.argument("player", 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(5, 1024)).executes(setLengthLeashLength) - ) - ) - ) - ) - - ); - literalArgumentBuilder.then( - $$leashRoot.then( - Commands.literal("data") - .then(Commands.argument("targetPlayer", EntityArgument.player()).executes(getRefPlayerLeashData) - .then(Commands.literal("get") - .executes(getRefPlayerLeashData) + 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.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.argument("BlockPos", BlockPosArgument.blockPos()) + .executes(setRefPlayerLeashDataByBlockPos) ) ) - ) + .then(Commands.literal("clear").requires(cs -> cs.hasPermission(2)).executes(clearSelfLeashData)) + ) ); - literalArgumentBuilder.then( - $$leashRoot.then( - Commands.literal("data") + + LiteralArgumentBuilder SelfData = $$leashRoot.then( + Commands.literal("data") .then(Commands.literal("get") .executes(geSelfLeashData) ) @@ -229,12 +273,25 @@ public class LeashCommand { .executes(setSelfLeashDataByBlockPos) ) ) - ) + .then(Commands.literal("clear").requires(cs -> cs.hasPermission(2)) + .executes(clearSelfLeashData) + ) ); - dispatcher.register(literalArgumentBuilder); + + if(shouldUsePrefix) { + literalArgumentBuilder + .then(RefPlayerLeashLength) + .then(SelfLeashLength) + .then(RefPLayerData) + .then(SelfData); + dispatcher.register(literalArgumentBuilder); + } else { + nodeList.forEach(dispatcher::register); + } + } - private static @Nullable Integer LeashLengthResultInt(ServerPlayer player, CommandSourceStack source) throws Exception { + private static @Nullable Integer LeashLengthGetResultInt(ServerPlayer player, CommandSourceStack source) throws Exception { Leashable.LeashData leashDataFromEntityData = ((PlayerLeashable) player).getLeashDataFromEntityData(); if(leashDataFromEntityData == null) { @@ -247,7 +304,7 @@ public class LeashCommand { return null; } - private static @Nullable Integer LeashDataBlockPosResultInt(CommandContext context, CommandSourceStack source, ServerPlayer player) { + 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; @@ -267,10 +324,10 @@ public class LeashCommand { } Component leashDataEntityDisplayName = leashDataEntity.getDisplayName(); - return LeashDataCommonPartResultInt(source, player, leashDataEntity, leashedPlayer, targetPlayerDisplayName, leashDataEntityDisplayName); + return LeashDataCommonPartSetResultInt(source, player, leashDataEntity, leashedPlayer, targetPlayerDisplayName, leashDataEntityDisplayName); } - private static @Nullable Integer LeashDataEntityResultInt(CommandContext context, ServerPlayer player, CommandSourceStack source) throws CommandSyntaxException { + 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(); @@ -279,10 +336,10 @@ public class LeashCommand { source.sendFailure(Component.translatable(LEASH_DATA_SET_FAILED_FORBID_SAME_ENTITY)); return 1; } - return LeashDataCommonPartResultInt(source, player, leashDataEntity, leashedPlayer, targetPlayerDisplayName, leashDataEntityDisplayName); + return LeashDataCommonPartSetResultInt(source, player, leashDataEntity, leashedPlayer, targetPlayerDisplayName, leashDataEntityDisplayName); } - private static @Nullable Integer LeashDataCommonPartResultInt(CommandSourceStack source, ServerPlayer player, Entity leashDataEntity, PlayerLeashable leashedPlayer, Component targetPlayerDisplayName, Component 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; @@ -296,6 +353,15 @@ public class LeashCommand { 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; + } } diff --git a/src/main/java/com/r3944realms/leashedplayer/content/entities/LeashRopeArrow.java b/src/main/java/com/r3944realms/leashedplayer/content/entities/LeashRopeArrow.java new file mode 100644 index 0000000..d82beaf --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/content/entities/LeashRopeArrow.java @@ -0,0 +1,115 @@ +package com.r3944realms.leashedplayer.content.entities; + +import com.r3944realms.leashedplayer.content.items.ModItemRegister; +import com.r3944realms.leashedplayer.modInterface.PlayerLeashable; +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.EntityType; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.EntityHitResult; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class LeashRopeArrow extends AbstractArrow { + protected LeashRopeArrow(EntityType entityType,Level pLevel) { + super(entityType, pLevel); + } + + protected LeashRopeArrow(double pX, double pY, double pZ, Level pLevel, ItemStack pPickupItemStack, @Nullable ItemStack pFiredFromWeapon, @Nullable ServerPlayer serverPlayer) { + super(ModEntityRegister.LEASH_ROPE_ARROW.get(), pX, pY, pZ, pLevel, pPickupItemStack, pFiredFromWeapon); + if(serverPlayer != null && !level().isClientSide) { + ((PlayerLeashable)serverPlayer).setLeashedTo(this, true); + } + } + + public LeashRopeArrow(LivingEntity pOwner, Level pLevel, ItemStack pPickupItemStack, @Nullable ItemStack pFiredFromWeapon) { + super(ModEntityRegister.LEASH_ROPE_ARROW.get(), pOwner, pLevel, pPickupItemStack, pFiredFromWeapon); + if(pOwner instanceof PlayerLeashable lPlayer && !level().isClientSide) { + lPlayer.setLeashedTo(this, true); + } + } + + @Override + protected @NotNull ItemStack getDefaultPickupItem() { + return ModItemRegister.LEASH_ROPE_ARROW.get().getDefaultInstance(); + } + + @Override + public void setOwner(@Nullable Entity pEntity) { + super.setOwner(pEntity); + + this.pickup = this.pickup == Pickup.CREATIVE_ONLY ? this.pickup : Pickup.DISALLOWED; + } + + @Override + protected boolean tryPickup(@NotNull Player pPlayer) { + if(life <= 240) { + return false; + } else { + if(life >= 480 || this.ownedBy(pPlayer) && (this.pickup != Pickup.CREATIVE_ONLY) ) { + this.pickup = Pickup.ALLOWED; + if(this.ownedBy(pPlayer)) { + ((PlayerLeashable)pPlayer).dropLeash(true, false); + } else if (this.getOwner() instanceof PlayerLeashable pL){ + pL.setLeashedTo(this, false); + } + } + return super.tryPickup(pPlayer); + } + } + + @Override + protected void tickDespawn() { + this.life++; + if (this.life >= 2400) {//TODO 加到配置中去,修改 + ItemEntity leash_rope_arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, ModItemRegister.LEASH_ROPE_ARROW.get().getDefaultInstance()); + this.level().addFreshEntity(leash_rope_arrow); + this.discard(); + } + } + + @Override + protected void onHitBlock(@NotNull BlockHitResult pResult) { + if(!level().isClientSide) { + if (getOwner() instanceof PlayerLeashable pL) { + if (this.level().getBlockState(pResult.getBlockPos()).is(BlockTags.FENCES)) { + Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level()); + if(leashDataEntity != null) pL.dropLeash(true, true); + Entity leashKnotFence = PlayerLeashable.createLeashKnotFence((ServerLevel) this.level(), pResult.getBlockPos()); + pL.setLeashedTo(leashKnotFence, true); + ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, Items.ARROW.getDefaultInstance()); + this.level().addFreshEntity(arrow); + discard(); + } + } + } + super.onHitBlock(pResult); + + } + + @Override + protected void onHitEntity(@NotNull EntityHitResult pResult) { + if(!level().isClientSide()){ + if(pResult.getEntity() instanceof LivingEntity){ + if (getOwner() instanceof PlayerLeashable pL) { + Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level()); + if(leashDataEntity != null) pL.dropLeash(true, true); + pL.setLeashedTo(pResult.getEntity(), true); + ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, Items.ARROW.getDefaultInstance()); + this.level().addFreshEntity(arrow); + discard(); + } + } + } + super.onHitEntity(pResult); + } +} diff --git a/src/main/java/com/r3944realms/leashedplayer/content/entities/ModEntityRegister.java b/src/main/java/com/r3944realms/leashedplayer/content/entities/ModEntityRegister.java new file mode 100644 index 0000000..434bebf --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/content/entities/ModEntityRegister.java @@ -0,0 +1,28 @@ +package com.r3944realms.leashedplayer.content.entities; + +import com.r3944realms.leashedplayer.LeashedPlayer; +import net.minecraft.core.registries.Registries; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.MobCategory; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredHolder; +import net.neoforged.neoforge.registries.DeferredRegister; + +public class ModEntityRegister { + public static final DeferredRegister> ENTITY_TYPE = DeferredRegister.create(Registries.ENTITY_TYPE, LeashedPlayer.MOD_ID); + public static final DeferredHolder ,EntityType> LEASH_ROPE_ARROW = ENTITY_TYPE.register( + "leash_rope_arrow", + () -> EntityType.Builder.of(LeashRopeArrow::new, MobCategory.MISC) + .sized(0.5F, 0.5F) + .eyeHeight(0.13F) + .clientTrackingRange(4) + .updateInterval(20) + .build("leash_rope_arrow") + ); + public static String getEntityNameKey(String entityName) { + return "entity." + LeashedPlayer.MOD_ID + "." + entityName; + } + public static void register(IEventBus eventBus) { + ENTITY_TYPE.register(eventBus); + } +} diff --git a/src/main/java/com/r3944realms/leashedplayer/content/items/LeashRopeArrowItem.java b/src/main/java/com/r3944realms/leashedplayer/content/items/LeashRopeArrowItem.java new file mode 100644 index 0000000..21842a4 --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/content/items/LeashRopeArrowItem.java @@ -0,0 +1,29 @@ +package com.r3944realms.leashedplayer.content.items; + +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.projectile.AbstractArrow; +import net.minecraft.world.item.ArrowItem; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; + +public class LeashRopeArrowItem extends ArrowItem { + public static final String descKey = "item.leash_rope_arrow.description"; + public LeashRopeArrowItem(Item.Properties pProperties) { + super(pProperties); + } + + public @NotNull AbstractArrow createArrow(@NotNull Level pLevel, @NotNull ItemStack pAmmo, @NotNull LivingEntity pShooter, @Nullable ItemStack pWeapon) { + return new com.r3944realms.leashedplayer.content.entities.LeashRopeArrow(pShooter, pLevel, pAmmo.copyWithCount(1), pWeapon); + } + + @Override + public @NotNull Component getDescription() { + return Component.translatable(descKey).withStyle(ChatFormatting.GRAY); + } +} diff --git a/src/main/java/com/r3944realms/leashedplayer/content/items/ModCreativeTab.java b/src/main/java/com/r3944realms/leashedplayer/content/items/ModCreativeTab.java new file mode 100644 index 0000000..f397878 --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/content/items/ModCreativeTab.java @@ -0,0 +1,37 @@ +package com.r3944realms.leashedplayer.content.items; + +import com.r3944realms.leashedplayer.LeashedPlayer; +import net.minecraft.core.registries.Registries; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.CreativeModeTabs; + +import net.minecraft.world.item.Items; +import net.neoforged.bus.api.IEventBus; + +import net.neoforged.neoforge.registries.DeferredRegister; +import org.jetbrains.annotations.NotNull; + +import java.util.function.Supplier; + +public class ModCreativeTab { + public static final DeferredRegister CREATIVE_MODE_TABS = + DeferredRegister.create(Registries.CREATIVE_MODE_TAB, LeashedPlayer.MOD_ID); + public static final String LEASHED_PLAYER_TAB_STRING = "creativetab." + LeashedPlayer.MOD_ID; + public static final String LEASHED_PLAYER_ITEM = "leashedplayer_tab"; + public static final Supplier TEST_TAB = CREATIVE_MODE_TABS.register(LEASHED_PLAYER_ITEM,() -> CreativeModeTab.builder() + .withTabsBefore(CreativeModeTabs.COMBAT) + .title(Component.translatable(getCreativeMod(LEASHED_PLAYER_ITEM))) + .icon(() -> ModItemRegister.LEASH_ROPE_ARROW.get().getDefaultInstance()) + .displayItems(((pParameters, pOutput) -> { + pOutput.accept(Items.LEAD); + pOutput.accept(ModItemRegister.LEASH_ROPE_ARROW.get()); + })).build()); + public static String getCreativeMod(@NotNull String tabs) { + return LEASHED_PLAYER_TAB_STRING + "." + tabs; + } + public static void register(IEventBus eventBus) { + CREATIVE_MODE_TABS.register(eventBus); + } + +} diff --git a/src/main/java/com/r3944realms/leashedplayer/content/items/ModItemRegister.java b/src/main/java/com/r3944realms/leashedplayer/content/items/ModItemRegister.java new file mode 100644 index 0000000..f3cdb3e --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/content/items/ModItemRegister.java @@ -0,0 +1,33 @@ +package com.r3944realms.leashedplayer.content.items; + +import com.r3944realms.leashedplayer.LeashedPlayer; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.item.Item; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.registries.DeferredRegister; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +public class ModItemRegister { + public static final DeferredRegister ITEMS = + DeferredRegister.create(BuiltInRegistries.ITEM, LeashedPlayer.MOD_ID); + public static final List> ITEM_SUPPLIER = new ArrayList<>(); + public static final Supplier LEASH_ROPE_ARROW = ModItemRegister.register("leash_rope_arrow", + () -> new LeashRopeArrowItem(new Item.Properties().stacksTo(16)) + ); + public static Supplier register(String name, Supplier supplier) { + return register(name, supplier, true); + } + + public static Supplier register(String name, Supplier supplier, boolean shouldJoinSupplierLists) { + Supplier supplierItem = ITEMS.register(name, supplier); + if(shouldJoinSupplierLists) ITEM_SUPPLIER.add(supplierItem); + return supplierItem; + } + + public static void register(IEventBus eventBus) { + ITEMS.register(eventBus); + } +} 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 da8b418..d3acc97 100644 --- a/src/main/java/com/r3944realms/leashedplayer/datagen/LanguageAndOtherData/ModLangKeyValue.java +++ b/src/main/java/com/r3944realms/leashedplayer/datagen/LanguageAndOtherData/ModLangKeyValue.java @@ -1,8 +1,13 @@ package com.r3944realms.leashedplayer.datagen.LanguageAndOtherData; import com.r3944realms.leashedplayer.content.commands.LeashCommand; +import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow; +import com.r3944realms.leashedplayer.content.entities.ModEntityRegister; import com.r3944realms.leashedplayer.content.gamerules.Server.CreateLeashFenceKnotEntityIfAbsent; import com.r3944realms.leashedplayer.content.gamerules.Server.TeleportWithLeashedPlayers; +import com.r3944realms.leashedplayer.content.items.LeashRopeArrowItem; +import com.r3944realms.leashedplayer.content.items.ModCreativeTab; +import com.r3944realms.leashedplayer.content.items.ModItemRegister; import com.r3944realms.leashedplayer.utils.Enum.LanguageEnum; import com.r3944realms.leashedplayer.utils.Enum.ModPartEnum; import net.minecraft.world.item.Item; @@ -12,24 +17,36 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; import java.util.function.Supplier; +import static com.r3944realms.leashedplayer.content.items.ModCreativeTab.LEASHED_PLAYER_ITEM; + public enum ModLangKeyValue { + //ITEM + ITEM_LEASH_ROPE_ARROW(ModItemRegister.LEASH_ROPE_ARROW, ModPartEnum.ITEM, "Leash Rope Arrow", "拴绳箭", "拴繩箭", true), + //ITEM_DESC + DESC_ITEM_LEASH_ROPE_ARROW(LeashRopeArrowItem.descKey, ModPartEnum.DESCRIPTION, "Arrows with ropes attached?","带有拴绳的箭矢?", "帶有拴繩的箭矢?", false), + //ENTITY + LEASH_ROPE_ARROW(ModEntityRegister.getEntityNameKey("leash_rope_arrow"), ModPartEnum.ENTITY, "Leash Rope Arrow", "拴绳箭", "拴繩箭", false), + //CREATIVE_TAB + CREATIVE_TAB_NAME(ModCreativeTab.getCreativeMod(LEASHED_PLAYER_ITEM), ModPartEnum.CREATIVE_TAB, "Leashed Player","可拴玩家", "可拴玩家", false), //COMMAND_MESSAGE 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_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_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_CLEAR(LeashCommand.LEASH_DATA_CLEAR, ModPartEnum.COMMAND, "%1$s's LeashData(LeashHolderEntity: %2$s) now is clear", "%1$s的拴绳数据(拴绳持有者实体:%2$s)现在已清除", "%1$s的拴繩數據(拴繩持有者實體:%2$s)現在已清除", false), MESSAGE_LEASH_SET_FAILED_FORBID_SAME_ENTITY(LeashCommand.LEASH_DATA_SET_FAILED_FORBID_SAME_ENTITY, ModPartEnum.COMMAND, "Prohibit setting the same entity","禁止设置同一实体", "禁止設置同一實體", false), + MESSAGE_LEASH_CLEAR_FAILED(LeashCommand.LEASH_DATA_CLEAR_FAILED_NO_DATA, ModPartEnum.COMMAND, "%1$s has no LeashData can be clear", "%1$s沒有拴绳数据可清除", "%1$s沒有拴繩數據實體可被清除", false), //GAME_RULE_NAME - 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), + 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, "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), + 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; diff --git a/src/main/java/com/r3944realms/leashedplayer/datagen/ModDataGeneratorHandler.java b/src/main/java/com/r3944realms/leashedplayer/datagen/ModDataGeneratorHandler.java index b22d04d..d9ce1f5 100644 --- a/src/main/java/com/r3944realms/leashedplayer/datagen/ModDataGeneratorHandler.java +++ b/src/main/java/com/r3944realms/leashedplayer/datagen/ModDataGeneratorHandler.java @@ -1,7 +1,7 @@ package com.r3944realms.leashedplayer.datagen; import com.r3944realms.leashedplayer.LeashedPlayer; -import com.r3944realms.leashedplayer.datagen.provider.ModLanguageProvider; +import com.r3944realms.leashedplayer.datagen.provider.*; import com.r3944realms.leashedplayer.utils.Enum.LanguageEnum; import net.minecraft.core.HolderLookup; import net.minecraft.data.DataProvider; @@ -24,6 +24,9 @@ public class ModDataGeneratorHandler { addLanguage(event, LanguageEnum.SimpleChinese, "zh_cn"); addLanguage(event, LanguageEnum.TraditionalChinese, "zh_tw"); addLanguage(event, LanguageEnum.LiteraryChinese, "lzh"); + ItemModelGenerator(event, existingFileHelper); + RecipeGenerator(event, HolderFolder); + ModTagsProvider(event, event.getLookupProvider(), existingFileHelper); } private static void addLanguage(GatherDataEvent event, LanguageEnum language, String lan_regex){ event.getGenerator().addProvider( @@ -31,4 +34,28 @@ public class ModDataGeneratorHandler { (DataProvider.Factory) pOutput -> new ModLanguageProvider(pOutput, LeashedPlayer.MOD_ID, language) ); } + private static void ItemModelGenerator(GatherDataEvent event, ExistingFileHelper helper) { + event.getGenerator().addProvider( + event.includeClient(), + (DataProvider.Factory) pOutput -> new ModItemModelProvider(pOutput, LeashedPlayer.MOD_ID, helper) + ); + } + private static void RecipeGenerator(GatherDataEvent event, CompletableFuture future) { + event.getGenerator().addProvider( + event.includeServer(), + (DataProvider.Factory) pOutput -> new ModRecipeProvider(pOutput, future) + ); + } + private static void ModTagsProvider(GatherDataEvent event, CompletableFuture completableFuture, ExistingFileHelper helper) { + ModBlockTagProvider modBlockTagProvider = event.getGenerator().addProvider( + event.includeServer(), + (DataProvider.Factory) pOutput -> + new ModBlockTagProvider(pOutput, completableFuture, LeashedPlayer.MOD_ID, helper) + ); + event.getGenerator().addProvider( + event.includeServer(), + (DataProvider.Factory) pOutput -> + new ModItemTagProvider(pOutput, completableFuture, modBlockTagProvider.contentsGetter(), helper) + ); + } } diff --git a/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModBlockTagProvider.java b/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModBlockTagProvider.java new file mode 100644 index 0000000..5208def --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModBlockTagProvider.java @@ -0,0 +1,21 @@ +package com.r3944realms.leashedplayer.datagen.provider; + +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.neoforged.neoforge.common.data.BlockTagsProvider; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.concurrent.CompletableFuture; + +public class ModBlockTagProvider extends BlockTagsProvider { + public ModBlockTagProvider(PackOutput output, CompletableFuture lookupProvider, String modId, @Nullable ExistingFileHelper existingFileHelper) { + super(output, lookupProvider, modId, existingFileHelper); + } + + @Override + protected void addTags(HolderLookup.@NotNull Provider pProvider) { + + } +} diff --git a/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModItemModelProvider.java b/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModItemModelProvider.java new file mode 100644 index 0000000..3dd69c9 --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModItemModelProvider.java @@ -0,0 +1,43 @@ +package com.r3944realms.leashedplayer.datagen.provider; + + +import com.r3944realms.leashedplayer.datagen.LanguageAndOtherData.ModLangKeyValue; +import net.minecraft.data.PackOutput; +import net.minecraft.world.item.Item; +import net.neoforged.neoforge.client.model.generators.ItemModelProvider; +import net.neoforged.neoforge.common.data.ExistingFileHelper; + +import java.util.ArrayList; +import java.util.List; + +public class ModItemModelProvider extends ItemModelProvider { + private static List objectList; + public ModItemModelProvider(PackOutput output, String modId, ExistingFileHelper existingFileHelper) { + super(output, modId, existingFileHelper); + objectList = new ArrayList<>(); + init(); + } + private void init() { + for(ModLangKeyValue obj : ModLangKeyValue.values()) { + if(!obj.isDefaultItem()) continue; + objectList.add(obj.getItem()); + } + } + /** + * @implNote 先有纹理才会成功构建 + */ + private void DefaultModItemModelRegister() { + objectList.forEach(this::basicItem); + } + private void AdvancedModItemModelRegister() { + /*手动生成更快,其实*/ + } + + @Override + protected void registerModels() { + // 注册默认材质物品模型 + DefaultModItemModelRegister(); + // 注册进阶材质物品模型(非模板大量需要,可以用BlockBench生成的就行了) + AdvancedModItemModelRegister(); + } +} diff --git a/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModItemTagProvider.java b/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModItemTagProvider.java new file mode 100644 index 0000000..faecd65 --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModItemTagProvider.java @@ -0,0 +1,26 @@ +package com.r3944realms.leashedplayer.datagen.provider; + +import com.r3944realms.leashedplayer.LeashedPlayer; +import com.r3944realms.leashedplayer.content.items.ModItemRegister; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.minecraft.data.tags.ItemTagsProvider; +import net.minecraft.tags.ItemTags; +import net.minecraft.world.level.block.Block; +import net.neoforged.neoforge.common.data.ExistingFileHelper; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.CompletableFuture; + +public class ModItemTagProvider extends ItemTagsProvider { + + public ModItemTagProvider(PackOutput pOutput, CompletableFuture pLookupProvider, CompletableFuture> pBlockTags, ExistingFileHelper pExistingFileHelper) { + super(pOutput, pLookupProvider, pBlockTags, LeashedPlayer.MOD_ID, pExistingFileHelper); + } + + @Override + protected void addTags(HolderLookup.@NotNull Provider pProvider) { + this.tag(ItemTags.ARROWS) + .add(ModItemRegister.LEASH_ROPE_ARROW.get()); + } +} diff --git a/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModRecipeProvider.java b/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModRecipeProvider.java new file mode 100644 index 0000000..6b15279 --- /dev/null +++ b/src/main/java/com/r3944realms/leashedplayer/datagen/provider/ModRecipeProvider.java @@ -0,0 +1,29 @@ +package com.r3944realms.leashedplayer.datagen.provider; + +import com.r3944realms.leashedplayer.content.items.ModItemRegister; +import net.minecraft.core.HolderLookup; +import net.minecraft.data.PackOutput; +import net.minecraft.data.recipes.*; +import net.minecraft.world.item.Items; +import org.jetbrains.annotations.NotNull; + +import java.util.concurrent.CompletableFuture; + +public class ModRecipeProvider extends RecipeProvider { + public ModRecipeProvider(PackOutput pOutput, CompletableFuture future) { + super(pOutput, future); + } + + @Override + protected void buildRecipes(@NotNull RecipeOutput pRecipeOutput) { + + ShapelessRecipeBuilder.shapeless(RecipeCategory.MISC, ModItemRegister.LEASH_ROPE_ARROW.get(),1) + .requires(Items.LEAD) + .requires(Items.ARROW) + .unlockedBy("has_lead",has(Items.LEAD)) + .save(pRecipeOutput); + + } + + +} \ No newline at end of file diff --git a/src/main/java/com/r3944realms/leashedplayer/mixin/both/MixinEntity.java b/src/main/java/com/r3944realms/leashedplayer/mixin/both/MixinEntity.java index 2f9fdf2..f4247a1 100644 --- a/src/main/java/com/r3944realms/leashedplayer/mixin/both/MixinEntity.java +++ b/src/main/java/com/r3944realms/leashedplayer/mixin/both/MixinEntity.java @@ -4,11 +4,14 @@ import com.r3944realms.leashedplayer.modInterface.PlayerLeashable; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Leashable; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Redirect; @Mixin(Entity.class) -public class MixinEntity { +public abstract class MixinEntity { + @Shadow public abstract void igniteForSeconds(float pSeconds); + /** * 这里重定向,当实体类实现了{@link PlayerLeashable}接口时,
* 阻止原版的{@link Leashable}中 的tickLeash方法调用,将其
@@ -25,4 +28,5 @@ public class MixinEntity { Leashable.tickLeash(entity); } } + } 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 c55faa0..29099ef 100644 --- a/src/main/java/com/r3944realms/leashedplayer/mixin/both/MixinPlayer.java +++ b/src/main/java/com/r3944realms/leashedplayer/mixin/both/MixinPlayer.java @@ -1,5 +1,9 @@ package com.r3944realms.leashedplayer.mixin.both; +import com.r3944realms.leashedplayer.LeashedPlayer; +import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig; +import com.r3944realms.leashedplayer.content.commands.LeashCommand; +import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow; import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension; import com.r3944realms.leashedplayer.modInterface.PlayerLeashable; import net.minecraft.nbt.CompoundTag; @@ -7,10 +11,12 @@ import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.level.ServerLevel; +import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Leashable; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; @@ -22,11 +28,11 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import javax.annotation.Nullable; +import java.util.Objects; import java.util.function.Consumer; @Mixin(Player.class) public abstract class MixinPlayer extends LivingEntity implements PlayerLeashable { - @Unique @Nullable private LeashData Pl$LeashData;//Data @@ -53,41 +59,55 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl } @Unique private static void Pl$UpdateLeash(Entity holderEntity, Entity restrainedEntity) { - if(holderEntity == null || holderEntity.level() != restrainedEntity.level()) + if (holderEntity == null || holderEntity.level() != restrainedEntity.level()) { return; - float leashLength = 6.0f; - if(restrainedEntity instanceof ILivingEntityExtension iEntity) { - //获取长度 - float leashLengthFormValue = iEntity.getLeashLength(); - leashLength = leashLengthFormValue > 6 ? leashLengthFormValue : 6; - } - //两者距离 - float distance = holderEntity.distanceTo(restrainedEntity); - //大于长度情况 - if(distance > leashLength) { - //作用对象(实体所坐载体还是实体【根据isPassenger来判断】 - Entity applyMovementEntity = restrainedEntity.isPassenger() ? restrainedEntity.getVehicle() : restrainedEntity; - if(applyMovementEntity != null){ - double dX = (holderEntity.getX() - applyMovementEntity.getX()) / (double) distance; - double dY = (holderEntity.getY() - applyMovementEntity.getY()) / (double) distance; - double dZ = (holderEntity.getZ() - applyMovementEntity.getZ()) / (double) distance; - //给予作用实体其向holderEntity的一个速度动量 - applyMovementEntity.setDeltaMovement( - applyMovementEntity.getDeltaMovement().add( - Math.copySign(dX * dX * 0.4d, dX), - Math.copySign(dY * dY * 0.4d, dY), - Math.copySign(dZ * dZ * 0.4d, dZ) - ) - ); - //刹车,避免偏激移动 - Whimsy$Brake(applyMovementEntity, 1, 1, 1); - } } - //降低坠落伤害 + float leashLength = LeashCommand.MIN_VALUE; + if (restrainedEntity instanceof ILivingEntityExtension iEntity) { + // 获取绳长 + float leashLengthFormValue = iEntity.getLeashLength(); + leashLength = leashLengthFormValue > LeashCommand.MIN_VALUE ? leashLengthFormValue : LeashCommand.MIN_VALUE; + } + + // 两者距离 + float distance = holderEntity.distanceTo(restrainedEntity); + Entity applyMovementEntity = restrainedEntity.isPassenger() ? restrainedEntity.getVehicle() : restrainedEntity; + + // 仅当距离大于绳长时施加拉力 + if (applyMovementEntity != null && distance > leashLength) { + // 计算朝向持有者的拉力方向 + double dX = (holderEntity.getX() - applyMovementEntity.getX()) / (double) distance; + double dY = (holderEntity.getY() - applyMovementEntity.getY()) / (double) distance; + double dZ = (holderEntity.getZ() - applyMovementEntity.getZ()) / (double) distance; + + // 拉力大小,距离越远拉力越强,但施加一个最大限制 + double pullStrength = Math.min((distance - leashLength) * 0.1, 1.0); // 限制最大拉力 + applyMovementEntity.setDeltaMovement( + applyMovementEntity.getDeltaMovement().add( + dX * pullStrength, + dY * pullStrength, + dZ * pullStrength + ) + ); + + // 控制速度不要过快,避免偏激移动 + Whimsy$Brake(applyMovementEntity, entity -> { + Vec3 deltaMovement = entity.getDeltaMovement(); + entity.setDeltaMovement( + Math.min(Math.abs(deltaMovement.x), 1.0) * Math.signum(deltaMovement.x), + Math.min(Math.abs(deltaMovement.y), 1.0) * Math.signum(deltaMovement.y), + Math.min(Math.abs(deltaMovement.z), 1.0) * Math.signum(deltaMovement.z) + ); + entity.hurtMarked = true; + }); + } + + // 降低坠落伤害 restrainedEntity.checkSlowFallDistance(); } + /** * 刹车( * @param pEntity 刹车的实体 @@ -98,9 +118,9 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl @Unique private static void Whimsy$Brake(Entity pEntity, double pMaxX, double pMaxY, double pMaxZ) { Vec3 deltaMovement = pEntity.getDeltaMovement(); - double dX = deltaMovement.x > pMaxX ? 0 : deltaMovement.x; - double dY = deltaMovement.y > pMaxY ? 0 : deltaMovement.y; - double dZ = deltaMovement.z > pMaxZ ? 0 : deltaMovement.z; + double dX = Math.abs(deltaMovement.x) > pMaxX ? 0 : deltaMovement.x; + double dY = Math.abs(deltaMovement.y) > pMaxY ? 0 : deltaMovement.y; + double dZ = Math.abs(deltaMovement.z) > pMaxZ ? 0 : deltaMovement.z; pEntity.setDeltaMovement(dX, dY,dZ); pEntity.hurtMarked = true; } @@ -115,9 +135,9 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl if(pOpt == null) { consumer = entity -> { Vec3 deltaMovement = entity.getDeltaMovement(); - double dX = deltaMovement.x > 1 ? 0 : deltaMovement.x; - double dY = deltaMovement.y > 1 ? 0 : deltaMovement.y; - double dZ = deltaMovement.z > 1 ? 0 : deltaMovement.z; + double dX = Math.abs(deltaMovement.x) > 1 ? 0 : deltaMovement.x; + double dY = Math.abs(deltaMovement.y) > 1 ? 0 : deltaMovement.y; + double dZ = Math.abs(deltaMovement.z) > 1 ? 0 : deltaMovement.z; entity.setDeltaMovement(dX, dY,dZ); entity.hurtMarked = true; }; @@ -130,27 +150,34 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl if(this.Pl$LeashData == null) return;//没有Data直接退出 //info -> Holder整理 Pl$RestoreLeashFormSave(); - //默认值设为6.0f距离 - float leashLength = 6.0f; + //默认值设为 + float leashLength = LeashCommand.MIN_VALUE; Entity entity = this.Pl$LeashData.leashHolder; //保存数据 saveLeashData(Pl$LeashData); if(this instanceof ILivingEntityExtension iEntityExtension) { //获取设定值 float leashLengthSelf = iEntityExtension.getLeashLength(); - leashLength = leashLengthSelf > 6 ? leashLengthSelf : 6; + leashLength = leashLengthSelf > LeashCommand.MIN_VALUE ? leashLengthSelf : LeashCommand.MIN_VALUE; } if (entity != null) { - if(!isAlive() || !entity.isAlive() || distanceTo(entity) > Math.max(leashLength * 2.0f, 10.0f)){ + float breakDistanceTime = (entity instanceof LeashRopeArrow) ? LeashedPlayer.M1() * LeashedPlayer.M2() : LeashedPlayer.M1(); + if(!isAlive() || !entity.isAlive() || distanceTo(entity) > Math.max(leashLength * breakDistanceTime, LeashCommand.MIN_VALUE * breakDistanceTime)){ //玩家死亡 或 持有者不存在 或 距离大于设定值的2倍(长度2倍若低于10格,则选10格) , // 则取消拴绳关系,并掉落拴绳 - dropLeash(true, true); - } else if(distanceTo(entity) > leashLength * 1.3f) { - //大于1.3倍绳长则会让其跳跃(在<1.25格阻拦情况下,跳跃阻拦 - jumpFromGround(); + boolean shouldDrop = !(entity instanceof LeashRopeArrow); + dropLeash(true, shouldDrop); + } else if(distanceTo(entity) > leashLength * 0.65f * breakDistanceTime && entity.onGround()) { + //大于1.3倍绳长则会让其跳跃(在<1.25格阻拦情况下,跳跃阻拦//TODO:待擴展 + Entity applyMovementEntity = this.isPassenger() ? this.getVehicle() : this; + if(applyMovementEntity instanceof LivingEntity applyMovementLivingEntity) { + applyMovementLivingEntity.jumpFromGround(); + } + } } } + @Override public Entity getLeashHolder() { if (Pl$LeashData == null) return null; @@ -176,7 +203,8 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl if(Pl$LeashData.leashHolder != null) {//且LeashHolder不为null,则直接用它 setLeashedTo(Pl$LeashData.leashHolder, true); return; - } return; + } + return; } if(this.Pl$LeashData.delayedLeashInfo.left().isPresent()) { diff --git a/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinEntityRenderer.java b/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinEntityRenderer.java index e75bb3b..2b11020 100644 --- a/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinEntityRenderer.java +++ b/src/main/java/com/r3944realms/leashedplayer/mixin/client/MixinEntityRenderer.java @@ -1,13 +1,17 @@ package com.r3944realms.leashedplayer.mixin.client; +import com.mojang.blaze3d.vertex.PoseStack; import net.minecraft.client.player.AbstractClientPlayer; +import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.entity.EntityRenderer; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EntityRenderer.class) public abstract class MixinEntityRenderer { @@ -22,8 +26,9 @@ public abstract class MixinEntityRenderer { private @NotNull Vec3 ret(Entity instance, float pPartialTick) { if(instance instanceof AbstractClientPlayer) { //为了使拴绳在在第三视角下位于玩家脖子处 - return instance.getLeashOffset(pPartialTick).add(0, -0.2, -0.2); + return instance.getLeashOffset(pPartialTick).add(0, -0.2, -0.2);//TODO:待擴展Vec3 } return instance.getLeashOffset(pPartialTick);//非实现这个接口则不变 } + } 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 1badcb3..0ef5316 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,8 @@ package com.r3944realms.leashedplayer.mixin.client; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.datafixers.util.Either; +import com.r3944realms.leashedplayer.LeashedPlayer; +import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow; import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension; import com.r3944realms.leashedplayer.modInterface.IPlayerRendererExtension; import com.r3944realms.leashedplayer.modInterface.PlayerLeashable; @@ -61,13 +63,13 @@ public abstract class MixinLevelRenderer { for(Entity entity : this.level.entitiesForRendering()) { //对于玩家实体拴绳渲染(从第一人称视角) if (entity instanceof AbstractClientPlayer abstractClientPlayer) { - if(!(pCamera.getEntity() instanceof AbstractClientPlayer)) return; + if(!(pCamera.getEntity() instanceof AbstractClientPlayer)) continue; Minecraft mc = Minecraft.getInstance(); PlayerRenderer playerRenderer = (PlayerRenderer) mc.getEntityRenderDispatcher().getRenderer(abstractClientPlayer); IPlayerRendererExtension playerRendererExtension = (IPlayerRendererExtension) playerRenderer; if (mc.options.getCameraType().isFirstPerson()) { Leashable.LeashData leashDataFromEntityData = ((PlayerLeashable) abstractClientPlayer).getLeashDataFromEntityData(); - if(leashDataFromEntityData == null) return; + if(leashDataFromEntityData == null) continue; Either delayedLeashInfo = leashDataFromEntityData.delayedLeashInfo; if(delayedLeashInfo != null) { float partialTickTime = pCamera.getPartialTickTime(); @@ -92,7 +94,7 @@ public abstract class MixinLevelRenderer { if (playerByUUID != null) { playerRendererExtension.renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, playerByUUID); } else { - float MaxLeashLength = ((ILivingEntityExtension) abstractClientPlayer).getLeashLength() * 2f; + float MaxLeashLength = ((ILivingEntityExtension) abstractClientPlayer).getLeashLength() * LeashedPlayer.M1() * LeashedPlayer.M2(); List entities = level.getEntities( null, new AABB( @@ -112,9 +114,13 @@ public abstract class MixinLevelRenderer { } } if (holder != null) { - playerRendererExtension.renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, holder); + if(holder instanceof LeashRopeArrow) { + playerRendererExtension.renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, holder, new Vec3(0.,-0.09, 0));//TODO: 待擴展Vec3 + } + else playerRendererExtension.renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, holder); } } + break; } } } 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 a5ba5bc..b8769be 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,8 @@ 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.LeashedPlayer; +import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow; import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension; import com.r3944realms.leashedplayer.modInterface.IPlayerRendererExtension; import com.r3944realms.leashedplayer.modInterface.PlayerLeashable; @@ -61,9 +63,10 @@ public abstract class MixinPlayerRenderer extends LivingEntityRenderer entities = level.getEntities( - null, + null, new AABB( pEntity.getX() - MaxLeashLength, pEntity.getY() - MaxLeashLength, @@ -81,7 +84,10 @@ public abstract class MixinPlayerRenderer extends LivingEntityRenderer 总结 * 这些数学运算主要用于计算实体在三维空间中的位置和方向,以确保在渲染链状结构(如拴住的绳索)时,链条能够跟随实体的移动和旋转并正确显示。在图形编程中,这些计算非常常见,尤其是在处理旋转、插值和光照效果时。 */ + @SuppressWarnings("AddedMixinMembersNamePattern") @Unique public void renderLeashForCamera( @@ -163,13 +170,14 @@ public abstract class MixinPlayerRenderer extends LivingEntityRenderer void renderLeash(AbstractClientPlayer pEntity, float pPartialTick, PoseStack pPoseStack, MultiBufferSource pBufferSource, E pLeashHolder, Vec3 holderOffset) { + pPoseStack.pushPose(); + Vec3 vec3 = pLeashHolder.getRopeHoldPosition(pPartialTick).add(holderOffset); + double d0 = (double)(pEntity.getPreciseBodyRotation(pPartialTick) * (float) (Math.PI / 180.0)) + (Math.PI / 2); + Vec3 vec31 = pEntity.getLeashOffset(pPartialTick); + double d1 = Math.cos(d0) * vec31.z + Math.sin(d0) * vec31.x; + double d2 = Math.sin(d0) * vec31.z - Math.cos(d0) * vec31.x; + double d3 = Mth.lerp(pPartialTick, pEntity.xo, pEntity.getX()) + d1; + double d4 = Mth.lerp(pPartialTick, pEntity.yo, pEntity.getY()) + vec31.y; + double d5 = Mth.lerp(pPartialTick, pEntity.zo, pEntity.getZ()) + d2; + pPoseStack.translate(d1, vec31.y, d2); + float f = (float)(vec3.x - d3); + float f1 = (float)(vec3.y - d4); + float f2 = (float)(vec3.z - d5); + float f3 = 0.025F; + VertexConsumer vertexconsumer = pBufferSource.getBuffer(RenderType.leash()); + Matrix4f matrix4f = pPoseStack.last().pose(); + float f4 = Mth.invSqrt(f * f + f2 * f2) * 0.025F / 2.0F; + float f5 = f2 * f4; + float f6 = f * f4; + BlockPos blockpos = BlockPos.containing(pEntity.getEyePosition(pPartialTick)); + BlockPos blockpos1 = BlockPos.containing(pLeashHolder.getEyePosition(pPartialTick)); + int i = this.getBlockLightLevel(pEntity, blockpos); + int j = 0; + int k = pEntity.level().getBrightness(LightLayer.SKY, blockpos); + int l = pEntity.level().getBrightness(LightLayer.SKY, blockpos1); + + for (int i1 = 0; i1 <= 24; i1++) { + addVertexPair(vertexconsumer, matrix4f, f, f1, f2, i, j, k, l, 0.025F, 0.025F, f5, f6, i1, false); + } + + for (int j1 = 24; j1 >= 0; j1--) { + addVertexPair(vertexconsumer, matrix4f, f, f1, f2, i, j, k, l, 0.025F, 0.0F, f5, f6, j1, true); + } + + pPoseStack.popPose(); + } } \ No newline at end of file diff --git a/src/main/java/com/r3944realms/leashedplayer/modInterface/IPlayerRendererExtension.java b/src/main/java/com/r3944realms/leashedplayer/modInterface/IPlayerRendererExtension.java index 90d5038..c5d50fc 100644 --- a/src/main/java/com/r3944realms/leashedplayer/modInterface/IPlayerRendererExtension.java +++ b/src/main/java/com/r3944realms/leashedplayer/modInterface/IPlayerRendererExtension.java @@ -1,13 +1,24 @@ package com.r3944realms.leashedplayer.modInterface; import net.minecraft.client.Camera; +import net.minecraft.world.phys.Vec3; public interface IPlayerRendererExtension { - void renderLeashForCamera( + default void renderLeashForCamera( Camera pCamera, float pPartialTick, com.mojang.blaze3d.vertex.PoseStack pPoseStack, net.minecraft.client.renderer.MultiBufferSource pBufferSource, E pLeashHolder + ) { + renderLeashForCamera(pCamera, pPartialTick, pPoseStack, pBufferSource, pLeashHolder, Vec3.ZERO); + } + void renderLeashForCamera( + Camera pCamera, + float pPartialTick, + com.mojang.blaze3d.vertex.PoseStack pPoseStack, + net.minecraft.client.renderer.MultiBufferSource pBufferSource, + E pLeashHolder, + Vec3 holderOffset ); } diff --git a/src/main/java/com/r3944realms/leashedplayer/modInterface/PlayerLeashable.java b/src/main/java/com/r3944realms/leashedplayer/modInterface/PlayerLeashable.java index 0d21fad..9e154be 100644 --- a/src/main/java/com/r3944realms/leashedplayer/modInterface/PlayerLeashable.java +++ b/src/main/java/com/r3944realms/leashedplayer/modInterface/PlayerLeashable.java @@ -3,6 +3,7 @@ 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.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Leashable; import net.minecraft.world.entity.decoration.LeashFenceKnotEntity; @@ -56,6 +57,39 @@ public interface PlayerLeashable extends Leashable { //这边覆写去掉了乘坐相关的逻辑,即乘坐状态下也可以正常被栓住,不影响其乘坐状态 } + @Nullable + static Entity getLeashDataEntity(@NotNull ServerPlayer serverPlayer , @NotNull ServerLevel serverLevel) { + LeashData leashDataFromEntityData = ((PlayerLeashable) serverPlayer).getLeashDataFromEntityData(); + if (leashDataFromEntityData != null) { + return getLeashDataEntity(leashDataFromEntityData, serverLevel); + } + else return null; + } + + static Entity getLeashDataEntityOrThrown(@NotNull ServerPlayer serverPlayer ,@NotNull ServerLevel serverLevel) throws Exception { + Entity leashedEntity = getLeashDataEntity(serverPlayer, serverLevel); + if(leashedEntity == null) throw new Exception("invalid"); + else return leashedEntity; + } + + @Nullable + static Entity getLeashDataEntity(@NotNull Leashable.LeashData leashDataFromEntityData, @NotNull ServerLevel level) { + if(leashDataFromEntityData.delayedLeashInfo != null) { + Optional UUID = leashDataFromEntityData.delayedLeashInfo.left(); + Optional BlockPos = leashDataFromEntityData.delayedLeashInfo.right(); + if (UUID.isPresent()) { + return level.getEntity(UUID.get()); + } else return BlockPos.map(pos -> LeashFenceKnotEntity.getOrCreateKnot(level, pos)).orElse(null); + } + else if(leashDataFromEntityData.leashHolder != null) { + return leashDataFromEntityData.leashHolder; + } + else if(leashDataFromEntityData.delayedLeashHolderId != 0) { + return level.getEntity(leashDataFromEntityData.delayedLeashHolderId); + } + else return null; + } + static Entity getLeashDataEntityOrThrown(@NotNull Leashable.LeashData leashDataFromEntityData, @NotNull ServerLevel level) throws Exception { if(leashDataFromEntityData.delayedLeashInfo != null) { Optional UUID = leashDataFromEntityData.delayedLeashInfo.left(); diff --git a/src/main/java/com/r3944realms/leashedplayer/utils/Util.java b/src/main/java/com/r3944realms/leashedplayer/utils/Util.java index 6d28729..39ef08a 100644 --- a/src/main/java/com/r3944realms/leashedplayer/utils/Util.java +++ b/src/main/java/com/r3944realms/leashedplayer/utils/Util.java @@ -1,6 +1,12 @@ package com.r3944realms.leashedplayer.utils; +import com.r3944realms.leashedplayer.LeashedPlayer; import com.r3944realms.leashedplayer.content.gamerules.Gamerules; +import net.neoforged.fml.loading.FMLPaths; + +import java.io.File; + +import static com.r3944realms.leashedplayer.utils.Logger.logger; public class Util { public static String getGameruleName(Class clazz) { @@ -10,4 +16,25 @@ public class Util { return Gamerules.GAMERULE_PREFIX + gamerulesName; } + public static void configFileCreate(String[] children) {//初始化配置文件目录 + File configFile = new File(FMLPaths.CONFIGDIR.get().toFile(), LeashedPlayer.MOD_ID); + if (!configFile.exists()) { + boolean mkdirSuccess = configFile.mkdirs(); + if (!mkdirSuccess) { + logger.error("failed to create config directory for whimsicality"); + throw new RuntimeException("failed to create config directory for " + LeashedPlayer.MOD_ID); + } else { + for (String child : children) { + File file = new File(configFile, child); + if (!file.exists()) { + boolean mkdirChildrenSuccess = file.mkdirs(); + if (!mkdirChildrenSuccess) { + logger.error("failed to create " + child + " directory for +" + LeashedPlayer.MOD_ID); + throw new RuntimeException("failed to create " + child + " directory for" +LeashedPlayer.MOD_ID); + } + } + } + } + } + } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index e6a6f50..1976920 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -11,4 +11,6 @@ public net.minecraft.world.level.GameRules$Type (Ljava/util/function/Suppl #因为'net.minecraft.world.level.GameRules.VisitorCaller' 在 'net.minecraft.world.level.GameRules' 中不为 public。无法从外部软件包访问 public net.minecraft.world.level.GameRules$VisitorCaller #Interface #private -> public -public net.minecraft.world.entity.Leashable$LeashData delayedLeashHolderId # delayedLeashHolderId \ No newline at end of file +public net.minecraft.world.entity.Leashable$LeashData delayedLeashHolderId # delayedLeashHolderId +#private -> protect +protected net.minecraft.world.entity.projectile.AbstractArrow life # life \ No newline at end of file diff --git a/src/main/resources/assets/leashedplayer/textures/entity/projectiles/leash_rope_arrow.png b/src/main/resources/assets/leashedplayer/textures/entity/projectiles/leash_rope_arrow.png new file mode 100644 index 0000000000000000000000000000000000000000..29333767c13d16b60b61b98aeb068f8f425353a1 GIT binary patch literal 260 zcmV+f0sH=mP)40*J%L3K!@@FYQCP4Ef*1`OtO}mNCL0AW;04B0SQLZ}f>jU%!QgDvBHCQ| zOjFjVFoyprGhtv}<{ubiNRq}F!j)pgxK-ggiJ5e&TulcbVQHHFEZAGjVgkV7bVIip zz-+eIUG9iNh5hl2C{%dmIU4Oc0O0z3fVDo9QV4)(v*FaCfHaT-9C#>A5DeEPJ$TZ7?02u#C>=S{wa# z&ow#jw^?jbo;B(q$1*sV6YOsXETc2BWB&GU^AjA#2}Ye^E&NtchRt3ZVVrzCuVQ|N zcb6Qi?X|Z3B}yqemcjL6M#nPv1yY66G-V;tf&oAXL8TOh5WfiuN%8(!qMJL)uVnQW S;U=R10000