Observe spawn protection and mob griefing rules when trying to apply spells that affect blocks

This commit is contained in:
Sollace 2021-12-28 03:32:59 +02:00
parent c31eba5f04
commit 6e24ca9c6f
7 changed files with 25 additions and 13 deletions

View file

@ -15,8 +15,10 @@ import com.minelittlepony.unicopia.util.VecHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameRules;
import net.minecraft.world.World;
/**
@ -58,6 +60,13 @@ public interface Caster<E extends LivingEntity> extends Owned<E>, Levelled, Affi
return getEntity().getBlockPos();
}
default boolean canModifyAt(BlockPos pos) {
if (getMaster() instanceof PlayerEntity) {
return !getWorld().canPlayerModifyAt((PlayerEntity)getMaster(), pos);
}
return getWorld().getGameRules().getBoolean(GameRules.DO_MOB_GRIEFING);
}
default void playSound(SoundEvent sound, float volume, float pitch) {
getWorld().playSound(null, getEntity().getX(), getEntity().getY(), getEntity().getZ(), sound, getEntity().getSoundCategory(), volume, pitch);
}

View file

@ -44,7 +44,7 @@ public class CatapultSpell extends AbstractSpell implements ProjectileSpell {
@Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) {
if (!projectile.isClient()) {
if (!projectile.isClient() && projectile.canModifyAt(pos)) {
createBlockEntity(projectile.world, pos, e -> apply(projectile, e));
}
}
@ -92,9 +92,11 @@ public class CatapultSpell extends AbstractSpell implements ProjectileSpell {
EntityHitResult result = (EntityHitResult)ray;
Optional.ofNullable(result.getEntity()).ifPresent(apply);
} else if (ray.getType() == HitResult.Type.BLOCK) {
if (caster.canModifyAt(((BlockHitResult)ray).getBlockPos())) {
createBlockEntity(caster.getWorld(), ((BlockHitResult)ray).getBlockPos(), apply);
}
}
}
static void createBlockEntity(World world, BlockPos bpos, @Nullable Consumer<Entity> apply) {

View file

@ -22,6 +22,7 @@ import net.minecraft.nbt.NbtCompound;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
/**
@ -135,7 +136,7 @@ public class DarkVortexSpell extends AttractiveSpell {
if (radius > 5) {
Vec3d origin = getOrigin(source);
PosHelper.getAllInRegionMutable(source.getOrigin(), new Sphere(false, radius)).forEach(i -> {
if (!source.getWorld().getFluidState(i).isEmpty()) {
if (!canAffect(source, i)) {
return;
}
if (source.getOrigin().isWithinDistance(i, getEventHorizonRadius())) {
@ -153,6 +154,12 @@ public class DarkVortexSpell extends AttractiveSpell {
return super.applyEntities(source);
}
protected boolean canAffect(Caster<?> source, BlockPos pos) {
return source.canModifyAt(pos)
&& source.getWorld().getFluidState(pos).isEmpty()
&& source.getWorld().getBlockState(pos).getHardness(source.getWorld(), pos) >= 0;
}
// 1. force decreases with distance: distance scale 1 -> 0
// 2. max force (at dist 0) is taken from accumulated mass
// 3. force reaches 0 at distance of drawDropOffRange
@ -226,9 +233,3 @@ public class DarkVortexSpell extends AttractiveSpell {
accumulatedMass = compound.getFloat("accumulatedMass");
}
}

View file

@ -59,7 +59,7 @@ public class FireSpell extends AbstractAreaEffectSpell implements ProjectileSpel
}
return PosHelper.getAllInRegionMutable(source.getOrigin(), new Sphere(false, Math.max(0, 4 + getTraits().get(Trait.POWER)))).reduce(false,
(r, i) -> applyBlocks(source.getWorld(), i),
(r, i) -> source.canModifyAt(i) && applyBlocks(source.getWorld(), i),
(a, b) -> a || b)
|| applyEntities(null, source.getWorld(), source.getOriginVector());
}

View file

@ -45,7 +45,7 @@ public class IceSpell extends AbstractSpell {
PosHelper.getAllInRegionMutable(source.getOrigin(), effect_range)
.forEach(i -> {
if (applyBlockSingle(owner, source.getWorld(), i)) {
if (source.canModifyAt(i) && applyBlockSingle(owner, source.getWorld(), i)) {
ParticleUtils.spawnParticle(source.getWorld(), ParticleTypes.SPLASH, new Vec3d(
i.getX() + source.getWorld().random.nextFloat(),
i.getY() + 1,

View file

@ -44,7 +44,7 @@ public class InfernoSpell extends FireSpell {
for (int i = 0; i < radius; i++) {
BlockPos pos = new BlockPos(shape.computePoint(w.random).add(origin));
if (converter.convert(w, pos)) {
if (source.canModifyAt(pos) && converter.convert(w, pos)) {
playEffect(w, pos);
}
}

View file

@ -29,7 +29,7 @@ public class ScorchSpell extends FireSpell {
public boolean tick(Caster<?> source, Situation situation) {
BlockPos pos = PosHelper.findSolidGroundAt(source.getWorld(), source.getOrigin(), source.getPhysics().getGravitySignum());
if (StateMaps.FIRE_AFFECTED.convert(source.getWorld(), pos)) {
if (source.canModifyAt(pos) && StateMaps.FIRE_AFFECTED.convert(source.getWorld(), pos)) {
source.spawnParticles(new Sphere(false, Math.max(1, getTraits().get(Trait.POWER))), 5, p -> {
source.addParticle(ParticleTypes.SMOKE, PosHelper.offset(p, pos), Vec3d.ZERO);
});