diff --git a/src/main/java/carpet/fakes/WorldInterface.java b/src/main/java/carpet/fakes/WorldInterface.java index 495ecde9..3c969187 100644 --- a/src/main/java/carpet/fakes/WorldInterface.java +++ b/src/main/java/carpet/fakes/WorldInterface.java @@ -5,12 +5,18 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import org.jetbrains.annotations.Nullable; +import java.util.List; import java.util.Map; +import java.util.function.Predicate; public interface WorldInterface { - Map getPrecookedMobs(); + Map, Entity> getPrecookedMobs(); boolean setBlockStateWithBlockEntity(BlockPos blockPos, BlockState blockState, BlockEntity newBlockEntity, int int1); + + List getOtherEntitiesLimited(@Nullable Entity except, Box box, Predicate predicate, int limit); } diff --git a/src/main/java/carpet/mixins/LivingEntity_maxCollisionsMixin.java b/src/main/java/carpet/mixins/LivingEntity_maxCollisionsMixin.java index cff8cb60..424007d7 100644 --- a/src/main/java/carpet/mixins/LivingEntity_maxCollisionsMixin.java +++ b/src/main/java/carpet/mixins/LivingEntity_maxCollisionsMixin.java @@ -1,6 +1,7 @@ package carpet.mixins; import carpet.CarpetSettings; +import carpet.fakes.WorldInterface; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; @@ -28,33 +29,35 @@ public abstract class LivingEntity_maxCollisionsMixin extends Entity @Shadow protected abstract void pushAway(Entity entity_1); @Inject(method = "tickCramming", cancellable = true, at = @At("HEAD")) - private void tickPushingReplacement(CallbackInfo ci) - { - List list_1 = this.world.getOtherEntities(this, this.getBoundingBox(), EntityPredicates.canBePushedBy(this)); - if (!list_1.isEmpty()) { - int int_1 = this.world.getGameRules().getInt(GameRules.MAX_ENTITY_CRAMMING); - int int_2; - if (int_1 > 0 && list_1.size() > int_1 - 1 && this.random.nextInt(4) == 0) { - int_2 = 0; + private void tickPushingReplacement(CallbackInfo ci) { + List entities; + if (CarpetSettings.maxEntityCollisions > 0) + entities = ((WorldInterface) this.world).getOtherEntitiesLimited( + this, + this.getBoundingBox(), + EntityPredicates.canBePushedBy(this), + CarpetSettings.maxEntityCollisions); + else + entities = this.world.getOtherEntities(this, this.getBoundingBox(), EntityPredicates.canBePushedBy(this)); - for(int int_3 = 0; int_3 < list_1.size(); ++int_3) { - if (!((Entity)list_1.get(int_3)).hasVehicle()) { - ++int_2; + if (!entities.isEmpty()) { + int maxEntityCramming = this.world.getGameRules().getInt(GameRules.MAX_ENTITY_CRAMMING); + if (maxEntityCramming > 0 && entities.size() > maxEntityCramming - 1 && this.random.nextInt(4) == 0) { + int candidates = 0; + + for (Entity entity : entities) { + if (!entity.hasVehicle()) { + ++candidates; } } - if (int_2 > int_1 - 1) { + if (candidates > maxEntityCramming - 1) { this.damage(DamageSource.CRAMMING, 6.0F); } } - int limit = list_1.size(); - if (CarpetSettings.maxEntityCollisions > 0) - limit = Math.min(limit, CarpetSettings.maxEntityCollisions); - - for(int_2 = 0; int_2 < limit; ++int_2) { - Entity entity_1 = (Entity)list_1.get(int_2); - this.pushAway(entity_1); + for (Entity entity : entities) { + this.pushAway(entity); } } ci.cancel(); diff --git a/src/main/java/carpet/mixins/SpawnHelperMixin.java b/src/main/java/carpet/mixins/SpawnHelperMixin.java index f97cf954..4f4b7c75 100644 --- a/src/main/java/carpet/mixins/SpawnHelperMixin.java +++ b/src/main/java/carpet/mixins/SpawnHelperMixin.java @@ -138,7 +138,7 @@ public class SpawnHelperMixin { if (CarpetSettings.lagFreeSpawning) { - Map precookedMobs = ((WorldInterface)world_1).getPrecookedMobs(); + Map, Entity> precookedMobs = ((WorldInterface)world_1).getPrecookedMobs(); if (precookedMobs.containsKey(entityType)) //this mob has been 's but not used yet return precookedMobs.get(entityType); diff --git a/src/main/java/carpet/mixins/World_getOtherEntitiesLimited.java b/src/main/java/carpet/mixins/World_getOtherEntitiesLimited.java new file mode 100644 index 00000000..3b6eafc0 --- /dev/null +++ b/src/main/java/carpet/mixins/World_getOtherEntitiesLimited.java @@ -0,0 +1,63 @@ +package carpet.mixins; + +import carpet.fakes.WorldInterface; +import com.google.common.collect.Lists; +import net.minecraft.entity.Entity; +import net.minecraft.entity.boss.dragon.EnderDragonEntity; +import net.minecraft.entity.boss.dragon.EnderDragonPart; +import net.minecraft.util.math.Box; +import net.minecraft.util.profiler.Profiler; +import net.minecraft.world.World; +import net.minecraft.world.entity.EntityLookup; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.List; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.Predicate; + +@Mixin(World.class) +public abstract class World_getOtherEntitiesLimited implements WorldInterface { + + private static final RuntimeException CONTROL_FLOW_EXCEPTION = new RuntimeException("Should be caught for control flow in World_getOtherEntitiesLimited!"); + + @Override + public List getOtherEntitiesLimited(@Nullable Entity except, Box box, Predicate predicate, int limit) { + this.getProfiler().visit("getEntities"); + AtomicInteger checkedEntities = new AtomicInteger(); + List list = Lists.newArrayList(); + try { + this.getEntityLookup().forEachIntersects(box, (entity) -> { + if (checkedEntities.getAndIncrement() > limit) { + throw CONTROL_FLOW_EXCEPTION; + } + + if (entity != except && predicate.test(entity)) { + list.add(entity); + } + + if (entity instanceof EnderDragonEntity) { + EnderDragonPart[] var4 = ((EnderDragonEntity) entity).getBodyParts(); + + for (EnderDragonPart enderDragonPart : var4) { + if (entity != except && predicate.test(enderDragonPart)) { + list.add(enderDragonPart); + } + } + } + }); + } catch (RuntimeException e) { + if (e != CONTROL_FLOW_EXCEPTION) + // If it wasn't the exception we were watching, rethrow it + throw e; + } + return list; + } + + @Shadow + public abstract Profiler getProfiler(); + + @Shadow + protected abstract EntityLookup getEntityLookup(); +} diff --git a/src/main/java/carpet/mixins/World_tickMixin.java b/src/main/java/carpet/mixins/World_tickMixin.java index 0514d750..76102f3a 100644 --- a/src/main/java/carpet/mixins/World_tickMixin.java +++ b/src/main/java/carpet/mixins/World_tickMixin.java @@ -3,23 +3,18 @@ package carpet.mixins; import carpet.fakes.WorldInterface; import carpet.helpers.TickSpeed; import carpet.utils.CarpetProfiler; -import net.minecraft.block.entity.BlockEntity; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityType; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.util.profiler.Profiler; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; 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; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import java.util.HashMap; -import java.util.Iterator; import java.util.Map; import java.util.function.Consumer; @@ -30,9 +25,9 @@ public abstract class World_tickMixin implements WorldInterface CarpetProfiler.ProfilerToken currentSection; CarpetProfiler.ProfilerToken entitySection; - Map precookedMobs = new HashMap<>(); + Map, Entity> precookedMobs = new HashMap<>(); - public Map getPrecookedMobs() + public Map, Entity> getPrecookedMobs() { return precookedMobs; } diff --git a/src/main/resources/carpet.mixins.json b/src/main/resources/carpet.mixins.json index c3ee0540..24f70d9b 100644 --- a/src/main/resources/carpet.mixins.json +++ b/src/main/resources/carpet.mixins.json @@ -86,6 +86,7 @@ "PistonHandler_pushLimitMixin", "PoweredRailBlock_powerLimitMixin", "LivingEntity_maxCollisionsMixin", + "World_getOtherEntitiesLimited", "CoralBlockMixin", "CoralFanBlockMixin", "CoralFeatureMixin", @@ -241,4 +242,4 @@ "injectors": { "defaultRequire": 1 } -} \ No newline at end of file +}