mirror of
https://github.com/GeyserMC/PackConverter.git
synced 2025-12-19 14:59:21 +00:00
Add JsonMappings to order to allow other converters to have mappings
This commit is contained in:
@@ -26,6 +26,7 @@
|
||||
|
||||
package org.geysermc.pack.converter.bootstrap;
|
||||
|
||||
import org.geysermc.pack.converter.util.DefaultLogListener;
|
||||
import org.geysermc.pack.converter.util.LogListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -33,7 +34,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
|
||||
public class BootstrapLogListener implements LogListener {
|
||||
public class BootstrapLogListener extends DefaultLogListener {
|
||||
private final ThunderGUI gui;
|
||||
|
||||
public BootstrapLogListener(ThunderGUI gui) {
|
||||
@@ -45,21 +46,26 @@ public class BootstrapLogListener implements LogListener {
|
||||
if (gui.debugMode.get()) {
|
||||
appendText("DEBUG: " + message);
|
||||
}
|
||||
|
||||
super.debug(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void info(@NotNull String message) {
|
||||
appendText(message);
|
||||
super.info(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void warn(@NotNull String message) {
|
||||
appendText("WARNING: " + message);
|
||||
super.warn(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void error(@NotNull String message) {
|
||||
appendText("ERROR: " + message);
|
||||
super.error(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,6 +79,7 @@ public class BootstrapLogListener implements LogListener {
|
||||
|
||||
appendText(writer.toString());
|
||||
}
|
||||
super.error(message, exception);
|
||||
}
|
||||
|
||||
private void appendText(String text) {
|
||||
|
||||
@@ -80,7 +80,7 @@ public final class AssetConverters {
|
||||
public static final ConverterPipeline<Model, BedrockModel> MODEL = create(ModelConverter.INSTANCE);
|
||||
public static final ConverterPipeline<SoundRegistry, Map<String, SoundDefinitions>> SOUND_REGISTRY = create(
|
||||
(pack, context) -> pack.soundRegistries(), SoundRegistryConverter.INSTANCE);
|
||||
public static final ConverterPipeline<Sound, Sound> SOUND = create(extractor(SoundSerializer.CATEGORY), SoundConverter.INSTANCE);
|
||||
public static final ConverterPipeline<Sound, Sound> SOUND = create(SoundConverter.INSTANCE);
|
||||
public static final ConverterPipeline<Texture, TransformedTexture> TEXTURE = create(TextureConverter.INSTANCE);
|
||||
|
||||
private static <JavaAsset, BedrockAsset> ConverterPipeline<JavaAsset, BedrockAsset> createSingle(BiFunction<ResourcePack, ExtractionContext, JavaAsset> extractor,
|
||||
|
||||
@@ -27,11 +27,10 @@
|
||||
package org.geysermc.pack.converter.type.sound;
|
||||
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import org.geysermc.pack.converter.pipeline.AssetCombiner;
|
||||
import org.geysermc.pack.converter.pipeline.AssetConverter;
|
||||
import org.geysermc.pack.converter.pipeline.CombineContext;
|
||||
import org.geysermc.pack.converter.pipeline.ConversionContext;
|
||||
import org.geysermc.pack.converter.pipeline.*;
|
||||
import org.geysermc.pack.converter.util.JsonMappings;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
import team.unnamed.creative.sound.Sound;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
@@ -40,11 +39,17 @@ import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class SoundConverter implements AssetConverter<Sound, Sound>, AssetCombiner<Sound> {
|
||||
public class SoundConverter implements AssetExtractor<Sound>, AssetConverter<Sound, Sound>, AssetCombiner<Sound> {
|
||||
public static final SoundConverter INSTANCE = new SoundConverter();
|
||||
|
||||
@Override
|
||||
public Collection<Sound> extract(ResourcePack pack, ExtractionContext context) {
|
||||
return pack.sounds();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Sound convert(Sound sound, ConversionContext context) throws Exception {
|
||||
return sound;
|
||||
@@ -52,11 +57,15 @@ public class SoundConverter implements AssetConverter<Sound, Sound>, AssetCombin
|
||||
|
||||
@Override
|
||||
public void include(BedrockResourcePack pack, List<Sound> sounds, CombineContext context) {
|
||||
JsonMappings mappings = JsonMappings.getMapping("sounds");
|
||||
|
||||
List<String> exported = new ArrayList<>();
|
||||
Path output = pack.directory().resolve(SoundRegistryConverter.BEDROCK_SOUNDS_LOCATION);
|
||||
|
||||
for (Sound sound : sounds) {
|
||||
String path = sound.key().value();
|
||||
String javaPath = sound.key().value();
|
||||
List<String> paths = mappings.map(javaPath);
|
||||
for (String path : paths) {
|
||||
if (exported.contains(path)) {
|
||||
context.warn("Conflicting sound file " + sound.key() + "!");
|
||||
continue;
|
||||
@@ -76,3 +85,4 @@ public class SoundConverter implements AssetConverter<Sound, Sound>, AssetCombin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformedTexture;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.JsonMappings;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
@@ -78,7 +80,7 @@ public class TextureConverter implements AssetExtractor<Texture>, AssetConverter
|
||||
// TODO ideally textures should be transformed individually in the convert process, and not together in the extraction process, but this is hard to achieve,
|
||||
// TODO and will need another big refactor to the texture transformation code
|
||||
// TODO for now this will work, but for library users it might be nice to be able to properly convert singular textures with transformations
|
||||
TextureMappings mappings = TextureMappings.textureMappings();
|
||||
JsonMappings mappings = JsonMappings.getMapping("textures");
|
||||
List<Texture> textures = new ArrayList<>(pack.textures());
|
||||
|
||||
context.info("Transforming textures...");
|
||||
@@ -103,8 +105,8 @@ public class TextureConverter implements AssetExtractor<Texture>, AssetConverter
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable TransformedTexture convert(Texture texture, ConversionContext context) throws Exception {
|
||||
TextureMappings mappings = TextureMappings.textureMappings();
|
||||
public @NotNull TransformedTexture convert(Texture texture, ConversionContext context) throws Exception {
|
||||
JsonMappings mappings = JsonMappings.getMapping("textures");
|
||||
TransformedTexture transformed = new TransformedTexture(texture);
|
||||
|
||||
String input = texture.key().value();
|
||||
@@ -113,36 +115,13 @@ public class TextureConverter implements AssetExtractor<Texture>, AssetConverter
|
||||
String rootPath = relativePath.substring(0, relativePath.indexOf('/'));
|
||||
String bedrockRoot = DIRECTORY_LOCATIONS.getOrDefault(rootPath, rootPath);
|
||||
|
||||
Object mappingObject = mappings.textures(relativePath);
|
||||
|
||||
if (mappingObject == null) {
|
||||
mappingObject = mappings.textures(rootPath);
|
||||
List<String> mapping = mappings.map(relativePath);
|
||||
List<String> transformedOutputs = new ArrayList<>();
|
||||
for (String item : mapping) {
|
||||
transformedOutputs.add(bedrockRoot + item.substring(item.indexOf('/')) + ".png");
|
||||
}
|
||||
|
||||
String fallbackPath = bedrockRoot + "/" + relativePath.substring(relativePath.indexOf('/') + 1) + ".png";
|
||||
if (mappingObject instanceof Map<?,?> keyMappings) { // Handles common subdirectories
|
||||
String sanitizedName = input.substring(input.indexOf('/') + 1);
|
||||
if (sanitizedName.endsWith(".png")) sanitizedName = sanitizedName.substring(0, sanitizedName.length() - 4);
|
||||
|
||||
Object bedrockOutput = keyMappings.get(sanitizedName);
|
||||
if (bedrockOutput instanceof String bedrockPath) {
|
||||
transformed.output(bedrockRoot + "/" + bedrockPath + ".png");
|
||||
} else if (bedrockOutput instanceof List<?> paths) {
|
||||
for (String bedrockPath : (List<String>) paths) {
|
||||
transformed.output(bedrockRoot + "/" + bedrockPath + ".png");
|
||||
}
|
||||
} else { // Fallback
|
||||
transformed.output(fallbackPath);
|
||||
}
|
||||
} else if (mappingObject instanceof String str) { // Direct mappings
|
||||
transformed.output(str + ".png");
|
||||
} else if (mappingObject instanceof List<?> paths) { // Mappings where duplicate code paths exist
|
||||
for (String path : (List<String>) paths) {
|
||||
transformed.output(path + ".png");
|
||||
}
|
||||
} else { // Fallback
|
||||
transformed.output(fallbackPath);
|
||||
}
|
||||
transformed.output(transformedOutputs);
|
||||
|
||||
return transformed;
|
||||
}
|
||||
@@ -206,6 +185,8 @@ public class TextureConverter implements AssetExtractor<Texture>, AssetConverter
|
||||
}
|
||||
}
|
||||
|
||||
Files.createDirectories(output.getParent());
|
||||
|
||||
try (OutputStream stream = Files.newOutputStream(output)) {
|
||||
ImageIO.write(bedrockImage, "png", stream);
|
||||
}
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/PackConverter
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.type.texture;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import lombok.ToString;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
@ToString
|
||||
public class TextureMappings extends LinkedHashMap<String, Object> {
|
||||
private static TextureMappings INSTANCE;
|
||||
|
||||
@Nullable
|
||||
public Object textures(@NotNull String key) {
|
||||
return this.get(key);
|
||||
}
|
||||
|
||||
public static TextureMappings textureMappings() {
|
||||
if (INSTANCE != null) {
|
||||
return INSTANCE;
|
||||
}
|
||||
InputStream mappingsStream = TextureMappings.class.getResourceAsStream("/mappings/textures.json");
|
||||
if (mappingsStream == null) {
|
||||
throw new RuntimeException("Could not find textures.json mappings file!");
|
||||
}
|
||||
|
||||
return INSTANCE = new Gson().fromJson(new InputStreamReader(mappingsStream), TextureMappings.class);
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,8 @@ package org.geysermc.pack.converter.type.texture.transformer;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import org.geysermc.pack.converter.type.texture.TextureMappings;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.JsonMappings;
|
||||
import org.geysermc.pack.converter.util.LogListener;
|
||||
import org.geysermc.pack.converter.util.LogListenerHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -46,7 +46,7 @@ import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class TransformContext implements LogListenerHelper {
|
||||
private final TextureMappings mappings;
|
||||
private final JsonMappings mappings;
|
||||
private final Collection<Texture> textures;
|
||||
// TODO figure out how to handle this, this is executed in the extraction phase and ideally bedrock pack wouldn't be accessed then
|
||||
@Deprecated(forRemoval = true)
|
||||
@@ -57,7 +57,7 @@ public class TransformContext implements LogListenerHelper {
|
||||
private final Map<Key, Texture> byKey = new HashMap<>();
|
||||
|
||||
public TransformContext(
|
||||
TextureMappings mappings,
|
||||
JsonMappings mappings,
|
||||
Collection<Texture> textures,
|
||||
BedrockResourcePack bedrockPack,
|
||||
ResourcePack javaPack,
|
||||
@@ -76,7 +76,7 @@ public class TransformContext implements LogListenerHelper {
|
||||
}
|
||||
}
|
||||
|
||||
public TextureMappings mappings() {
|
||||
public JsonMappings mappings() {
|
||||
return this.mappings;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ import java.util.List;
|
||||
|
||||
public class TransformedTexture {
|
||||
private final Texture texture;
|
||||
private final List<String> outputs = new ArrayList<>();
|
||||
private List<String> outputs = new ArrayList<>();
|
||||
|
||||
public TransformedTexture(@NotNull Texture texture) {
|
||||
this.texture = texture;
|
||||
@@ -50,7 +50,7 @@ public class TransformedTexture {
|
||||
return outputs;
|
||||
}
|
||||
|
||||
public void output(@NotNull String output) {
|
||||
outputs.add(output);
|
||||
public void output(@NotNull List<String> output) {
|
||||
outputs = new ArrayList<>(output);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2025 GeyserMC. http://geysermc.org
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* @author GeyserMC
|
||||
* @link https://github.com/GeyserMC/PackConverter
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.util;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class JsonMappings {
|
||||
private static final Map<String, JsonMappings> CACHE = new HashMap<>();
|
||||
|
||||
public static JsonMappings getMapping(String name) {
|
||||
if (CACHE.containsKey(name)) {
|
||||
return CACHE.get(name);
|
||||
}
|
||||
InputStream mappingsStream = JsonMappings.class.getResourceAsStream("/mappings/%s.json".formatted(name));
|
||||
if (mappingsStream == null) {
|
||||
throw new RuntimeException("Could not find %s.json mappings file!".formatted(name));
|
||||
}
|
||||
|
||||
JsonObject jsonMappings = JsonParser.parseReader(new InputStreamReader(mappingsStream)).getAsJsonObject();
|
||||
|
||||
Map<String, List<String>> mappings = new HashMap<>();
|
||||
|
||||
for (Map.Entry<String, JsonElement> entry : jsonMappings.entrySet()) {
|
||||
mappings.putAll(extractMapping(entry.getValue(), entry.getKey(), List.of()));
|
||||
}
|
||||
|
||||
JsonMappings instance = new JsonMappings(mappings);
|
||||
CACHE.put(name, instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private static Map<String, List<String>> extractMapping(JsonElement element, String key, List<String> parents) {
|
||||
if (element.isJsonObject()) {
|
||||
Map<String, List<String>> mappings = new HashMap<>();
|
||||
|
||||
for (Map.Entry<String, JsonElement> entry : element.getAsJsonObject().entrySet()) {
|
||||
List<String> newParents = new ArrayList<>(parents);
|
||||
newParents.add(key);
|
||||
mappings.putAll(extractMapping(entry.getValue(), key + "/" + entry.getKey(), newParents));
|
||||
}
|
||||
|
||||
return mappings;
|
||||
} else if (element.isJsonArray()) {
|
||||
List<String> paths = new ArrayList<>();
|
||||
|
||||
for (JsonElement arrayElement : element.getAsJsonArray()) {
|
||||
if (arrayElement.isJsonPrimitive()) {
|
||||
paths.add(arrayElement.getAsString());
|
||||
} else {
|
||||
throw new RuntimeException("Invalid item found within mapping file, items in an array must be primitives.");
|
||||
}
|
||||
}
|
||||
|
||||
return Map.of(key, paths);
|
||||
} else if (element.isJsonPrimitive()) {
|
||||
String prefix = "";
|
||||
if (!parents.isEmpty()) prefix = String.join("/", parents) + "/";
|
||||
return Map.of(key, List.of(prefix + element.getAsString()));
|
||||
}
|
||||
|
||||
return Map.of();
|
||||
}
|
||||
|
||||
private final Map<String, List<String>> mappings;
|
||||
|
||||
private JsonMappings(Map<String, List<String>> mappings) {
|
||||
this.mappings = mappings;
|
||||
}
|
||||
|
||||
public List<String> map(String input) {
|
||||
return mappings.getOrDefault(input, List.of(input));
|
||||
}
|
||||
}
|
||||
1
converter/src/main/resources/mappings/sounds.json
Normal file
1
converter/src/main/resources/mappings/sounds.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
Reference in New Issue
Block a user