1
0
mirror of https://github.com/GeyserMC/Rainbow.git synced 2025-12-19 14:59:16 +00:00

Remove PackConverter for now

This commit is contained in:
Eclipse
2025-10-14 08:06:36 +00:00
parent 16db0fe788
commit 73bd8222be
8 changed files with 0 additions and 642 deletions

View File

@@ -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 {

View File

@@ -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());
}
}

View File

@@ -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<Converter<?>> 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<ActionListener<?>> 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) {

View File

@@ -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<ResourceCategory<?>, Object2ObjectMap<Key, Object>> cache = new Reference2ObjectOpenHashMap<>();
private final Object2ObjectMap<String, SoundRegistry> soundRegistryCache = new Object2ObjectOpenHashMap<>();
private final Object2ObjectMap<Key, Texture> textureCache = new Object2ObjectOpenHashMap<>();
@SuppressWarnings("unchecked")
private <T extends Keyed & ResourcePackPart> T cacheOrDeserialize(ResourceCategory<T> deserializer, Key key) {
Object2ObjectMap<Key, Object> deserializerCache = cache.computeIfAbsent(deserializer, cacheKey -> new Object2ObjectOpenHashMap<>());
return (T) deserializerCache.computeIfAbsent(key, cacheKey -> StreamResourceContainer.super.deserialize(deserializer, key));
}
@Override
public <T extends Keyed & ResourcePackPart> @Nullable T deserialize(ResourceCategory<T> 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));
}
}

View File

@@ -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> 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();
}
}

View File

@@ -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();
}
}

View File

@@ -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> resource = resourceManager.getResource(KeyUtil.keyToResourceLocation(key));
if (resource.isPresent()) {
return resource.get().open();
}
return null;
}
@Override
public List<Key> 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<String> 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<Overlay> overlays() {
return List.of();
}
}

View File

@@ -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<Key> assets(String category);
Collection<String> 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 <T extends Keyed & ResourcePackPart> List<T> collect(ResourceCategory<T> category, Function<Key, T> deserializer,
Function<String, List<Key>> assetLookup) {
return assetLookup.apply(category.folder(-1)).stream()
.map(deserializer)
.filter(Objects::nonNull)
.toList();
}
@Nullable
default <T extends Keyed & ResourcePackPart> T deserialize(ResourceCategory<T> 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<Atlas> 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<BlockState> 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> 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<Font> 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<Item> 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<Language> 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<Model> 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<SoundRegistry> 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<Sound> 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<Texture> 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<String, Writable> unknownFiles() {
return Map.of();
}
@FunctionalInterface
interface ResourceOpener {
InputStream open(Key key) throws IOException;
}
}