More work towards making it possible to move state maps to json

This commit is contained in:
Sollace 2021-06-12 14:54:01 +02:00
parent 3c1eaec5d4
commit 241daec138
4 changed files with 186 additions and 150 deletions

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.block.state;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
@ -8,6 +9,7 @@ import javax.annotation.Nullable;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Material;
import net.minecraft.state.property.Property;
import net.minecraft.tag.Tag;
import net.minecraft.world.World;
@ -16,43 +18,22 @@ import net.minecraft.world.World;
* A collection of block-state mappings.
*
*/
class BlockStateMap extends ArrayList<StateMapping> implements BlockStateConverter {
private static final long serialVersionUID = 2602772651960588745L;
class BlockStateMap implements BlockStateConverter {
private final List<StateMapping> mappings;
public void removeBlock(Predicate<BlockState> mapper) {
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));
}
public <T extends Comparable<T>> void setProperty(Block block, Property<T> property, T to) {
add(StateMapping.setProperty(block, property, to));
BlockStateMap(List<StateMapping> mappings) {
this.mappings = new ArrayList<>(mappings);
}
@Override
public boolean canConvert(@Nullable BlockState state) {
return state != null && stream().anyMatch(i -> i.test(state));
return state != null && mappings.stream().anyMatch(i -> i.test(state));
}
@Override
@Nonnull
public BlockState getConverted(World world, @Nonnull BlockState state) {
for (StateMapping i : this) {
for (StateMapping i : mappings) {
if (i.test(state)) {
return i.apply(world, state);
}
@ -60,4 +41,48 @@ class BlockStateMap extends ArrayList<StateMapping> implements BlockStateConvert
return state;
}
public static class Builder {
protected final ArrayList<StateMapping> items = new ArrayList<>();
public Builder add(StateMapping mapping) {
items.add(mapping);
return this;
}
public Builder removeBlock(Predicate<BlockState> mapper) {
return add(StateMapping.removeBlock(mapper));
}
public Builder removeBlock(Block from) {
return add(StateMapping.removeBlock(s -> s.isOf(from)));
}
public Builder replaceMaterial(Material from, Block to) {
return add(StateMapping.replaceMaterial(from, to));
}
public Builder replaceBlock(Block from, Block to) {
return add(StateMapping.replaceBlock(from, to));
}
public Builder replaceBlock(Tag<Block> from, Block to) {
return add(StateMapping.replaceBlock(from, to));
}
public <T extends Comparable<T>> Builder replaceProperty(Block block, Property<T> property, T from, T to) {
return add(StateMapping.replaceProperty(block, property, from, to));
}
public <T extends Comparable<T>> Builder setProperty(Block block, Property<T> property, T to) {
return add(StateMapping.build(
s -> s.isOf(block),
(w, s) -> s.with(property, to)));
}
@SuppressWarnings("unchecked")
public <T extends BlockStateConverter> T build() {
return (T)new BlockStateMap(items);
}
}
}

View file

@ -1,18 +1,26 @@
package com.minelittlepony.unicopia.block.state;
class ReversableBlockStateMap extends BlockStateMap implements ReversableBlockStateConverter {
private static final long serialVersionUID = 6154365988455383098L;
import java.util.List;
import java.util.stream.Collectors;
private final BlockStateMap inverse = new BlockStateMap();
class ReversableBlockStateMap extends BlockStateMap implements ReversableBlockStateConverter {
private final BlockStateMap inverse;
ReversableBlockStateMap(List<StateMapping> mappings) {
super(mappings);
inverse = new BlockStateMap(mappings.stream().map(StateMapping::inverse).collect(Collectors.toList()));
}
@Override
public BlockStateMap getInverse() {
return inverse;
}
@Override
public boolean add(StateMapping mapping) {
inverse.add(mapping.inverse());
return super.add(mapping);
public static class Builder extends BlockStateMap.Builder {
@Override
@SuppressWarnings("unchecked")
public <T extends BlockStateConverter> T build() {
return (T)new ReversableBlockStateMap(items);
}
}
}

View file

@ -1,6 +1,5 @@
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;
@ -10,13 +9,36 @@ import javax.annotation.Nonnull;
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.Property;
import net.minecraft.tag.Tag;
import net.minecraft.world.World;
interface StateMapping extends Predicate<BlockState>, BiFunction<World, BlockState, BlockState> {
Random RNG = new Random();
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(Material.WATER), Blocks.ICE);
}
static Predicate<BlockState> isOf(Material mat) {
return s -> s.getMaterial() == mat;
}
static StateMapping removeBlock(Predicate<BlockState> mapper) {
return build(
@ -24,10 +46,6 @@ interface StateMapping extends Predicate<BlockState>, BiFunction<World, BlockSta
(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),
@ -42,7 +60,7 @@ interface StateMapping extends Predicate<BlockState>, BiFunction<World, BlockSta
@SuppressWarnings("unchecked")
static StateMapping replaceBlock(Block from, Block to) {
return build(
s -> s.getBlock() == from,
s -> s.isOf(from),
(w, s) -> {
BlockState newState = to.getDefaultState();
for (@SuppressWarnings("rawtypes") Property i : s.getProperties()) {
@ -57,21 +75,23 @@ interface StateMapping extends Predicate<BlockState>, BiFunction<World, BlockSta
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.isOf(block) && s.get(property) == from,
(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,
(w, s) -> s.with(property, to));
static StateMapping build(Predicate<BlockState> predicate, Block result) {
return build(predicate, (w, s) -> result.getDefaultState());
}
static StateMapping build(Predicate<BlockState> predicate, BiFunction<World, BlockState, BlockState> converter) {
return build(predicate, converter, s -> s);
}
static StateMapping build(Predicate<BlockState> predicate, Block result, Function<StateMapping, StateMapping> inverter) {
return build(predicate, (w, s) -> result.getDefaultState(), inverter);
}
static StateMapping build(Predicate<BlockState> predicate, BiFunction<World, BlockState, BlockState> converter, Function<StateMapping, StateMapping> inverter) {
return new StateMapping() {
private StateMapping inverse;
@ -104,9 +124,7 @@ interface StateMapping extends Predicate<BlockState>, BiFunction<World, BlockSta
* @return True if the state can be converted
*/
@Override
default boolean test(@Nonnull BlockState state) {
return true;
}
boolean test(@Nonnull BlockState state);
/**
* Converts the given state based on this mapping
@ -117,15 +135,11 @@ interface StateMapping extends Predicate<BlockState>, BiFunction<World, BlockSta
*/
@Nonnull
@Override
default BlockState apply(World world, @Nonnull BlockState state) {
return state;
}
BlockState apply(World world, @Nonnull BlockState state);
/**
* Gets the inverse of this mapping if one exists. Otherwise returns itself.
*/
@Nonnull
default StateMapping inverse() {
return this;
}
StateMapping inverse();
}

View file

@ -1,114 +1,103 @@
package com.minelittlepony.unicopia.block.state;
import java.util.function.Predicate;
import com.minelittlepony.unicopia.util.Registries;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.FarmlandBlock;
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.Util;
import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
public class StateMaps {
public static final BlockStateConverter ICE_AFFECTED = register(Util.make(new BlockStateMap(), a -> {
a.add(StateMapping.build(
s -> s.getMaterial() == Material.WATER,
(w, s) -> Blocks.ICE.getDefaultState()));
a.add(StateMapping.build(
s -> s.getMaterial() == Material.LAVA,
(w, s) -> Blocks.OBSIDIAN.getDefaultState()));
a.add(StateMapping.build(
s -> s.getBlock() == Blocks.SNOW,
(w, s) -> {
s = s.cycle(SnowBlock.LAYERS);
if (s.get(SnowBlock.LAYERS) >= 7) {
return Blocks.SNOW_BLOCK.getDefaultState();
}
private static final Registry<BlockStateConverter> REGISTRY = Registries.createSimple(new Identifier("unicopia", "state_map"));
return s;
}));
a.replaceBlock(Blocks.FIRE, Blocks.AIR);
a.setProperty(Blocks.REDSTONE_WIRE, RedstoneWireBlock.POWER, 0);
}), "ice");
public static final BlockStateConverter ICE_AFFECTED = register("ice", new BlockStateMap.Builder()
.replaceMaterial(Material.WATER, Blocks.ICE)
.replaceMaterial(Material.LAVA, Blocks.OBSIDIAN)
.add(StateMapping.incrementSnow())
.replaceBlock(Blocks.FIRE, Blocks.AIR)
.setProperty(Blocks.REDSTONE_WIRE, RedstoneWireBlock.POWER, 0));
public static final ReversableBlockStateConverter MOSS_AFFECTED = register(Util.make(new ReversableBlockStateMap(), a -> {
a.replaceBlock(Blocks.MOSSY_COBBLESTONE, Blocks.COBBLESTONE);
a.replaceBlock(Blocks.MOSSY_COBBLESTONE_SLAB, Blocks.COBBLESTONE_SLAB);
a.replaceBlock(Blocks.MOSSY_COBBLESTONE_STAIRS, Blocks.COBBLESTONE_STAIRS);
a.replaceBlock(Blocks.MOSSY_COBBLESTONE_WALL, Blocks.COBBLESTONE_WALL);
a.replaceBlock(Blocks.MOSSY_STONE_BRICK_SLAB, Blocks.STONE_BRICK_SLAB);
a.replaceBlock(Blocks.MOSSY_STONE_BRICK_STAIRS, Blocks.STONE_BRICK_STAIRS);
a.replaceBlock(Blocks.MOSSY_STONE_BRICK_WALL, Blocks.MOSSY_STONE_BRICK_WALL);
a.replaceBlock(Blocks.MOSSY_STONE_BRICKS, Blocks.STONE_BRICKS);
a.replaceBlock(Blocks.INFESTED_MOSSY_STONE_BRICKS, Blocks.INFESTED_STONE_BRICKS);
}), "moss");
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(Util.make(new BlockStateMap(), a -> {
a.replaceBlock(Blocks.CHISELED_STONE_BRICKS, Blocks.INFESTED_CHISELED_STONE_BRICKS);
a.replaceBlock(Blocks.COBBLESTONE, Blocks.INFESTED_COBBLESTONE);
a.replaceBlock(Blocks.CRACKED_STONE_BRICKS, Blocks.INFESTED_CRACKED_STONE_BRICKS);
a.replaceBlock(Blocks.MOSSY_STONE_BRICKS, Blocks.INFESTED_MOSSY_STONE_BRICKS);
a.replaceBlock(Blocks.STONE, Blocks.INFESTED_STONE);
a.replaceBlock(Blocks.STONE_BRICKS, Blocks.INFESTED_STONE_BRICKS);
}), "infestation");
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)
.replaceBlock(Blocks.CRACKED_STONE_BRICKS, Blocks.INFESTED_CRACKED_STONE_BRICKS)
.replaceBlock(Blocks.MOSSY_STONE_BRICKS, Blocks.INFESTED_MOSSY_STONE_BRICKS)
.replaceBlock(Blocks.STONE, Blocks.INFESTED_STONE)
.replaceBlock(Blocks.STONE_BRICKS, Blocks.INFESTED_STONE_BRICKS));
public static final BlockStateConverter FIRE_AFFECTED = register(Util.make(new BlockStateMap(), a -> {
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);
a.replaceBlock(Blocks.MOSSY_COBBLESTONE, Blocks.COBBLESTONE);
a.replaceBlock(Blocks.MOSSY_COBBLESTONE_WALL, Blocks.COBBLESTONE_WALL);
a.replaceBlock(Blocks.MOSSY_STONE_BRICKS, Blocks.STONE_BRICKS);
a.replaceBlock(Blocks.INFESTED_MOSSY_STONE_BRICKS, Blocks.INFESTED_STONE_BRICKS);
a.replaceBlock(Blocks.PODZOL, Blocks.COARSE_DIRT);
a.setProperty(Blocks.FARMLAND, FarmlandBlock.MOISTURE, 0);
a.add(StateMapping.build(
s -> s.getBlock() == Blocks.DIRT,
(w, s) -> (w.random.nextFloat() <= 0.15 ? Blocks.COARSE_DIRT.getDefaultState() : s)));
}), "fire");
public static final BlockStateConverter FIRE_AFFECTED = register("fire", new BlockStateMap.Builder()
.removeBlock(Blocks.SNOW)
.removeBlock(Blocks.SNOW_BLOCK)
.removeBlock(StateMaps::isPlant)
.replaceBlock(Blocks.ICE, Blocks.WATER)
.replaceBlock(Blocks.PACKED_ICE, Blocks.WATER)
.replaceBlock(Blocks.CLAY, Blocks.BROWN_CONCRETE)
.replaceBlock(Blocks.OBSIDIAN, Blocks.LAVA)
.replaceBlock(Blocks.GRASS_BLOCK, Blocks.DIRT)
.replaceBlock(Blocks.MOSSY_COBBLESTONE, Blocks.COBBLESTONE)
.replaceBlock(Blocks.MOSSY_COBBLESTONE_WALL, Blocks.COBBLESTONE_WALL)
.replaceBlock(Blocks.MOSSY_STONE_BRICKS, Blocks.STONE_BRICKS)
.replaceBlock(Blocks.INFESTED_MOSSY_STONE_BRICKS, Blocks.INFESTED_STONE_BRICKS)
.replaceBlock(Blocks.PODZOL, Blocks.COARSE_DIRT)
.setProperty(Blocks.FARMLAND, FarmlandBlock.MOISTURE, 0)
.add(StateMapping.build(isOf(Blocks.DIRT), (w, s) -> (w.random.nextFloat() <= 0.15 ? Blocks.COARSE_DIRT.getDefaultState() : s))));
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,
(w, s) -> Blocks.OBSIDIAN.getDefaultState(),
s -> StateMapping.replaceBlock(Blocks.OBSIDIAN, Blocks.WATER)));
a.add(StateMapping.build(
s -> s.getBlock() instanceof PlantBlock,
(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),
(w, s) -> Blocks.NETHER_QUARTZ_ORE.getDefaultState(),
s -> StateMapping.replaceBlock(Blocks.NETHER_QUARTZ_ORE, Blocks.COAL_ORE)));
}), "hellfire");
public static final ReversableBlockStateConverter HELLFIRE_AFFECTED = register("hellfire", new ReversableBlockStateMap.Builder()
.replaceBlock(Blocks.GRASS_BLOCK, Blocks.WARPED_NYLIUM)
.replaceBlock(Blocks.STONE, Blocks.NETHERRACK)
.replaceBlock(Blocks.SAND, Blocks.SOUL_SAND)
.replaceBlock(Blocks.GRAVEL, Blocks.SOUL_SAND)
.replaceBlock(Blocks.DIRT, Blocks.SOUL_SOIL)
.replaceBlock(Blocks.COARSE_DIRT, Blocks.SOUL_SOIL)
.replaceBlock(Blocks.TORCH, Blocks.SOUL_TORCH)
.replaceBlock(Blocks.WALL_TORCH, Blocks.SOUL_WALL_TORCH)
.replaceBlock(Blocks.OAK_LOG, Blocks.WARPED_STEM)
.replaceBlock(Blocks.STRIPPED_OAK_LOG, Blocks.STRIPPED_WARPED_STEM)
.replaceBlock(Blocks.STRIPPED_OAK_WOOD, Blocks.STRIPPED_WARPED_HYPHAE)
.replaceBlock(Blocks.OAK_PLANKS, Blocks.WARPED_PLANKS)
.replaceBlock(Blocks.OAK_DOOR, Blocks.WARPED_DOOR)
.replaceBlock(Blocks.OAK_STAIRS, Blocks.WARPED_STAIRS)
.replaceBlock(Blocks.OAK_TRAPDOOR, Blocks.WARPED_TRAPDOOR)
.replaceBlock(Blocks.OAK_PRESSURE_PLATE, Blocks.WARPED_PRESSURE_PLATE)
.replaceBlock(Blocks.OAK_BUTTON, Blocks.WARPED_BUTTON)
.replaceBlock(Blocks.OAK_FENCE, Blocks.WARPED_FENCE)
.replaceBlock(Blocks.OAK_FENCE_GATE, Blocks.WARPED_FENCE_GATE)
.replaceBlock(BlockTags.LEAVES, Blocks.WARPED_HYPHAE)
.replaceMaterial(Material.WATER, Blocks.OBSIDIAN)
.add(StateMapping.build(StateMaps::isPlant, Blocks.NETHER_WART, s -> StateMapping.replaceBlock(Blocks.NETHER_WART, Blocks.GRASS)))
.add(StateMapping.build(s -> !s.isOf(Blocks.NETHER_QUARTZ_ORE) && isOre(s), Blocks.NETHER_QUARTZ_ORE, s -> StateMapping.replaceBlock(Blocks.NETHER_QUARTZ_ORE, Blocks.COAL_ORE))));
private static <T extends BlockStateConverter> T register(T value, String name) {
return value;
private static <T extends BlockStateConverter> T register(String name, BlockStateMap.Builder value) {
return Registry.register(REGISTRY, new Identifier("unicopia", name), value.build());
}
static Predicate<BlockState> isOf(Block block) {
return s -> s.isOf(block);
}
static boolean isPlant(BlockState s) {
return s.getBlock() instanceof PlantBlock;
}
static boolean isOre(BlockState s) {
return s.getBlock() instanceof OreBlock;
}
}