Polish up the inferno spell and refactor block state mapping a little

This commit is contained in:
Sollace 2021-03-03 20:06:57 +02:00
parent 3fda44eba6
commit afd437d9cf
8 changed files with 122 additions and 42 deletions

View file

@ -6,6 +6,7 @@ import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.Magical;
import com.minelittlepony.unicopia.ability.magic.Thrown;
import com.minelittlepony.unicopia.block.state.StateMaps;
import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.PosHelper;
@ -37,7 +38,6 @@ import net.minecraft.world.explosion.Explosion.DestructionType;
*/
public class FireSpell extends AbstractSpell implements Thrown, Attached {
private static final Shape VISUAL_EFFECT_RANGE = new Sphere(false, 0.5);
private static final Shape EFFECT_RANGE = new Sphere(false, 4);
protected FireSpell(SpellType<?> type) {
@ -69,7 +69,7 @@ public class FireSpell extends AbstractSpell implements Thrown, Attached {
}
protected void generateParticles(Caster<?> source) {
source.spawnParticles(VISUAL_EFFECT_RANGE, source.getLevel().get() * 6, pos -> {
source.spawnParticles(EFFECT_RANGE, (1 + source.getLevel().get()) * 6, pos -> {
source.addParticle(ParticleTypes.LARGE_SMOKE, pos, Vec3d.ZERO);
});
}
@ -79,13 +79,8 @@ public class FireSpell extends AbstractSpell implements Thrown, Attached {
Block id = state.getBlock();
if (id != Blocks.AIR) {
if (id == Blocks.ICE || id == Blocks.PACKED_ICE) {
world.setBlockState(pos, (world.getDimension().isUltrawarm() ? Blocks.AIR : Blocks.WATER).getDefaultState());
playEffect(world, pos);
return true;
} else if (id == Blocks.NETHERRACK) {
if (world.getBlockState(pos.up()).getMaterial() == Material.AIR) {
if (id == Blocks.NETHERRACK) {
if (world.isAir(pos.up())) {
if (world.random.nextInt(300) == 0) {
world.setBlockState(pos.up(), Blocks.FIRE.getDefaultState());
@ -114,7 +109,7 @@ public class FireSpell extends AbstractSpell implements Thrown, Attached {
return true;
}
} else {
BlockState newState = StateMaps.FIRE_AFFECTED.getConverted(state);
BlockState newState = StateMaps.FIRE_AFFECTED.getConverted(world, state);
if (!state.equals(newState)) {
world.setBlockState(pos, newState, 3);
@ -175,10 +170,14 @@ public class FireSpell extends AbstractSpell implements Thrown, Attached {
int y = pos.getY();
int z = pos.getZ();
world.playSound(x + 0.5F, y + 0.5F, z + 0.5F, SoundEvents.BLOCK_FURNACE_FIRE_CRACKLE, SoundCategory.AMBIENT, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F, true);
world.playSound(null, pos, SoundEvents.BLOCK_FURNACE_FIRE_CRACKLE, SoundCategory.AMBIENT, 0.5F, 2.6F + (world.random.nextFloat() - world.random.nextFloat()) * 0.8F);
for (int i = 0; i < 8; ++i) {
world.addParticle(ParticleTypes.LARGE_SMOKE, x + Math.random(), y + Math.random(), z + Math.random(), 0, 0, 0);
ParticleUtils.spawnParticle(ParticleTypes.LARGE_SMOKE, world, new Vec3d(
x + Math.random(),
y + Math.random(),
z + Math.random()
), Vec3d.ZERO);
}
}

View file

@ -69,7 +69,7 @@ public class IceSpell extends AbstractSpell implements Thrown, Attached {
BlockState state = world.getBlockState(pos);
Block id = state.getBlock();
BlockState converted = StateMaps.ICE_AFFECTED.getConverted(state);
BlockState converted = StateMaps.ICE_AFFECTED.getConverted(world, state);
if (!state.equals(converted)) {
world.setBlockState(pos, converted, 3);

View file

@ -1,12 +1,15 @@
package com.minelittlepony.unicopia.ability.magic.spell;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.block.state.BlockStateConverter;
import com.minelittlepony.unicopia.block.state.StateMaps;
import com.minelittlepony.unicopia.util.MagicalDamageSource;
import com.minelittlepony.unicopia.util.shape.Shape;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.block.BlockState;
import net.minecraft.block.DoorBlock;
import net.minecraft.block.enums.DoubleBlockHalf;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
@ -22,6 +25,10 @@ public class InfernoSpell extends FireSpell {
@Override
public boolean onThrownTick(Caster<?> source) {
if (source.isClient()) {
generateParticles(source);
}
World w = source.getWorld();
if (!w.isClient) {
@ -30,14 +37,24 @@ public class InfernoSpell extends FireSpell {
Vec3d origin = source.getOriginVector();
BlockStateConverter converter = w.getDimension().isUltrawarm() ? StateMaps.HELLFIRE_AFFECTED.getInverse() : StateMaps.HELLFIRE_AFFECTED;
for (int i = 0; i < radius; i++) {
BlockPos pos = new BlockPos(shape.computePoint(w.random).add(origin));
BlockState state = w.getBlockState(pos);
BlockState newState = StateMaps.HELLFIRE_AFFECTED.getConverted(state);
BlockState newState = converter.getConverted(w, state);
if (!state.equals(newState)) {
w.setBlockState(pos, newState, 3);
if (newState.getBlock() instanceof DoorBlock) {
boolean lower = newState.get(DoorBlock.HALF) == DoubleBlockHalf.LOWER;
BlockPos other = lower ? pos.up() : pos.down();
w.setBlockState(other, newState.with(DoorBlock.HALF, lower ? DoubleBlockHalf.UPPER : DoubleBlockHalf.LOWER), 16 | 2);
}
w.setBlockState(pos, newState, 16 | 2);
playEffect(w, pos);
}
@ -54,7 +71,7 @@ public class InfernoSpell extends FireSpell {
}
}
}
return false;
return true;
}
@Override

View file

@ -27,7 +27,7 @@ public class ScorchSpell extends FireSpell {
BlockState state = source.getWorld().getBlockState(pos);
BlockState newState = StateMaps.FIRE_AFFECTED.getConverted(state);
BlockState newState = StateMaps.FIRE_AFFECTED.getConverted(source.getWorld(), state);
if (!state.equals(newState)) {
source.getWorld().setBlockState(pos, newState, 3);

View file

@ -4,6 +4,7 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import net.minecraft.block.BlockState;
import net.minecraft.world.World;
public interface BlockStateConverter {
/**
@ -23,5 +24,5 @@ public interface BlockStateConverter {
* @return The converted state if there is one, otherwise null
*/
@Nonnull
BlockState getConverted(@Nonnull BlockState state);
BlockState getConverted(World world, @Nonnull BlockState state);
}

View file

@ -9,6 +9,8 @@ import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Property;
import net.minecraft.tag.Tag;
import net.minecraft.world.World;
/**
* A collection of block-state mappings.
@ -21,10 +23,19 @@ class BlockStateMap extends ArrayList<StateMapping> implements BlockStateConvert
add(StateMapping.removeBlock(mapper));
}
public void removeBlock(Block from) {
add(StateMapping.removeBlock(from));
}
public void replaceBlock(Block from, Block to) {
add(StateMapping.replaceBlock(from, to));
}
public void replaceBlock(Tag<Block> from, Block to) {
add(StateMapping.replaceBlock(from, to));
}
public <T extends Comparable<T>> void replaceProperty(Block block, Property<T> property, T from, T to) {
add(StateMapping.replaceProperty(block, property, from, to));
}
@ -40,10 +51,10 @@ class BlockStateMap extends ArrayList<StateMapping> implements BlockStateConvert
@Override
@Nonnull
public BlockState getConverted(@Nonnull BlockState state) {
public BlockState getConverted(World world, @Nonnull BlockState state) {
for (StateMapping i : this) {
if (i.test(state)) {
return i.apply(state);
return i.apply(world, state);
}
}

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.block.state;
import java.util.Random;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;
@ -9,40 +11,68 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.state.property.Property;
import net.minecraft.tag.Tag;
import net.minecraft.world.World;
interface StateMapping extends Predicate<BlockState>, Function<BlockState, BlockState> {
interface StateMapping extends Predicate<BlockState>, BiFunction<World, BlockState, BlockState> {
Random RNG = new Random();
static StateMapping removeBlock(Predicate<BlockState> mapper) {
return build(
mapper,
s -> Blocks.AIR.getDefaultState());
(w, s) -> Blocks.AIR.getDefaultState());
}
static StateMapping removeBlock(Block from) {
return removeBlock(s -> s.isOf(from));
}
static StateMapping replaceBlock(Tag<Block> tag, Block to) {
return build(
s -> s.isIn(tag),
(w, s) -> to.getDefaultState(),
s -> build(
p -> p.isOf(to),
(w, p) -> tag.getRandom(w.random).getDefaultState()
)
);
}
@SuppressWarnings("unchecked")
static StateMapping replaceBlock(Block from, Block to) {
return build(
s -> s.getBlock() == from,
s -> to.getDefaultState(),
(w, s) -> {
BlockState newState = to.getDefaultState();
for (@SuppressWarnings("rawtypes") Property i : s.getProperties()) {
if (newState.contains(i)) {
newState = newState.with(i, s.get(i));
}
}
return newState;
},
s -> replaceBlock(to, from));
}
static <T extends Comparable<T>> StateMapping replaceProperty(Block block, Property<T> property, T from, T to) {
return build(
s -> s.getBlock() == block && s.get(property) == from,
s -> s.with(property, to),
(w, s) -> s.with(property, to),
s -> replaceProperty(block, property, to, from));
}
static <T extends Comparable<T>> StateMapping setProperty(Block block, Property<T> property, T to) {
return build(
s -> s.getBlock() == block,
s -> s.with(property, to));
(w, s) -> s.with(property, to));
}
static StateMapping build(Predicate<BlockState> predicate, Function<BlockState, BlockState> converter) {
static StateMapping build(Predicate<BlockState> predicate, BiFunction<World, BlockState, BlockState> converter) {
return build(predicate, converter, s -> s);
}
static StateMapping build(Predicate<BlockState> predicate, Function<BlockState, BlockState> converter, Function<StateMapping, StateMapping> inverter) {
static StateMapping build(Predicate<BlockState> predicate, BiFunction<World, BlockState, BlockState> converter, Function<StateMapping, StateMapping> inverter) {
return new StateMapping() {
private StateMapping inverse;
@ -52,8 +82,8 @@ interface StateMapping extends Predicate<BlockState>, Function<BlockState, Block
}
@Override
public BlockState apply(BlockState state) {
return converter.apply(state);
public BlockState apply(World world, BlockState state) {
return converter.apply(world, state);
}
@Override
@ -87,7 +117,7 @@ interface StateMapping extends Predicate<BlockState>, Function<BlockState, Block
*/
@Nonnull
@Override
default BlockState apply(@Nonnull BlockState state) {
default BlockState apply(World world, @Nonnull BlockState state) {
return state;
}

View file

@ -7,19 +7,20 @@ 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.Util;
public class StateMaps {
public static final BlockStateConverter ICE_AFFECTED = register(Util.make(new BlockStateMap(), a -> {
a.add(StateMapping.build(
s -> s.getMaterial() == Material.WATER,
s -> Blocks.ICE.getDefaultState()));
(w, s) -> Blocks.ICE.getDefaultState()));
a.add(StateMapping.build(
s -> s.getMaterial() == Material.LAVA,
s -> Blocks.OBSIDIAN.getDefaultState()));
(w, s) -> Blocks.OBSIDIAN.getDefaultState()));
a.add(StateMapping.build(
s -> s.getBlock() == Blocks.SNOW,
s -> {
(w, s) -> {
s = s.cycle(SnowBlock.LAYERS);
if (s.get(SnowBlock.LAYERS) >= 7) {
return Blocks.SNOW_BLOCK.getDefaultState();
@ -53,8 +54,11 @@ public class StateMaps {
}), "infestation");
public static final BlockStateConverter FIRE_AFFECTED = register(Util.make(new BlockStateMap(), a -> {
a.removeBlock(s -> s.getBlock() == Blocks.SNOW || s.getBlock() == Blocks.SNOW_BLOCK);
a.removeBlock(Blocks.SNOW);
a.removeBlock(Blocks.SNOW_BLOCK);
a.removeBlock(s -> s.getBlock() instanceof PlantBlock);
a.replaceBlock(Blocks.ICE, Blocks.WATER);
a.replaceBlock(Blocks.PACKED_ICE, Blocks.WATER);
a.replaceBlock(Blocks.CLAY, Blocks.BROWN_CONCRETE);
a.replaceBlock(Blocks.OBSIDIAN, Blocks.LAVA);
a.replaceBlock(Blocks.GRASS_BLOCK, Blocks.DIRT);
@ -66,24 +70,42 @@ public class StateMaps {
a.setProperty(Blocks.FARMLAND, FarmlandBlock.MOISTURE, 0);
a.add(StateMapping.build(
s -> s.getBlock() == Blocks.DIRT,
s -> (Math.random() <= 0.15 ? Blocks.COARSE_DIRT.getDefaultState() : s)));
(w, s) -> (w.random.nextFloat() <= 0.15 ? Blocks.COARSE_DIRT.getDefaultState() : s)));
}), "fire");
public static final BlockStateConverter HELLFIRE_AFFECTED = register(Util.make(new BlockStateMap(), a -> {
a.add(StateMapping.build(
s -> s.getBlock() == Blocks.GRASS_BLOCK || s.getBlock() == Blocks.DIRT || s.getBlock() == Blocks.STONE,
s -> Blocks.NETHERRACK.getDefaultState()));
public static final ReversableBlockStateConverter HELLFIRE_AFFECTED = register(Util.make(new ReversableBlockStateMap(), a -> {
a.replaceBlock(Blocks.GRASS_BLOCK, Blocks.WARPED_NYLIUM);
a.replaceBlock(Blocks.STONE, Blocks.NETHERRACK);
a.replaceBlock(Blocks.SAND, Blocks.SOUL_SAND);
a.replaceBlock(Blocks.GRAVEL, Blocks.SOUL_SAND);
a.replaceBlock(Blocks.DIRT, Blocks.SOUL_SOIL);
a.replaceBlock(Blocks.COARSE_DIRT, Blocks.SOUL_SOIL);
a.replaceBlock(Blocks.TORCH, Blocks.SOUL_TORCH);
a.replaceBlock(Blocks.WALL_TORCH, Blocks.SOUL_WALL_TORCH);
a.replaceBlock(Blocks.OAK_LOG, Blocks.WARPED_STEM);
a.replaceBlock(Blocks.STRIPPED_OAK_LOG, Blocks.STRIPPED_WARPED_STEM);
a.replaceBlock(Blocks.STRIPPED_OAK_WOOD, Blocks.STRIPPED_WARPED_HYPHAE);
a.replaceBlock(Blocks.OAK_PLANKS, Blocks.WARPED_PLANKS);
a.replaceBlock(Blocks.OAK_DOOR, Blocks.WARPED_DOOR);
a.replaceBlock(Blocks.OAK_STAIRS, Blocks.WARPED_STAIRS);
a.replaceBlock(Blocks.OAK_TRAPDOOR, Blocks.WARPED_TRAPDOOR);
a.replaceBlock(Blocks.OAK_PRESSURE_PLATE, Blocks.WARPED_PRESSURE_PLATE);
a.replaceBlock(Blocks.OAK_BUTTON, Blocks.WARPED_BUTTON);
a.replaceBlock(Blocks.OAK_FENCE, Blocks.WARPED_FENCE);
a.replaceBlock(Blocks.OAK_FENCE_GATE, Blocks.WARPED_FENCE_GATE);
a.replaceBlock(BlockTags.LEAVES, Blocks.WARPED_HYPHAE);
a.add(StateMapping.build(
s -> s.getMaterial() == Material.WATER,
s -> Blocks.OBSIDIAN.getDefaultState()));
(w, s) -> Blocks.OBSIDIAN.getDefaultState(),
s -> StateMapping.replaceBlock(Blocks.OBSIDIAN, Blocks.WATER)));
a.add(StateMapping.build(
s -> s.getBlock() instanceof PlantBlock,
s -> Blocks.NETHER_WART.getDefaultState()));
(w, s) -> Blocks.NETHER_WART.getDefaultState(),
s -> StateMapping.replaceBlock(Blocks.NETHER_WART, Blocks.GRASS)));
a.add(StateMapping.build(
s -> (s.getBlock() != Blocks.NETHER_QUARTZ_ORE) && (s.getBlock() instanceof OreBlock),
s -> Blocks.NETHER_QUARTZ_ORE.getDefaultState()));
(w, s) -> Blocks.NETHER_QUARTZ_ORE.getDefaultState(),
s -> StateMapping.replaceBlock(Blocks.NETHER_QUARTZ_ORE, Blocks.COAL_ORE)));
}), "hellfire");
private static <T extends BlockStateConverter> T register(T value, String name) {