Got themes working. ><

This commit is contained in:
Waterpicker 2022-08-22 09:35:51 -05:00
parent aed736f968
commit d6171fb15e
7 changed files with 168 additions and 49 deletions

View file

@ -2,25 +2,28 @@ package org.dimdev.dimdoors.datagen;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import com.google.gson.JsonElement;
import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.JsonOps;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.data.DataCache;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.DataProvider;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.tag.BlockTags;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.api.util.ResourceUtil;
import org.dimdev.dimdoors.pockets.theme.Converter;
import org.dimdev.dimdoors.pockets.theme.TaggedConverter;
import org.dimdev.dimdoors.block.ModBlocks;
import org.dimdev.dimdoors.pockets.theme.Theme;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Optional;
import java.util.function.BiConsumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class ThemeProvider implements DataProvider {
private static final Logger LOGGER = LogManager.getLogger();
@ -36,7 +39,7 @@ public class ThemeProvider implements DataProvider {
public void run(DataCache cache) throws IOException {
Path path = this.generator.getOutput();
BiConsumer<Identifier, JsonObject> consumer = (identifier, json) -> {
BiConsumer<Identifier, JsonElement> consumer = (identifier, json) -> {
Path outputPath = getOutput(path, identifier);
try {
@ -49,20 +52,26 @@ public class ThemeProvider implements DataProvider {
generatePatterns(consumer);
}
protected void generatePatterns(BiConsumer<Identifier, JsonObject> consumer) {
protected void generatePatterns(BiConsumer<Identifier, JsonElement> consumer) {
theme(new Identifier("dimdoors", "oak"),
TaggedConverter.of(BlockTags.STAIRS, Blocks.OAK_STAIRS),
TaggedConverter.of(BlockTags.LOGS, Blocks.OAK_LOG),
TaggedConverter.of(BlockTags.SLABS, Blocks.OAK_SLAB),
TaggedConverter.of(BlockTags.LEAVES, Blocks.OAK_LEAVES))
of(BlockTags.STAIRS, Blocks.OAK_STAIRS),
of(BlockTags.LOGS, Blocks.OAK_LOG),
of(BlockTags.SLABS, Blocks.OAK_SLAB),
of(BlockTags.LEAVES, Blocks.OAK_LEAVES),
of(ModBlocks.BLACK_FABRIC, Blocks.QUARTZ_BLOCK))
.run(consumer);
}
private TaggedThemeBuilder theme(Identifier id, Converter... converters) {
private Pair<Theme.Entry, Block> of(Object obj, Block block) {
return Pair.of(Theme.Entry.of(obj), block);
}
private TaggedThemeBuilder theme(Identifier id, Pair<Theme.Entry, Block>... converters) {
return new TaggedThemeBuilder(id, converters);
}
@Override
public String getName() {
return "Theme";
@ -73,24 +82,17 @@ public class ThemeProvider implements DataProvider {
}
public static class TaggedThemeBuilder {
private final List<Converter> converters;
private final Theme theme ;
private Identifier id;
public TaggedThemeBuilder(Identifier id, Converter... converters) {
public TaggedThemeBuilder(Identifier id, Pair<Theme.Entry, Block>... converters) {
this.id = id;
this.converters = List.of(converters);
this.theme = new Theme(Stream.of(converters).collect(Collectors.toMap(Pair::getFirst, Pair::getSecond)));
}
public void run(BiConsumer<Identifier, JsonObject> consumer) {
JsonObject object = new JsonObject();
JsonArray converters = new JsonArray();
this.converters.stream().map(converter -> converter.toNbt(new NbtCompound())).map(ResourceUtil.NBT_TO_JSON).forEach(converters::add);
object.add("converters", converters);
public void run(BiConsumer<Identifier, JsonElement> consumer) {
JsonElement object = JsonOps.INSTANCE.withEncoder(Theme.CODEC).andThen(DataResult::result).andThen(Optional::get).apply(theme);
consumer.accept(id, object);
}
}

View file

@ -30,9 +30,9 @@ public class ResourceUtil {
private static final Logger LOGGER = LogManager.getLogger();
private static final Gson GSON = new GsonBuilder().setLenient().setPrettyPrinting().create();
public static final BiFunction<String, Identifier, Path<String>> PATH_KEY_PROVIDER = (startingPath, id) -> Path.stringPath(id.getNamespace() + ":" + id.getPath().substring(0, id.getPath().lastIndexOf(".")).substring(startingPath.length() + (startingPath.endsWith("/") ? 0 : 1)));
public static final BiFunction<String, Identifier, Path<String>> PATH_KEY_PROVIDER = (startingPath, id) -> Path.stringPath(id.getNamespace() + ":" + id.getPath().substring(0, id.getPath().lastIndexOf(".")).substring(startingPath.length() + (startingPath.endsWith("/") ? 0 : 1)));
public static final BiFunction<String, Identifier, Identifier> IDENTIFIER_PROVIDER = (s, identifier) -> identifier;
public static final BiFunction<String, Identifier, String> STRING_PROVIDER = (startingPath, id) -> id.getNamespace() + ":" + id.getPath().substring(0, id.getPath().lastIndexOf(".")).substring(startingPath.length() + (startingPath.endsWith("/") ? 0 : 1));
public static final ComposableFunction<JsonElement, NbtElement> JSON_TO_NBT = json -> JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, json);

View file

@ -42,11 +42,10 @@ public class ThemeArgumentType implements ArgumentType<Theme> {
return getThemes()
.keySet()
.parallelStream()
.map(id -> "\"" + id + "\"")
.collect(Collectors.toCollection(TreeSet::new));
}
private Map<Identifier, Theme> getThemes() {
private Map<String, Theme> getThemes() {
return PocketLoader.getInstance().getThemes();
}

View file

@ -3,13 +3,13 @@ package org.dimdev.dimdoors.pockets;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtOps;
import net.minecraft.resource.ResourceManager;
import net.minecraft.util.Identifier;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.dimdev.dimdoors.api.util.*;
import org.dimdev.dimdoors.pockets.generator.PocketGenerator;
import org.dimdev.dimdoors.pockets.theme.Converter;
import org.dimdev.dimdoors.pockets.theme.Theme;
import org.dimdev.dimdoors.pockets.virtual.VirtualPocket;
import org.dimdev.dimdoors.util.schematic.Schematic;
@ -29,7 +29,7 @@ public class PocketLoader implements SimpleSynchronousResourceReloadListener {
private SimpleTree<String, VirtualPocket> virtualPockets = new SimpleTree<>(String.class);
private SimpleTree<String, PocketTemplate> templates = new SimpleTree<>(String.class);
private SimpleTree<String, NbtElement> dataTree = new SimpleTree<>(String.class);
private Map<Identifier, Theme> themes = new HashMap<>();
private Map<String, Theme> themes = new HashMap<>();
private PocketLoader() {
}
@ -43,8 +43,8 @@ public class PocketLoader implements SimpleSynchronousResourceReloadListener {
dataTree.clear();
themes.clear();
dataTree = ResourceUtil.loadResourcePathToMap(manager, "pockets/json", ".json", new SimpleTree<>(String.class), ResourceUtil.NBT_READER.composeIdentity(), ResourceUtil.PATH_KEY_PROVIDER).join();
themes = ResourceUtil.loadResourcePathToMap(manager, "pockets/themes", ".json", new HashMap<>(), ResourceUtil.NBT_READER.andThenReader(PocketLoader.this::loadTheme), ResourceUtil.IDENTIFIER_PROVIDER).join();
dataTree = ResourceUtil.loadResourcePathToMap(manager, "pockets/jsonss", ".json", new SimpleTree<>(String.class), ResourceUtil.NBT_READER.composeIdentity(), ResourceUtil.PATH_KEY_PROVIDER).join();
themes = ResourceUtil.loadResourcePathToMap(manager, "pockets/themes", ".json", new HashMap<>(), ResourceUtil.NBT_READER.andThenReader(this::loadTheme), ResourceUtil.STRING_PROVIDER).join();
CompletableFuture<SimpleTree<String, PocketGenerator>> futurePocketGeneratorMap = ResourceUtil.loadResourcePathToMap(manager, "pockets/generators", ".json", new SimpleTree<>(String.class), ResourceUtil.NBT_READER.andThenReader(pocketGeneratorLoader(manager)), ResourceUtil.PATH_KEY_PROVIDER);
CompletableFuture<SimpleTree<String, VirtualPocket>> futurePocketGroups = ResourceUtil.loadResourcePathToMap(manager, "pockets/groups", ".json", new SimpleTree<>(String.class), ResourceUtil.NBT_READER.andThenReader(virtualPocketLoader(manager)), ResourceUtil.PATH_KEY_PROVIDER);
@ -106,12 +106,8 @@ public class PocketLoader implements SimpleSynchronousResourceReloadListener {
}
}
private Theme loadTheme(NbtElement nbt, Identifier ignore) {
if(nbt instanceof NbtCompound compound && compound.contains("converters")) {
return new Theme(compound.getList("converters", NbtElement.COMPOUND_TYPE).stream().map(NbtCompound.class::cast).map(Converter::deserialize).collect(Collectors.toList()));
} else {
return Theme.NONE;
}
private Theme loadTheme(NbtElement nbt, String ignore) {
return NbtOps.INSTANCE.withParser(Theme.CODEC).apply(nbt).setPartial(Theme.NONE).getOrThrow(true, System.out::println);
}
public WeightedList<PocketGenerator, PocketGenerationContext> getPocketsMatchingTags(List<String> required, List<String> blackList, boolean exact) {
@ -134,12 +130,12 @@ public class PocketLoader implements SimpleSynchronousResourceReloadListener {
return this.pocketGroups;
}
public Map<Identifier, Theme> getThemes() {
public Map<String, Theme> getThemes() {
return this.themes;
}
public Theme getTheme(Identifier id) {
return this.themes.get(id);
return this.themes.getOrDefault(id.toString(), Theme.NONE);
}
public SimpleTree<String, VirtualPocket> getVirtualPockets() {

View file

@ -102,6 +102,7 @@ public interface Modifier extends ReferenceSerializable {
ModifierType<RelativeReferenceModifier> RELATIVE_REFERENCE_MODIFIER_TYPE = register(new Identifier("dimdoors", RelativeReferenceModifier.KEY), RelativeReferenceModifier::new);
ModifierType<OffsetModifier> OFFSET_MODIFIER_TYPE = register(new Identifier("dimdoors", OffsetModifier.KEY), OffsetModifier::new);
ModifierType<AbsoluteRiftBlockEntityModifier> ABSOLUTE_RIFT_BLOCK_ENTITY_MODIFIER_TYPE = register(new Identifier("dimdoors", AbsoluteRiftBlockEntityModifier.KEY), AbsoluteRiftBlockEntityModifier::new);
ModifierType<ThemeModifier> THEME_MODIFIER_TYPE = register(new Identifier("dimdoors", ThemeModifier.KEY), ThemeModifier::new);
Modifier fromNbt(NbtCompound nbt, ResourceManager manager);

View file

@ -0,0 +1,75 @@
package org.dimdev.dimdoors.pockets.modifier;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.resource.ResourceManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.Chunk;
import org.dimdev.dimdoors.api.util.BlockBoxUtil;
import org.dimdev.dimdoors.pockets.PocketGenerationContext;
import org.dimdev.dimdoors.pockets.PocketLoader;
import org.dimdev.dimdoors.pockets.theme.Theme;
import org.dimdev.dimdoors.world.pocket.type.LazyGenerationPocket;
import org.dimdev.dimdoors.world.pocket.type.Pocket;
public class ThemeModifier extends AbstractLazyModifier {
public static final String KEY = "theme";
private Identifier themeId = null;
@Override
protected NbtCompound toNbtInternal(NbtCompound nbt, boolean allowReference) {
super.toNbtInternal(nbt, allowReference);
if(themeId != null) nbt.putString("theme", themeId.toString());
return nbt;
}
@Override
public void applyToChunk(LazyGenerationPocket pocket, Chunk chunk) {
BlockBox chunkBox = BlockBoxUtil.getBox(chunk);
BlockBox pocketBox = pocket.getBox();
Theme theme = PocketLoader.getInstance().getTheme(themeId);
if(pocketBox.intersects(chunkBox)) {
BlockPos.stream(pocketBox).forEach(blockBox -> chunk.setBlockState(blockBox, theme.apply(chunk.getBlockState(blockBox)), false));
}
}
@Override
public Modifier fromNbt(NbtCompound nbt, ResourceManager manager) {
themeId = null;
if(nbt.contains("theme")) {
themeId = Identifier.tryParse(nbt.getString("theme"));
}
return this;
}
@Override
public ModifierType<? extends Modifier> getType() {
return ModifierType.THEME_MODIFIER_TYPE;
}
@Override
public String getKey() {
return KEY;
}
@Override
public void apply(PocketGenerationContext parameters, RiftManager manager) {
if(!manager.isPocketLazy()) {
Theme theme = PocketLoader.getInstance().getTheme(themeId);
ServerWorld world = parameters.world();
BlockPos.stream(manager.getPocket().getBox()).forEach(blockPos -> world.setBlockState(blockPos, theme.apply(world.getBlockState(blockPos))));
}
}
@Override
public void apply(PocketGenerationContext parameters, Pocket.PocketBuilder<?, ?> builder) {
}
}

View file

@ -1,23 +1,69 @@
package org.dimdev.dimdoors.pockets.theme;
import com.mojang.datafixers.util.Either;
import com.mojang.serialization.Codec;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.state.property.Property;
import net.minecraft.tag.TagKey;
import net.minecraft.util.dynamic.Codecs;
import net.minecraft.util.registry.Registry;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.function.Predicate;
public record Theme(List<Converter> converters) implements Function<BlockState, BlockState> {
public static final Theme NONE = new Theme(List.of());
public record Theme(Map<Entry, Block> entries) implements Function<BlockState, BlockState> {
public static Codec<Theme> CODEC = Codec.unboundedMap(Entry.CODEC, Registry.BLOCK.getCodec()).xmap(Theme::new, Theme::entries);
public static final Theme NONE = new Theme(Map.of());
@Override
public BlockState apply(BlockState blockState) {
for (Converter converter : converters) {
if (converter.test(blockState)) {
BlockState apply = converter.apply(blockState);
if (apply != null) return apply;
if(entries.isEmpty()) return blockState;
for (Map.Entry<Entry, Block> converter : entries.entrySet()) {
if (converter.getKey().test(blockState)) {
BlockState apply = converter.getValue().getDefaultState();
if (apply != null) {
for (Map.Entry<Property<?>, Comparable<?>> a : blockState.getEntries().entrySet()) {
if (apply.contains(a.getKey())) {
apply = apply.with((Property) a.getKey(), (Comparable) a.getValue());
}
}
return apply;
}
return blockState;
}
}
return blockState;
}
public interface Entry extends Predicate<BlockState> {
Codec<Entry> CODEC = Codecs.xor(TagKey.stringCodec(Registry.BLOCK_KEY), Registry.BLOCK.getCodec())
.xmap(a -> a.mapBoth(TagEntry::new, BlockEntry::new), b -> b.mapBoth(TagEntry::tag, BlockEntry::block))
.xmap(either -> either.map(Function.identity(), Function.identity()), entry -> entry instanceof TagEntry ? Either.left((TagEntry) entry) : Either.right((BlockEntry) entry));
public static Entry of(Object obj) {
if(obj instanceof TagKey tag) return new TagEntry(tag);
else if(obj instanceof Block block) return new BlockEntry(block);
else return null;
}
record TagEntry(TagKey<Block> tag) implements Entry {
@Override
public boolean test(BlockState blockState) {
return blockState.isIn(tag);
}
}
record BlockEntry(Block block) implements Entry {
@Override
public boolean test(BlockState blockState) {
return blockState.isOf(block);
}
}
}
}