Skip to content

Commit

Permalink
Merge pull request #2334 from TelepathicGrunt/trunk/1.20
Browse files Browse the repository at this point in the history
Optimize anti beacon to not deadlock worldgen or lag entities
  • Loading branch information
Lothrazar authored Dec 11, 2023
2 parents 42d60e8 + b840d93 commit bb665d8
Show file tree
Hide file tree
Showing 5 changed files with 163 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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 };
Expand Down Expand Up @@ -74,6 +78,29 @@ public static void absorbPotions(Level world, BlockPos pos) {
}
}

public static void markNearbyEntitiesWithAntiBeaconPosition(Level world, BlockPos pos) {
List<LivingEntity> 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<MobEffect> cureMe = new ArrayList<>();
for (MobEffect mobEffect : e.getActiveEffectsMap().keySet()) {
Expand Down Expand Up @@ -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<BlockPos> 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);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 <E extends BlockEntity> void clientTick(Level level, BlockPos blockPos, BlockState blockState, TileAntiBeacon e) {
Expand Down
Original file line number Diff line number Diff line change
@@ -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<CompoundTag> {

public static Capability<LivingEntityCapabilityStorage> CYCLIC_LIVING_ENTITY = CapabilityManager.get(new CapabilityToken<>() {});
private LivingEntityCapabilityStorage livingEntityAntiBeaconPosition = null;
private final LazyOptional<LivingEntityCapabilityStorage> opt = LazyOptional.of(this::createMe);

@Nonnull
private LivingEntityCapabilityStorage createMe() {
if (livingEntityAntiBeaconPosition == null) {
livingEntityAntiBeaconPosition = new LivingEntityCapabilityStorage();
}
return livingEntityAntiBeaconPosition;
}

@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap) {
if (cap == CYCLIC_LIVING_ENTITY) {
return opt.cast();
}
return LazyOptional.empty();
}

@Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> 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);
}
}
Original file line number Diff line number Diff line change
@@ -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"));
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -22,11 +25,18 @@ public static void onAttachCapabilitiesPlayer(AttachCapabilitiesEvent<Entity> 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
}

0 comments on commit bb665d8

Please sign in to comment.