The ice spell will now clear out a space around the player when used while submerged

This commit is contained in:
Sollace 2021-12-29 17:48:47 +02:00
parent 097aa1d8cf
commit 3f80822deb
3 changed files with 61 additions and 44 deletions

View file

@ -22,7 +22,9 @@ import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.TntEntity;
import net.minecraft.entity.Entity.RemovalReason;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.state.property.Properties;
import net.minecraft.tag.BlockTags;
import net.minecraft.tag.FluidTags;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
@ -33,7 +35,7 @@ public class IceSpell extends AbstractSpell {
.build();
private final int rad = 3;
private final Shape effect_range = new Sphere(false, rad);
private final Shape outerRange = new Sphere(false, rad);
protected IceSpell(SpellType<?> type, SpellTraits traits) {
super(type, traits);
@ -43,17 +45,34 @@ public class IceSpell extends AbstractSpell {
public boolean tick(Caster<?> source, Situation situation) {
LivingEntity owner = source.getMaster();
PosHelper.getAllInRegionMutable(source.getOrigin(), effect_range)
.forEach(i -> {
if (source.canModifyAt(i) && applyBlockSingle(owner, source.getWorld(), i)) {
boolean submerged = source.getEntity().isSubmergedInWater() || source.getEntity().isSubmergedIn(FluidTags.LAVA);
long blocksAffected = PosHelper.getAllInRegionMutable(source.getOrigin(), outerRange).filter(i -> {
if (source.canModifyAt(i) && applyBlockSingle(owner, source.getWorld(), i, situation)) {
if (submerged & source.getOrigin().isWithinDistance(i, rad - 1)) {
BlockState state = source.getWorld().getBlockState(i);
if (state.isIn(BlockTags.ICE) || state.isOf(Blocks.OBSIDIAN)) {
source.getWorld().setBlockState(i, Blocks.AIR.getDefaultState(), Block.NOTIFY_NEIGHBORS);
} else if (!state.getFluidState().isEmpty()) {
source.getWorld().setBlockState(i, state.with(Properties.WATERLOGGED, false), Block.NOTIFY_NEIGHBORS);
}
}
ParticleUtils.spawnParticle(source.getWorld(), ParticleTypes.SPLASH, new Vec3d(
i.getX() + source.getWorld().random.nextFloat(),
i.getY() + 1,
i.getZ() + source.getWorld().random.nextFloat()), Vec3d.ZERO);
}
});
return applyEntities(source.getMaster(), source.getWorld(), source.getOriginVector());
return true;
}
return false;
}).count();
source.subtractEnergyCost(Math.min(10, blocksAffected));
return applyEntities(source.getMaster(), source.getWorld(), source.getOriginVector()) && situation == Situation.PROJECTILE;
}
protected boolean applyEntities(LivingEntity owner, World world, Vec3d pos) {
@ -73,17 +92,19 @@ public class IceSpell extends AbstractSpell {
return true;
}
private boolean applyBlockSingle(Entity owner, World world, BlockPos pos) {
private boolean applyBlockSingle(Entity owner, World world, BlockPos pos, Situation situation) {
BlockState state = world.getBlockState(pos);
if (StateMaps.ICE_AFFECTED.convert(world, pos)) {
if ((situation == Situation.PROJECTILE
&& StateMaps.SNOW_PILED.convert(world, pos))
|| StateMaps.ICE_AFFECTED.convert(world, pos)) {
return true;
}
if (world.isTopSolid(pos, owner)
|| state.isOf(Blocks.SNOW)
|| state.isIn(BlockTags.LEAVES)) {
incrementIce(world, pos.up());
addSnowLayer(world, pos.up());
return true;
}
@ -103,7 +124,7 @@ public class IceSpell extends AbstractSpell {
);
}
private static void incrementIce(World world, BlockPos pos) {
private static void addSnowLayer(World world, BlockPos pos) {
BlockState state = world.getBlockState(pos);
Block id = state.getBlock();

View file

@ -10,36 +10,39 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.Material;
import net.minecraft.block.SnowBlock;
import net.minecraft.state.property.IntProperty;
import net.minecraft.state.property.Property;
import net.minecraft.tag.Tag;
import net.minecraft.world.World;
interface StateMapping extends Predicate<BlockState>, BiFunction<World, BlockState, BlockState> {
static StateMapping incrementSnow() {
return build(
isOf(Blocks.SNOW),
(w, s) -> {
s = s.cycle(SnowBlock.LAYERS);
if (s.get(SnowBlock.LAYERS) >= 7) {
return Blocks.SNOW_BLOCK.getDefaultState();
}
return s;
});
}
static Predicate<BlockState> isOf(Block block) {
return s -> s.isOf(block);
}
static StateMapping replaceMaterial(Material mat, Block block) {
return build(isOf(mat), block);
}
static Predicate<BlockState> isOf(Material mat) {
return s -> s.getMaterial() == mat;
}
static StateMapping cycleProperty(Block block, IntProperty property, int stopAt) {
if (stopAt < 0) {
return build(
isOf(block),
(w, s) -> s.cycle(property)
);
}
return build(
isOf(block).and(state -> state.get(property) < stopAt),
(w, s) -> s.get(property) >= stopAt ? s : s.cycle(property)
);
}
static StateMapping replaceMaterial(Material mat, Block block) {
return build(isOf(mat), block);
}
static StateMapping removeBlock(Predicate<BlockState> mapper) {
return build(
mapper,
@ -133,8 +136,8 @@ interface StateMapping extends Predicate<BlockState>, BiFunction<World, BlockSta
*
* @return The converted state
*/
@NotNull
@Override
@NotNull
BlockState apply(World world, @NotNull BlockState state);
/**

View file

@ -12,6 +12,7 @@ import net.minecraft.block.Material;
import net.minecraft.block.OreBlock;
import net.minecraft.block.PlantBlock;
import net.minecraft.block.RedstoneWireBlock;
import net.minecraft.block.SnowBlock;
import net.minecraft.tag.BlockTags;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
@ -19,24 +20,16 @@ import net.minecraft.util.registry.Registry;
public class StateMaps {
private static final Registry<BlockStateConverter> REGISTRY = Registries.createSimple(new Identifier("unicopia", "state_map"));
public static final BlockStateConverter SNOW_PILED = register("snow_piled", new BlockStateMap.Builder()
.add(StateMapping.cycleProperty(Blocks.SNOW, SnowBlock.LAYERS, 7)));
public static final BlockStateConverter ICE_AFFECTED = register("ice", new BlockStateMap.Builder()
.replaceMaterial(Material.WATER, Blocks.ICE)
.replaceMaterial(Material.LAVA, Blocks.OBSIDIAN)
.add(StateMapping.incrementSnow())
.add(StateMapping.cycleProperty(Blocks.SNOW, SnowBlock.LAYERS, 7))
.replaceBlock(Blocks.FIRE, Blocks.AIR)
.setProperty(Blocks.REDSTONE_WIRE, RedstoneWireBlock.POWER, 0));
public static final ReversableBlockStateConverter MOSS_AFFECTED = register("moss", new ReversableBlockStateMap.Builder()
.replaceBlock(Blocks.MOSSY_COBBLESTONE, Blocks.COBBLESTONE)
.replaceBlock(Blocks.MOSSY_COBBLESTONE_SLAB, Blocks.COBBLESTONE_SLAB)
.replaceBlock(Blocks.MOSSY_COBBLESTONE_STAIRS, Blocks.COBBLESTONE_STAIRS)
.replaceBlock(Blocks.MOSSY_COBBLESTONE_WALL, Blocks.COBBLESTONE_WALL)
.replaceBlock(Blocks.MOSSY_STONE_BRICK_SLAB, Blocks.STONE_BRICK_SLAB)
.replaceBlock(Blocks.MOSSY_STONE_BRICK_STAIRS, Blocks.STONE_BRICK_STAIRS)
.replaceBlock(Blocks.MOSSY_STONE_BRICK_WALL, Blocks.MOSSY_STONE_BRICK_WALL)
.replaceBlock(Blocks.MOSSY_STONE_BRICKS, Blocks.STONE_BRICKS)
.replaceBlock(Blocks.INFESTED_MOSSY_STONE_BRICKS, Blocks.INFESTED_STONE_BRICKS));
public static final BlockStateConverter SILVERFISH_AFFECTED = register("infestation", new BlockStateMap.Builder()
.replaceBlock(Blocks.CHISELED_STONE_BRICKS, Blocks.INFESTED_CHISELED_STONE_BRICKS)
.replaceBlock(Blocks.COBBLESTONE, Blocks.INFESTED_COBBLESTONE)