2024-09-07
版本0.0.3.1 添加: 1.新的游戏规则KeepLeashNotDropTime(保持拴绳箭实体存活时间 2.新的纹理 包括弓弩材质发射拴绳箭新材质 3.新的配置文件内容 4.所有指令现在 可以同时作用多个玩家对象了 调整: 1.拾取拴绳箭的逻辑, 在落地后2s后可以通过按住Shift靠近后拾取 2.优化逻辑 3. 创造模式拴绳箭拾取逻辑修正 修复: 1.拴繩不能正常掉落的問題 2. data clear节点指令错误(笔误 具體新内容請見 README.md 介紹
15
README.md
|
|
@ -1,4 +1,4 @@
|
|||
# 版本 0.0.3.0-Beta.0.1 提前介绍 【注意:本解釋簡繁混寫,因爲趕時間,所以並不怎麽規範,請諒解】
|
||||
# 版本 0.0.3.1-Alpha-2 提前介绍 【注意:本解釋簡繁混寫,因爲趕時間,所以並不怎麽規範,請諒解】
|
||||
## 简介
|
||||
现在开始你可以用拴绳拴住玩家,也可以拴住自己了,不如尝试拴住彼此来通关我的世界吧(
|
||||
|
||||
|
|
@ -12,14 +12,16 @@
|
|||
1. 可改变指令前命名空间和关闭命名空间
|
||||
2. 修改命令拴绳的可设置的长度范围
|
||||
3. 设置拴绳在达到多少倍的拴绳长度后掉落
|
||||
4. 拴绳箭最大存活时间
|
||||
|
||||
## 新物品 和 实体
|
||||
### 拴绳箭
|
||||
获得飞一样的感觉(操作不当可能会摔死
|
||||
#### 射中实体时,会将射击者拴绳绑定在改实体上(该实体父类必须是有LivingEntity类型),同时拴绳箭会以普通的箭矢掉落
|
||||
#### 射中栅栏时,会自动将玩家拴在上面 ,同时拴绳箭会以普通的箭矢掉落
|
||||
## 指令
|
||||
|
||||
#### 在地面上的箭可以通过按Shift靠近来捡起,如果捡起实体为发射箭矢玩家,则直接获取拴绳箭矢,如果捡起者为非发射者则成为发送者的拴绳持有者,并获得普通箭矢
|
||||
## 指令
|
||||
可能会因为配置中差异性导致前缀'lp'变为其它或取消其存在,以模组配置文件为准
|
||||
* `/lp leash length [<玩家>] set <长度> ` - 设置该玩家的拴绳长度 [ 如果<玩家>为空则代表执行对象是自己 ,<长度> 为在 5 ~ 1024之间的浮点数 ]
|
||||
|
||||
* `/lp leash length [<玩家>] [get]` - 顯示该玩家的拴绳长度 [ 如果<玩家>为空则代表执行对象是自己 , [get] 可不写]
|
||||
|
|
@ -28,8 +30,13 @@
|
|||
|
||||
* `/lp leash data [<玩家>] [get]` - 顯示该玩家的拴绳數據 [ 如果<玩家>为空则代表执行对象是自己 , [get] 可不写]
|
||||
|
||||
* `/lp leash clear [<玩家[可多个对象]>] ` - 清除該玩家的的拴繩數據實體 [ 如果<玩家>为空则代表执行对象是自己 ]
|
||||
|
||||
|
||||
## 游戏规则
|
||||
|
||||
* `LP.TeleportWithLeashedPlayers` - 此規則啓用后, 被栓玩家將會随玩家拴绳持有者一起传送 [默认值: True]
|
||||
|
||||
* `LP.CreateLeashFenceKnotEntityIfAbsent` - 此規則啓用后, 在設置 leashData 時,如果對應方塊坐標上的柵欄沒有拴繩結則會自動創建這個實體並綁定 [默认值: True]
|
||||
* `LP.CreateLeashFenceKnotEntityIfAbsent` - 此規則啓用后, 在設置 leashData 時,如果對應方塊坐標上的柵欄沒有拴繩結則會自動創建這個實體並綁定 [默认值: True]
|
||||
|
||||
* `LP.KeepLeashNotDropTime` - 此规则决定,当拴绳关系创建时一段时间里,即是距离已经达到了断裂距离,也保持其不断裂 [默认值: 240ticks ,可设置范围[80, 1200]ticks]
|
||||
BIN
Resource/crossbow_leash_rope_arrow.png
Normal file
|
After Width: | Height: | Size: 475 B |
|
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 243 B |
|
|
@ -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.3.0-Beta.0.1
|
||||
mod_version=0.0.3.1
|
||||
# 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
|
||||
|
|
|
|||
|
|
@ -1,2 +1,6 @@
|
|||
// 1.21.1 2024-09-05T13:27:19.7536653 Item Models: leashedplayer
|
||||
// 1.21.1 2024-09-07T10:24:45.3887825 Item Models: leashedplayer
|
||||
5846df9d85726428905701120ef34c9324c20faf assets/leashedplayer/models/item/bow_lra_pulling_0.json
|
||||
845a7316b86e26f88c6932d4ef2656126503727a assets/leashedplayer/models/item/bow_lra_pulling_1.json
|
||||
5bd1f9f28b91005c587f1c38fb77cd19b59495e3 assets/leashedplayer/models/item/bow_lra_pulling_2.json
|
||||
83946f4d60d0fb1758d6553c36330506c8e48ada assets/leashedplayer/models/item/crossbow_leash_rope_arrow.json
|
||||
114d3cc5832ef047403114504483c6f3ea07e77c assets/leashedplayer/models/item/leash_rope_arrow.json
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:item/bow",
|
||||
"textures": {
|
||||
"layer0": "leashedplayer:item/bow_lra_pulling_0"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:item/bow",
|
||||
"textures": {
|
||||
"layer0": "leashedplayer:item/bow_lra_pulling_1"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:item/bow",
|
||||
"textures": {
|
||||
"layer0": "leashedplayer:item/bow_lra_pulling_2"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"parent": "minecraft:item/crossbow",
|
||||
"textures": {
|
||||
"layer0": "leashedplayer:item/crossbow_leash_rope_arrow"
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,37 @@
|
|||
package com.r3944realms.leashedplayer;
|
||||
|
||||
import com.r3944realms.leashedplayer.client.renders.LeashRopeArrowRenderer;
|
||||
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
|
||||
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
|
||||
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
|
||||
import net.minecraft.client.renderer.item.ItemProperties;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.component.ChargedProjectiles;
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
|
||||
|
||||
@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD, modid = LeashedPlayer.MOD_ID)
|
||||
public class ClientEventHandler {
|
||||
@SubscribeEvent
|
||||
public static void onRegisterItemProperties(FMLClientSetupEvent event) {
|
||||
event.enqueueWork(() -> {
|
||||
ItemProperties.register(Items.CROSSBOW, ResourceLocation.withDefaultNamespace("leash_rope_arrow"),
|
||||
((pStack, pLevel, pEntity, pSeed) -> {
|
||||
ChargedProjectiles chargedProjectiles = pStack.get(DataComponents.CHARGED_PROJECTILES);
|
||||
return chargedProjectiles != null && chargedProjectiles.contains(ModItemRegister.LEASH_ROPE_ARROW.get()) ? 1.0F : 0.0F;
|
||||
}));
|
||||
ItemProperties.register(Items.BOW, ResourceLocation.withDefaultNamespace("leash_rope_arrow_pulling"),
|
||||
((pStack, pLevel, pEntity, pSeed) ->
|
||||
(pEntity != null && pEntity.isUsingItem() && pEntity.getUseItem() == pStack && LeashRopeArrow.isLeashRopeArrow(pStack, pEntity)) ? 1.0F: 0.0F
|
||||
));
|
||||
});
|
||||
|
||||
}
|
||||
@SubscribeEvent
|
||||
public static void RegisterRenderer(EntityRenderersEvent.RegisterRenderers event) {
|
||||
event.registerEntityRenderer(ModEntityRegister.LEASH_ROPE_ARROW.get(), LeashRopeArrowRenderer::new);
|
||||
|
|
|
|||
|
|
@ -5,13 +5,63 @@ import com.r3944realms.leashedplayer.content.commands.LeashCommand;
|
|||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.neoforged.bus.api.SubscribeEvent;
|
||||
import net.neoforged.fml.common.EventBusSubscriber;
|
||||
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.neoforged.neoforge.event.RegisterCommandsEvent;
|
||||
|
||||
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID)
|
||||
|
||||
public class CommonEventHandler {
|
||||
@SubscribeEvent
|
||||
public static void onRegisterCommander(RegisterCommandsEvent event) {
|
||||
CommandDispatcher<CommandSourceStack> dispatcher = event.getDispatcher();
|
||||
LeashCommand.register(dispatcher);
|
||||
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID)
|
||||
public static class Game extends CommonEventHandler {
|
||||
@SubscribeEvent
|
||||
public static void onRegisterCommander(RegisterCommandsEvent event) {
|
||||
CommandDispatcher<CommandSourceStack> dispatcher = event.getDispatcher();
|
||||
LeashCommand.register(dispatcher);
|
||||
}
|
||||
|
||||
}
|
||||
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID, bus = EventBusSubscriber.Bus.MOD)
|
||||
public static class Mod extends CommonEventHandler {
|
||||
@SubscribeEvent
|
||||
public static void onCommonSetup(FMLCommonSetupEvent event) {
|
||||
// NeoForge.EVENT_BUS.addListener(Mod::onPlayerTick);
|
||||
}
|
||||
// public static void onPlayerTick(PlayerTickEvent.Pre event) {
|
||||
// if (!event.getEntity().level().isClientSide && !event.getEntity().isUsingItem()) {
|
||||
// Player player = event.getEntity();
|
||||
//
|
||||
// // 检测玩家视线中的实体
|
||||
// Entity entity = getEntityLookedAt(player);
|
||||
//
|
||||
// // 如果实体是自定义箭实体
|
||||
// if (entity instanceof LeashRopeArrow la) {
|
||||
//
|
||||
// // 处理玩家右键点击箭的交互逻辑
|
||||
// if (player.isShiftKeyDown()) { // 可以结合 Shift 键
|
||||
// if(la.pickup == AbstractArrow.Pickup.ALLOWED || ( player.isCreative() && la.pickup != AbstractArrow.Pickup.DISALLOWED )){
|
||||
// player.take(la, 1);
|
||||
// player.addItem(ModItemRegister.LEASH_ROPE_ARROW.get().getDefaultInstance());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // 射线检测方法,获取玩家视线内的实体//TODO:分离 Maybe XD
|
||||
// private static Entity getEntityLookedAt(Player player) {
|
||||
// double reach = 5.0D; // 设置射线检测距离 //TODO:与Player互动距离同步
|
||||
// Vec3 eyePosition = player.getEyePosition(1.0F);
|
||||
// Vec3 lookVector = player.getViewVector(1.0F).scale(reach);
|
||||
// Vec3 targetPosition = eyePosition.add(lookVector);
|
||||
//
|
||||
// // 创建一个射线并检测结果
|
||||
// AABB boundingBox = player.getBoundingBox().expandTowards(lookVector).inflate(1.0D, 1.0D, 1.0D);
|
||||
// EntityHitResult hitResult = ProjectileUtil.getEntityHitResult(player, eyePosition, targetPosition, boundingBox, e -> e instanceof LeashRopeArrow, reach);
|
||||
//
|
||||
// return hitResult == null ? null : hitResult.getEntity();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,14 +2,12 @@ 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<String> LeashedPlayerModCommandPrefix;
|
||||
public static final ModConfigSpec.BooleanValue EnableLeashPlayerCommandPrefix;
|
||||
public static ModConfigSpec.IntValue MinimumLeashLengthCanBeSet, MaximumLeashLengthCanBeSet;
|
||||
public static ModConfigSpec.IntValue MinimumLeashLengthCanBeSet, MaximumLeashLengthCanBeSet, TheLeashArrowMaxLifeTime;
|
||||
public static ModConfigSpec.ConfigValue<Float> TheMultipleThatLeashRopeArrowBreakLength, TheLeashBreakLengthTimesBase;
|
||||
static {
|
||||
BUILDER.comment("Leash Player Config");
|
||||
|
|
@ -23,7 +21,7 @@ public class LeashPlayerCommonConfig {
|
|||
|
||||
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);
|
||||
|
||||
TheLeashArrowMaxLifeTime = BUILDER.comment("If the LeashArrowEntity's life is bigger than this value ,it will be discrad", "[ Default : 2400, Invalid Range:[1200 , 10240]").defineInRange("TheLeashArrowMaxLifeTime",2400, 1200, 10240);
|
||||
BUILDER.pop();
|
||||
|
||||
BUILDER.push("Misc");
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ import com.mojang.brigadier.Command;
|
|||
import com.mojang.brigadier.CommandDispatcher;
|
||||
import com.mojang.brigadier.arguments.FloatArgumentType;
|
||||
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||
|
||||
import com.mojang.brigadier.context.CommandContext;
|
||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||
import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig;
|
||||
|
|
@ -26,6 +25,7 @@ import net.minecraft.world.entity.Leashable;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class LeashCommand {
|
||||
|
|
@ -79,7 +79,7 @@ public class LeashCommand {
|
|||
Command<CommandSourceStack> getRefPlayerLeashLength = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
try {
|
||||
ServerPlayer player = EntityArgument.getPlayer(context, "player");
|
||||
ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer");
|
||||
float leashLength = ((ILivingEntityExtension)player).getLeashLength();
|
||||
source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SHOW, player.getDisplayName(), leashLength), true);
|
||||
} catch (Exception e) {
|
||||
|
|
@ -88,6 +88,20 @@ public class LeashCommand {
|
|||
}
|
||||
return 0;
|
||||
};
|
||||
Command<CommandSourceStack> getRefPlayersLeashLength = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
try {
|
||||
Collection<ServerPlayer> playerCol = EntityArgument.getPlayers(context, "targetPlayers");
|
||||
playerCol.forEach(player -> {
|
||||
float leashLength = ((ILivingEntityExtension) player).getLeashLength();
|
||||
source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SHOW, player.getDisplayName(), leashLength), true);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
source.sendFailure(Component.translatable(LEASH_FAILED));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
Command<CommandSourceStack> setSelfLengthLeashLength = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
try {
|
||||
|
|
@ -101,10 +115,10 @@ public class LeashCommand {
|
|||
}
|
||||
return 0;
|
||||
};
|
||||
Command<CommandSourceStack> setLengthLeashLength = context -> {
|
||||
Command<CommandSourceStack> setRefPlayerLengthLeashLength = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
try {
|
||||
ServerPlayer player = EntityArgument.getPlayer(context, "player");
|
||||
ServerPlayer player = EntityArgument.getPlayer(context, "targetPlayer");
|
||||
float leashLength = context.getArgument("leashLength", Float.class);
|
||||
((ILivingEntityExtension)player).setLeashLength(leashLength);
|
||||
source.sendSuccess(() -> Component.translatable(LEASH_LENGTH_SET, player.getDisplayName(), leashLength), true);
|
||||
|
|
@ -114,6 +128,25 @@ public class LeashCommand {
|
|||
}
|
||||
return 0;
|
||||
};
|
||||
Command<CommandSourceStack> setRefPlayersLengthLeashLength = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
float leashLength = context.getArgument("leashLength", Float.class);
|
||||
try {
|
||||
Collection<ServerPlayer> playerCol = EntityArgument.getPlayers(context, "targetPlayer");
|
||||
playerCol.forEach(player -> {
|
||||
try {
|
||||
((ILivingEntityExtension)player).setLeashLength(leashLength);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
source.sendFailure(Component.translatable(LEASH_FAILED));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
//获取Data 构造一个MutableComponent显示数据
|
||||
Command<CommandSourceStack> geSelfLeashData = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
|
@ -140,6 +173,24 @@ public class LeashCommand {
|
|||
}
|
||||
return 0;
|
||||
};
|
||||
Command<CommandSourceStack> getRefPlayersLeashData = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
try {
|
||||
Collection<ServerPlayer> playerCol = EntityArgument.getPlayers(context, "targetPlayers");
|
||||
playerCol.forEach(player -> {
|
||||
try {
|
||||
LeashLengthGetResultInt(player, source);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
source.sendFailure(Component.translatable(LEASH_FAILED));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
//设置前要判断其实体距离(同一维度,且距离不得大于其绳长的1.2倍(待定,也许可以设置在配置文件里)
|
||||
Command<CommandSourceStack> setSelfLeashDataEntity = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
|
|
@ -182,6 +233,37 @@ public class LeashCommand {
|
|||
}
|
||||
return 0;
|
||||
};
|
||||
Command<CommandSourceStack> setRefPlayersLeashDataEntity = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
try {
|
||||
Collection<ServerPlayer> playerCol = EntityArgument.getPlayers(context, "targetPlayers");
|
||||
playerCol.forEach(player -> {
|
||||
try {
|
||||
LeashDataEntitySetResultInt(context, player, source);
|
||||
} catch (CommandSyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
} catch (Exception e) {
|
||||
source.sendFailure(Component.translatable(LEASH_FAILED));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
Command<CommandSourceStack> setRefPlayersLeashDataByBlockPos = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
try {
|
||||
Collection<ServerPlayer> playerCol = EntityArgument.getPlayers(context, "targetPlayers");
|
||||
playerCol.forEach(player -> {
|
||||
LeashDataBlockPosSetResultInt(context, source, player);
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
source.sendFailure(Component.translatable(LEASH_FAILED));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
Command<CommandSourceStack> setRefPlayerLeashDataByBlockPos = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
try {
|
||||
|
|
@ -195,6 +277,7 @@ public class LeashCommand {
|
|||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
Command<CommandSourceStack> clearSelfLeashData = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
try {
|
||||
|
|
@ -212,8 +295,25 @@ public class LeashCommand {
|
|||
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;
|
||||
Integer x = LeashDataClearResultInt(source, PlayerLeashable.getLeashDataEntity(player, source.getLevel()),player);
|
||||
|
||||
} catch (Exception e) {
|
||||
source.sendFailure(Component.translatable(LEASH_FAILED));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
Command<CommandSourceStack> clearRefPlayersLeashData = context -> {
|
||||
CommandSourceStack source = context.getSource();
|
||||
try {
|
||||
Collection<ServerPlayer> playerCol = EntityArgument.getPlayers(context, "targetPlayers");
|
||||
playerCol.forEach(player -> {
|
||||
try {
|
||||
LeashDataClearResultInt(source, PlayerLeashable.getLeashDataEntity(player, source.getLevel()),player);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
} catch (Exception e) {
|
||||
source.sendFailure(Component.translatable(LEASH_FAILED));
|
||||
|
|
@ -232,11 +332,19 @@ public class LeashCommand {
|
|||
|
||||
LiteralArgumentBuilder<CommandSourceStack> RefPlayerLeashLength = $$leashRoot.then(
|
||||
Commands.literal("length")
|
||||
.then(Commands.argument("player", EntityArgument.player()).executes(getRefPlayerLeashLength)
|
||||
.then(Commands.argument("targetPlayer", EntityArgument.player()).executes(getRefPlayerLeashLength)
|
||||
.then(Commands.literal("get").executes(getRefPlayerLeashLength))
|
||||
.then(Commands.literal("set").requires(cs -> cs.hasPermission(2))
|
||||
.then(
|
||||
Commands.argument("leashLength", FloatArgumentType.floatArg(MIN_VALUE, MAX_VALUE)).executes(setLengthLeashLength)
|
||||
Commands.argument("leashLength", FloatArgumentType.floatArg(MIN_VALUE, MAX_VALUE)).executes(setRefPlayerLengthLeashLength)
|
||||
)
|
||||
)
|
||||
)
|
||||
.then(Commands.argument("targetPlayers", EntityArgument.players()).executes(getRefPlayerLeashLength)
|
||||
.then(Commands.literal("get").executes(getRefPlayerLeashLength))
|
||||
.then(Commands.literal("set").requires(cs -> cs.hasPermission(2))
|
||||
.then(
|
||||
Commands.argument("leashLength", FloatArgumentType.floatArg(MIN_VALUE, MAX_VALUE)).executes(setRefPlayerLengthLeashLength)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
|
@ -256,9 +364,22 @@ public class LeashCommand {
|
|||
.executes(setRefPlayerLeashDataByBlockPos)
|
||||
)
|
||||
)
|
||||
.then(Commands.literal("clear").requires(cs -> cs.hasPermission(2)).executes(clearSelfLeashData))
|
||||
.then(Commands.literal("clear").requires(cs -> cs.hasPermission(2)).executes(clearRefPlayerLeashData))
|
||||
)
|
||||
);
|
||||
.then(Commands.argument("targetPlayers", EntityArgument.players()).executes(getRefPlayersLeashData)
|
||||
.then(Commands.literal("get")
|
||||
.executes(getRefPlayerLeashData)
|
||||
)
|
||||
.then(Commands.literal("set").requires(cs -> cs.hasPermission(2))
|
||||
.then(Commands.argument("holderEntity", EntityArgument.entity())
|
||||
.executes(setRefPlayersLeashDataEntity)
|
||||
)
|
||||
.then(Commands.argument("BlockPos", BlockPosArgument.blockPos())
|
||||
.executes(setRefPlayersLeashDataByBlockPos)
|
||||
)
|
||||
)
|
||||
.then(Commands.literal("clear").requires(cs -> cs.hasPermission(2)).executes(clearRefPlayersLeashData))
|
||||
));
|
||||
|
||||
LiteralArgumentBuilder<CommandSourceStack> SelfData = $$leashRoot.then(
|
||||
Commands.literal("data")
|
||||
|
|
@ -353,6 +474,7 @@ 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()));
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
package com.r3944realms.leashedplayer.content.entities;
|
||||
|
||||
import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig;
|
||||
import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry;
|
||||
import com.r3944realms.leashedplayer.content.gamerules.Server.KeepLeashNotDropTime;
|
||||
import com.r3944realms.leashedplayer.content.items.LeashRopeArrowItem;
|
||||
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
|
||||
import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension;
|
||||
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
|
|
@ -8,6 +13,7 @@ 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.decoration.LeashFenceKnotEntity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.entity.projectile.AbstractArrow;
|
||||
|
|
@ -20,6 +26,7 @@ import org.jetbrains.annotations.NotNull;
|
|||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class LeashRopeArrow extends AbstractArrow {
|
||||
private static final int maxLifeTime = LeashPlayerCommonConfig.TheLeashArrowMaxLifeTime.get();
|
||||
protected LeashRopeArrow(EntityType<? extends AbstractArrow> entityType,Level pLevel) {
|
||||
super(entityType, pLevel);
|
||||
}
|
||||
|
|
@ -37,6 +44,17 @@ public class LeashRopeArrow extends AbstractArrow {
|
|||
lPlayer.setLeashedTo(this, true);
|
||||
}
|
||||
}
|
||||
public static boolean isLeashRopeArrow(ItemStack bowStack, LivingEntity entity) {
|
||||
if (entity instanceof Player player) {
|
||||
|
||||
// 获取将要发射的弹药
|
||||
ItemStack projectileStack = player.getProjectile(bowStack);
|
||||
|
||||
// 判断该弹药是否为改箭
|
||||
return projectileStack.getItem() instanceof LeashRopeArrowItem;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull ItemStack getDefaultPickupItem() {
|
||||
|
|
@ -52,25 +70,75 @@ public class LeashRopeArrow extends AbstractArrow {
|
|||
|
||||
@Override
|
||||
protected boolean tryPickup(@NotNull Player pPlayer) {
|
||||
if(life <= 240) {
|
||||
//时间1.40 禁止
|
||||
//时间2.240
|
||||
// 如果(非仅创造拾取)
|
||||
// 如果 (按Shift )
|
||||
// 如果(拥有者) -> 拾取到完整箭,取消绑定(super给父类处理)
|
||||
// 否则:时间仍为原需时间 ->不能获取完整的箭,重绑定(当前拥有者的Holder是否为本箭,“是”才重绑定)
|
||||
// 否则: 禁止
|
||||
// 否则:
|
||||
// 如果 (按Shift )
|
||||
// 如果(拥有者) -> 且拾取到完整箭,取消绑定
|
||||
// 否则:时间仍为原需时间 ->不能获取完整的箭,重绑定
|
||||
// 否则: 禁止
|
||||
//时间3
|
||||
// 如果(拥有者) -> 拾取到完整箭,取消绑定
|
||||
// 否则:不能获取完整的箭,重绑定
|
||||
|
||||
if(life <= 40 ) {
|
||||
return false;
|
||||
} else {
|
||||
if(life >= 480 || this.ownedBy(pPlayer) && (this.pickup != Pickup.CREATIVE_ONLY) ) {
|
||||
this.pickup = Pickup.ALLOWED;
|
||||
}
|
||||
else {
|
||||
PlayerLeashable playerLeashable = (PlayerLeashable) pPlayer;
|
||||
if(life <= 240) {
|
||||
if(pPlayer.isShiftKeyDown()) {
|
||||
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) this.getOwner(), (ServerLevel) level());
|
||||
if(this.ownedBy(pPlayer)) {
|
||||
this.pickup = Pickup.ALLOWED;
|
||||
if(this.equals(leashDataEntity)) playerLeashable.dropLeash(true, false);
|
||||
} else {
|
||||
if(life >= 120) {
|
||||
Entity owner = getOwner();
|
||||
if( owner != null ) {
|
||||
if(this.equals(leashDataEntity)) {
|
||||
((PlayerLeashable) owner).setLeashedTo(pPlayer, true);
|
||||
ItemEntity itemEntity = new ItemEntity(level(), getX(), getY(), getZ(), Items.ARROW.getDefaultInstance());
|
||||
level().addFreshEntity(itemEntity);
|
||||
discard();
|
||||
}
|
||||
} else return true;
|
||||
} else return false;
|
||||
}
|
||||
} else return false;
|
||||
|
||||
}
|
||||
else {
|
||||
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) this.getOwner(), (ServerLevel) level());
|
||||
if(this.ownedBy(pPlayer)) {
|
||||
((PlayerLeashable)pPlayer).dropLeash(true, false);
|
||||
} else if (this.getOwner() instanceof PlayerLeashable pL){
|
||||
pL.setLeashedTo(this, false);
|
||||
this.pickup = Pickup.ALLOWED;
|
||||
if(this.equals(leashDataEntity)) playerLeashable.dropLeash(true, false);
|
||||
} else {
|
||||
if(this.equals(leashDataEntity)) {
|
||||
Entity owner = getOwner();
|
||||
((PlayerLeashable)owner).setLeashedTo(pPlayer, true);
|
||||
ItemEntity itemEntity = new ItemEntity(level(), getX(), getY(), getZ(), Items.ARROW.getDefaultInstance());
|
||||
level().addFreshEntity(itemEntity);
|
||||
discard();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return super.tryPickup(pPlayer);
|
||||
}
|
||||
|
||||
return super.tryPickup(pPlayer);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void tickDespawn() {
|
||||
this.life++;
|
||||
if (this.life >= 2400) {//TODO 加到配置中去,修改
|
||||
if (this.life >= maxLifeTime) {
|
||||
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();
|
||||
|
|
@ -83,8 +151,10 @@ public class LeashRopeArrow extends AbstractArrow {
|
|||
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);
|
||||
if(leashDataEntity != null) pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
|
||||
Entity leashKnotFence = PlayerLeashable.createLeashKnotFence((ServerLevel) this.level(), pResult.getBlockPos());
|
||||
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
|
||||
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
|
||||
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);
|
||||
|
|
@ -99,14 +169,30 @@ public class LeashRopeArrow extends AbstractArrow {
|
|||
@Override
|
||||
protected void onHitEntity(@NotNull EntityHitResult pResult) {
|
||||
if(!level().isClientSide()){
|
||||
if(pResult.getEntity() instanceof LivingEntity){
|
||||
Entity entity = pResult.getEntity();
|
||||
if(entity instanceof LivingEntity){
|
||||
if(entity.equals(this.getOwner())) return;
|
||||
if (getOwner() instanceof PlayerLeashable pL) {
|
||||
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
|
||||
if(leashDataEntity != null) pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
|
||||
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, Items.ARROW.getDefaultInstance());
|
||||
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
|
||||
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
|
||||
pL.setLeashedTo(pResult.getEntity(), true);
|
||||
this.level().addFreshEntity(arrow);
|
||||
discard();
|
||||
}
|
||||
} else if (entity instanceof LeashFenceKnotEntity leashKnotFence) {
|
||||
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());
|
||||
ILivingEntityExtension pLL = (ILivingEntityExtension) pL;
|
||||
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
|
||||
pL.setLeashedTo(leashKnotFence, true);
|
||||
this.level().addFreshEntity(arrow);
|
||||
discard();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
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.server.MinecraftServer;
|
||||
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 java.util.function.BiConsumer;
|
||||
|
||||
import static com.r3944realms.leashedplayer.content.gamerules.Gamerules.GAMERULE_REGISTRY;
|
||||
|
||||
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID, bus = EventBusSubscriber.Bus.MOD)
|
||||
public class KeepLeashNotDropTime {
|
||||
public static final int DEFAULT_VALUE = 240;
|
||||
public static final String ID = Util.getGameruleName(KeepLeashNotDropTime.class);
|
||||
public static final String DESCRIPTION_KEY = Gamerules.getDescriptionKey(KeepLeashNotDropTime.class);
|
||||
public static final String NAME_KEY = Gamerules.getNameKey(KeepLeashNotDropTime.class);
|
||||
public static final GameRules.Category CATEGORY = GameRules.Category.MISC;
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onCommonSetup(final FMLCommonSetupEvent event) {
|
||||
GAMERULE_REGISTRY.registerGamerule(ID, CATEGORY, DEFAULT_VALUE, 80, 1200, (BiConsumer<MinecraftServer, GameRules.IntegerValue>) (i, j)->{});
|
||||
}
|
||||
}
|
||||
|
|
@ -7,10 +7,12 @@ 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.item.TooltipFlag;
|
||||
import net.minecraft.world.level.Level;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class LeashRopeArrowItem extends ArrowItem {
|
||||
public static final String descKey = "item.leash_rope_arrow.description";
|
||||
|
|
@ -26,4 +28,8 @@ public class LeashRopeArrowItem extends ArrowItem {
|
|||
public @NotNull Component getDescription() {
|
||||
return Component.translatable(descKey).withStyle(ChatFormatting.GRAY);
|
||||
}
|
||||
public void appendHoverText(@NotNull ItemStack pStack, Item.@NotNull TooltipContext pContext, @NotNull List<Component> pTooltipComponents, @NotNull TooltipFlag pTooltipFlag) {
|
||||
//TODO:也许会做
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,8 @@ 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
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.KeepLeashNotDropTime;
|
||||
import com.r3944realms.leashedplayer.content.gamerules.Server.TeleportWithLeashedPlayers;
|
||||
import com.r3944realms.leashedplayer.content.items.LeashRopeArrowItem;
|
||||
import com.r3944realms.leashedplayer.content.items.ModCreativeTab;
|
||||
|
|
@ -44,10 +44,11 @@ public enum ModLangKeyValue {
|
|||
//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),
|
||||
KEEP_LEASH_NOT_DROP_TIME(KeepLeashNotDropTime.NAME_KEY, ModPartEnum.NAME, "Keep leash alive Time", "保持拴绳不掉落的时间", "保持其不掉落的時間", 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),
|
||||
|
||||
CREATE_LEASH_FENCE_KNOT_ENTITY_IF_ABSENT_DESCRIPTION(CreateLeashFenceKnotEntityIfAbsent.DESCRIPTION_KEY, ModPartEnum.DESCRIPTION, "Create LeashKnot Entity if it's absent on fence", "如果在栅栏处缺失拴绳结,则创建它", "如果在柵欄処缺失拴繩結,則創建它", false),
|
||||
KEEP_LEASH_NOT_DROP_TIME_DESCRIPTION(KeepLeashNotDropTime.DESCRIPTION_KEY, ModPartEnum.DESCRIPTION,"The time of Keep new leash which has far distance alive (Tick)", "当距离过远时,保持新建拴绳不掉落的时间 (刻)", "儅距離過遠時,保持其不掉落的時間(刻)", false),
|
||||
;
|
||||
private final Supplier<?> supplier;
|
||||
private String key;
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
package com.r3944realms.leashedplayer.datagen.provider;
|
||||
|
||||
|
||||
import com.r3944realms.leashedplayer.LeashedPlayer;
|
||||
import com.r3944realms.leashedplayer.datagen.LanguageAndOtherData.ModLangKeyValue;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.neoforged.neoforge.client.model.generators.ItemModelProvider;
|
||||
import net.neoforged.neoforge.client.model.generators.ModelFile;
|
||||
import net.neoforged.neoforge.common.data.ExistingFileHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -31,6 +34,18 @@ public class ModItemModelProvider extends ItemModelProvider {
|
|||
}
|
||||
private void AdvancedModItemModelRegister() {
|
||||
/*手动生成更快,其实*/
|
||||
getBuilder("crossbow_leash_rope_arrow")
|
||||
.parent(new ModelFile.UncheckedModelFile("item/crossbow"))
|
||||
.texture("layer0", ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "item/crossbow_leash_rope_arrow"));
|
||||
getBuilder("bow_lra_pulling_0")
|
||||
.parent(new ModelFile.UncheckedModelFile("item/bow"))
|
||||
.texture("layer0", ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "item/bow_lra_pulling_0"));
|
||||
getBuilder("bow_lra_pulling_1")
|
||||
.parent(new ModelFile.UncheckedModelFile("item/bow"))
|
||||
.texture("layer0", ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "item/bow_lra_pulling_1"));
|
||||
getBuilder("bow_lra_pulling_2")
|
||||
.parent(new ModelFile.UncheckedModelFile("item/bow"))
|
||||
.texture("layer0", ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "item/bow_lra_pulling_2"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -3,7 +3,10 @@ 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.data.recipes.RecipeCategory;
|
||||
import net.minecraft.data.recipes.RecipeOutput;
|
||||
import net.minecraft.data.recipes.RecipeProvider;
|
||||
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
|
||||
import net.minecraft.world.item.Items;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||
|
||||
@Mixin(LivingEntity.class)
|
||||
public abstract class MixinLivingEntity extends Entity implements ILivingEntityExtension {
|
||||
@Unique
|
||||
protected int Pl$LeashKeepTick;//保存状态,当超过断裂绳长时若LeashKeepTick大于0,则不断裂
|
||||
|
||||
public MixinLivingEntity(EntityType<?> pEntityType, Level pLevel) {
|
||||
super(pEntityType, pLevel);
|
||||
}
|
||||
|
|
@ -35,6 +38,17 @@ public abstract class MixinLivingEntity extends Entity implements ILivingEntityE
|
|||
this.entityData.set(DATA_ENTITY_LEASH_LENGTH, length);
|
||||
}
|
||||
|
||||
@SuppressWarnings("AddedMixinMembersNamePattern")
|
||||
@Override
|
||||
public void setKeepLeashTick(int keepTick) {
|
||||
this.Pl$LeashKeepTick = Math.max(keepTick, 0);
|
||||
}
|
||||
@SuppressWarnings("AddedMixinMembersNamePattern")
|
||||
@Override
|
||||
public int getKeepLeashTick() {
|
||||
return this.Pl$LeashKeepTick;
|
||||
}
|
||||
|
||||
@Inject(method = {"defineSynchedData"}, at = {@At("TAIL")})
|
||||
//定义Client/Server实体同步数据
|
||||
private void defineSyncData(SynchedEntityData.Builder pBuilder, CallbackInfo ci) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
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;
|
||||
|
|
@ -11,12 +10,10 @@ 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;
|
||||
|
|
@ -28,7 +25,6 @@ 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)
|
||||
|
|
@ -37,6 +33,7 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl
|
|||
@Nullable
|
||||
private LeashData Pl$LeashData;//Data
|
||||
|
||||
|
||||
@SuppressWarnings("WrongEntityDataParameterClass")
|
||||
@Unique//客户端与服务器端的实体同步数据
|
||||
private static final EntityDataAccessor<CompoundTag> Pl$LEASH_DATA = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG);
|
||||
|
|
@ -146,8 +143,10 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl
|
|||
}
|
||||
@Unique
|
||||
protected void Pl$tickLeash() {
|
||||
|
||||
if(this.Pl$LeashData == null) return;//没有Data直接退出
|
||||
ILivingEntityExtension self = (ILivingEntityExtension) this;
|
||||
int keepLeashTick = self.getKeepLeashTick();
|
||||
|
||||
//info -> Holder整理
|
||||
Pl$RestoreLeashFormSave();
|
||||
//默认值设为
|
||||
|
|
@ -155,27 +154,27 @@ public abstract class MixinPlayer extends LivingEntity implements PlayerLeashabl
|
|||
Entity entity = this.Pl$LeashData.leashHolder;
|
||||
//保存数据
|
||||
saveLeashData(Pl$LeashData);
|
||||
if(this instanceof ILivingEntityExtension iEntityExtension) {
|
||||
//获取设定值
|
||||
float leashLengthSelf = iEntityExtension.getLeashLength();
|
||||
leashLength = leashLengthSelf > LeashCommand.MIN_VALUE ? leashLengthSelf : LeashCommand.MIN_VALUE;
|
||||
}
|
||||
ILivingEntityExtension iEntityExtension = (ILivingEntityExtension) this;//获取设定值
|
||||
float leashLengthSelf = iEntityExtension.getLeashLength();
|
||||
leashLength = leashLengthSelf > LeashCommand.MIN_VALUE ? leashLengthSelf : LeashCommand.MIN_VALUE;
|
||||
if (entity != null) {
|
||||
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格) ,
|
||||
if(!isAlive() || !entity.isAlive() ||( distanceTo(entity) > Math.max(leashLength * breakDistanceTime, LeashCommand.MIN_VALUE * breakDistanceTime) && keepLeashTick == 0)){
|
||||
//玩家死亡 或 持有者不存在 或 距离大于设定值的 breakDistanceTime 倍且keepTick <=0(长度的 breakDistanceTime 倍若低于 LeashCommand.MIN_VALUE 格,则选 LeashCommand.MIN_VALUE 格) ,
|
||||
// 则取消拴绳关系,并掉落拴绳
|
||||
boolean shouldDrop = !(entity instanceof LeashRopeArrow);
|
||||
dropLeash(true, shouldDrop);
|
||||
} else if(distanceTo(entity) > leashLength * 0.65f * breakDistanceTime && entity.onGround()) {
|
||||
//大于1.3倍绳长则会让其跳跃(在<1.25格阻拦情况下,跳跃阻拦//TODO:待擴展
|
||||
//大于eashLength * 0.65f * breakDistanceTime 倍绳长且在地面则会让其跳跃(在<1.25格阻拦情况下,跳跃阻拦//TODO:待擴展
|
||||
Entity applyMovementEntity = this.isPassenger() ? this.getVehicle() : this;
|
||||
if(applyMovementEntity instanceof LivingEntity applyMovementLivingEntity) {
|
||||
applyMovementLivingEntity.jumpFromGround();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if(keepLeashTick > 0) {//keepTick--
|
||||
self.setKeepLeashTick(keepLeashTick - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
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 {
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@ 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;
|
||||
|
|
@ -115,7 +114,7 @@ public abstract class MixinLevelRenderer {
|
|||
}
|
||||
if (holder != null) {
|
||||
if(holder instanceof LeashRopeArrow) {
|
||||
playerRendererExtension.renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, holder, new Vec3(0.,-0.09, 0));//TODO: 待擴展Vec3
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ public abstract class MixinPlayerRenderer extends LivingEntityRenderer<AbstractC
|
|||
}
|
||||
if (holder != null) {
|
||||
if(holder instanceof LeashRopeArrow) {
|
||||
renderLeash(pEntity, pPartialTicks, pPoseStack, pBuffer, holder, new Vec3(0,-0.09, 0));//TODO: 待擴展Vec3
|
||||
renderLeash(pEntity, pPartialTicks, pPoseStack, pBuffer, holder, new Vec3(0,0, 0));//TODO: 待擴展Vec3
|
||||
}
|
||||
else renderLeash(pEntity, pPartialTicks, pPoseStack, pBuffer, holder);
|
||||
}
|
||||
|
|
@ -232,11 +232,13 @@ public abstract class MixinPlayerRenderer extends LivingEntityRenderer<AbstractC
|
|||
|
||||
poseStack.popPose();
|
||||
}
|
||||
@SuppressWarnings("AddedMixinMembersNamePattern")
|
||||
@Unique
|
||||
protected <E extends Entity> 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);
|
||||
Vec3 vec31 = pEntity.getLeashOffset(pPartialTick).add(0, -0.2, -0.2);//TODO:待擴展Vec3);
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ package com.r3944realms.leashedplayer.mixin.item;
|
|||
|
||||
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.InteractionResult;
|
||||
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;
|
||||
|
|
@ -36,13 +39,17 @@ public class MixinLeadItem {
|
|||
//非创造模式减少,防止刷物品
|
||||
if(!pPlayer.isCreative()) mainHandItem.shrink(1);
|
||||
//自己
|
||||
PlayerLeashable self = (PlayerLeashable) pPlayer;
|
||||
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) pPlayer, (ServerLevel) pLevel);
|
||||
PlayerLeashable playerLeashable = (PlayerLeashable) pPlayer;
|
||||
if(leashDataEntity != null) {
|
||||
playerLeashable.dropLeash(true, true);
|
||||
}
|
||||
//获取拴绳结实体
|
||||
LeashFenceKnotEntity leashfenceknotentity = LeashFenceKnotEntity.getOrCreateKnot(pLevel, pPos);
|
||||
//播放绳结被放置的声音
|
||||
leashfenceknotentity.playPlacementSound();
|
||||
//将自己与拴绳结绑定LeashData
|
||||
self.setLeashedTo(leashfenceknotentity, true);
|
||||
playerLeashable.setLeashedTo(leashfenceknotentity, true);
|
||||
pLevel.gameEvent(GameEvent.BLOCK_ATTACH, pPos, GameEvent.Context.of(pPlayer));
|
||||
cir.setReturnValue(InteractionResult.SUCCESS);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package com.r3944realms.leashedplayer.mixin.server;
|
|||
import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry;
|
||||
import com.r3944realms.leashedplayer.content.gamerules.Server.TeleportWithLeashedPlayers;
|
||||
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
|
||||
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
|
@ -17,6 +16,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static com.r3944realms.leashedplayer.utils.Logger.logger;
|
||||
@Mixin(ServerGamePacketListenerImpl.class)
|
||||
public class MixinServerGamePacketListenerImpl {
|
||||
|
|
|
|||
|
|
@ -12,4 +12,17 @@ public interface ILivingEntityExtension {
|
|||
* @param length 拴绳的长度(Float)
|
||||
*/
|
||||
void setLeashLength(float length);
|
||||
|
||||
/**
|
||||
* 设置超出断裂长度后等待时间,如果时间到仍超出则会执行断裂操作
|
||||
* @apiNote 该为服务器方法,只能在服务器端调用,切勿在客户端线程调用
|
||||
* @param keepTick 等待tick(int)
|
||||
*/
|
||||
void setKeepLeashTick(int keepTick);
|
||||
/**
|
||||
* 获取超出断裂长度后等待时间,如果时间到仍超出则会执行断裂操作
|
||||
* @apiNote 该为服务器方法,只能在服务器端调用,切勿在客户端线程调用
|
||||
* @return keepTick 等待tick(int)
|
||||
*/
|
||||
int getKeepLeashTick();
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 260 B After Width: | Height: | Size: 259 B |
|
After Width: | Height: | Size: 368 B |
|
After Width: | Height: | Size: 388 B |
|
After Width: | Height: | Size: 412 B |
|
After Width: | Height: | Size: 475 B |
|
Before Width: | Height: | Size: 268 B After Width: | Height: | Size: 243 B |
70
src/main/resources/assets/minecraft/models/item/bow.json
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "minecraft:item/bow"
|
||||
},
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [ -80, 260, -40 ],
|
||||
"translation": [ -1, -2, 2.5 ],
|
||||
"scale": [ 0.9, 0.9, 0.9 ]
|
||||
},
|
||||
"thirdperson_lefthand": {
|
||||
"rotation": [ -80, -280, 40 ],
|
||||
"translation": [ -1, -2, 2.5 ],
|
||||
"scale": [ 0.9, 0.9, 0.9 ]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [ 0, -90, 25 ],
|
||||
"translation": [ 1.13, 3.2, 1.13],
|
||||
"scale": [ 0.68, 0.68, 0.68 ]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [ 0, 90, -25 ],
|
||||
"translation": [ 1.13, 3.2, 1.13],
|
||||
"scale": [ 0.68, 0.68, 0.68 ]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"predicate": {
|
||||
"pulling": 1
|
||||
},
|
||||
"model": "minecraft:item/bow_pulling_0"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"pulling": 1,
|
||||
"pull": 0.65
|
||||
},
|
||||
"model": "minecraft:item/bow_pulling_1"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"pulling": 1,
|
||||
"pull": 0.9
|
||||
},
|
||||
"model": "minecraft:item/bow_pulling_2"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"leash_rope_arrow_pulling": 1
|
||||
},
|
||||
"model": "leashedplayer:item/bow_lra_pulling_0"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"leash_rope_arrow_pulling": 1,
|
||||
"pull": 0.65
|
||||
},
|
||||
"model": "leashedplayer:item/bow_lra_pulling_1"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"leash_rope_arrow_pulling": 1,
|
||||
"pull": 0.9
|
||||
},
|
||||
"model": "leashedplayer:item/bow_lra_pulling_2"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
{
|
||||
"parent": "minecraft:item/generated",
|
||||
"textures": {
|
||||
"layer0": "minecraft:item/crossbow_standby"
|
||||
},
|
||||
"display": {
|
||||
"thirdperson_righthand": {
|
||||
"rotation": [ -90, 0, -60 ],
|
||||
"translation": [ 2, 0.1, -3 ],
|
||||
"scale": [ 0.9, 0.9, 0.9 ]
|
||||
},
|
||||
"thirdperson_lefthand": {
|
||||
"rotation": [ -90, 0, 30 ],
|
||||
"translation": [ 2, 0.1, -3 ],
|
||||
"scale": [ 0.9, 0.9, 0.9 ]
|
||||
},
|
||||
"firstperson_righthand": {
|
||||
"rotation": [ -90, 0, -55 ],
|
||||
"translation": [ 1.13, 3.2, 1.13],
|
||||
"scale": [ 0.68, 0.68, 0.68 ]
|
||||
},
|
||||
"firstperson_lefthand": {
|
||||
"rotation": [ -90, 0, 35 ],
|
||||
"translation": [ 1.13, 3.2, 1.13],
|
||||
"scale": [ 0.68, 0.68, 0.68 ]
|
||||
}
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"predicate": {
|
||||
"pulling": 1
|
||||
},
|
||||
"model": "minecraft:item/crossbow_pulling_0"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"pulling": 1,
|
||||
"pull": 0.58
|
||||
},
|
||||
"model": "minecraft:item/crossbow_pulling_1"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"pulling": 1,
|
||||
"pull": 1.0
|
||||
},
|
||||
"model": "minecraft:item/crossbow_pulling_2"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"charged": 1
|
||||
},
|
||||
"model": "minecraft:item/crossbow_arrow"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"charged": 1,
|
||||
"firework": 1
|
||||
},
|
||||
"model": "minecraft:item/crossbow_firework"
|
||||
},
|
||||
{
|
||||
"predicate": {
|
||||
"charged": 1,
|
||||
"leash_rope_arrow": 1
|
||||
},
|
||||
"model": "leashedplayer:item/crossbow_leash_rope_arrow"
|
||||
}
|
||||
]
|
||||
}
|
||||