Fixed concurrent modification exception when using the ice spell. #90

This commit is contained in:
Sollace 2023-01-09 10:38:32 +00:00
parent 8c04bb710a
commit 71ca9614bb
4 changed files with 19 additions and 8 deletions

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.ability.magic.spell.effect;
import java.util.List;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
@ -70,10 +72,13 @@ public class IceSpell extends AbstractSpell {
}
protected boolean applyEntities(Caster<?> source, Vec3d pos) {
return !VecHelper.findInRange(source.asEntity(), source.asWorld(), pos, 3, i -> applyEntitySingle(source, i)).isEmpty();
List<Entity> entities = VecHelper.findInRange(source.asEntity(), source.asWorld(), pos, 3);
entities.forEach(entity -> applyEntitySingle(source, entity));
return !entities.isEmpty();
}
protected boolean applyEntitySingle(Caster<?> source, Entity e) {
protected void applyEntitySingle(Caster<?> source, Entity e) {
if (e instanceof TntEntity) {
e.remove(RemovalReason.DISCARDED);
e.getEntityWorld().setBlockState(e.getBlockPos(), Blocks.TNT.getDefaultState());
@ -82,8 +87,6 @@ public class IceSpell extends AbstractSpell {
} else {
e.damage(MagicalDamageSource.create("cold", source.getMaster()), 2);
}
return true;
}
private boolean applyBlockSingle(Entity owner, World world, BlockPos pos, Situation situation) {

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.ability.magic.spell.effect;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@ -20,6 +21,7 @@ import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.VecHelper;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.player.PlayerEntity;
@ -33,6 +35,7 @@ import net.minecraft.util.math.Vec3d;
* A spell that pulls health from other entities and delivers it to the caster.
*/
public class SiphoningSpell extends AbstractAreaEffectSpell {
static final Predicate<Entity> TARGET_PREDICATE = EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(EntityPredicates.VALID_LIVING_ENTITY);
private int ticksUpset;
@ -80,9 +83,7 @@ public class SiphoningSpell extends AbstractAreaEffectSpell {
}
private Stream<LivingEntity> getTargets(Caster<?> source) {
return VecHelper.findInRange(null, source.asWorld(), source.getOriginVector(), 4 + source.getLevel().getScaled(6), EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(e -> e instanceof LivingEntity))
.stream()
.map(e -> (LivingEntity)e);
return VecHelper.findInRange(null, source.asWorld(), source.getOriginVector(), 4 + source.getLevel().getScaled(6), TARGET_PREDICATE).stream().map(e -> (LivingEntity)e);
}
private void distributeHealth(Caster<?> source) {

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.item;
import java.util.*;
import java.util.function.Predicate;
import java.util.function.Supplier;
import com.google.common.base.Suppliers;
@ -31,6 +32,7 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Artifact {
static final Predicate<Entity> TARGET_PREDICATE = EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(EntityPredicates.VALID_ENTITY).and(e -> (e instanceof PlayerEntity || e instanceof MobEntity));
private static final Supplier<Map<Item, Item>> ITEM_MAP = Suppliers.memoize(() -> {
return Map.of(
Items.BUCKET, UItems.LOVE_BUCKET,
@ -115,7 +117,7 @@ public class CrystalHeartItem extends Item implements FloatingArtefactEntity.Art
List<LivingEntity> outputs = new ArrayList<>();
List<ItemEntity> containers = new ArrayList<>();
VecHelper.findInRange(entity, entity.world, entity.getPos(), 20, EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.and(e -> !e.isRemoved() && (e instanceof PlayerEntity || e instanceof MobEntity))).forEach(e -> {
VecHelper.findInRange(entity, entity.world, entity.getPos(), 20, TARGET_PREDICATE).forEach(e -> {
LivingEntity living = (LivingEntity)e;
if (e instanceof PlayerEntity

View file

@ -32,4 +32,9 @@ public interface VecHelper {
double diameter = radius * 2;
return w.getOtherEntities(origin, Box.of(pos, diameter, diameter, diameter), predicate == null ? inRange(pos, radius) : inRange(pos, radius).and(predicate));
}
static List<Entity> findInRange(@Nullable Entity origin, EntityView w, Vec3d pos, double radius) {
double diameter = radius * 2;
return w.getOtherEntities(origin, Box.of(pos, diameter, diameter, diameter), inRange(pos, radius));
}
}