package com.r3944realms.leashedplayer.content.entities; import com.r3944realms.leashedplayer.config.LeashPlayerCommonConfig; import com.r3944realms.leashedplayer.content.effects.ModEffectRegister; import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry; import com.r3944realms.leashedplayer.content.gamerules.Server.KeepLeashNotDropTime; 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; import net.minecraft.tags.BlockTags; import net.minecraft.world.effect.MobEffectInstance; 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.decoration.LeashFenceKnotEntity; 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 { private static final int maxLifeTime = LeashPlayerCommonConfig.TheLeashArrowMaxLifeTime.get(); protected LeashRopeArrow(EntityType entityType,Level pLevel) { super(entityType, pLevel); } public LeashRopeArrow(EntityType 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) { Entity leashDataEntity = PlayerLeashable.getLeashDataEntity(serverPlayer, (ServerLevel) level()); if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) { leashRopeArrow.setOwner(null); } ((PlayerLeashable)serverPlayer).setLeashedTo(this, true); } } public LeashRopeArrow(EntityType entityType, LivingEntity pOwner, Level pLevel, ItemStack pPickupItemStack, @Nullable ItemStack pFiredFromWeapon) { super(entityType, pOwner, pLevel, pPickupItemStack, pFiredFromWeapon); if(pOwner instanceof PlayerLeashable lPlayer && !level().isClientSide) { Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) lPlayer, (ServerLevel) level()); if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) { leashRopeArrow.setOwner(null); } 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); 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 boolean tryPickup(@NotNull Player pPlayer) { //时间1.40 禁止 //时间2.240 // 如果(非仅创造拾取) // 如果 (按Shift ) // 如果(拥有者) -> 拾取到完整箭,取消绑定(super给父类处理) // 否则:时间仍为原需时间 ->不能获取完整的箭,重绑定(当前拥有者的Holder是否为本箭,“是”才重绑定) // 否则: 禁止 // 否则: // 如果 (按Shift ) // 如果(拥有者) -> 且拾取到完整箭,取消绑定 // 否则:时间仍为原需时间 ->不能获取完整的箭,重绑定 // 否则: 禁止 //时间3 // 如果(拥有者) -> 拾取到完整箭,取消绑定 // 否则:不能获取完整的箭,重绑定 if(life <= 40 ) { return false; } else { PlayerLeashable playerLeashable = (PlayerLeashable) pPlayer; if(this.getOwner() == null) {//未有Owner始终可检 return true; } if(life <= 240) { if(pPlayer.isShiftKeyDown()) { Entity leashDataEntity = this.getOwner() instanceof PlayerLeashable ? PlayerLeashable.getLeashDataEntity((ServerPlayer) this.getOwner(), (ServerLevel) level()) : this.getOwner(); 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)) { if(owner instanceof PlayerLeashable player) { player.setLeashedTo(pPlayer, true); } else if(owner instanceof Leashable leashable) { leashable.setLeashedTo(pPlayer, true); } ItemEntity itemEntity = new ItemEntity(level(), getX(), getY(), getZ(), getOrginalItemStack()); level().addFreshEntity(itemEntity); discard(); // } } else return true; } else return false; } } else return false; } else { Entity leashDataEntity = this.getOwner() instanceof PlayerLeashable ? PlayerLeashable.getLeashDataEntity((ServerPlayer) this.getOwner(), (ServerLevel) level()) : this.getOwner(); if(this.ownedBy(pPlayer)) { this.pickup = Pickup.ALLOWED; if(this.equals(leashDataEntity)) playerLeashable.dropLeash(true, false); } else { Entity owner = getOwner(); if(owner instanceof PlayerLeashable player) { player.setLeashedTo(pPlayer, true); } else if(owner instanceof Leashable leashable) { leashable.setLeashedTo(pPlayer, true); } ItemEntity itemEntity = new ItemEntity(level(), getX(), getY(), getZ(), getOrginalItemStack()); level().addFreshEntity(itemEntity); discard(); } } } return super.tryPickup(pPlayer); } protected void hitOnEntityHandler(Entity pEntity) { //NOOP } protected ItemStack getOrginalItemStack() { return Items.ARROW.getDefaultInstance(); } protected ItemStack getSelfItemStack() { return ModItemRegister.LEASH_ROPE_ARROW.get().getDefaultInstance(); } @Override protected void tickDespawn() { this.life++; if (this.life >= maxLifeTime) { ItemEntity leash_rope_arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack()); 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, !(leashDataEntity instanceof LeashRopeArrow)); if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) { leashRopeArrow.setOwner(null); } } 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, getOrginalItemStack()); this.level().addFreshEntity(arrow); discard(); } } else if(getOwner() instanceof Leashable L) { if (this.level().getBlockState(pResult.getBlockPos()).is(BlockTags.FENCES)) { Entity leashDataEntity = this.getOwner(); if(leashDataEntity != null) { L.dropLeash(true, false); if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) { leashRopeArrow.setOwner(null); } } Entity leashKnotFence = LeashFenceKnotEntity.getOrCreateKnot(this.level(), pResult.getBlockPos()); L.setLeashedTo(leashKnotFence, true); ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack()); this.level().addFreshEntity(arrow); discard(); } } } super.onHitBlock(pResult); } @Override protected void onHitEntity(@NotNull EntityHitResult pResult) { if(!level().isClientSide()){ Entity entity = pResult.getEntity(); hitOnEntityHandler(entity); if(this.getOwner() instanceof LivingEntity livingEntity ) { MobEffectInstance effect = livingEntity.getEffect(ModEffectRegister.NO_LEASH_EFFECT); if(effect != null && effect.getDuration() > 0) { this.setOwner(null); } } if(entity instanceof LivingEntity livingEntity) { if(livingEntity.equals(this.getOwner())) return; if(this.getOwner() == null && livingEntity instanceof PlayerLeashable pL) { //发射器发出或命令生成 setOwner(livingEntity); Entity leashDataEntity = PlayerLeashable.getLeashDataEntity((ServerPlayer) getOwner(), (ServerLevel) level()); if(leashDataEntity != null) { pL.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow)); if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) { leashRopeArrow.setOwner(null); } } ILivingEntityExtension pLL = (ILivingEntityExtension) pL; pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID)); 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) { leashRopeArrow.setOwner(null); } } ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack()); 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 Leashable leashable) { if (getOwner() == null) { Entity leashDataEntity = leashable.getLeashHolder(); if (leashDataEntity != null) { leashable.dropLeash(true, !(leashDataEntity instanceof LeashRopeArrow)); if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) { leashRopeArrow.setOwner(null); } } leashable.setLeashedTo(this, true); this.setOwner(entity); return; } } if(entity instanceof LivingEntity living) { if(this.getOwner() != null && this.getOwner()instanceof Leashable leashable) { leashable.setLeashedTo(living, true); ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack()); this.level().addFreshEntity(arrow); discard(); return; } } ItemEntity lead = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, Items.LEAD.getDefaultInstance()); this.level().addFreshEntity(lead); } } 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); if(leashDataEntity instanceof LeashRopeArrow leashRopeArrow) { leashRopeArrow.setOwner(null); } } ItemEntity arrow = new ItemEntity(this.level(), this.position().x, this.position().y, this.position().z, getOrginalItemStack()); ILivingEntityExtension pLL = (ILivingEntityExtension) pL; pLL.setKeepLeashTick(GameruleRegistry.getGameruleIntValue(level(), KeepLeashNotDropTime.ID)); 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); } }