diff --git a/src/main/datagen/org/dimdev/dimdoors/datagen/ThemeProvider.java b/src/main/datagen/org/dimdev/dimdoors/datagen/ThemeProvider.java index 5fd51401..36b33e3e 100644 --- a/src/main/datagen/org/dimdev/dimdoors/datagen/ThemeProvider.java +++ b/src/main/datagen/org/dimdev/dimdoors/datagen/ThemeProvider.java @@ -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 consumer = (identifier, json) -> { + BiConsumer consumer = (identifier, json) -> { Path outputPath = getOutput(path, identifier); try { @@ -49,20 +52,26 @@ public class ThemeProvider implements DataProvider { generatePatterns(consumer); } - protected void generatePatterns(BiConsumer consumer) { + protected void generatePatterns(BiConsumer 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 of(Object obj, Block block) { + return Pair.of(Theme.Entry.of(obj), block); + } + + private TaggedThemeBuilder theme(Identifier id, Pair... 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 converters; + private final Theme theme ; private Identifier id; - public TaggedThemeBuilder(Identifier id, Converter... converters) { + public TaggedThemeBuilder(Identifier id, Pair... 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 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 consumer) { + JsonElement object = JsonOps.INSTANCE.withEncoder(Theme.CODEC).andThen(DataResult::result).andThen(Optional::get).apply(theme); consumer.accept(id, object); } } diff --git a/src/main/java/org/dimdev/dimdoors/api/util/ResourceUtil.java b/src/main/java/org/dimdev/dimdoors/api/util/ResourceUtil.java index 3e347be7..9de41f37 100644 --- a/src/main/java/org/dimdev/dimdoors/api/util/ResourceUtil.java +++ b/src/main/java/org/dimdev/dimdoors/api/util/ResourceUtil.java @@ -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> 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> 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 IDENTIFIER_PROVIDER = (s, identifier) -> identifier; + public static final BiFunction STRING_PROVIDER = (startingPath, id) -> id.getNamespace() + ":" + id.getPath().substring(0, id.getPath().lastIndexOf(".")).substring(startingPath.length() + (startingPath.endsWith("/") ? 0 : 1)); public static final ComposableFunction JSON_TO_NBT = json -> JsonOps.INSTANCE.convertTo(NbtOps.INSTANCE, json); diff --git a/src/main/java/org/dimdev/dimdoors/command/arguments/ThemeArgumentType.java b/src/main/java/org/dimdev/dimdoors/command/arguments/ThemeArgumentType.java index 35f088b2..0c4cbc79 100644 --- a/src/main/java/org/dimdev/dimdoors/command/arguments/ThemeArgumentType.java +++ b/src/main/java/org/dimdev/dimdoors/command/arguments/ThemeArgumentType.java @@ -42,11 +42,10 @@ public class ThemeArgumentType implements ArgumentType { return getThemes() .keySet() .parallelStream() - .map(id -> "\"" + id + "\"") .collect(Collectors.toCollection(TreeSet::new)); } - private Map getThemes() { + private Map getThemes() { return PocketLoader.getInstance().getThemes(); } diff --git a/src/main/java/org/dimdev/dimdoors/pockets/PocketLoader.java b/src/main/java/org/dimdev/dimdoors/pockets/PocketLoader.java index 27359b70..a9dfd4a7 100644 --- a/src/main/java/org/dimdev/dimdoors/pockets/PocketLoader.java +++ b/src/main/java/org/dimdev/dimdoors/pockets/PocketLoader.java @@ -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 virtualPockets = new SimpleTree<>(String.class); private SimpleTree templates = new SimpleTree<>(String.class); private SimpleTree dataTree = new SimpleTree<>(String.class); - private Map themes = new HashMap<>(); + private Map 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> futurePocketGeneratorMap = ResourceUtil.loadResourcePathToMap(manager, "pockets/generators", ".json", new SimpleTree<>(String.class), ResourceUtil.NBT_READER.andThenReader(pocketGeneratorLoader(manager)), ResourceUtil.PATH_KEY_PROVIDER); CompletableFuture> 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 getPocketsMatchingTags(List required, List blackList, boolean exact) { @@ -134,12 +130,12 @@ public class PocketLoader implements SimpleSynchronousResourceReloadListener { return this.pocketGroups; } - public Map getThemes() { + public Map getThemes() { return this.themes; } public Theme getTheme(Identifier id) { - return this.themes.get(id); + return this.themes.getOrDefault(id.toString(), Theme.NONE); } public SimpleTree getVirtualPockets() { diff --git a/src/main/java/org/dimdev/dimdoors/pockets/modifier/Modifier.java b/src/main/java/org/dimdev/dimdoors/pockets/modifier/Modifier.java index e8c17c82..6b0a33b4 100644 --- a/src/main/java/org/dimdev/dimdoors/pockets/modifier/Modifier.java +++ b/src/main/java/org/dimdev/dimdoors/pockets/modifier/Modifier.java @@ -102,6 +102,7 @@ public interface Modifier extends ReferenceSerializable { ModifierType RELATIVE_REFERENCE_MODIFIER_TYPE = register(new Identifier("dimdoors", RelativeReferenceModifier.KEY), RelativeReferenceModifier::new); ModifierType OFFSET_MODIFIER_TYPE = register(new Identifier("dimdoors", OffsetModifier.KEY), OffsetModifier::new); ModifierType ABSOLUTE_RIFT_BLOCK_ENTITY_MODIFIER_TYPE = register(new Identifier("dimdoors", AbsoluteRiftBlockEntityModifier.KEY), AbsoluteRiftBlockEntityModifier::new); + ModifierType THEME_MODIFIER_TYPE = register(new Identifier("dimdoors", ThemeModifier.KEY), ThemeModifier::new); Modifier fromNbt(NbtCompound nbt, ResourceManager manager); diff --git a/src/main/java/org/dimdev/dimdoors/pockets/modifier/ThemeModifier.java b/src/main/java/org/dimdev/dimdoors/pockets/modifier/ThemeModifier.java new file mode 100644 index 00000000..69b6ed1a --- /dev/null +++ b/src/main/java/org/dimdev/dimdoors/pockets/modifier/ThemeModifier.java @@ -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 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) { + + } +} diff --git a/src/main/java/org/dimdev/dimdoors/pockets/theme/Theme.java b/src/main/java/org/dimdev/dimdoors/pockets/theme/Theme.java index 92c78527..1f7ee057 100644 --- a/src/main/java/org/dimdev/dimdoors/pockets/theme/Theme.java +++ b/src/main/java/org/dimdev/dimdoors/pockets/theme/Theme.java @@ -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 converters) implements Function { - public static final Theme NONE = new Theme(List.of()); +public record Theme(Map entries) implements Function { + public static Codec 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 converter : entries.entrySet()) { + if (converter.getKey().test(blockState)) { + BlockState apply = converter.getValue().getDefaultState(); + if (apply != null) { + for (Map.Entry, 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 { + Codec 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 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); + } + } + } }