diff --git a/build-logic/src/main/kotlin/rainbow.base-conventions.gradle.kts b/build-logic/src/main/kotlin/rainbow.base-conventions.gradle.kts index 2eb4e5a..ee2f1cb 100644 --- a/build-logic/src/main/kotlin/rainbow.base-conventions.gradle.kts +++ b/build-logic/src/main/kotlin/rainbow.base-conventions.gradle.kts @@ -34,13 +34,6 @@ dependencies { modImplementation(libs.fabric.loader) modImplementation(libs.fabric.api) - - implementation(libs.creative.api) - implementation(libs.creative.serializer.minecraft) - implementation(libs.packconverter) - include(libs.creative.api) - include(libs.creative.serializer.minecraft) - include(libs.packconverter) } tasks { diff --git a/rainbow/src/main/java/org/geysermc/rainbow/KeyUtil.java b/rainbow/src/main/java/org/geysermc/rainbow/KeyUtil.java deleted file mode 100644 index 5811cfc..0000000 --- a/rainbow/src/main/java/org/geysermc/rainbow/KeyUtil.java +++ /dev/null @@ -1,16 +0,0 @@ -package org.geysermc.rainbow; - -import net.kyori.adventure.key.Key; -import net.minecraft.resources.ResourceLocation; - -@SuppressWarnings("PatternValidation") -public interface KeyUtil { - - static Key resourceLocationToKey(ResourceLocation location) { - return Key.key(location.getNamespace(), location.getPath()); - } - - static ResourceLocation keyToResourceLocation(Key key) { - return ResourceLocation.fromNamespaceAndPath(key.namespace(), key.value()); - } -} diff --git a/rainbow/src/main/java/org/geysermc/rainbow/Rainbow.java b/rainbow/src/main/java/org/geysermc/rainbow/Rainbow.java index d14f252..f0f4eba 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/Rainbow.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/Rainbow.java @@ -2,39 +2,16 @@ package org.geysermc.rainbow; import com.mojang.logging.LogUtils; import net.fabricmc.api.ClientModInitializer; -import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager; import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.command.v2.ArgumentTypeRegistry; -import net.fabricmc.loader.api.FabricLoader; -import net.minecraft.client.Minecraft; import net.minecraft.commands.synchronization.SingletonArgumentInfo; -import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; -import org.geysermc.pack.bedrock.resource.BedrockResourcePack; -import org.geysermc.pack.converter.PackConversionContext; -import org.geysermc.pack.converter.PackConverter; -import org.geysermc.pack.converter.converter.ActionListener; -import org.geysermc.pack.converter.converter.Converter; -import org.geysermc.pack.converter.converter.base.PackManifestConverter; -import org.geysermc.pack.converter.converter.lang.LangConverter; -import org.geysermc.pack.converter.converter.misc.SplashTextConverter; -import org.geysermc.pack.converter.converter.model.ModelConverter; -import org.geysermc.pack.converter.data.ConversionData; -import org.geysermc.pack.converter.util.DefaultLogListener; -import org.geysermc.pack.converter.util.LogListener; import org.geysermc.rainbow.command.CommandSuggestionsArgumentType; import org.geysermc.rainbow.command.PackGeneratorCommand; -import org.geysermc.rainbow.creative.MinecraftCreativeResourcePack; import org.geysermc.rainbow.mapper.PackMapper; import org.slf4j.Logger; -import javax.imageio.ImageIO; -import java.io.IOException; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; - public class Rainbow implements ClientModInitializer { public static final String MOD_ID = "rainbow"; @@ -52,58 +29,6 @@ public class Rainbow implements ClientModInitializer { ArgumentTypeRegistry.registerArgumentType(getModdedLocation("command_suggestions"), CommandSuggestionsArgumentType.class, SingletonArgumentInfo.contextFree(CommandSuggestionsArgumentType::new)); - - ClientCommandRegistrationCallback.EVENT.register((dispatcher, buildContext) -> { - dispatcher.register(ClientCommandManager.literal("debugtest") - .executes(context -> { - - PackConverter packConverter = new PackConverter() - .packName("RAINBOW-TEST") - .output(FabricLoader.getInstance().getGameDir().resolve("pack-convert-out")); - Path tmpDir = FabricLoader.getInstance().getGameDir().resolve("pack-convert-temp"); - - ImageIO.scanForPlugins(); - MinecraftCreativeResourcePack resourcePack = new MinecraftCreativeResourcePack(Minecraft.getInstance().getResourceManager()); - BedrockResourcePack bedrockResourcePack = new BedrockResourcePack(tmpDir); - - LogListener logListener = new DefaultLogListener(); - final Converter.ConversionDataCreationContext conversionDataCreationContext = new Converter.ConversionDataCreationContext( - packConverter, logListener, null, tmpDir, resourcePack, resourcePack - ); - - - List> converters = new ArrayList<>(); - converters.add(new PackManifestConverter()); - converters.add(new LangConverter()); - converters.add(new ModelConverter()); - - int errors = 0; - for (Converter converter : converters) { - ConversionData data = converter.createConversionData(conversionDataCreationContext); - PackConversionContext conversionContext = new PackConversionContext<>(data, packConverter, resourcePack, bedrockResourcePack, logListener); - - List> actionListeners = List.of(); - try { - actionListeners.forEach(actionListener -> actionListener.preConvert((PackConversionContext) conversionContext)); - converter.convert(conversionContext); - actionListeners.forEach(actionListener -> actionListener.postConvert((PackConversionContext) conversionContext)); - } catch (Throwable t) { - logListener.error("Error converting pack!", t); - errors++; - } - } - - try { - bedrockResourcePack.export(); - } catch (IOException e) { - throw new RuntimeException(e); - } - context.getSource().sendFeedback(Component.literal("exporting, " + errors + " errors")); - - return 0; - }) - ); - }); } public static ResourceLocation getModdedLocation(String path) { diff --git a/rainbow/src/main/java/org/geysermc/rainbow/creative/CachingStreamResourceContainer.java b/rainbow/src/main/java/org/geysermc/rainbow/creative/CachingStreamResourceContainer.java deleted file mode 100644 index 1beb8c5..0000000 --- a/rainbow/src/main/java/org/geysermc/rainbow/creative/CachingStreamResourceContainer.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.geysermc.rainbow.creative; - -import it.unimi.dsi.fastutil.objects.Object2ObjectMap; -import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; -import it.unimi.dsi.fastutil.objects.Reference2ObjectMap; -import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.key.Keyed; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import team.unnamed.creative.part.ResourcePackPart; -import team.unnamed.creative.serialize.minecraft.ResourceCategory; -import team.unnamed.creative.sound.SoundRegistry; -import team.unnamed.creative.texture.Texture; - -@SuppressWarnings("UnstableApiUsage") -public abstract class CachingStreamResourceContainer implements StreamResourceContainer { - private final Reference2ObjectMap, Object2ObjectMap> cache = new Reference2ObjectOpenHashMap<>(); - private final Object2ObjectMap soundRegistryCache = new Object2ObjectOpenHashMap<>(); - private final Object2ObjectMap textureCache = new Object2ObjectOpenHashMap<>(); - - @SuppressWarnings("unchecked") - private T cacheOrDeserialize(ResourceCategory deserializer, Key key) { - Object2ObjectMap deserializerCache = cache.computeIfAbsent(deserializer, cacheKey -> new Object2ObjectOpenHashMap<>()); - return (T) deserializerCache.computeIfAbsent(key, cacheKey -> StreamResourceContainer.super.deserialize(deserializer, key)); - } - - @Override - public @Nullable T deserialize(ResourceCategory deserializer, Key key) { - return cacheOrDeserialize(deserializer, key); - } - - @Override - public @Nullable SoundRegistry soundRegistry(@NotNull String namespace) { - return soundRegistryCache.computeIfAbsent(namespace, cacheNamespace -> StreamResourceContainer.super.soundRegistry(namespace)); - } - - @Override - public @Nullable Texture texture(@NotNull Key key) { - return textureCache.computeIfAbsent(key, cacheKey -> StreamResourceContainer.super.texture(key)); - } -} diff --git a/rainbow/src/main/java/org/geysermc/rainbow/creative/ImmutableResourceContainer.java b/rainbow/src/main/java/org/geysermc/rainbow/creative/ImmutableResourceContainer.java deleted file mode 100644 index 4859eb4..0000000 --- a/rainbow/src/main/java/org/geysermc/rainbow/creative/ImmutableResourceContainer.java +++ /dev/null @@ -1,140 +0,0 @@ -package org.geysermc.rainbow.creative; - -import net.kyori.adventure.key.Key; -import org.jetbrains.annotations.NotNull; -import team.unnamed.creative.atlas.Atlas; -import team.unnamed.creative.base.Writable; -import team.unnamed.creative.blockstate.BlockState; -import team.unnamed.creative.equipment.Equipment; -import team.unnamed.creative.font.Font; -import team.unnamed.creative.item.Item; -import team.unnamed.creative.lang.Language; -import team.unnamed.creative.model.Model; -import team.unnamed.creative.overlay.ResourceContainer; -import team.unnamed.creative.resources.MergeStrategy; -import team.unnamed.creative.sound.Sound; -import team.unnamed.creative.sound.SoundRegistry; -import team.unnamed.creative.texture.Texture; - -@SuppressWarnings("NonExtendableApiUsage") -public interface ImmutableResourceContainer extends ResourceContainer { - - private static T thr() { - throw new UnsupportedOperationException("ResourceContainer is immutable"); - } - - @Override - default void atlas(@NotNull Atlas atlas) { - thr(); - } - - @Override - default boolean removeAtlas(@NotNull Key key) { - return thr(); - } - - @Override - default void blockState(@NotNull BlockState state) { - thr(); - } - - @Override - default boolean removeBlockState(@NotNull Key key) { - return thr(); - } - - @Override - default void equipment(@NotNull Equipment equipment) { - thr(); - } - - @Override - default boolean removeEquipment(@NotNull Key key) { - return thr(); - } - - @Override - default void font(@NotNull Font font) { - thr(); - } - - @Override - default boolean removeFont(@NotNull Key key) { - return thr(); - } - - @Override - default void item(@NotNull Item item) { - thr(); - } - - @Override - default boolean removeItem(@NotNull Key key) { - return thr(); - } - - @Override - default void language(@NotNull Language language) { - thr(); - } - - @Override - default boolean removeLanguage(@NotNull Key key) { - return thr(); - } - - @Override - default void model(@NotNull Model model) { - thr(); - } - - @Override - default boolean removeModel(@NotNull Key key) { - return thr(); - } - - @Override - default void soundRegistry(@NotNull SoundRegistry soundRegistry) { - thr(); - } - - @Override - default boolean removeSoundRegistry(@NotNull String namespace) { - return thr(); - } - - @Override - default void sound(@NotNull Sound sound) { - thr(); - } - - @Override - default boolean removeSound(@NotNull Key key) { - return thr(); - } - - @Override - default void texture(@NotNull Texture texture) { - thr(); - } - - @Override - default boolean removeTexture(@NotNull Key key) { - return thr(); - } - - @Override - default void unknownFile(@NotNull String path, @NotNull Writable data) { - thr(); - } - - @Override - default boolean removeUnknownFile(@NotNull String path) { - return thr(); - } - - @Override - default void merge(@NotNull ResourceContainer other, @NotNull MergeStrategy strategy) { - thr(); - } -} diff --git a/rainbow/src/main/java/org/geysermc/rainbow/creative/ImmutableResourcePack.java b/rainbow/src/main/java/org/geysermc/rainbow/creative/ImmutableResourcePack.java deleted file mode 100644 index 37edc55..0000000 --- a/rainbow/src/main/java/org/geysermc/rainbow/creative/ImmutableResourcePack.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.geysermc.rainbow.creative; - -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import team.unnamed.creative.ResourcePack; -import team.unnamed.creative.base.Writable; -import team.unnamed.creative.metadata.Metadata; -import team.unnamed.creative.metadata.sodium.SodiumMeta; -import team.unnamed.creative.overlay.Overlay; - -@SuppressWarnings("NonExtendableApiUsage") -public interface ImmutableResourcePack extends ResourcePack, ImmutableResourceContainer { - - private static void thr() { - throw new UnsupportedOperationException("ResourcePack is immutable"); - } - - @Override - default void icon(@Nullable Writable icon) { - thr(); - } - - @Override - default void metadata(@NotNull Metadata metadata) { - thr(); - } - - @Override - default void overlay(@NotNull Overlay overlay) { - thr(); - } - - @Override - default void sodiumMeta(@NotNull SodiumMeta sodiumMeta) { - thr(); - } -} diff --git a/rainbow/src/main/java/org/geysermc/rainbow/creative/MinecraftCreativeResourcePack.java b/rainbow/src/main/java/org/geysermc/rainbow/creative/MinecraftCreativeResourcePack.java deleted file mode 100644 index 09e3314..0000000 --- a/rainbow/src/main/java/org/geysermc/rainbow/creative/MinecraftCreativeResourcePack.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.geysermc.rainbow.creative; - -import net.kyori.adventure.key.Key; -import net.minecraft.server.packs.resources.Resource; -import net.minecraft.server.packs.resources.ResourceManager; -import org.geysermc.rainbow.KeyUtil; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import team.unnamed.creative.base.Writable; -import team.unnamed.creative.metadata.Metadata; -import team.unnamed.creative.overlay.Overlay; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Collection; -import java.util.List; -import java.util.Optional; -import java.util.regex.Pattern; - -public class MinecraftCreativeResourcePack extends CachingStreamResourceContainer implements ImmutableResourcePack { - // Matches a path in 3 groups: the first directory, the rest of the path, and the file extension (e.g. .json) - private static final Pattern PATH_SANITIZE_REGEX = Pattern.compile("(^\\w+/)(.*)(\\.\\w+$)"); - - private final ResourceManager resourceManager; - - public MinecraftCreativeResourcePack(ResourceManager resourceManager) { - this.resourceManager = resourceManager; - } - - @Override - public @Nullable InputStream open(Key key) throws IOException { - Optional resource = resourceManager.getResource(KeyUtil.keyToResourceLocation(key)); - if (resource.isPresent()) { - return resource.get().open(); - } - return null; - } - - @Override - public List assets(String category) { - return resourceManager.listResources(category, resource -> true).keySet().stream() - .map(location -> location.withPath(path -> PATH_SANITIZE_REGEX.matcher(path).replaceAll("$2"))) - .map(KeyUtil::resourceLocationToKey) - .toList(); - } - - @Override - public Collection namespaces() { - return resourceManager.getNamespaces(); - } - - @Override - public @Nullable Writable icon() { - return null; - } - - @Override - public @NotNull Metadata metadata() { - return Metadata.empty(); - } - - @Override - public @Nullable Overlay overlay(@NotNull String directory) { - return null; - } - - @Override - public @NotNull Collection overlays() { - return List.of(); - } -} diff --git a/rainbow/src/main/java/org/geysermc/rainbow/creative/StreamResourceContainer.java b/rainbow/src/main/java/org/geysermc/rainbow/creative/StreamResourceContainer.java deleted file mode 100644 index f260518..0000000 --- a/rainbow/src/main/java/org/geysermc/rainbow/creative/StreamResourceContainer.java +++ /dev/null @@ -1,254 +0,0 @@ -package org.geysermc.rainbow.creative; - -import com.google.gson.JsonElement; -import net.kyori.adventure.key.Key; -import net.kyori.adventure.key.Keyed; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import team.unnamed.creative.atlas.Atlas; -import team.unnamed.creative.base.Writable; -import team.unnamed.creative.blockstate.BlockState; -import team.unnamed.creative.equipment.Equipment; -import team.unnamed.creative.font.Font; -import team.unnamed.creative.item.Item; -import team.unnamed.creative.lang.Language; -import team.unnamed.creative.metadata.Metadata; -import team.unnamed.creative.model.Model; -import team.unnamed.creative.part.ResourcePackPart; -import team.unnamed.creative.serialize.minecraft.GsonUtil; -import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackStructure; -import team.unnamed.creative.serialize.minecraft.ResourceCategory; -import team.unnamed.creative.serialize.minecraft.atlas.AtlasSerializer; -import team.unnamed.creative.serialize.minecraft.blockstate.BlockStateSerializer; -import team.unnamed.creative.serialize.minecraft.equipment.EquipmentCategory; -import team.unnamed.creative.serialize.minecraft.font.FontSerializer; -import team.unnamed.creative.serialize.minecraft.item.ItemSerializer; -import team.unnamed.creative.serialize.minecraft.language.LanguageSerializer; -import team.unnamed.creative.serialize.minecraft.metadata.MetadataSerializer; -import team.unnamed.creative.serialize.minecraft.model.ModelSerializer; -import team.unnamed.creative.serialize.minecraft.sound.SoundRegistrySerializer; -import team.unnamed.creative.serialize.minecraft.sound.SoundSerializer; -import team.unnamed.creative.sound.Sound; -import team.unnamed.creative.sound.SoundRegistry; -import team.unnamed.creative.texture.Texture; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.nio.charset.StandardCharsets; -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; - -@SuppressWarnings({"UnstableApiUsage", "PatternValidation"}) -public interface StreamResourceContainer extends ImmutableResourceContainer { - - @Nullable - InputStream open(Key key) throws IOException; - - List assets(String category); - - Collection namespaces(); - - String METADATA_EXTENSION = MinecraftResourcePackStructure.METADATA_EXTENSION; - String TEXTURE_EXTENSION = MinecraftResourcePackStructure.TEXTURE_EXTENSION; - String TEXTURE_CATEGORY = MinecraftResourcePackStructure.TEXTURES_FOLDER; - String SOUNDS_FILE = MinecraftResourcePackStructure.SOUNDS_FILE; - - private static Key addExtensionAndCategory(Key key, String category, String extension) { - return Key.key(key.namespace(), category + "/" + key.value() + extension); - } - - private static JsonElement parseJson(InputStream input) throws IOException { - try (Reader reader = new InputStreamReader(input, StandardCharsets.UTF_8)) { - return GsonUtil.parseReader(reader); - } - } - - @Nullable - private static Writable writable(Key key, String category, String extension, ResourceOpener opener) throws IOException { - Key withExtension = addExtensionAndCategory(key, category, extension); - try (InputStream input = opener.open(withExtension)) { - if (input != null) { - return Writable.inputStream(() -> opener.open(withExtension)); - } - } - return null; - } - - private static List collect(ResourceCategory category, Function deserializer, - Function> assetLookup) { - return assetLookup.apply(category.folder(-1)).stream() - .map(deserializer) - .filter(Objects::nonNull) - .toList(); - } - - @Nullable - default T deserialize(ResourceCategory category, Key key) { - Key withExtensionAndCategory = addExtensionAndCategory(key, category.folder(-1), category.extension(-1)); - try (InputStream input = open(withExtensionAndCategory)) { - if (input != null) { - return category.deserializer().deserialize(input, key); - } - } catch (IOException exception) { - throw new RuntimeException(exception); - } - return null; - } - - @Override - default @Nullable Atlas atlas(@NotNull Key key) { - return deserialize(AtlasSerializer.CATEGORY, key); - } - - @Override - default @NotNull Collection atlases() { - return collect(AtlasSerializer.CATEGORY, this::atlas, this::assets); - } - - @Override - default @Nullable BlockState blockState(@NotNull Key key) { - return deserialize(BlockStateSerializer.CATEGORY, key); - } - - @Override - @NotNull - default Collection blockStates() { - return collect(BlockStateSerializer.CATEGORY, this::blockState, this::assets); - } - - @Override - default @Nullable Equipment equipment(@NotNull Key key) { - return deserialize(EquipmentCategory.INSTANCE, key); - } - - @Override - @NotNull - default Collection equipment() { - return collect(EquipmentCategory.INSTANCE, this::equipment, this::assets); - } - - @Override - default @Nullable Font font(@NotNull Key key) { - return deserialize(FontSerializer.CATEGORY, key); - } - - @Override - @NotNull - default Collection fonts() { - return collect(FontSerializer.CATEGORY, this::font, this::assets); - } - - @Override - default @Nullable Item item(@NotNull Key key) { - return deserialize(ItemSerializer.CATEGORY, key); - } - - @Override - @NotNull - default Collection items() { - return collect(ItemSerializer.CATEGORY, this::item, this::assets); - } - - @Override - default @Nullable Language language(@NotNull Key key) { - return deserialize(LanguageSerializer.CATEGORY, key); - } - - @Override - @NotNull - default Collection languages() { - return collect(LanguageSerializer.CATEGORY, this::language, this::assets); - } - - @Override - default @Nullable Model model(@NotNull Key key) { - return deserialize(ModelSerializer.CATEGORY, key); - } - - @Override - @NotNull - default Collection models() { - return collect(ModelSerializer.CATEGORY, this::model, this::assets); - } - - @Override - default @Nullable SoundRegistry soundRegistry(@NotNull String namespace) { - try (InputStream input = open(Key.key(namespace, SOUNDS_FILE))) { - if (input != null) { - return SoundRegistrySerializer.INSTANCE.readFromTree(parseJson(input), namespace); - } - } catch (IOException exception) { - throw new RuntimeException(exception); - } - return null; - } - - @Override - @NotNull - default Collection soundRegistries() { - return namespaces().stream() - .map(this::soundRegistry) - .filter(Objects::nonNull) - .toList(); - } - - @Override - default @Nullable Sound sound(@NotNull Key key) { - return deserialize(SoundSerializer.CATEGORY, key); - } - - @Override - @NotNull - default Collection sounds() { - return collect(SoundSerializer.CATEGORY, this::sound, this::assets); - } - - @Override - default @Nullable Texture texture(@NotNull Key key) { - try { - Writable texture = writable(key, TEXTURE_CATEGORY, TEXTURE_EXTENSION, this::open); - if (texture != null) { - Metadata metadata = Metadata.empty(); - try (InputStream metadataStream = open(addExtensionAndCategory(key, TEXTURE_CATEGORY, METADATA_EXTENSION))) { - if (metadataStream != null) { - metadata = MetadataSerializer.INSTANCE.readFromTree(parseJson(metadataStream)); - } - } - return Texture.texture(key, texture, metadata); - } - } catch (IOException exception) { - throw new RuntimeException(exception); - } - return null; - } - - @Override - @NotNull - default Collection textures() { - return assets(TEXTURE_CATEGORY).stream() - .map(this::texture) - .filter(Objects::nonNull) - .toList(); - } - - @Override - default @Nullable Writable unknownFile(@NotNull String path) { - throw new UnsupportedOperationException("Unsupported by StreamResourceContainer"); - } - - @Override - default @NotNull Map unknownFiles() { - return Map.of(); - } - - @FunctionalInterface - interface ResourceOpener { - - InputStream open(Key key) throws IOException; - } -}