diff --git a/src/main/java/com/lothrazar/cyclic/block/antipotion/BlockAntiBeacon.java b/src/main/java/com/lothrazar/cyclic/block/antipotion/BlockAntiBeacon.java index 2dd8e32f3..be55e63d5 100644 --- a/src/main/java/com/lothrazar/cyclic/block/antipotion/BlockAntiBeacon.java +++ b/src/main/java/com/lothrazar/cyclic/block/antipotion/BlockAntiBeacon.java @@ -1,15 +1,16 @@ package com.lothrazar.cyclic.block.antipotion; -import java.util.ArrayList; -import java.util.List; import com.lothrazar.cyclic.ModCyclic; import com.lothrazar.cyclic.block.BlockCyclic; +import com.lothrazar.cyclic.capabilities.livingentity.LivingEntityCapProvider; +import com.lothrazar.cyclic.capabilities.livingentity.LivingEntityCapabilityStorage; +import com.lothrazar.cyclic.registry.BlockRegistry; import com.lothrazar.cyclic.registry.TileRegistry; -import com.lothrazar.library.util.BlockstatesUtil; import com.lothrazar.library.util.EntityUtil; import com.lothrazar.library.util.StringParseUtil; import net.minecraft.core.BlockPos; import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectCategory; import net.minecraft.world.entity.LivingEntity; @@ -26,6 +27,9 @@ import net.minecraftforge.eventbus.api.Event.Result; import net.minecraftforge.registries.ForgeRegistries; +import java.util.ArrayList; +import java.util.List; + public class BlockAntiBeacon extends BlockCyclic { private static final float[] COLOR = new float[] { 1, 1, 1 }; @@ -74,6 +78,29 @@ public static void absorbPotions(Level world, BlockPos pos) { } } + public static void markNearbyEntitiesWithAntiBeaconPosition(Level world, BlockPos pos) { + List all = world.getEntitiesOfClass(LivingEntity.class, EntityUtil.makeBoundingBox(pos, TileAntiBeacon.RADIUS.get(), TileAntiBeacon.RADIUS.get())); + for (LivingEntity e : all) { + LivingEntityCapabilityStorage livingEntityData = e.getCapability(LivingEntityCapProvider.CYCLIC_LIVING_ENTITY).orElse(null); + if (livingEntityData == null) { + continue; + } + + BlockPos oldPosition = livingEntityData.getClosestAntiBeaconPosition(); + if (oldPosition != null && world.getBlockState(oldPosition).is(BlockRegistry.ANTI_BEACON.get())) { + int oldDistance = e.blockPosition().distManhattan(oldPosition); + int newDistance = e.blockPosition().distManhattan(pos); + + if (newDistance < oldDistance) { + livingEntityData.setClosestAntiBeaconPosition(pos); + } + } + else { + livingEntityData.setClosestAntiBeaconPosition(pos); + } + } + } + private static void cureAllRelevant(LivingEntity e) { List cureMe = new ArrayList<>(); for (MobEffect mobEffect : e.getActiveEffectsMap().keySet()) { @@ -101,16 +128,41 @@ public void isPotionApplicable(MobEffectEvent.Applicable event) { if (event.getEffectInstance() == null) { return; } + //this will cancel it - if (BlockAntiBeacon.doesConfigBlockEffect(event.getEffectInstance().getEffect())) { + LivingEntity livingEntity = event.getEntity(); + if (BlockAntiBeacon.doesConfigBlockEffect(event.getEffectInstance().getEffect()) && + livingEntity.getCommandSenderWorld() instanceof ServerLevel serverLevel && + serverLevel.isLoaded(livingEntity.blockPosition())) { + + LivingEntityCapabilityStorage livingEntityData = livingEntity.getCapability(LivingEntityCapProvider.CYCLIC_LIVING_ENTITY).orElse(null); + if (livingEntityData == null) { + return; + } + + BlockPos closestAntiBeacon = livingEntityData.getClosestAntiBeaconPosition(); + if (closestAntiBeacon == null) { + return; + } + + if (livingEntity.blockPosition().distManhattan(closestAntiBeacon) > TileAntiBeacon.RADIUS.get()) { + livingEntityData.setClosestAntiBeaconPosition(null); + return; + } + + if (!serverLevel.getBlockState(closestAntiBeacon).getBlock().equals(this)) { + livingEntityData.setClosestAntiBeaconPosition(null); + return; + } + final boolean isPowered = false; // if im NOT powered, im running - List blocks = BlockstatesUtil.findBlocks(event.getEntity().getCommandSenderWorld(), - event.getEntity().blockPosition(), this, TileAntiBeacon.RADIUS.get(), isPowered); - //can - if (blocks != null && blocks.size() > 0) { - ModCyclic.LOGGER.info("[potion blocked] " + event.getEffectInstance()); - event.setResult(Result.DENY); + if (serverLevel.hasNeighborSignal(closestAntiBeacon) != isPowered) { + return; } + + //can + ModCyclic.LOGGER.info("[potion blocked] " + event.getEffectInstance()); + event.setResult(Result.DENY); } } } diff --git a/src/main/java/com/lothrazar/cyclic/block/antipotion/TileAntiBeacon.java b/src/main/java/com/lothrazar/cyclic/block/antipotion/TileAntiBeacon.java index 212898a18..0626f3724 100644 --- a/src/main/java/com/lothrazar/cyclic/block/antipotion/TileAntiBeacon.java +++ b/src/main/java/com/lothrazar/cyclic/block/antipotion/TileAntiBeacon.java @@ -33,9 +33,13 @@ public static void serverTick(Level level, BlockPos blockPos, BlockState blockSt //ok go tile.tick(level, blockPos); if (tile.timer <= 0) { + BlockAntiBeacon.markNearbyEntitiesWithAntiBeaconPosition(level, blockPos); BlockAntiBeacon.absorbPotions(level, blockPos); tile.timer = TICKS.get(); } + else { + tile.timer--; + } } public static void clientTick(Level level, BlockPos blockPos, BlockState blockState, TileAntiBeacon e) { diff --git a/src/main/java/com/lothrazar/cyclic/capabilities/livingentity/LivingEntityCapProvider.java b/src/main/java/com/lothrazar/cyclic/capabilities/livingentity/LivingEntityCapProvider.java new file mode 100644 index 000000000..0c8f91c39 --- /dev/null +++ b/src/main/java/com/lothrazar/cyclic/capabilities/livingentity/LivingEntityCapProvider.java @@ -0,0 +1,55 @@ +package com.lothrazar.cyclic.capabilities.livingentity; + +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.capabilities.ICapabilityProvider; +import net.minecraftforge.common.util.INBTSerializable; +import net.minecraftforge.common.util.LazyOptional; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +public class LivingEntityCapProvider implements ICapabilityProvider, INBTSerializable { + + public static Capability CYCLIC_LIVING_ENTITY = CapabilityManager.get(new CapabilityToken<>() {}); + private LivingEntityCapabilityStorage livingEntityAntiBeaconPosition = null; + private final LazyOptional opt = LazyOptional.of(this::createMe); + + @Nonnull + private LivingEntityCapabilityStorage createMe() { + if (livingEntityAntiBeaconPosition == null) { + livingEntityAntiBeaconPosition = new LivingEntityCapabilityStorage(); + } + return livingEntityAntiBeaconPosition; + } + + @Nonnull + @Override + public LazyOptional getCapability(@Nonnull Capability cap) { + if (cap == CYCLIC_LIVING_ENTITY) { + return opt.cast(); + } + return LazyOptional.empty(); + } + + @Nonnull + @Override + public LazyOptional getCapability(@Nonnull Capability cap, @Nullable Direction side) { + return getCapability(cap); + } + + @Override + public CompoundTag serializeNBT() { + CompoundTag nbt = new CompoundTag(); + createMe().saveNBTData(nbt); + return nbt; + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + createMe().loadNBTData(nbt); + } +} diff --git a/src/main/java/com/lothrazar/cyclic/capabilities/livingentity/LivingEntityCapabilityStorage.java b/src/main/java/com/lothrazar/cyclic/capabilities/livingentity/LivingEntityCapabilityStorage.java new file mode 100644 index 000000000..590363fe0 --- /dev/null +++ b/src/main/java/com/lothrazar/cyclic/capabilities/livingentity/LivingEntityCapabilityStorage.java @@ -0,0 +1,32 @@ +package com.lothrazar.cyclic.capabilities.livingentity; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.NbtUtils; + +public class LivingEntityCapabilityStorage { + + BlockPos closestAntiBeaconPosition = null; + + public LivingEntityCapabilityStorage() {} + + public BlockPos getClosestAntiBeaconPosition() { + return closestAntiBeaconPosition; + } + + public void setClosestAntiBeaconPosition(BlockPos closestAntiBeaconPosition) { + this.closestAntiBeaconPosition = closestAntiBeaconPosition; + } + + public void saveNBTData(CompoundTag compound) { + if (closestAntiBeaconPosition != null) { + compound.put("closestAntiBeaconPosition", NbtUtils.writeBlockPos(closestAntiBeaconPosition)); + } + } + + public void loadNBTData(CompoundTag compound) { + if (compound.contains("closestAntiBeaconPosition")) { + closestAntiBeaconPosition = NbtUtils.readBlockPos(compound.getCompound("closestAntiBeaconPosition")); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/lothrazar/cyclic/registry/CapabilityRegistry.java b/src/main/java/com/lothrazar/cyclic/registry/CapabilityRegistry.java index d4e40252f..21f884b8a 100644 --- a/src/main/java/com/lothrazar/cyclic/registry/CapabilityRegistry.java +++ b/src/main/java/com/lothrazar/cyclic/registry/CapabilityRegistry.java @@ -1,10 +1,13 @@ package com.lothrazar.cyclic.registry; import com.lothrazar.cyclic.ModCyclic; +import com.lothrazar.cyclic.capabilities.livingentity.LivingEntityCapProvider; +import com.lothrazar.cyclic.capabilities.livingentity.LivingEntityCapabilityStorage; import com.lothrazar.cyclic.capabilities.player.PlayerCapProvider; import com.lothrazar.cyclic.capabilities.player.PlayerCapabilityStorage; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; import net.minecraftforge.event.AttachCapabilitiesEvent; @@ -22,11 +25,18 @@ public static void onAttachCapabilitiesPlayer(AttachCapabilitiesEvent ev event.addCapability(new ResourceLocation(ModCyclic.MODID, "data"), new PlayerCapProvider()); } } + if (event.getObject() instanceof LivingEntity) { + if (!event.getObject().getCapability(LivingEntityCapProvider.CYCLIC_LIVING_ENTITY).isPresent()) { + // The living entity does not already have this capability so we need to add the capability provider here + event.addCapability(new ResourceLocation(ModCyclic.MODID, "living_entity_data"), new LivingEntityCapProvider()); + } + } } @SubscribeEvent public void onRegisterCapabilities(RegisterCapabilitiesEvent event) { event.register(PlayerCapabilityStorage.class); + event.register(LivingEntityCapabilityStorage.class); } // Finally we need to register our capability in a RegisterCapabilitiesEvent }