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.Entity;
import net.minecraft.entity.LivingEntity; import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameRules;
import net.minecraft.world.World; import net.minecraft.world.World;
/** /**
@ -58,6 +60,13 @@ public interface Caster<E extends LivingEntity> extends Owned<E>, Levelled, Affi
return getEntity().getBlockPos(); 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) { default void playSound(SoundEvent sound, float volume, float pitch) {
getWorld().playSound(null, getEntity().getX(), getEntity().getY(), getEntity().getZ(), sound, getEntity().getSoundCategory(), volume, 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 @Override
public void onImpact(MagicProjectileEntity projectile, BlockPos pos, BlockState state) { 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)); createBlockEntity(projectile.world, pos, e -> apply(projectile, e));
} }
} }
@ -92,9 +92,11 @@ public class CatapultSpell extends AbstractSpell implements ProjectileSpell {
EntityHitResult result = (EntityHitResult)ray; EntityHitResult result = (EntityHitResult)ray;
Optional.ofNullable(result.getEntity()).ifPresent(apply); Optional.ofNullable(result.getEntity()).ifPresent(apply);
} else if (ray.getType() == HitResult.Type.BLOCK) { } else if (ray.getType() == HitResult.Type.BLOCK) {
if (caster.canModifyAt(((BlockHitResult)ray).getBlockPos())) {
createBlockEntity(caster.getWorld(), ((BlockHitResult)ray).getBlockPos(), apply); createBlockEntity(caster.getWorld(), ((BlockHitResult)ray).getBlockPos(), apply);
} }
} }
}
static void createBlockEntity(World world, BlockPos bpos, @Nullable Consumer<Entity> 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.particle.ParticleTypes;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents; import net.minecraft.sound.SoundEvents;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
/** /**
@ -135,7 +136,7 @@ public class DarkVortexSpell extends AttractiveSpell {
if (radius > 5) { if (radius > 5) {
Vec3d origin = getOrigin(source); Vec3d origin = getOrigin(source);
PosHelper.getAllInRegionMutable(source.getOrigin(), new Sphere(false, radius)).forEach(i -> { PosHelper.getAllInRegionMutable(source.getOrigin(), new Sphere(false, radius)).forEach(i -> {
if (!source.getWorld().getFluidState(i).isEmpty()) { if (!canAffect(source, i)) {
return; return;
} }
if (source.getOrigin().isWithinDistance(i, getEventHorizonRadius())) { if (source.getOrigin().isWithinDistance(i, getEventHorizonRadius())) {
@ -153,6 +154,12 @@ public class DarkVortexSpell extends AttractiveSpell {
return super.applyEntities(source); 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 // 1. force decreases with distance: distance scale 1 -> 0
// 2. max force (at dist 0) is taken from accumulated mass // 2. max force (at dist 0) is taken from accumulated mass
// 3. force reaches 0 at distance of drawDropOffRange // 3. force reaches 0 at distance of drawDropOffRange
@ -226,9 +233,3 @@ public class DarkVortexSpell extends AttractiveSpell {
accumulatedMass = compound.getFloat("accumulatedMass"); 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, 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) (a, b) -> a || b)
|| applyEntities(null, source.getWorld(), source.getOriginVector()); || applyEntities(null, source.getWorld(), source.getOriginVector());
} }

View file

@ -45,7 +45,7 @@ public class IceSpell extends AbstractSpell {
PosHelper.getAllInRegionMutable(source.getOrigin(), effect_range) PosHelper.getAllInRegionMutable(source.getOrigin(), effect_range)
.forEach(i -> { .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( ParticleUtils.spawnParticle(source.getWorld(), ParticleTypes.SPLASH, new Vec3d(
i.getX() + source.getWorld().random.nextFloat(), i.getX() + source.getWorld().random.nextFloat(),
i.getY() + 1, i.getY() + 1,

View file

@ -44,7 +44,7 @@ public class InfernoSpell extends FireSpell {
for (int i = 0; i < radius; i++) { for (int i = 0; i < radius; i++) {
BlockPos pos = new BlockPos(shape.computePoint(w.random).add(origin)); 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); playEffect(w, pos);
} }
} }

View file

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