mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-01 11:36:43 +01:00
Move state maps to resources
This commit is contained in:
parent
3d704b7def
commit
1de9313610
15 changed files with 929 additions and 361 deletions
|
@ -17,7 +17,6 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
|||
import com.minelittlepony.unicopia.ability.magic.spell.trait.TraitLoader;
|
||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
||||
import com.minelittlepony.unicopia.block.UBlocks;
|
||||
import com.minelittlepony.unicopia.block.state.StateMaps;
|
||||
import com.minelittlepony.unicopia.command.Commands;
|
||||
import com.minelittlepony.unicopia.container.UScreenHandlers;
|
||||
import com.minelittlepony.unicopia.entity.UEntities;
|
||||
|
@ -70,7 +69,6 @@ public class Unicopia implements ModInitializer {
|
|||
Race.bootstrap();
|
||||
SpellType.bootstrap();
|
||||
Abilities.bootstrap();
|
||||
StateMaps.bootstrap();
|
||||
UScreenHandlers.bootstrap();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,15 +1,24 @@
|
|||
package com.minelittlepony.unicopia.block.state;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.enums.DoubleBlockHalf;
|
||||
import net.minecraft.state.property.Properties;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public interface BlockStateConverter {
|
||||
|
||||
static ReversableBlockStateConverter of(Identifier id) {
|
||||
return new StateMapLoader.Indirect<ReversableBlockStateConverter>(id, Optional.empty());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this collection contains a mapping capable of converting the given state.
|
||||
*
|
||||
|
@ -49,16 +58,17 @@ public interface BlockStateConverter {
|
|||
}
|
||||
|
||||
if (!newState.contains(Properties.DOUBLE_BLOCK_HALF)) {
|
||||
world.setBlockState(pos, newState, 16 | 2);
|
||||
world.setBlockState(pos, newState, Block.FORCE_STATE | Block.NOTIFY_LISTENERS);
|
||||
return true;
|
||||
}
|
||||
|
||||
// for two-tall blocks (like doors) we have to update it's sibling
|
||||
boolean lower = newState.get(Properties.DOUBLE_BLOCK_HALF) == DoubleBlockHalf.LOWER;
|
||||
BlockPos other = lower ? pos.up() : pos.down();
|
||||
|
||||
if (world.getBlockState(other).isOf(state.getBlock())) {
|
||||
world.setBlockState(other, newState.with(Properties.DOUBLE_BLOCK_HALF, lower ? DoubleBlockHalf.UPPER : DoubleBlockHalf.LOWER), 16 | 2);
|
||||
world.setBlockState(pos, newState, 16 | 2);
|
||||
world.setBlockState(other, newState.with(Properties.DOUBLE_BLOCK_HALF, lower ? DoubleBlockHalf.UPPER : DoubleBlockHalf.LOWER), Block.FORCE_STATE | Block.NOTIFY_LISTENERS);
|
||||
world.setBlockState(pos, newState, Block.FORCE_STATE | Block.NOTIFY_LISTENERS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,88 +0,0 @@
|
|||
package com.minelittlepony.unicopia.block.state;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.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.TagKey;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
* A collection of block-state mappings.
|
||||
*
|
||||
*/
|
||||
class BlockStateMap implements BlockStateConverter {
|
||||
private final List<StateMapping> mappings;
|
||||
|
||||
BlockStateMap(List<StateMapping> mappings) {
|
||||
this.mappings = new ArrayList<>(mappings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConvert(@Nullable BlockState state) {
|
||||
return state != null && mappings.stream().anyMatch(i -> i.test(state));
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public BlockState getConverted(World world, @NotNull BlockState state) {
|
||||
for (StateMapping i : mappings) {
|
||||
if (i.test(state)) {
|
||||
return i.apply(world, state);
|
||||
}
|
||||
}
|
||||
|
||||
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(TagKey<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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
package com.minelittlepony.unicopia.block.state;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.gson.*;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class JsonReversableBlockStateConverter implements ReversableBlockStateConverter {
|
||||
|
||||
private final List<BlockStateConverter> entries;
|
||||
|
||||
@Nullable
|
||||
private ReversableBlockStateConverter inverse;
|
||||
|
||||
public JsonReversableBlockStateConverter(JsonElement json) {
|
||||
this(new ArrayList<>(), null);
|
||||
JsonHelper.getArray(json.getAsJsonObject(), "entries").forEach(entry -> {
|
||||
entries.add(Entry.of(entry.getAsJsonObject(), true));
|
||||
});
|
||||
}
|
||||
|
||||
public JsonReversableBlockStateConverter(List<BlockStateConverter> entries, @Nullable ReversableBlockStateConverter inverse) {
|
||||
this.inverse = inverse;
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConvert(@Nullable BlockState state) {
|
||||
return entries.stream().anyMatch(entry -> entry.canConvert(state));
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getConverted(World world, @NotNull BlockState state) {
|
||||
return entries.stream().filter(entry -> entry.canConvert(state))
|
||||
.findFirst()
|
||||
.map(entry -> entry.getConverted(world, state))
|
||||
.orElse(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateConverter getInverse() {
|
||||
if (inverse == null) {
|
||||
inverse = new JsonReversableBlockStateConverter(entries.stream()
|
||||
.filter(entry -> entry instanceof ReversableBlockStateConverter)
|
||||
.map(entry -> ((ReversableBlockStateConverter)entry).getInverse())
|
||||
.filter(Objects::nonNull)
|
||||
.toList(), this);
|
||||
}
|
||||
return inverse;
|
||||
}
|
||||
|
||||
record Entry (
|
||||
Predicate<BlockState> match,
|
||||
StateChange stateChange,
|
||||
Optional<Entry> inverse
|
||||
) implements ReversableBlockStateConverter {
|
||||
public static Entry of(JsonObject json, boolean allowInversion) {
|
||||
return new Entry(
|
||||
StatePredicate.of(json.get("match")),
|
||||
StateChange.fromJson(JsonHelper.getObject(json, "apply")),
|
||||
allowInversion && json.has("inverse") ? Optional.of(of(JsonHelper.getObject(json, "inverse"), false)) : Optional.empty()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConvert(@Nullable BlockState state) {
|
||||
return state != null && match.test(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getConverted(World world, @NotNull BlockState state) {
|
||||
return stateChange.getConverted(world, state);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BlockStateConverter getInverse() {
|
||||
return inverse.orElseGet(() -> {
|
||||
return stateChange.getInverse()
|
||||
.flatMap(invertedMatch -> StatePredicate.getInverse(match)
|
||||
.map(invertedStateChange -> new Entry(invertedMatch, invertedStateChange, Optional.of(this))))
|
||||
.orElse(null);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package com.minelittlepony.unicopia.block.state;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public static class Builder extends BlockStateMap.Builder {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends BlockStateConverter> T build() {
|
||||
return (T)new ReversableBlockStateMap(items);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package com.minelittlepony.unicopia.block.state;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.state.property.Property;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public abstract class StateChange {
|
||||
private static final Map<Identifier, Function<JsonObject, StateChange>> SERIALIZERS = new HashMap<>();
|
||||
|
||||
static {
|
||||
SERIALIZERS.put(Unicopia.id("set_state"), json -> {
|
||||
final String sstate = JsonHelper.getString(json, "state");
|
||||
final Identifier id = new Identifier(sstate);
|
||||
final float chance = JsonHelper.getFloat(json, "chance", -1);
|
||||
|
||||
return new StateChange() {
|
||||
@Override
|
||||
public Optional<Predicate<BlockState>> getInverse() {
|
||||
final StateChange self = this;
|
||||
final Predicate<BlockState> test = StatePredicate.ofState(sstate);
|
||||
return Optional.of(new StatePredicate() {
|
||||
@Override
|
||||
public StateChange getInverse() {
|
||||
return self;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState state) {
|
||||
return test.test(state);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getConverted(World world, @NotNull BlockState state) {
|
||||
if (chance > 0 && world.random.nextFloat() > chance) {
|
||||
return state;
|
||||
}
|
||||
return Registry.BLOCK.getOrEmpty(id).map(Block::getDefaultState)
|
||||
.map(newState -> merge(newState, state))
|
||||
.orElse(state);
|
||||
}
|
||||
};
|
||||
});
|
||||
SERIALIZERS.put(Unicopia.id("set_property"), json -> {
|
||||
final String name = JsonHelper.getString(json, "property");
|
||||
final String value = json.get("value").getAsString();
|
||||
final float chance = JsonHelper.getFloat(json, "chance", -1);
|
||||
|
||||
return new StateChange() {
|
||||
@Override
|
||||
public @NotNull BlockState getConverted(World world, @NotNull BlockState state) {
|
||||
if (chance > 0 && world.random.nextFloat() > chance) {
|
||||
return state;
|
||||
}
|
||||
return StatePredicate.getProperty(state, name).flatMap(property -> {
|
||||
return property.parse(value).map(v -> state.with(property, v));
|
||||
}).orElse(state);
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
SERIALIZERS.put(Unicopia.id("cycle_property"), json -> {
|
||||
final String name = JsonHelper.getString(json, "property");
|
||||
final float chance = JsonHelper.getFloat(json, "chance", -1);
|
||||
|
||||
return new StateChange() {
|
||||
@Override
|
||||
public @NotNull BlockState getConverted(World world, @NotNull BlockState state) {
|
||||
if (chance > 0 && world.random.nextFloat() > chance) {
|
||||
return state;
|
||||
}
|
||||
return StatePredicate.getProperty(state, name).map(property -> state.cycle(property)).orElse(state);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
public Optional<Predicate<BlockState>> getInverse() {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public abstract @NotNull BlockState getConverted(World world, @NotNull BlockState state);
|
||||
|
||||
public static StateChange fromJson(JsonObject json) {
|
||||
String action = JsonHelper.getString(json, "action");
|
||||
return Optional.of(SERIALIZERS.get(new Identifier(action))).map(serializer -> {
|
||||
return serializer.apply(json);
|
||||
}).orElseThrow(() -> new IllegalArgumentException("Invalid action " + action));
|
||||
}
|
||||
|
||||
private static BlockState merge(BlockState into, BlockState from) {
|
||||
for (var property : from.getProperties()) {
|
||||
if (into.contains(property)) {
|
||||
into = copy(into, from, property);
|
||||
}
|
||||
}
|
||||
return into;
|
||||
}
|
||||
|
||||
private static <T extends Comparable<T>> BlockState copy(BlockState to, BlockState from, Property<T> property) {
|
||||
return to.with(property, from.get(property));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package com.minelittlepony.unicopia.block.state;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.util.Resources;
|
||||
|
||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.resource.JsonDataLoader;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.profiler.Profiler;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public class StateMapLoader extends JsonDataLoader implements IdentifiableResourceReloadListener {
|
||||
private static final Identifier ID = Unicopia.id("data/state_maps");
|
||||
|
||||
public static final StateMapLoader INSTANCE = new StateMapLoader();
|
||||
|
||||
private Map<Identifier, ReversableBlockStateConverter> converters = new HashMap<>();
|
||||
|
||||
public StateMapLoader() {
|
||||
super(Resources.GSON, "state_maps");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply(Map<Identifier, JsonElement> data, ResourceManager manager, Profiler profiler) {
|
||||
converters = data.entrySet().stream().collect(Collectors.toMap(
|
||||
Map.Entry::getKey,
|
||||
entry -> new JsonReversableBlockStateConverter(entry.getValue())
|
||||
));
|
||||
}
|
||||
|
||||
static class Indirect<T extends BlockStateConverter> implements ReversableBlockStateConverter {
|
||||
private final Identifier id;
|
||||
private final BlockStateConverter inverse;
|
||||
|
||||
public Indirect(Identifier id, Optional<BlockStateConverter> inverse) {
|
||||
this.id = id;
|
||||
this.inverse = inverse.orElseGet(() -> new StateMapLoader.Indirect<>(id, Optional.of(this)) {
|
||||
@Override
|
||||
public Optional<BlockStateConverter> get() {
|
||||
return Optional.ofNullable(INSTANCE.converters.get(id)).map(map -> map.getInverse());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canConvert(@Nullable BlockState state) {
|
||||
return get().filter(map -> map.canConvert(state)).isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getConverted(World world, @NotNull BlockState state) {
|
||||
return get().map(map -> map.getConverted(world, state)).orElse(state);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Optional<T> get() {
|
||||
return Optional.ofNullable((T)INSTANCE.converters.get(id));
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockStateConverter getInverse() {
|
||||
return inverse;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
package com.minelittlepony.unicopia.block.state;
|
||||
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
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.Material;
|
||||
import net.minecraft.state.property.IntProperty;
|
||||
import net.minecraft.state.property.Property;
|
||||
import net.minecraft.tag.TagKey;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
interface StateMapping extends Predicate<BlockState>, BiFunction<World, BlockState, BlockState> {
|
||||
|
||||
static Predicate<BlockState> isOf(Block block) {
|
||||
return s -> s.isOf(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,
|
||||
(w, s) -> Blocks.AIR.getDefaultState());
|
||||
}
|
||||
|
||||
static StateMapping replaceBlock(TagKey<Block> tag, Block to) {
|
||||
return build(
|
||||
s -> s.isIn(tag),
|
||||
(w, s) -> to.getDefaultState(),
|
||||
s -> build(
|
||||
p -> p.isOf(to),
|
||||
(w, p) -> Registries.entriesForTag(w, tag).getRandom(w.random).get().value().getDefaultState()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static StateMapping replaceBlock(Block from, Block to) {
|
||||
return build(
|
||||
s -> s.isOf(from),
|
||||
(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.isOf(block) && s.get(property) == from,
|
||||
(w, s) -> s.with(property, to),
|
||||
s -> replaceProperty(block, property, to, from));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState state) {
|
||||
return predicate.test(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState apply(World world, BlockState state) {
|
||||
return converter.apply(world, state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StateMapping inverse() {
|
||||
if (inverse == null) {
|
||||
inverse = inverter.apply(this);
|
||||
}
|
||||
return inverse;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this state can be converted by this mapping
|
||||
*
|
||||
* @param state State to check
|
||||
*
|
||||
* @return True if the state can be converted
|
||||
*/
|
||||
@Override
|
||||
boolean test(@NotNull BlockState state);
|
||||
|
||||
/**
|
||||
* Converts the given state based on this mapping
|
||||
*
|
||||
* @param state State to convert
|
||||
*
|
||||
* @return The converted state
|
||||
*/
|
||||
@Override
|
||||
@NotNull
|
||||
BlockState apply(World world, @NotNull BlockState state);
|
||||
|
||||
/**
|
||||
* Gets the inverse of this mapping if one exists. Otherwise returns itself.
|
||||
*/
|
||||
@NotNull
|
||||
StateMapping inverse();
|
||||
}
|
|
@ -1,99 +1,15 @@
|
|||
package com.minelittlepony.unicopia.block.state;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.block.UBlocks;
|
||||
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.registry.Registry;
|
||||
public interface StateMaps {
|
||||
BlockStateConverter SNOW_PILED = of("snow_piled");
|
||||
BlockStateConverter ICE_AFFECTED = of("ice");
|
||||
BlockStateConverter SILVERFISH_AFFECTED = of("infestation");
|
||||
BlockStateConverter FIRE_AFFECTED = of("fire");
|
||||
ReversableBlockStateConverter HELLFIRE_AFFECTED = of("hellfire");
|
||||
|
||||
public class StateMaps {
|
||||
private static final Registry<BlockStateConverter> REGISTRY = Registries.createSimple(Unicopia.id("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.FROSTED_ICE)
|
||||
.replaceMaterial(Material.LAVA, UBlocks.FROSTED_OBSIDIAN)
|
||||
.add(StateMapping.cycleProperty(Blocks.SNOW, SnowBlock.LAYERS, 7))
|
||||
.replaceBlock(Blocks.FIRE, Blocks.AIR)
|
||||
.setProperty(Blocks.REDSTONE_WIRE, RedstoneWireBlock.POWER, 0));
|
||||
|
||||
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("fire", new BlockStateMap.Builder()
|
||||
.removeBlock(Blocks.SNOW)
|
||||
.removeBlock(Blocks.SNOW_BLOCK)
|
||||
.removeBlock(StateMaps::isPlant)
|
||||
.replaceBlock(BlockTags.ICE, Blocks.WATER)
|
||||
.replaceBlock(Blocks.CLAY, Blocks.BROWN_CONCRETE)
|
||||
.replaceBlock(Blocks.OBSIDIAN, Blocks.LAVA)
|
||||
.replaceBlock(UBlocks.FROSTED_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("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(String name, BlockStateMap.Builder value) {
|
||||
return Registry.register(REGISTRY, Unicopia.id(name), value.build());
|
||||
private static ReversableBlockStateConverter of(String name) {
|
||||
return BlockStateConverter.of(Unicopia.id(name));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public static void bootstrap() {}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,262 @@
|
|||
package com.minelittlepony.unicopia.block.state;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.IntPredicate;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import com.google.common.base.Predicates;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.state.property.Property;
|
||||
import net.minecraft.tag.TagKey;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.JsonHelper;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.util.registry.RegistryEntry;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
public abstract class StatePredicate implements Predicate<BlockState> {
|
||||
|
||||
public abstract StateChange getInverse();
|
||||
|
||||
@Override
|
||||
public abstract boolean test(BlockState state);
|
||||
|
||||
public static Optional<StateChange> getInverse(Predicate<BlockState> predicate) {
|
||||
if (predicate instanceof StatePredicate p) {
|
||||
return Optional.of(p.getInverse());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public static Predicate<BlockState> of(JsonElement json) {
|
||||
|
||||
List<Predicate<BlockState>> predicates = new ArrayList<>();
|
||||
|
||||
if (json.isJsonArray()) {
|
||||
json.getAsJsonArray().forEach(element -> predicates.add(of(element)));
|
||||
if (predicates.isEmpty()) {
|
||||
return Predicates.alwaysFalse();
|
||||
}
|
||||
return state -> predicates.stream().anyMatch(pred -> pred.test(state));
|
||||
}
|
||||
|
||||
JsonObject o = json.getAsJsonObject();
|
||||
if (o.has("state")) {
|
||||
predicates.add(ofState(JsonHelper.getString(o, "state")));
|
||||
}
|
||||
if (o.has("tag")) {
|
||||
Optional.of(JsonHelper.getString(o, "tag")).map(s -> TagKey.of(Registry.BLOCK_KEY, new Identifier(s))).ifPresent(tag -> {
|
||||
predicates.add(new StatePredicate() {
|
||||
@Override
|
||||
public StateChange getInverse() {
|
||||
final Optional<Predicate<BlockState>> self = Optional.of(this);
|
||||
return new StateChange() {
|
||||
@Override
|
||||
public Optional<Predicate<BlockState>> getInverse() {
|
||||
return self;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getConverted(World world, @NotNull BlockState state) {
|
||||
return Registry.BLOCK.getOrCreateEntryList(tag)
|
||||
.getRandom(world.random)
|
||||
.map(RegistryEntry::value)
|
||||
.map(Block::getDefaultState)
|
||||
.orElse(state);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState state) {
|
||||
return state.isIn(tag);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
if (o.has("builtin")) {
|
||||
predicates.add(ofBuiltIn(JsonHelper.getString(o, "builtin")));
|
||||
}
|
||||
|
||||
if (predicates.isEmpty()) {
|
||||
return Predicates.alwaysFalse();
|
||||
}
|
||||
|
||||
if (predicates.size() == 1) {
|
||||
return predicates.get(0);
|
||||
}
|
||||
|
||||
return allOf(predicates);
|
||||
}
|
||||
|
||||
private static Predicate<BlockState> allOf(List<Predicate<BlockState>> predicates) {
|
||||
return state -> {
|
||||
return predicates.isEmpty() || predicates.stream().allMatch(p -> p.test(state));
|
||||
};
|
||||
}
|
||||
|
||||
private static Predicate<BlockState> ofBuiltIn(String type) {
|
||||
switch (type) {
|
||||
case "plants": return StatePredicate::isPlant;
|
||||
case "ores": return StatePredicate::isOre;
|
||||
default: throw new IllegalArgumentException("Invalid builtin type: " + type);
|
||||
}
|
||||
}
|
||||
|
||||
static boolean isPlant(BlockState s) {
|
||||
return s.getBlock() instanceof PlantBlock;
|
||||
}
|
||||
|
||||
static boolean isOre(BlockState s) {
|
||||
return s.getBlock() instanceof OreBlock;
|
||||
}
|
||||
|
||||
public static Predicate<BlockState> ofState(String state) {
|
||||
Identifier id = new Identifier(state.split("{")[0]);
|
||||
List<PropertyOp> properties = Optional.of(state)
|
||||
.filter(s -> s.contains("{"))
|
||||
.stream()
|
||||
.flatMap(s -> Stream.of(s.split("{")[1].split("}")[0].split(",")))
|
||||
.map(PropertyOp::of)
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (properties.isEmpty()) {
|
||||
return new StatePredicate() {
|
||||
@Override
|
||||
public StateChange getInverse() {
|
||||
final Optional<Predicate<BlockState>> self = Optional.of(this);
|
||||
return new StateChange() {
|
||||
@Override
|
||||
public Optional<Predicate<BlockState>> getInverse() {
|
||||
return self;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getConverted(World world, @NotNull BlockState state) {
|
||||
return Registry.BLOCK.getOrEmpty(id).map(Block::getDefaultState).orElse(state);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState state) {
|
||||
return Registry.BLOCK.getOrEmpty(id).filter(state::isOf).isPresent();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return new StatePredicate() {
|
||||
@Override
|
||||
public StateChange getInverse() {
|
||||
final Optional<Predicate<BlockState>> self = Optional.of(this);
|
||||
return new StateChange() {
|
||||
@Override
|
||||
public Optional<Predicate<BlockState>> getInverse() {
|
||||
return self;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull BlockState getConverted(World world, @NotNull BlockState state) {
|
||||
return Registry.BLOCK.getOrEmpty(id).map(Block::getDefaultState).map(newState -> {
|
||||
for (PropertyOp prop : properties) {
|
||||
newState = prop.applyTo(world, newState);
|
||||
}
|
||||
return newState;
|
||||
}).orElse(state);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState state) {
|
||||
return Registry.BLOCK.getOrEmpty(id).filter(state::isOf).isPresent() && properties.stream().allMatch(p -> p.test(state));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private record PropertyOp (String name, String value, Comparison op) implements Predicate<BlockState> {
|
||||
public static Optional<PropertyOp> of(String pattern) {
|
||||
String[] splitten = pattern.split("[=<>]", 2);
|
||||
if (pattern.indexOf('=') == splitten[0].length()) {
|
||||
return Optional.of(new PropertyOp(splitten[0], splitten[1], Comparison.EQUAL));
|
||||
}
|
||||
if (pattern.indexOf('<') == splitten[0].length()) {
|
||||
return Optional.of(new PropertyOp(splitten[0], splitten[1], Comparison.LESS));
|
||||
}
|
||||
if (pattern.indexOf('>') == splitten[0].length()) {
|
||||
return Optional.of(new PropertyOp(splitten[0], splitten[1], Comparison.GREATER));
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public BlockState applyTo(World world, BlockState state) {
|
||||
return getProperty(state, name).flatMap(property -> {
|
||||
return property.parse(value).map(val -> {
|
||||
return applyValidValue(world, property, val, state);
|
||||
});
|
||||
}).orElse(state);
|
||||
}
|
||||
|
||||
private <T extends Comparable<T>> BlockState applyValidValue(World world, Property<T> property, T allowedValue, BlockState state) {
|
||||
if (op == Comparison.EQUAL) {
|
||||
return state.with(property, allowedValue);
|
||||
}
|
||||
if (op == Comparison.GREATER) {
|
||||
var allowedValues = property.getValues().stream().filter(v -> op.test(v.compareTo(allowedValue))).toList();
|
||||
if (!allowedValues.contains(state.get(property))) {
|
||||
int index = world.random.nextInt(allowedValues.size());
|
||||
return state.with(property, allowedValues.remove(index));
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(BlockState state) {
|
||||
return getProperty(state, name)
|
||||
.flatMap(property -> property.parse(value)
|
||||
.filter(v -> op.test(state.get(property).compareTo(v))))
|
||||
.isPresent();
|
||||
}
|
||||
|
||||
enum Comparison implements IntPredicate {
|
||||
LESS {
|
||||
@Override
|
||||
public boolean test(int value) {
|
||||
return value < 0;
|
||||
}
|
||||
},
|
||||
GREATER {
|
||||
@Override
|
||||
public boolean test(int value) {
|
||||
return value > 0;
|
||||
}
|
||||
},
|
||||
EQUAL {
|
||||
@Override
|
||||
public boolean test(int value) {
|
||||
return value == 0;
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public abstract boolean test(int value);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T extends Comparable<T>> Optional<Property<T>> getProperty(BlockState state, String name) {
|
||||
return (Optional<Property<T>>)(Object)state.getProperties().stream()
|
||||
.filter(property -> property.getName().contentEquals(name))
|
||||
.findFirst();
|
||||
}
|
||||
}
|
94
src/main/resources/data/unicopia/state_maps/fire.json
Normal file
94
src/main/resources/data/unicopia/state_maps/fire.json
Normal file
|
@ -0,0 +1,94 @@
|
|||
{
|
||||
"replace": false,
|
||||
"entries": [
|
||||
{
|
||||
"match": [
|
||||
{ "state": "minecraft:snow" },
|
||||
{ "state": "minecraft:snow_block" },
|
||||
{ "builtin": "plants" }
|
||||
],
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:air"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:ice" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:water"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:clay" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:brown_concrete"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": [
|
||||
{ "state": "minecraft:obsidian" },
|
||||
{ "state": "unicopia:frosted_obsidian" }
|
||||
],
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:lava"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:grass_block" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:dirt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:mossy_cobblestone" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:cobblestone"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:mossy_cobblestone_wall" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:cobblestone_wall"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": [
|
||||
{ "state": "minecraft:mossy_stone_bricks" },
|
||||
{ "state": "minecraft:infested_mossy_stone_bricks" }
|
||||
],
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:stone_bricks"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:podzol" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:coarse_dirt"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:farmland" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_property",
|
||||
"property": "moisture",
|
||||
"value": 0
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:dirt" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:coarse_dirt",
|
||||
"chance": 0.15
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
169
src/main/resources/data/unicopia/state_maps/hellfire.json
Normal file
169
src/main/resources/data/unicopia/state_maps/hellfire.json
Normal file
|
@ -0,0 +1,169 @@
|
|||
{
|
||||
"replace": false,
|
||||
"entries": [
|
||||
{
|
||||
"match": { "state": "minecraft:grass_block" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_nylium"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:stone" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:netherrack"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:sand" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:soul_sand"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": [
|
||||
{ "state": "minecraft:dirt" },
|
||||
{ "state": "minecraft:coarse_dirt" }
|
||||
],
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:soul_soil"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:torch" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:soul_torch"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:wall_torch" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:soul_wall_torch"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:oak_log" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_stem"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:stripped_oak_log" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:stripped_warped_stem"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:stripped_oak_wood" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:stripped_warped_hyphae"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:oak_planks" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_planks"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:oak_door" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_door"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:oak_stairs" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_stairs"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:oak_trapdoor" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_trapdoor"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:oak_pressure_plate" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_pressure_plate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:oak_button" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_button"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:oak_fence" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_fence"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:oak_fence_gate" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_fence_gate"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "tag": "minecraft:leaves" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:warped_hyphae"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:water" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:obsidian"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "builtin": "plants" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:nether_wart"
|
||||
},
|
||||
"reverse": {
|
||||
"match": { "state": "minecraft:nether_wart" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:grass"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "builtin": "ores" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:nether_quartz_ore"
|
||||
},
|
||||
"reverse": {
|
||||
"match": { "state": "minecraft:nether_quartz_ore" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:coal_ore"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
35
src/main/resources/data/unicopia/state_maps/ice.json
Normal file
35
src/main/resources/data/unicopia/state_maps/ice.json
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"parent": "unicopia:snow_piled",
|
||||
"replace": false,
|
||||
"entries": [
|
||||
{
|
||||
"match": { "state": "minecraft:water" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:frosted_ice"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:lava" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "unicopia:frosted_obsidian"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:fire" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:air"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:redstone_wire" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_property",
|
||||
"property": "power",
|
||||
"value": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
47
src/main/resources/data/unicopia/state_maps/infestation.json
Normal file
47
src/main/resources/data/unicopia/state_maps/infestation.json
Normal file
|
@ -0,0 +1,47 @@
|
|||
{
|
||||
"replace": false,
|
||||
"entries": [
|
||||
{
|
||||
"match": { "state": "minecraft:chiseled_stone_bricks" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:infested_chiseled_stone_bricks"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:cobblestone" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:infested_cobblestone"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:cracked_stone_bricks" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:infested_cracked_stone_bricks"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:mossy_stone_bricks" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:infested_mossy_stone_bricks"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:stone" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:infested_stone"
|
||||
}
|
||||
},
|
||||
{
|
||||
"match": { "state": "minecraft:stone_bricks" },
|
||||
"apply": {
|
||||
"action": "unicopia:set_state",
|
||||
"state": "minecraft:infested_stone_bricks"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
12
src/main/resources/data/unicopia/state_maps/snow_piled.json
Normal file
12
src/main/resources/data/unicopia/state_maps/snow_piled.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"replace": false,
|
||||
"entries": [
|
||||
{
|
||||
"match": { "state": "minecraft:snow{layers<7}" },
|
||||
"apply": {
|
||||
"action": "unicopia:cycle_property",
|
||||
"property": "layers"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in a new issue