2024/12/07

实装了贴贴拴绳箭的内容
整理了下代码结构
先推测试
This commit is contained in:
叁玖领域 2024-12-07 13:33:39 +08:00
parent e615fc6f09
commit f10221a2c0
11 changed files with 291 additions and 133 deletions

View File

@ -35,7 +35,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=MIT
# The mod version. See https://semver.org/
mod_version=0.0.3.9.9.8
mod_version=0.0.3.9.9.9
# 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

View File

@ -2,16 +2,13 @@ package com.r3944realms.leashedplayer;
import com.mojang.brigadier.CommandDispatcher;
import com.r3944realms.leashedplayer.content.commands.*;
import com.r3944realms.leashedplayer.content.effects.ModEffectRegister;
import com.r3944realms.leashedplayer.content.effects.ModPotionRegister;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import com.r3944realms.leashedplayer.content.entities.LittlePlayer;
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry;
import com.r3944realms.leashedplayer.content.gamerules.Server.OpenTOPNeededModeWhenScreenIsNotNull;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.content.misc.LeadBreakItemBehavior;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import com.r3944realms.leashedplayer.network.client.BooleanGameRuleValueChangeData;
import com.r3944realms.leashedplayer.utils.Logger;
import com.r3944realms.leashedplayer.utils.Util;
@ -22,11 +19,8 @@ import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.Leashable;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.animal.Fox;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
@ -102,23 +96,6 @@ public class CommonEventHandler {
if (level.isClientSide()) {
return;
}
if (entity instanceof LivingEntity living) {
MobEffectInstance effect = living.getEffect(ModEffectRegister.NO_LEASH_EFFECT);
if (effect != null && effect.getDuration() != 0) {
if (entity instanceof PlayerLeashable player) {
if (player.getLeashHolder() != null) {
if (player.getLeashHolder() instanceof LeashRopeArrow arrow)
arrow.setOwner(null);
player.dropLeash(true, !(player.getLeashHolder() instanceof LeashRopeArrow));
}
} else if (entity instanceof Leashable leashable) {
if (leashable.getLeashHolder() != null) {
if (leashable.getLeashHolder() instanceof LeashRopeArrow arrow)
arrow.setOwner(null);
leashable.dropLeash(true, !(leashable.getLeashHolder() instanceof LeashRopeArrow));
}
}
}
if (entity instanceof Fox fox) {
if (fox.getMainHandItem().is(ItemTags.ANVIL)) {
fox.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
@ -175,6 +152,6 @@ public class CommonEventHandler {
}
}
}

View File

@ -7,7 +7,7 @@ public class LeashPlayerCommonConfig {
public static final ModConfigSpec SPEC;
public static final ModConfigSpec.ConfigValue<String> LeashedPlayerModCommandPrefix;
public static final ModConfigSpec.BooleanValue EnableLeashPlayerCommandPrefix;
public static ModConfigSpec.IntValue MinimumLeashLengthCanBeSet, MaximumLeashLengthCanBeSet, TheLeashArrowMaxLifeTime;
public static ModConfigSpec.IntValue MinimumLeashLengthCanBeSet, MaximumLeashLengthCanBeSet, TheLeashArrowMaxLifeTime, TheNestleArrowMaxLifeTime;
public static ModConfigSpec.DoubleValue TheMultipleThatLeashRopeArrowBreakLength, TheLeashBreakLengthTimesBase;
static {
BUILDER.comment("Leash Player Config");
@ -20,8 +20,9 @@ public class LeashPlayerCommonConfig {
BUILDER.pop();
BUILDER.comment("Leash Player Arrow");
BUILDER.push("LeashRopeArrow");
TheMultipleThatLeashRopeArrowBreakLength = BUILDER.comment("How many times is the length of the arrow rope based on BreakLength TimeBase", "[ Default : 5.0f, Invalid Range:[2.0f, 10.0f] ]").defineInRange("TheMultipleArrowBreak", 5.0f, 2.0f , 10.0f);
TheMultipleThatLeashRopeArrowBreakLength = BUILDER.comment("How many times is the length of the arrow rope based on BreakLength TimeBase", "[ Default : 5.0f, Invalid Range:[2.0f, 10.0f] ]").defineInRange("TheMultipleArrowBreak", 5.0f, 2.0f, 10.0f);
TheLeashArrowMaxLifeTime = BUILDER.comment("If the LeashArrowEntity's life is bigger than this value ,it will be discarded", "[ Default : 2400, Invalid Range:[1200 , 10240]]").defineInRange("TheLeashArrowMaxLifeTime",2400, 1200, 10240);
TheNestleArrowMaxLifeTime = BUILDER.comment("If the NestleArrowEntity's life is bigger than this value ,it will be discarded\", \"[ Default : 2400, Invalid Range:[1200 , 10240]]").defineInRange("TheNestleArrowMaxLifeTime",2400, 1200, 10240);
BUILDER.pop();
BUILDER.comment("Leash Player Misc");
BUILDER.push("Misc");

View File

@ -1,6 +1,7 @@
package com.r3944realms.leashedplayer.content.effects;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.effects.type.NoLeashEffect;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
@ -12,9 +13,9 @@ import java.util.function.Supplier;
public class ModEffectRegister {
public static DeferredRegister<MobEffect> MOB_EFFECT = DeferredRegister.create(Registries.MOB_EFFECT, LeashedPlayer.MOD_ID);
public static DeferredHolder<MobEffect, ? extends MobEffect> NO_LEASH_EFFECT = register(
public static DeferredHolder<MobEffect, NoLeashEffect> NO_LEASH_EFFECT = register(
"no_leash",
() -> new MobEffect(MobEffectCategory.NEUTRAL, 12063764)
() -> new NoLeashEffect(MobEffectCategory.NEUTRAL, 12063764)
);
public static <T extends MobEffect>DeferredHolder<MobEffect, T> register(String name, Supplier<T> effect) {
return MOB_EFFECT.register(name, effect);

View File

@ -0,0 +1,37 @@
package com.r3944realms.leashedplayer.content.effects.type;
import com.r3944realms.leashedplayer.content.effects.ModEffectRegister;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Leashable;
import net.minecraft.world.entity.LivingEntity;
import org.jetbrains.annotations.NotNull;
public class NoLeashEffect extends MobEffect {
public NoLeashEffect(MobEffectCategory pCategory, int pColor) {
super(pCategory, pColor);
}
@Override
public boolean applyEffectTick(@NotNull LivingEntity pLivingEntity, int pAmplifier) {
MobEffectInstance effect = pLivingEntity.getEffect(ModEffectRegister.NO_LEASH_EFFECT);
if(effect != null && effect.getDuration() != 0) {
if (pLivingEntity instanceof Leashable leashable) {
if (leashable.getLeashHolder() instanceof LeashRopeArrow arrow) {
arrow.setOwner(null);
leashable.dropLeash(true, false);
}
leashable.dropLeash(true, true);
}
}
return true;
}
@Override
public boolean shouldApplyEffectTickThisTick(int pDuration, int pAmplifier) {
return true;
}
}

View File

@ -84,7 +84,7 @@ public class LeashRopeArrow extends AbstractArrow {
if(serverPlayer != null && !level().isClientSide) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity(serverPlayer, (ServerLevel) level());
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);
leashRopeArrow.setOwner(null);//将先前的箭矢置空
}
((PlayerLeashable)serverPlayer).setLeashedTo(this, true);
}
@ -93,7 +93,7 @@ public class LeashRopeArrow extends AbstractArrow {
public LeashRopeArrow(EntityType<? extends AbstractArrow> entityType, LivingEntity pOwner, Level pLevel, ItemStack pPickupItemStack, @Nullable ItemStack pFiredFromWeapon) {
super(entityType, pOwner, pLevel, pPickupItemStack, pFiredFromWeapon);
this.updateColor();
if(pOwner instanceof PlayerLeashable lPlayer && !level().isClientSide) {
if (pOwner instanceof PlayerLeashable lPlayer && !level().isClientSide) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) lPlayer, (ServerLevel) level());
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.setOwner(null);
@ -225,7 +225,6 @@ public class LeashRopeArrow extends AbstractArrow {
pLiving.addEffect(effectInstance, entity);
}
}
//NOOP
}
protected ItemStack getOrginalItemStack() {
return Items.ARROW.getDefaultInstance();
@ -330,12 +329,12 @@ public class LeashRopeArrow extends AbstractArrow {
@Override
protected void onHitEntity(@NotNull EntityHitResult pResult) {
if(!level().isClientSide()){
if (!level().isClientSide()) {
Entity entity = pResult.getEntity();
hitOnEntityHandler(entity);
if(this.getOwner() instanceof LivingEntity livingEntity ) {
if (this.getOwner() instanceof LivingEntity livingEntity ) {
MobEffectInstance effect = livingEntity.getEffect(ModEffectRegister.NO_LEASH_EFFECT);
if(effect != null && effect.getDuration() != 0) {
if (effect != null && effect.getDuration() != 0) {
livingEntity.playSound(SoundEvents.LEASH_KNOT_BREAK, 1, 1);
this.setOwner(null);
}
@ -356,12 +355,11 @@ public class LeashRopeArrow extends AbstractArrow {
pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID));
livingEntity.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
pL.setLeashedTo(this, true);
return;
} else if (this.getOwner() instanceof PlayerLeashable pL) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
if(leashDataEntity != null) {
pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
if (leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.playSound(SoundEvents.LEASH_KNOT_BREAK, 1, 1);
leashRopeArrow.setOwner(null);
}
@ -374,12 +372,12 @@ public class LeashRopeArrow extends AbstractArrow {
this.level().addFreshEntity(arrow);
discard();
} else {
if(entity instanceof Leashable leashable) {
if (entity instanceof Leashable leashable) {
if (getOwner() == null) {
Entity leashDataEntity = leashable.getLeashHolder();
if (leashDataEntity != null) {
leashable.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow));
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
if (leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.playSound(SoundEvents.LEASH_KNOT_BREAK, 1, 1);
leashRopeArrow.setOwner(null);
}
@ -390,8 +388,8 @@ public class LeashRopeArrow extends AbstractArrow {
return;
}
}
if(entity instanceof LivingEntity living) {
if(this.getOwner() != null && this.getOwner()instanceof Leashable leashable) {
if (entity instanceof LivingEntity living) {
if (this.getOwner() != null && this.getOwner()instanceof Leashable leashable) {
livingEntity.playSound(SoundEvents.LEASH_KNOT_PLACE, 1, 1);
leashable.setLeashedTo(living, true);
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
@ -407,9 +405,9 @@ public class LeashRopeArrow extends AbstractArrow {
else if (entity instanceof LeashFenceKnotEntity leashKnotFence) {
if (getOwner() instanceof PlayerLeashable pL) {
Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level());
if(leashDataEntity != null) {
if (leashDataEntity != null) {
pL.dropLeash(true, true);
if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
if (leashDataEntity instanceof LeashRopeArrow leashRopeArrow) {
leashRopeArrow.playSound(SoundEvents.LEASH_KNOT_BREAK, 1, 1);
leashRopeArrow.setOwner(null);
}
@ -421,14 +419,13 @@ public class LeashRopeArrow extends AbstractArrow {
pL.setLeashedTo(leashKnotFence, true);
this.level().addFreshEntity(arrow);
discard();
return;
}
} else {
ItemEntity lead = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, Items.LEAD.getDefaultInstance());
this.level().addFreshEntity(lead);
}
}
if(!level().isClientSide()) super.onHitEntity(pResult);
else super.onHitEntity(pResult);
}
/**
* Handles an entity event received from a {@link net.minecraft.network.protocol.game.ClientboundEntityEventPacket}.

View File

@ -1,29 +1,151 @@
package com.r3944realms.leashedplayer.content.entities;
import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import io.github.kunosayo.nestle.entity.NestleLeadNormalEntity;
import io.github.kunosayo.nestle.entity.NestleLeadPlayerEntity;
import io.github.kunosayo.nestle.entity.data.NestleLeadData;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.MobSpawnType;
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.EntityHitResult;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class NestleRopeArrow extends AbstractArrow {
public NestleRopeArrow(EntityType<? extends AbstractArrow> pEntityType, Level pLevel) {
private static final int maxLifeTime = LeashPlayerCommonConfig.TheNestleArrowMaxLifeTime.get();
protected NestleRopeArrow(EntityType<? extends AbstractArrow> pEntityType, Level pLevel) {
super(pEntityType, pLevel);
}
public NestleRopeArrow(EntityType<? extends AbstractArrow> entityType, double pX, double pY, double pZ, Level pLevel, ItemStack pPickupItemStack, @Nullable ItemStack pFiredFromWeapon, @Nullable ServerPlayer serverPlayer) {
super(entityType, pX, pY, pZ, pLevel, pPickupItemStack, pFiredFromWeapon);
if (serverPlayer != null && !level().isClientSide) {
if(serverPlayer.getVehicle() instanceof NestleRopeArrow nestleRopeArrow) {
nestleRopeArrow.removePassenger(serverPlayer);//重置先前的箭矢
nestleRopeArrow.setOwner(null);
}
serverPlayer.startRiding(this);
this.setOwner(serverPlayer);
}
}
public NestleRopeArrow(EntityType<? extends AbstractArrow> entityType, LivingEntity pOwner, Level pLevel, ItemStack pPickupItemStack, @Nullable ItemStack pFiredFromWeapon) {
super(entityType, pOwner, pLevel, pPickupItemStack, pFiredFromWeapon);
if (!level().isClientSide) {
if(pOwner.getVehicle() instanceof NestleRopeArrow nestleRopeArrow) {
nestleRopeArrow.removePassenger(pOwner);//重置先前的箭矢
nestleRopeArrow.setOwner(null);
}
pOwner.startRiding(this);
this.setOwner(pOwner);
}
}
@Override
protected @NotNull ItemStack getDefaultPickupItem() {
return ModItemRegister.NESTLE_ROPE_ARROW.get().getDefaultInstance();
}
protected ItemStack getOrginalItemStack() {
return Items.ARROW.getDefaultInstance();
}
protected ItemStack getSelfItemStack() {
return ModItemRegister.NESTLE_ROPE_ARROW.get().getDefaultInstance();
}
protected void hitOnEntityHandler(Entity pEntity) {
//NOOP
}
@Override
public void setOwner(@Nullable Entity pEntity) {
boolean isNull = pEntity == null;
this.ownerUUID = isNull ? null : pEntity.getUUID();
this.cachedOwner = isNull ? null : pEntity;
this.pickup = this.pickup == Pickup.CREATIVE_ONLY ? this.pickup : Pickup.DISALLOWED;
}
@Override
protected void tickDespawn() {
this.life++;
if (this.life >= maxLifeTime) {
ItemEntity nestle_arrow_item = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getSelfItemStack());
this.level().addFreshEntity(nestle_arrow_item);
this.discard();
}
}
@Override
protected boolean tryPickup(@NotNull Player pPlayer) {
if (life <= 40)
return false;
else {
this.pickup = Pickup.ALLOWED;
}
return super.tryPickup(pPlayer);
}
@Override
public void tick() {
super.tick();
Entity owner = getOwner();
if(owner != null && !owner.level().isClientSide) {
if (!inGround) {
if (owner.getVehicle() == null) owner.startRiding(this);
}
else {
owner.stopRiding();
setOwner(null);
}
}
}
@Override
protected void onHitEntity(@NotNull EntityHitResult pResult) {
if(!level().isClientSide) {
Entity entity = pResult.getEntity();
hitOnEntityHandler(entity);
Entity owner = this.getOwner();
if (owner == null && entity instanceof Player player) {
this.setOwner(player);
}
else if (owner != null && entity != owner ) {
if(entity instanceof LivingEntity livingEntity) {
ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack());
if (livingEntity instanceof Player player) {
if (NestleLeadData.isNestle(player, livingEntity)) {
arrow.setItem(getSelfItemStack());
} else {
NestleLeadData.nestleTwo((Player) owner, player);
NestleLeadPlayerEntity.inParamFrom = player.getUUID();
NestleLeadPlayerEntity.inParamTarget = entity.getUUID();
NestleLeadPlayerEntity.ENTITY_TYPE.spawn((ServerLevel)player.level(), player.getBlockPosBelowThatAffectsMyMovement(), MobSpawnType.EVENT);
}
} else {
Player player = (Player) owner;
if (NestleLeadData.isNestle(player, livingEntity)) {
arrow.setItem(getSelfItemStack());
} else {
NestleLeadData.nestleTwo(player, livingEntity);
NestleLeadNormalEntity.inParamFrom = player;
NestleLeadNormalEntity.inParamTarget = livingEntity;
NestleLeadNormalEntity.ENTITY_TYPE.spawn((ServerLevel)player.level(), player.getBlockPosBelowThatAffectsMyMovement(), MobSpawnType.EVENT);
NestleLeadNormalEntity.inParamFrom = null;
NestleLeadNormalEntity.inParamTarget = null;
}
}
this.level().addFreshEntity(arrow);
discard();
}
}
}
else super.onHitEntity(pResult);
}
}

View File

@ -1,4 +1,5 @@
package com.r3944realms.leashedplayer.integration.jei.category;
public class LeashedPlayerCategory {
}

View File

@ -2,7 +2,6 @@ package com.r3944realms.leashedplayer.mixin.both;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.commands.LeashCommand;
import com.r3944realms.leashedplayer.content.effects.ModEffectRegister;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
@ -12,7 +11,6 @@ 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.world.effect.MobEffectInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Leashable;
@ -21,7 +19,6 @@ 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;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
@ -30,10 +27,9 @@ 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, ILivingEntityExtension {
public abstract class MixinPlayer extends LivingEntity implements PlayerLeashable, ILivingEntityExtension {
@Unique
protected int Pl$LeashKeepTick;//保存状态当超过断裂绳长时若LeashKeepTick大于0则不断裂
@ -106,87 +102,15 @@ public abstract class
return;
}
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;
});
}
PlayerLeashable.legacyElasticRangeLeashBehaviour(holderEntity, restrainedEntity);
// 降低坠落伤害
restrainedEntity.checkSlowFallDistance();
}
/**
* 刹车
* @param pEntity 刹车的实体
* @param pMaxX X方向的最大动量
* @param pMaxY Y方向的最大动量
* @param pMaxZ Z方向的最大动量
*/
@Unique
private static void Whimsy$Brake(Entity pEntity, double pMaxX, double pMaxY, double pMaxZ) {
Vec3 deltaMovement = pEntity.getDeltaMovement();
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;
}
/**
* 刹车
* @param pEntity 刹车的实体
* @param pOpt 自定义规则
*/
@Unique
private static void Whimsy$Brake(Entity pEntity, @Nullable Consumer<Entity> pOpt) {
Consumer<Entity> consumer = pOpt;
if(pOpt == null) {
consumer = entity -> {
Vec3 deltaMovement = entity.getDeltaMovement();
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;
};
}
consumer.accept(pEntity);
}
@Unique
protected void Pl$tickLeash() {
if(this.Pl$LeashData == null) return;//没有Data直接退出
@ -203,12 +127,6 @@ public abstract class
ILivingEntityExtension iEntityExtension = this;//获取设定值
float leashLengthSelf = iEntityExtension.getLeashLength();
leashLength = leashLengthSelf > LeashCommand.MIN_VALUE ? leashLengthSelf : LeashCommand.MIN_VALUE;
MobEffectInstance effect = this.getEffect(ModEffectRegister.NO_LEASH_EFFECT);
if(effect != null && effect.getDuration() != 0) {
if (entity instanceof LeashRopeArrow arrow)
arrow.setOwner(null);
this.dropLeash(true, !(entity instanceof LeashRopeArrow));
}
if (entity != null) {
double breakDistanceTime = (entity instanceof LeashRopeArrow) ? LeashedPlayer.M1() * LeashedPlayer.M2() : LeashedPlayer.M1();
if(!isAlive() || !entity.isAlive() ||( distanceTo(entity) > Math.max(leashLength * breakDistanceTime, LeashCommand.MIN_VALUE * breakDistanceTime) && keepLeashTick == 0)){

View File

@ -1,6 +1,8 @@
package com.r3944realms.leashedplayer.modInterface;
import com.r3944realms.leashedplayer.content.commands.LeashCommand;
import com.r3944realms.leashedplayer.content.criteriaTriggers.ModCriteriaTriggers;
import com.r3944realms.leashedplayer.utils.Util;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket;
import net.minecraft.server.level.ServerLevel;
@ -10,6 +12,7 @@ import net.minecraft.world.entity.Leashable;
import net.minecraft.world.entity.decoration.LeashFenceKnotEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nullable;
@ -61,6 +64,72 @@ public interface PlayerLeashable extends Leashable {
//这边覆写去掉了乘坐相关的逻辑即乘坐状态下也可以正常被栓住不影响其乘坐状态
}
static void legacyElasticRangeLeashBehaviour(Entity holderEntity, Entity restrainedEntity) {
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) {
MethodA(holderEntity, applyMovementEntity, distance, leashLength);
// 控制速度不要过快避免偏激移动
Util.MovementBrake(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;
});
}
}
private static void MethodA(Entity holderEntity, Entity applyMovementEntity, float distance, float 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
)
);
}
private static void MethodB(Entity holderEntity, Entity applyMovementEntity, float distance, float leashLength) {
// 计算朝向持有者的拉力方向
double dX = (holderEntity.getX() - applyMovementEntity.getX()) / (double) distance;
double dZ = (holderEntity.getZ() - applyMovementEntity.getZ()) / (double) distance;
// 稳定点的目标高度
double targetY = holderEntity.getY() + 1.0; // 根据需要调整目标高度
double currentY = applyMovementEntity.getY();
double heightDifference = targetY - currentY;
// 控制垂直方向的拉力
double dY = heightDifference > 0.5 ? 0.1 : (heightDifference < -0.5 ? -0.1 : 0);
// 拉力大小距离越远拉力越强但施加一个最大限制
double pullStrength = Math.min((distance - leashLength) * 0.1, 1.0); // 限制最大拉力
applyMovementEntity.setDeltaMovement(
applyMovementEntity.getDeltaMovement().add(
dX * pullStrength,
dY,
dZ * pullStrength
)
);
}
@Nullable
static Entity getLeashDataEntity(@NotNull ServerPlayer serverPlayer , @NotNull ServerLevel serverLevel) {
LeashData leashDataFromEntityData = ((PlayerLeashable) serverPlayer).getLeashDataFromEntityData();

View File

@ -16,6 +16,7 @@ import java.io.File;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import static com.r3944realms.leashedplayer.utils.Logger.logger;
@ -98,4 +99,38 @@ public class Util {
}
else return null;
}
/**
* 刹车
* @param pEntity 刹车的实体
* @param pMaxX X方向的最大动量
* @param pMaxY Y方向的最大动量
* @param pMaxZ Z方向的最大动量
*/
public static void MovementBrake(Entity pEntity, double pMaxX, double pMaxY, double pMaxZ) {
Vec3 deltaMovement = pEntity.getDeltaMovement();
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;
}
/**
* 刹车
* @param pEntity 刹车的实体
* @param pOpt 自定义规则
*/
public static void MovementBrake(Entity pEntity, @javax.annotation.Nullable Consumer<Entity> pOpt) {
Consumer<Entity> consumer = pOpt;
if(pOpt == null) {
consumer = entity -> {
Vec3 deltaMovement = entity.getDeltaMovement();
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;
};
}
consumer.accept(pEntity);
}
}