mirror of
https://github.com/GeyserMC/PackConverter.git
synced 2025-12-19 14:59:21 +00:00
Split conversion process into 3 parts, make converters more standalone (#42)
* Work on splitting converters * Properly split converting of sound registries and sounds * Testing stuff * Implement splitting of texture conversion, still some things to do * Add bedrock pack back to TransformContext * Transition * AssetCollector -> AssetCombiner * Remove unnecessary interfaces * Re-implement action listeners * Final things * Cleanup * Some Javadocs, fixup copyright * Relocate pipeline classes and rename converter package -> type, create KeyUtil to lessen code warnings
This commit is contained in:
@@ -28,7 +28,7 @@ package org.geysermc.pack.converter.bootstrap;
|
||||
|
||||
import com.formdev.flatlaf.intellijthemes.FlatArcDarkIJTheme;
|
||||
import org.geysermc.pack.converter.PackConverter;
|
||||
import org.geysermc.pack.converter.converter.Converters;
|
||||
import org.geysermc.pack.converter.pipeline.AssetConverters;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Path;
|
||||
@@ -77,7 +77,7 @@ public class Main {
|
||||
.input(Path.of(inputPath))
|
||||
.output(Path.of(outputPath))
|
||||
.packName(packName)
|
||||
.converters(Converters.defaultConverters(debug))
|
||||
.converters(AssetConverters.converters(debug))
|
||||
.convert()
|
||||
.pack();
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@ package org.geysermc.pack.converter.bootstrap;
|
||||
|
||||
import com.twelvemonkeys.image.BufferedImageIcon;
|
||||
import org.geysermc.pack.converter.PackConverter;
|
||||
import org.geysermc.pack.converter.converter.Converters;
|
||||
import org.geysermc.pack.converter.pipeline.AssetConverters;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.ZipUtils;
|
||||
|
||||
@@ -128,7 +128,7 @@ public class ThunderGUI extends JFrame {
|
||||
.output(outputPath)
|
||||
.packName(packName.getText().isBlank() ? inputPath.getFileName().toString() : packName.getText())
|
||||
.vanillaPackPath(vanillaPackPath)
|
||||
.converters(Converters.defaultConverters(this.debugMode.get()))
|
||||
.converters(AssetConverters.converters(this.debugMode.get()))
|
||||
.logListener(logListener)
|
||||
.convert()
|
||||
.pack();
|
||||
|
||||
@@ -1,71 +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;
|
||||
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import org.geysermc.pack.converter.data.ConversionData;
|
||||
import org.geysermc.pack.converter.util.LogListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public record PackConversionContext<T extends ConversionData>(
|
||||
@NotNull T data,
|
||||
@NotNull PackConverter packConverter,
|
||||
@NotNull ResourcePack javaResourcePack,
|
||||
@NotNull BedrockResourcePack bedrockResourcePack,
|
||||
@NotNull LogListener logListener) {
|
||||
|
||||
public Path inputDirectory() {
|
||||
return this.data.inputDirectory();
|
||||
}
|
||||
|
||||
public Path outputDirectory() {
|
||||
return this.data.outputDirectory();
|
||||
}
|
||||
|
||||
public void debug(@NotNull String message) {
|
||||
this.logListener.debug(message);
|
||||
}
|
||||
|
||||
public void info(@NotNull String message) {
|
||||
this.logListener.info(message);
|
||||
}
|
||||
|
||||
public void warn(@NotNull String message) {
|
||||
this.logListener.warn(message);
|
||||
}
|
||||
|
||||
public void error(@NotNull String message) {
|
||||
this.logListener.error(message);
|
||||
}
|
||||
|
||||
public void error(@NotNull String message, @NotNull Throwable exception) {
|
||||
this.logListener.error(message, exception);
|
||||
}
|
||||
}
|
||||
@@ -28,10 +28,12 @@ package org.geysermc.pack.converter;
|
||||
|
||||
import org.apache.commons.io.file.PathUtils;
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import org.geysermc.pack.converter.converter.ActionListener;
|
||||
import org.geysermc.pack.converter.converter.Converter;
|
||||
import org.geysermc.pack.converter.data.ConversionData;
|
||||
import org.geysermc.pack.converter.util.*;
|
||||
import org.geysermc.pack.converter.pipeline.ConverterPipeline;
|
||||
import org.geysermc.pack.converter.util.DefaultLogListener;
|
||||
import org.geysermc.pack.converter.util.LogListener;
|
||||
import org.geysermc.pack.converter.util.NioDirectoryFileTreeReader;
|
||||
import org.geysermc.pack.converter.util.VanillaPackProvider;
|
||||
import org.geysermc.pack.converter.util.ZipUtils;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
@@ -43,9 +45,8 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
|
||||
/**
|
||||
@@ -63,11 +64,9 @@ public final class PackConverter {
|
||||
private boolean compressed;
|
||||
private boolean enforcePackCheck = false;
|
||||
|
||||
private final Map<Class<?>, List<ActionListener<?>>> actionListeners = new IdentityHashMap<>();
|
||||
|
||||
private BiConsumer<ResourcePack, BedrockResourcePack> postProcessor;
|
||||
|
||||
private final List<Converter<?>> converters = new ArrayList<>();
|
||||
private final List<ConverterPipeline<?, ?>> converters = new ArrayList<>();
|
||||
|
||||
private Path tmpDir;
|
||||
|
||||
@@ -187,7 +186,7 @@ public final class PackConverter {
|
||||
* @param converter the converter to add
|
||||
* @return this instance
|
||||
*/
|
||||
public PackConverter converter(@NotNull Converter<?> converter) {
|
||||
public PackConverter converter(@NotNull ConverterPipeline<?, ?> converter) {
|
||||
this.converters.add(converter);
|
||||
return this;
|
||||
}
|
||||
@@ -198,7 +197,7 @@ public final class PackConverter {
|
||||
* @param converters the converters to add
|
||||
* @return this instance
|
||||
*/
|
||||
public PackConverter converters(@NotNull List<? extends Converter<?>> converters) {
|
||||
public PackConverter converters(@NotNull List<? extends ConverterPipeline<?, ?>> converters) {
|
||||
this.converters.addAll(converters);
|
||||
return this;
|
||||
}
|
||||
@@ -227,42 +226,6 @@ public final class PackConverter {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a list of action listeners for a specific conversion data class.
|
||||
* <p>
|
||||
* This is particularly useful for external programs that may rely on
|
||||
* various bits of information from the pack converter at different
|
||||
* stages.
|
||||
*
|
||||
* @param clazz the conversion data class
|
||||
* @param actionListeners the action listeners
|
||||
* @return this instance
|
||||
* @param <T> the conversion data type
|
||||
*/
|
||||
public <T extends ConversionData> PackConverter actionListeners(@NotNull Class<T> clazz, @NotNull ActionListener<T>... actionListeners) {
|
||||
this.actionListeners.put(clazz, List.of(actionListeners));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the action listeners.
|
||||
* <p>
|
||||
* This is particularly useful for external programs that may rely on
|
||||
* various bits of information from the pack converter at different
|
||||
* stages.
|
||||
*
|
||||
* @param actionListeners the action listeners
|
||||
* @return this instance
|
||||
* @param <T> the conversion data type
|
||||
*/
|
||||
public <T extends ConversionData> PackConverter actionListeners(@NotNull Map<Class<T>, List<ActionListener<T>>> actionListeners) {
|
||||
for (Map.Entry<Class<T>, List<ActionListener<T>>> entry : actionListeners.entrySet()) {
|
||||
this.actionListeners.put(entry.getKey(), (List) entry.getValue());
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the post processor for the converted resource pack.
|
||||
* <p>
|
||||
@@ -320,25 +283,10 @@ public final class PackConverter {
|
||||
ResourcePack vanillaResourcePack = MinecraftResourcePackReader.minecraft().readFromZipFile(vanillaPackPath);
|
||||
BedrockResourcePack bedrockResourcePack = new BedrockResourcePack(this.tmpDir);
|
||||
|
||||
final Converter.ConversionDataCreationContext conversionDataCreationContext = new Converter.ConversionDataCreationContext(
|
||||
this, logListener, input, this.tmpDir, javaResourcePack, vanillaResourcePack
|
||||
);
|
||||
|
||||
int errors = 0;
|
||||
for (Converter converter : this.converters) {
|
||||
ConversionData data = converter.createConversionData(conversionDataCreationContext);
|
||||
PackConversionContext<?> context = new PackConversionContext<>(data, this, javaResourcePack, bedrockResourcePack, this.logListener);
|
||||
|
||||
List<ActionListener<?>> actionListeners = this.actionListeners.getOrDefault(data.getClass(), List.of());
|
||||
try {
|
||||
actionListeners.forEach(actionListener -> actionListener.preConvert((PackConversionContext) context));
|
||||
converter.convert(context);
|
||||
actionListeners.forEach(actionListener -> actionListener.postConvert((PackConversionContext) context));
|
||||
} catch (Throwable t) {
|
||||
this.logListener.error("Error converting pack!", t);
|
||||
errors++;
|
||||
}
|
||||
}
|
||||
int errors = converters.stream()
|
||||
.mapToInt(converter -> converter.convert(javaResourcePack, Optional.of(vanillaResourcePack),
|
||||
bedrockResourcePack, packName(), textureSubdirectory, logListener))
|
||||
.sum();
|
||||
|
||||
if (this.postProcessor != null) {
|
||||
this.postProcessor.accept(javaResourcePack, bedrockResourcePack);
|
||||
|
||||
@@ -1,75 +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.converter.lang;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.converter.BaseConverter;
|
||||
import org.geysermc.pack.converter.converter.Converter;
|
||||
import org.geysermc.pack.converter.data.BaseConversionData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.lang.Language;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@AutoService(Converter.class)
|
||||
public class LangConverter extends BaseConverter {
|
||||
private static final String BEDROCK_TEXTS_LOCATION = "texts";
|
||||
|
||||
private final Pattern positionalStringReplacement = Pattern.compile("%([0-9]+)\\$s");
|
||||
|
||||
@Override
|
||||
public void convert(@NotNull PackConversionContext<BaseConversionData> context) throws Exception {
|
||||
Collection<Language> languages = context.javaResourcePack().languages();
|
||||
for (Language language : languages) {
|
||||
Map<String, String> strings = language.translations();
|
||||
|
||||
for (Map.Entry<String, String> entry : strings.entrySet()) {
|
||||
String value = entry.getValue();
|
||||
|
||||
// Replace %d with %s
|
||||
value = value.replace("%d", "%s");
|
||||
|
||||
// Replace `%x$s` with `%x`
|
||||
value = positionalStringReplacement.matcher(value).replaceAll("%$1");
|
||||
|
||||
entry.setValue(value);
|
||||
}
|
||||
|
||||
String languageKey = language.key().value();
|
||||
|
||||
// Convert the language key to the Bedrock equivalent
|
||||
if (languageKey.equals("no_no")) {
|
||||
languageKey = "nb_no";
|
||||
}
|
||||
|
||||
context.bedrockResourcePack().addLanguage(languageKey, strings);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,261 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2024 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.converter.model;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.ModelEntity;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.Geometry;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.Bones;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.Description;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.Cubes;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.Uv;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.Down;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.East;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.North;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.South;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.Up;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.West;
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.converter.Converter;
|
||||
import org.geysermc.pack.converter.data.ModelConversionData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
import team.unnamed.creative.base.CubeFace;
|
||||
import team.unnamed.creative.model.Element;
|
||||
import team.unnamed.creative.model.ElementFace;
|
||||
import team.unnamed.creative.model.ElementRotation;
|
||||
import team.unnamed.creative.model.Model;
|
||||
import team.unnamed.creative.texture.TextureUV;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@AutoService(Converter.class)
|
||||
public class ModelConverter implements Converter<ModelConversionData> {
|
||||
private static final String FORMAT_VERSION = "1.16.0";
|
||||
private static final String GEOMETRY_FORMAT = "geometry.%s";
|
||||
|
||||
private static final float[] ELEMENT_OFFSET = new float[] { 8, 0, 8 };
|
||||
|
||||
@Override
|
||||
public void convert(@NotNull PackConversionContext<ModelConversionData> context) throws Exception {
|
||||
ResourcePack javaPack = context.javaResourcePack();
|
||||
BedrockResourcePack bedrockPack = context.bedrockResourcePack();
|
||||
Collection<Model> models = javaPack.models();
|
||||
if (models.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ModelStitcher.Provider provider = context.data().getModelProvider();
|
||||
for (Model model : models) {
|
||||
model = new ModelStitcher(provider, model, context.logListener()).stitch();
|
||||
|
||||
List<Element> elements = model.elements();
|
||||
if (elements.isEmpty()) {
|
||||
context.debug("Model " + model.key().key() + " has no elements");
|
||||
continue;
|
||||
}
|
||||
|
||||
String value = model.key().value();
|
||||
context.debug("Converting model " + model.key().key() + ":" + value);
|
||||
|
||||
// TODO: Convert item models but save differently?
|
||||
if (value.startsWith("item/")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ModelEntity modelEntity = new ModelEntity();
|
||||
modelEntity.formatVersion(FORMAT_VERSION);
|
||||
|
||||
Geometry geometry = new Geometry();
|
||||
|
||||
String namespace = model.key().namespace();
|
||||
String fileName = value.substring(value.lastIndexOf('/') + 1);
|
||||
|
||||
String geoName = (namespace.equals(Key.MINECRAFT_NAMESPACE) ? "" : namespace + ".") + fileName;
|
||||
|
||||
// TODO: Don't hardcode all this
|
||||
Description description = new Description();
|
||||
description.identifier(String.format(GEOMETRY_FORMAT, geoName));
|
||||
description.textureWidth(16);
|
||||
description.textureHeight(16);
|
||||
description.visibleBoundsWidth(2);
|
||||
description.visibleBoundsHeight(2);
|
||||
description.visibleBoundsOffset(new float[] { 0.0f, 0.25f, 0.0f });
|
||||
geometry.description(description);
|
||||
|
||||
List<Bones> bones = new ArrayList<>();
|
||||
|
||||
// TODO: Should each element be its own bone rather
|
||||
// than its own cube in the same bone?
|
||||
int i = 0;
|
||||
for (Element element : elements) {
|
||||
float[] from = element.from().toArray();
|
||||
float[] to = element.to().toArray();
|
||||
|
||||
Bones bone = new Bones();
|
||||
bone.name("bone_" + i++);
|
||||
bone.pivot(new float[] { ELEMENT_OFFSET[0], ELEMENT_OFFSET[1], -ELEMENT_OFFSET[2] });
|
||||
|
||||
Cubes cube = new Cubes();
|
||||
cube.origin(new float[] { ELEMENT_OFFSET[0] - to[0], from[1], from[2] - ELEMENT_OFFSET[2] });
|
||||
cube.size(new float[] { to[0] - from[0], to[1] - from[1], to[2] - from[2] });
|
||||
|
||||
ElementRotation elementRotation = element.rotation();
|
||||
if (elementRotation != null) {
|
||||
float[] origin = elementRotation.origin().toArray();
|
||||
cube.pivot(new float[] { ELEMENT_OFFSET[0] - origin[0], ELEMENT_OFFSET[1] - origin[1], origin[2] - ELEMENT_OFFSET[2] });
|
||||
|
||||
float angle = elementRotation.angle();
|
||||
float[] rotation = new float[3];
|
||||
switch (elementRotation.axis()) {
|
||||
case X -> rotation[0] = -angle;
|
||||
case Y -> rotation[1] = -angle;
|
||||
case Z -> rotation[2] = -angle;
|
||||
}
|
||||
|
||||
cube.rotation(rotation);
|
||||
}
|
||||
|
||||
Uv uv = new Uv();
|
||||
for (Map.Entry<CubeFace, ElementFace> entry : element.faces().entrySet()) {
|
||||
CubeFace face = entry.getKey();
|
||||
ElementFace elementFace = entry.getValue();
|
||||
if (elementFace.uv0() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The Java pack lib we use does this weird thing where it
|
||||
// divides the UV by 16, so we need to multiply it by 16
|
||||
|
||||
String texture = elementFace.texture().replace("#", "");
|
||||
applyUv(uv, face, texture, multiplyUv(elementFace.uv0(), 16f));
|
||||
}
|
||||
|
||||
cube.uv(uv);
|
||||
bone.cubes(List.of(cube));
|
||||
|
||||
bones.add(bone);
|
||||
}
|
||||
|
||||
geometry.bones(bones);
|
||||
|
||||
modelEntity.geometry(List.of(geometry));
|
||||
|
||||
if (model.key().namespace().contains("entity")) {
|
||||
bedrockPack.addEntityModel(modelEntity, fileName + ".json");
|
||||
} else {
|
||||
// Bedrock only has a concept of entity or block models
|
||||
bedrockPack.addBlockModel(modelEntity, fileName + ".json");
|
||||
}
|
||||
|
||||
context.data().addStitchedModel(model);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelConversionData createConversionData(@NotNull ConversionDataCreationContext context) {
|
||||
return new ModelConversionData(
|
||||
context.inputDirectory(), context.outputDirectory(),
|
||||
ModelStitcher.vanillaProvider(context.javaResourcePack(), context.logListener(), context.vanillaResourcePack()),
|
||||
context.vanillaResourcePack()
|
||||
);
|
||||
}
|
||||
|
||||
private TextureUV multiplyUv(TextureUV textureUV, float mult) {
|
||||
return TextureUV.uv(textureUV.from().multiply(mult), textureUV.to().multiply(mult));
|
||||
}
|
||||
|
||||
private static void applyUv(Uv uv, CubeFace face, String texture, TextureUV faceUv) {
|
||||
float[] uvs;
|
||||
float[] uvSize;
|
||||
|
||||
// These values are flipped for some reason
|
||||
if (face == CubeFace.DOWN || face == CubeFace.UP) {
|
||||
uvs = new float[] { faceUv.to().x(), faceUv.to().y() };
|
||||
uvSize = new float[] { faceUv.from().x() - faceUv.to().x(), faceUv.from().y() - faceUv.to().y() };
|
||||
} else {
|
||||
uvs = new float[] { faceUv.from().x(), faceUv.from().y() };
|
||||
uvSize = new float[] { faceUv.to().x() - faceUv.from().x(), faceUv.to().y() - faceUv.from().y() };
|
||||
}
|
||||
|
||||
switch (face) {
|
||||
case NORTH -> {
|
||||
North north = new North();
|
||||
north.uv(uvs);
|
||||
north.uvSize(uvSize);
|
||||
north.materialInstance(texture);
|
||||
|
||||
uv.north(north);
|
||||
}
|
||||
case SOUTH -> {
|
||||
South south = new South();
|
||||
south.uv(uvs);
|
||||
south.uvSize(uvSize);
|
||||
south.materialInstance(texture);
|
||||
|
||||
uv.south(south);
|
||||
}
|
||||
case EAST -> {
|
||||
East east = new East();
|
||||
east.uv(uvs);
|
||||
east.uvSize(uvSize);
|
||||
east.materialInstance(texture);
|
||||
|
||||
uv.east(east);
|
||||
}
|
||||
case WEST -> {
|
||||
West west = new West();
|
||||
west.uv(uvs);
|
||||
west.uvSize(uvSize);
|
||||
west.materialInstance(texture);
|
||||
|
||||
uv.west(west);
|
||||
}
|
||||
case UP -> {
|
||||
Up up = new Up();
|
||||
up.uv(uvs);
|
||||
up.uvSize(uvSize);
|
||||
up.materialInstance(texture);
|
||||
|
||||
uv.up(up);
|
||||
}
|
||||
case DOWN -> {
|
||||
Down down = new Down();
|
||||
down.uv(uvs);
|
||||
down.uvSize(uvSize);
|
||||
down.materialInstance(texture);
|
||||
|
||||
uv.down(down);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +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.converter.sound;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.apache.commons.io.file.PathUtils;
|
||||
import org.geysermc.pack.bedrock.resource.sounds.sounddefinitions.SoundDefinitions;
|
||||
import org.geysermc.pack.bedrock.resource.sounds.sounddefinitions.Sounds;
|
||||
import org.geysermc.pack.converter.Constants;
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.converter.BaseConverter;
|
||||
import org.geysermc.pack.converter.converter.Converter;
|
||||
import org.geysermc.pack.converter.data.BaseConversionData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Unmodifiable;
|
||||
import team.unnamed.creative.sound.SoundEntry;
|
||||
import team.unnamed.creative.sound.SoundEvent;
|
||||
import team.unnamed.creative.sound.SoundRegistry;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.util.Collection;
|
||||
|
||||
@AutoService(Converter.class)
|
||||
public class SoundConverter extends BaseConverter {
|
||||
private static final String JAVA_SOUNDS_LOCATION = Constants.JAVA_PACK_LOCATION + "/sounds";
|
||||
private static final String BEDROCK_SOUNDS_LOCATION = "sounds";
|
||||
|
||||
@Override
|
||||
public void convert(@NotNull PackConversionContext<BaseConversionData> context) throws Exception {
|
||||
Collection<SoundRegistry> registry = context.javaResourcePack().soundRegistries();
|
||||
for (SoundRegistry soundRegistry : registry) {
|
||||
@Unmodifiable @NotNull Collection<SoundEvent> sounds = soundRegistry.sounds();
|
||||
|
||||
for (SoundEvent value : sounds) {
|
||||
String key = value.key().asString();
|
||||
|
||||
SoundDefinitions definition = new SoundDefinitions();
|
||||
definition.useLegacyMaxDistance(true); // TODO: Needed?
|
||||
definition.maxDistance(64); // ???
|
||||
for (SoundEntry sound : value.sounds()) {
|
||||
Sounds bedrockSound = new Sounds();
|
||||
bedrockSound.name(BEDROCK_SOUNDS_LOCATION + "/" + sound.key().value());
|
||||
bedrockSound.stream(sound.stream());
|
||||
bedrockSound.loadOnLowMemory(true);
|
||||
bedrockSound.volume(sound.volume());
|
||||
bedrockSound.pitch(sound.pitch());
|
||||
bedrockSound.weight(sound.weight());
|
||||
|
||||
definition.sounds().add(bedrockSound);
|
||||
}
|
||||
|
||||
context.bedrockResourcePack().addSoundDefinition(key, definition);
|
||||
}
|
||||
|
||||
// Relocate sound files
|
||||
Path input = context.inputDirectory().resolve(String.format(JAVA_SOUNDS_LOCATION, soundRegistry.namespace()));
|
||||
Path output = context.outputDirectory().resolve(BEDROCK_SOUNDS_LOCATION);
|
||||
|
||||
if (Files.notExists(output)) {
|
||||
Files.createDirectories(output);
|
||||
}
|
||||
|
||||
PathUtils.copyDirectory(input, output, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,207 +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.converter.texture;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.converter.Converter;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformedTexture;
|
||||
import org.geysermc.pack.converter.data.TextureConversionData;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
@AutoService(Converter.class)
|
||||
public class TextureConverter implements Converter<TextureConversionData> {
|
||||
public static final String BEDROCK_TEXTURES_LOCATION = "textures";
|
||||
|
||||
private final List<TextureTransformer> transformers = StreamSupport.stream(ServiceLoader.load(TextureTransformer.class).spliterator(), false)
|
||||
.sorted(Comparator.comparingInt(TextureTransformer::order))
|
||||
.toList();
|
||||
|
||||
public static final Map<String, String> DIRECTORY_LOCATIONS = Map.of(
|
||||
"block", "blocks",
|
||||
"item", "items",
|
||||
"gui", "ui"
|
||||
);
|
||||
|
||||
@Override
|
||||
public void convert(@NotNull PackConversionContext<TextureConversionData> context) throws Exception {
|
||||
TextureMappings mappings = TextureMappings.textureMappings();
|
||||
|
||||
List<Texture> textures = new ArrayList<>(context.javaResourcePack().textures());
|
||||
|
||||
context.info("Transforming textures...");
|
||||
TransformContext transformContext = new TransformContext(
|
||||
context,
|
||||
mappings,
|
||||
textures,
|
||||
context.bedrockResourcePack(),
|
||||
context.javaResourcePack()
|
||||
);
|
||||
for (TextureTransformer transformer : this.transformers) {
|
||||
transformer.transform(transformContext);
|
||||
}
|
||||
context.info("Transformed textures!");
|
||||
|
||||
context.info("Writing textures...");
|
||||
|
||||
for (Texture texture : textures) {
|
||||
String input = texture.key().value();
|
||||
Path texturePath = context.outputDirectory().resolve(BEDROCK_TEXTURES_LOCATION);
|
||||
Path potentialOutput = texturePath.resolve(input);
|
||||
String relativePath = texturePath.relativize(potentialOutput).toString().replace(File.separatorChar, '/');
|
||||
|
||||
if (relativePath.endsWith(".png")) relativePath = relativePath.substring(0, relativePath.length() - 4);
|
||||
|
||||
String rootPath = relativePath.substring(0, relativePath.indexOf('/'));
|
||||
String bedrockRoot = DIRECTORY_LOCATIONS.getOrDefault(rootPath, rootPath);
|
||||
|
||||
List<Path> outputs = new ArrayList<>();
|
||||
List<String> outputPaths = new ArrayList<>();
|
||||
|
||||
Object mappingObject = mappings.textures(relativePath);
|
||||
|
||||
if (mappingObject == null) {
|
||||
mappingObject = mappings.textures(rootPath);
|
||||
}
|
||||
|
||||
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) {
|
||||
outputPaths.add(bedrockRoot + "/" + bedrockPath + ".png");
|
||||
} else if (bedrockOutput instanceof List<?> paths) {
|
||||
for (String bedrockPath : (List<String>) paths) {
|
||||
outputPaths.add(bedrockRoot + "/" + bedrockPath + ".png");
|
||||
}
|
||||
} else { // Fallback
|
||||
outputPaths.add(fallbackPath);
|
||||
}
|
||||
} else if (mappingObject instanceof String str) { // Direct mappings
|
||||
outputPaths.add(str + ".png");
|
||||
} else if (mappingObject instanceof List<?> paths) { // Mappings where duplicate code paths exist
|
||||
for (String path : (List<String>) paths) {
|
||||
outputPaths.add(path + ".png");
|
||||
}
|
||||
} else { // Fallback
|
||||
outputPaths.add(fallbackPath);
|
||||
}
|
||||
|
||||
String bedrockDirectory = "%s/%s";
|
||||
if (context.data().textureSubdirectory() != null) {
|
||||
bedrockDirectory = "%s/" + context.data().textureSubdirectory() + "/%s";
|
||||
}
|
||||
|
||||
for (String outputPath : outputPaths) {
|
||||
context.debug(String.format("Converted %s to %s, writing texture.", input, outputPath));
|
||||
|
||||
String root = outputPath.substring(0, outputPath.indexOf('/'));
|
||||
String value = outputPath.substring(outputPath.indexOf('/') + 1);
|
||||
|
||||
outputs.add(texturePath.resolve((
|
||||
bedrockDirectory.formatted(root, value)
|
||||
).replace('/', File.separatorChar)));
|
||||
}
|
||||
|
||||
byte[] bytes = texture.data().toByteArray();
|
||||
|
||||
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes));
|
||||
|
||||
for (Path output : outputs) {
|
||||
TransformedTexture transformedTexture = new TransformedTexture(texture, output);
|
||||
|
||||
if (output.getParent() != null && Files.notExists(output.getParent())) {
|
||||
Files.createDirectories(output.getParent());
|
||||
}
|
||||
|
||||
BufferedImage bedrockImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D g = bedrockImage.createGraphics();
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.drawImage(image, 0, 0, null);
|
||||
g.dispose();
|
||||
|
||||
String pngKey = context.outputDirectory().relativize(output).toString().replace(File.separatorChar, '/');
|
||||
PngToTgaMappings.TgaMapping mapping = PngToTgaMappings.mapping(pngKey);
|
||||
if (mapping != null) {
|
||||
Path tgaPath = context.outputDirectory().resolve(mapping.value());
|
||||
if (Files.notExists(tgaPath.getParent())) {
|
||||
Files.createDirectories(tgaPath.getParent());
|
||||
}
|
||||
|
||||
ImageUtil.writeTGA(tgaPath, bedrockImage);
|
||||
if (!mapping.keep()) {
|
||||
Files.deleteIfExists(output);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
try (OutputStream stream = Files.newOutputStream(output)) {
|
||||
ImageIO.write(bedrockImage, "png", stream);
|
||||
}
|
||||
|
||||
context.data().addTransformedTexture(transformedTexture);
|
||||
}
|
||||
}
|
||||
|
||||
context.info("Written textures!");
|
||||
|
||||
context.info("Texture conversion complete!");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TextureConversionData createConversionData(@NotNull ConversionDataCreationContext context) {
|
||||
return new TextureConversionData(
|
||||
context.inputDirectory(),
|
||||
context.outputDirectory(),
|
||||
context.converter().textureSubdirectory(),
|
||||
context.vanillaResourcePack()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,62 +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.data;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public class BaseConversionData implements ConversionData {
|
||||
private final Path inputDirectory;
|
||||
private final Path outputDirectory;
|
||||
private final ResourcePack vanillaPack;
|
||||
|
||||
public BaseConversionData(@NotNull Path inputDirectory, @NotNull Path outputDirectory, @NotNull ResourcePack vanillaPack) {
|
||||
this.inputDirectory = inputDirectory;
|
||||
this.outputDirectory = outputDirectory;
|
||||
this.vanillaPack = vanillaPack;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Path inputDirectory() {
|
||||
return this.inputDirectory;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public Path outputDirectory() {
|
||||
return this.outputDirectory;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public ResourcePack vanillaPack() {
|
||||
return this.vanillaPack;
|
||||
}
|
||||
}
|
||||
@@ -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.data;
|
||||
|
||||
import lombok.Getter;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.model.ModelStitcher;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
import team.unnamed.creative.model.Model;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class ModelConversionData extends BaseConversionData {
|
||||
private final Map<Key, Model> stitchedModels = new HashMap<>();
|
||||
@Getter
|
||||
private final ModelStitcher.Provider modelProvider;
|
||||
|
||||
public ModelConversionData(@NotNull Path inputDirectory, @NotNull Path outputDirectory, ModelStitcher.Provider modelProvider, @NotNull ResourcePack vanillaPack) {
|
||||
super(inputDirectory, outputDirectory, vanillaPack);
|
||||
this.modelProvider = modelProvider;
|
||||
}
|
||||
|
||||
public void addStitchedModel(@NotNull Model model) {
|
||||
this.stitchedModels.put(model.key(), model);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Model model(@NotNull Key key) {
|
||||
return this.stitchedModels.get(key);
|
||||
}
|
||||
}
|
||||
@@ -1,61 +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.data;
|
||||
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformedTexture;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TextureConversionData extends BaseConversionData {
|
||||
private final List<TransformedTexture> transformedTextures = new ArrayList<>();
|
||||
private final String textureSubdirectory;
|
||||
|
||||
public TextureConversionData(@NotNull Path inputDirectory, @NotNull Path outputDirectory, @Nullable String textureSubdirectory, @NotNull ResourcePack vanillaPack) {
|
||||
super(inputDirectory, outputDirectory, vanillaPack);
|
||||
|
||||
this.textureSubdirectory = textureSubdirectory;
|
||||
}
|
||||
|
||||
public void addTransformedTexture(@NotNull TransformedTexture transformedTexture) {
|
||||
this.transformedTextures.add(transformedTexture);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<TransformedTexture> transformedTextures() {
|
||||
return this.transformedTextures;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String textureSubdirectory() {
|
||||
return this.textureSubdirectory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2019-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.pipeline;
|
||||
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Listeners for actions that occur during execution of a {@link ConverterPipeline}. All implemented listeners should be as pure as possible:
|
||||
* no side effects should occur, and no modifications should be made to received arguments, unless specifically stated this is allowed.
|
||||
*/
|
||||
public interface ActionListener<JavaAsset, BedrockAsset> {
|
||||
|
||||
/**
|
||||
* Executed after a {@link ConverterPipeline} has extracted all applicable {@link JavaAsset}s for conversion of a {@link ResourcePack}. This method
|
||||
* can be used to add extra {@link JavaAsset}s for conversion by adding them to the {@code extracted} collection, which is mutable.
|
||||
*
|
||||
* @param pack the resource pack that is used for extraction of {@link JavaAsset}s
|
||||
* @param extracted the {@link JavaAsset}s the {@link ConverterPipeline} has extracted from the resource pack
|
||||
* @param context the {@link ExtractionContext}
|
||||
*/
|
||||
default void postExtract(ResourcePack pack, Collection<JavaAsset> extracted, ExtractionContext context) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed after a {@link ConverterPipeline} has converted a {@link JavaAsset} to a {@link BedrockAsset}. This method
|
||||
* can be used to modify the {@link BedrockAsset} after conversion.
|
||||
*
|
||||
* <p><em>Please note that the {@link BedrockAsset} should be considered immutable, and no modifications should be made to it. Instead,
|
||||
* return a modified copy.</em></p>
|
||||
*
|
||||
* @param asset the {@link JavaAsset} that was converted
|
||||
* @param bedrockAsset the resulting {@link BedrockAsset}
|
||||
* @param context the {@link ConversionContext}
|
||||
* @return the modified {@link BedrockAsset}, or return the original if no modifications were made
|
||||
*/
|
||||
default BedrockAsset postConvert(JavaAsset asset, BedrockAsset bedrockAsset, ConversionContext context) {
|
||||
return bedrockAsset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed after a {@link ConverterPipeline} has added all converted {@link BedrockAsset}s to the {@link BedrockResourcePack}. This method
|
||||
* can be used to add additional assets to the output {@code pack}.
|
||||
*
|
||||
* @param pack the bedrock resource pack
|
||||
* @param assets the assets added to the bedrock resource pack (immutable)
|
||||
* @param context the {@link CombineContext}
|
||||
*/
|
||||
default void postInclude(BedrockResourcePack pack, List<BedrockAsset> assets, CombineContext context) {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2025-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.pipeline;
|
||||
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AssetCombiner<BedrockAsset> {
|
||||
|
||||
void include(BedrockResourcePack pack, List<BedrockAsset> assets, CombineContext context);
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2025-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.pipeline;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface AssetConverter<JavaAsset, BedrockAsset> {
|
||||
|
||||
@Nullable
|
||||
BedrockAsset convert(JavaAsset asset, ConversionContext context) throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2025-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.pipeline;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import net.kyori.adventure.key.Keyed;
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import org.geysermc.pack.bedrock.resource.Manifest;
|
||||
import org.geysermc.pack.bedrock.resource.sounds.sounddefinitions.SoundDefinitions;
|
||||
import org.geysermc.pack.converter.type.base.PackIconConverter;
|
||||
import org.geysermc.pack.converter.type.base.PackManifestConverter;
|
||||
import org.geysermc.pack.converter.type.lang.BedrockLanguage;
|
||||
import org.geysermc.pack.converter.type.lang.LangConverter;
|
||||
import org.geysermc.pack.converter.type.misc.SplashTextConverter;
|
||||
import org.geysermc.pack.converter.type.model.BedrockModel;
|
||||
import org.geysermc.pack.converter.type.model.ModelConverter;
|
||||
import org.geysermc.pack.converter.type.sound.SoundConverter;
|
||||
import org.geysermc.pack.converter.type.sound.SoundRegistryConverter;
|
||||
import org.geysermc.pack.converter.type.texture.TextureConverter;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformedTexture;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
import team.unnamed.creative.base.Writable;
|
||||
import team.unnamed.creative.lang.Language;
|
||||
import team.unnamed.creative.metadata.pack.PackMeta;
|
||||
import team.unnamed.creative.model.Model;
|
||||
import team.unnamed.creative.part.ResourcePackPart;
|
||||
import team.unnamed.creative.serialize.minecraft.ResourceCategory;
|
||||
import team.unnamed.creative.serialize.minecraft.language.LanguageSerializer;
|
||||
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.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@SuppressWarnings({"UnstableApiUsage", "unused"})
|
||||
public final class AssetConverters {
|
||||
private static final List<ConverterPipeline<?, ?>> CONVERTERS = new ArrayList<>();
|
||||
private static boolean bootstrapped = false;
|
||||
|
||||
public static final ConverterPipeline<PackMeta, Manifest> MANIFEST = createSingle(
|
||||
(pack, context) -> pack.packMeta(),
|
||||
PackManifestConverter.INSTANCE,
|
||||
BedrockResourcePack::manifest);
|
||||
public static final ConverterPipeline<Writable, byte[]> ICON = createSingle(PackIconConverter::extractIcon, PackIconConverter.INSTANCE, BedrockResourcePack::icon);
|
||||
public static final ConverterPipeline<Writable, JsonElement> SPLASH_TEXT = createSingle(
|
||||
(pack, context) -> pack.unknownFile("assets/minecraft/texts/splashes.txt"),
|
||||
SplashTextConverter.INSTANCE,
|
||||
(pack, splashes) -> pack.addExtraFile(splashes, "splashes.json"));
|
||||
public static final ConverterPipeline<Language, BedrockLanguage> LANGUAGE = create(extractor(LanguageSerializer.CATEGORY), LangConverter.INSTANCE);
|
||||
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<Texture, TransformedTexture> TEXTURE = create(TextureConverter.INSTANCE);
|
||||
|
||||
private static <JavaAsset, BedrockAsset> ConverterPipeline<JavaAsset, BedrockAsset> createSingle(BiFunction<ResourcePack, ExtractionContext, JavaAsset> extractor,
|
||||
AssetConverter<JavaAsset, BedrockAsset> converter,
|
||||
BiConsumer<BedrockResourcePack, BedrockAsset> collector) {
|
||||
return create(
|
||||
(pack, context) -> Optional.ofNullable(extractor.apply(pack, context))
|
||||
.map(List::of)
|
||||
.orElse(List.of()),
|
||||
converter,
|
||||
(pack, assets, context) -> collector.accept(pack, assets.get(0)));
|
||||
}
|
||||
|
||||
public static <JavaAsset, BedrockAsset,
|
||||
ConverterCombiner extends AssetConverter<JavaAsset, BedrockAsset>
|
||||
& AssetCombiner<BedrockAsset>> ConverterPipeline<JavaAsset, BedrockAsset> create(AssetExtractor<JavaAsset> extractor,
|
||||
ConverterCombiner converterCombiner) {
|
||||
return create(extractor, converterCombiner, converterCombiner);
|
||||
}
|
||||
|
||||
public static <JavaAsset, BedrockAsset,
|
||||
Pipeline extends AssetExtractor<JavaAsset> & AssetConverter<JavaAsset, BedrockAsset>
|
||||
& AssetCombiner<BedrockAsset>> ConverterPipeline<JavaAsset, BedrockAsset> create(Pipeline pipeline) {
|
||||
return create(pipeline, pipeline, pipeline);
|
||||
}
|
||||
|
||||
public static <JavaAsset, BedrockAsset> ConverterPipeline<JavaAsset, BedrockAsset> create(AssetExtractor<JavaAsset> extractor,
|
||||
AssetConverter<JavaAsset, BedrockAsset> converter,
|
||||
AssetCombiner<BedrockAsset> combiner) {
|
||||
ConverterPipeline<JavaAsset, BedrockAsset> pipeline = new ConverterPipeline<>(extractor, converter, combiner, false, Optional.empty());
|
||||
if (!bootstrapped) {
|
||||
CONVERTERS.add(pipeline);
|
||||
}
|
||||
return pipeline;
|
||||
}
|
||||
|
||||
public static List<ConverterPipeline<?, ?>> converters(boolean experimental) {
|
||||
return List.copyOf(CONVERTERS).stream()
|
||||
.filter(converter -> experimental || !converter.experimental())
|
||||
.toList();
|
||||
}
|
||||
|
||||
static {
|
||||
// This will cause 3rd-party converters made using the utility methods here to not be added to the CONVERTERS array
|
||||
bootstrapped = true;
|
||||
}
|
||||
|
||||
private static <JavaAsset extends Keyed & ResourcePackPart> AssetExtractor<JavaAsset> extractor(ResourceCategory<JavaAsset> category) {
|
||||
return (pack, context) -> category.lister().apply(pack);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2025-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
|
||||
@@ -24,21 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.data;
|
||||
package org.geysermc.pack.converter.pipeline;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
|
||||
public interface ConversionData {
|
||||
@FunctionalInterface
|
||||
public interface AssetExtractor<JavaAsset> {
|
||||
|
||||
@NotNull
|
||||
Path inputDirectory();
|
||||
|
||||
@NotNull
|
||||
Path outputDirectory();
|
||||
|
||||
@NotNull
|
||||
ResourcePack vanillaPack();
|
||||
Collection<JavaAsset> extract(ResourcePack pack, ExtractionContext context);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2025-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.pipeline;
|
||||
|
||||
import org.geysermc.pack.converter.util.LogListener;
|
||||
import org.geysermc.pack.converter.util.LogListenerHelper;
|
||||
|
||||
public record CombineContext(String textureSubDirectory, LogListener logListener) implements LogListenerHelper {
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2025-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.pipeline;
|
||||
|
||||
import org.geysermc.pack.converter.util.LogListener;
|
||||
import org.geysermc.pack.converter.util.LogListenerHelper;
|
||||
|
||||
public record ConversionContext(String packName, LogListener logListener) implements LogListenerHelper {
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (c) 2025-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.pipeline;
|
||||
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import org.geysermc.pack.converter.util.LogListener;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@SuppressWarnings("ClassCanBeRecord") // We don't want to expose the fields here
|
||||
public final class ConverterPipeline<JavaAsset, BedrockAsset>
|
||||
implements AssetExtractor<JavaAsset>, AssetConverter<JavaAsset, BedrockAsset>, AssetCombiner<BedrockAsset> {
|
||||
private final AssetExtractor<JavaAsset> extractor;
|
||||
private final AssetConverter<JavaAsset, BedrockAsset> converter;
|
||||
private final AssetCombiner<BedrockAsset> combiner;
|
||||
private final boolean experimental;
|
||||
private final Optional<ActionListener<JavaAsset, BedrockAsset>> listener;
|
||||
|
||||
public ConverterPipeline(AssetExtractor<JavaAsset> extractor,
|
||||
AssetConverter<JavaAsset, BedrockAsset> converter,
|
||||
AssetCombiner<BedrockAsset> combiner,
|
||||
boolean experimental,
|
||||
Optional<ActionListener<JavaAsset, BedrockAsset>> listener) {
|
||||
this.extractor = extractor;
|
||||
this.converter = converter;
|
||||
this.combiner = combiner;
|
||||
this.experimental = experimental;
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<JavaAsset> extract(ResourcePack pack, ExtractionContext context) {
|
||||
Collection<JavaAsset> extracted = extractor.extract(pack, context);
|
||||
listener.ifPresent(actionListener -> actionListener.postExtract(pack, extracted, context));
|
||||
return extracted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable BedrockAsset convert(JavaAsset asset, ConversionContext context) throws Exception {
|
||||
BedrockAsset converted = converter.convert(asset, context);
|
||||
return listener.map(actionListener -> actionListener.postConvert(asset, converted, context))
|
||||
.orElse(converted);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(BedrockResourcePack pack, List<BedrockAsset> assets, CombineContext context) {
|
||||
combiner.include(pack, assets, context);
|
||||
listener.ifPresent(actionListener -> actionListener.postInclude(pack, assets, context));
|
||||
}
|
||||
|
||||
public int convert(ResourcePack pack, Optional<ResourcePack> vanillaPack, BedrockResourcePack bedrockPack, String packName, String textureSubDirectory, LogListener logListener) {
|
||||
ExtractionContext extractionContext = new ExtractionContext(bedrockPack, vanillaPack, logListener);
|
||||
ConversionContext conversionContext = new ConversionContext(packName, logListener);
|
||||
CombineContext combineContext = new CombineContext(textureSubDirectory, logListener);
|
||||
|
||||
AtomicInteger errors = new AtomicInteger(0);
|
||||
List<BedrockAsset> converted = extract(pack, extractionContext).stream()
|
||||
.map(asset -> {
|
||||
try {
|
||||
return convert(asset, conversionContext);
|
||||
} catch (Exception exception) {
|
||||
errors.incrementAndGet();
|
||||
logListener.error("Failed to convert asset", exception);
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
if (!converted.isEmpty()) {
|
||||
include(bedrockPack, converted, combineContext);
|
||||
}
|
||||
|
||||
return errors.get();
|
||||
}
|
||||
|
||||
public boolean experimental() {
|
||||
return experimental;
|
||||
}
|
||||
|
||||
public ConverterPipeline<JavaAsset, BedrockAsset> withActionListener(ActionListener<JavaAsset, BedrockAsset> listener) {
|
||||
return new ConverterPipeline<>(extractor, converter, combiner, experimental, Optional.of(listener));
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2025-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
|
||||
@@ -24,34 +24,19 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter;
|
||||
package org.geysermc.pack.converter.pipeline;
|
||||
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.PackConverter;
|
||||
import org.geysermc.pack.converter.data.ConversionData;
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import org.geysermc.pack.converter.util.LogListener;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.geysermc.pack.converter.util.LogListenerHelper;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Optional;
|
||||
|
||||
public interface Converter<T extends ConversionData> {
|
||||
|
||||
void convert(@NotNull PackConversionContext<T> context) throws Exception;
|
||||
|
||||
T createConversionData(@NotNull ConversionDataCreationContext context);
|
||||
|
||||
default boolean isExperimental() {
|
||||
return false;
|
||||
}
|
||||
|
||||
record ConversionDataCreationContext(
|
||||
@NotNull PackConverter converter,
|
||||
@NotNull LogListener logListener,
|
||||
@NotNull Path inputDirectory,
|
||||
@NotNull Path outputDirectory,
|
||||
@NotNull ResourcePack javaResourcePack,
|
||||
@NotNull ResourcePack vanillaResourcePack
|
||||
) {
|
||||
}
|
||||
/**
|
||||
* @param bedrockResourcePack should never be used. The bedrock resource pack should not be written to during extraction, rather only during combination of converted assets.
|
||||
* The bedrock resource pack is only included here for legacy converters still making use of it, which will be rewritten soon.
|
||||
*/
|
||||
public record ExtractionContext(@Deprecated(forRemoval = true) BedrockResourcePack bedrockResourcePack,
|
||||
Optional<ResourcePack> vanillaPack, LogListener logListener) implements LogListenerHelper {
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-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
|
||||
@@ -24,33 +24,41 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.base;
|
||||
package org.geysermc.pack.converter.type.base;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.converter.BaseConverter;
|
||||
import org.geysermc.pack.converter.converter.Converter;
|
||||
import org.geysermc.pack.converter.data.BaseConversionData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.geysermc.pack.converter.pipeline.AssetConverter;
|
||||
import org.geysermc.pack.converter.pipeline.ConversionContext;
|
||||
import org.geysermc.pack.converter.pipeline.ExtractionContext;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
import team.unnamed.creative.base.Writable;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@AutoService(Converter.class)
|
||||
public class PackIconConverter extends BaseConverter {
|
||||
private static final Key UNKNOWN_PACK = Key.key(Key.MINECRAFT_NAMESPACE, "misc/unknown_pack.png");
|
||||
import java.util.Optional;
|
||||
|
||||
@Override
|
||||
public void convert(@NotNull PackConversionContext<BaseConversionData> context) throws Exception {
|
||||
Writable packIcon = context.javaResourcePack().icon();
|
||||
public class PackIconConverter implements AssetConverter<Writable, byte[]> {
|
||||
public static final PackIconConverter INSTANCE = new PackIconConverter();
|
||||
private static final Key UNKNOWN_PACK = KeyUtil.key(Key.MINECRAFT_NAMESPACE, "misc/unknown_pack.png");
|
||||
|
||||
public static Writable extractIcon(ResourcePack pack, ExtractionContext context) {
|
||||
Writable packIcon = pack.icon();
|
||||
if (packIcon == null) {
|
||||
if (context.javaResourcePack().texture(UNKNOWN_PACK) != null) {
|
||||
packIcon = context.javaResourcePack().texture(UNKNOWN_PACK).data();
|
||||
Texture unknownPackOverride = pack.texture(UNKNOWN_PACK);
|
||||
if (unknownPackOverride != null) {
|
||||
packIcon = unknownPackOverride.data();
|
||||
} else {
|
||||
packIcon = context.data().vanillaPack().texture(UNKNOWN_PACK).data();
|
||||
packIcon = context.vanillaPack()
|
||||
.flatMap(vanilla -> Optional.ofNullable(vanilla.texture(UNKNOWN_PACK)))
|
||||
.map(Texture::data)
|
||||
.orElse(null);
|
||||
}
|
||||
}
|
||||
return packIcon;
|
||||
}
|
||||
|
||||
context.bedrockResourcePack().icon(packIcon.toByteArray());
|
||||
@Override
|
||||
public byte[] convert(Writable writable, ConversionContext context) throws Exception {
|
||||
return writable.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2019-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
|
||||
@@ -24,36 +24,30 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.base;
|
||||
package org.geysermc.pack.converter.type.base;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.bedrock.resource.Manifest;
|
||||
import org.geysermc.pack.bedrock.resource.manifest.Header;
|
||||
import org.geysermc.pack.bedrock.resource.manifest.Modules;
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.converter.BaseConverter;
|
||||
import org.geysermc.pack.converter.converter.Converter;
|
||||
import org.geysermc.pack.converter.data.BaseConversionData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
import org.geysermc.pack.converter.pipeline.AssetConverter;
|
||||
import org.geysermc.pack.converter.pipeline.ConversionContext;
|
||||
import team.unnamed.creative.metadata.pack.PackMeta;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
@AutoService(Converter.class)
|
||||
public class PackManifestConverter extends BaseConverter {
|
||||
public class PackManifestConverter implements AssetConverter<PackMeta, Manifest> {
|
||||
public static final PackManifestConverter INSTANCE = new PackManifestConverter();
|
||||
private static final int FORMAT_VERSION = 2;
|
||||
|
||||
@Override
|
||||
public void convert(@NotNull PackConversionContext<BaseConversionData> context) throws Exception {
|
||||
ResourcePack javaPack = context.javaResourcePack();
|
||||
|
||||
public Manifest convert(PackMeta packMeta, ConversionContext context) throws Exception {
|
||||
Manifest manifest = new Manifest();
|
||||
manifest.formatVersion(FORMAT_VERSION);
|
||||
|
||||
Header header = new Header();
|
||||
header.description(javaPack.description());
|
||||
header.name(context.packConverter().packName());
|
||||
header.description(packMeta.description());
|
||||
header.name(context.packName());
|
||||
header.version(new float[] { 1, 0, 0 });
|
||||
header.minEngineVersion(new float[] { 1, 16, 0 });
|
||||
header.uuid(UUID.randomUUID().toString());
|
||||
@@ -61,12 +55,13 @@ public class PackManifestConverter extends BaseConverter {
|
||||
manifest.header(header);
|
||||
|
||||
Modules module = new Modules();
|
||||
module.description(javaPack.description());
|
||||
module.description(packMeta.description());
|
||||
module.type("resources");
|
||||
module.uuid(UUID.randomUUID().toString());
|
||||
module.version(new float[] { 1, 0, 0 });
|
||||
|
||||
manifest.modules(List.of(module));
|
||||
context.bedrockResourcePack().manifest(manifest);
|
||||
|
||||
return manifest;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2025-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
|
||||
@@ -24,8 +24,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter;
|
||||
package org.geysermc.pack.converter.type.lang;
|
||||
|
||||
public class Constants {
|
||||
public static final String JAVA_PACK_LOCATION = "assets/%s";
|
||||
import java.util.Map;
|
||||
|
||||
public record BedrockLanguage(String language, Map<String, String> strings) {
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright (c) 2019-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.type.lang;
|
||||
|
||||
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 team.unnamed.creative.lang.Language;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class LangConverter implements AssetConverter<Language, BedrockLanguage>, AssetCombiner<BedrockLanguage> {
|
||||
public static final LangConverter INSTANCE = new LangConverter();
|
||||
|
||||
private static final Pattern POSITIONAL_STRING_REPLACEMENT = Pattern.compile("%([0-9]+)\\$s");
|
||||
|
||||
@Override
|
||||
public BedrockLanguage convert(Language language, ConversionContext context) throws Exception {
|
||||
Map<String, String> strings = language.translations();
|
||||
|
||||
for (Map.Entry<String, String> entry : strings.entrySet()) {
|
||||
String value = entry.getValue();
|
||||
|
||||
// Replace %d with %s
|
||||
value = value.replace("%d", "%s");
|
||||
|
||||
// Replace `%x$s` with `%x`
|
||||
value = POSITIONAL_STRING_REPLACEMENT.matcher(value).replaceAll("%$1");
|
||||
|
||||
entry.setValue(value);
|
||||
}
|
||||
|
||||
String languageKey = language.key().value();
|
||||
|
||||
// Convert the language key to the Bedrock equivalent
|
||||
if (languageKey.equals("no_no")) {
|
||||
languageKey = "nb_no";
|
||||
}
|
||||
|
||||
return new BedrockLanguage(languageKey, strings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(BedrockResourcePack pack, List<BedrockLanguage> languages, CombineContext context) {
|
||||
Map<String, Map<String, String>> merged = new HashMap<>();
|
||||
|
||||
for (BedrockLanguage language : languages) {
|
||||
Map<String, String> mergedLanguage = merged.computeIfAbsent(language.language(), name -> new HashMap<>());
|
||||
for (Map.Entry<String, String> entry : language.strings().entrySet()) {
|
||||
if (mergedLanguage.containsKey(entry.getKey())) {
|
||||
context.warn("Conflicting language string " + entry.getKey() + "!");
|
||||
continue;
|
||||
}
|
||||
mergedLanguage.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
merged.forEach(pack::addLanguage);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2025 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2025-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
|
||||
@@ -24,38 +24,27 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.misc;
|
||||
package org.geysermc.pack.converter.type.misc;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.gson.*;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.converter.BaseConverter;
|
||||
import org.geysermc.pack.converter.converter.Converter;
|
||||
import org.geysermc.pack.converter.data.BaseConversionData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import org.geysermc.pack.converter.pipeline.AssetConverter;
|
||||
import org.geysermc.pack.converter.pipeline.ConversionContext;
|
||||
import team.unnamed.creative.base.Writable;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
|
||||
@AutoService(Converter.class)
|
||||
public class SplashTextConverter extends BaseConverter {
|
||||
private static final Gson GSON = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
public class SplashTextConverter implements AssetConverter<Writable, JsonElement> {
|
||||
public static final SplashTextConverter INSTANCE = new SplashTextConverter();
|
||||
|
||||
@Override
|
||||
public void convert(@NotNull PackConversionContext<BaseConversionData> context) throws Exception {
|
||||
Writable javaSplashText = context.javaResourcePack().unknownFile("assets/minecraft/texts/splashes.txt");
|
||||
if (javaSplashText == null) return;
|
||||
|
||||
String[] splashes = javaSplashText.toUTF8String().split("\n");
|
||||
public JsonElement convert(Writable writable, ConversionContext context) throws Exception {
|
||||
String[] splashes = writable.toUTF8String().split("\n");
|
||||
JsonArray splashesArray = new JsonArray();
|
||||
Arrays.stream(splashes).toList().forEach(splashesArray::add);
|
||||
JsonObject object = new JsonObject();
|
||||
object.add("splashes", splashesArray);
|
||||
|
||||
context.bedrockResourcePack().addExtraFile(GSON.toJson(object).getBytes(StandardCharsets.UTF_8), "splashes.json");
|
||||
return object;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2025-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
|
||||
@@ -24,19 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter;
|
||||
package org.geysermc.pack.converter.type.model;
|
||||
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.data.ConversionData;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.ModelEntity;
|
||||
|
||||
/**
|
||||
* A listener for actions that occur during pack conversion.
|
||||
*/
|
||||
public interface ActionListener<T extends ConversionData> {
|
||||
public record BedrockModel(ModelType type, String fileName, ModelEntity model) {
|
||||
|
||||
default void preConvert(PackConversionContext<T> context) {
|
||||
}
|
||||
|
||||
default void postConvert(PackConversionContext<T> context) {
|
||||
public enum ModelType {
|
||||
BLOCK,
|
||||
ENTITY
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2019-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.type.model;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.ModelEntity;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.Geometry;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.Bones;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.Description;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.Cubes;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.Uv;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.Down;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.East;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.North;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.South;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.Up;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.modelentity.geometry.bones.cubes.uv.West;
|
||||
import org.geysermc.pack.converter.pipeline.AssetCombiner;
|
||||
import org.geysermc.pack.converter.pipeline.AssetConverter;
|
||||
import org.geysermc.pack.converter.pipeline.AssetExtractor;
|
||||
import org.geysermc.pack.converter.pipeline.CombineContext;
|
||||
import org.geysermc.pack.converter.pipeline.ConversionContext;
|
||||
import org.geysermc.pack.converter.pipeline.ExtractionContext;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
import team.unnamed.creative.base.CubeFace;
|
||||
import team.unnamed.creative.model.Element;
|
||||
import team.unnamed.creative.model.ElementFace;
|
||||
import team.unnamed.creative.model.ElementRotation;
|
||||
import team.unnamed.creative.model.Model;
|
||||
import team.unnamed.creative.texture.TextureUV;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ModelConverter implements AssetExtractor<Model>, AssetConverter<Model, BedrockModel>, AssetCombiner<BedrockModel> {
|
||||
public static final ModelConverter INSTANCE = new ModelConverter();
|
||||
|
||||
private static final String FORMAT_VERSION = "1.16.0";
|
||||
private static final String GEOMETRY_FORMAT = "geometry.%s";
|
||||
|
||||
private static final float[] ELEMENT_OFFSET = new float[] { 8, 0, 8 };
|
||||
|
||||
@Override
|
||||
public Collection<Model> extract(ResourcePack pack, ExtractionContext context) {
|
||||
ModelStitcher.Provider modelProvider = context.vanillaPack()
|
||||
.map(vanilla -> ModelStitcher.vanillaProvider(pack, vanilla))
|
||||
.orElseGet(() -> ModelStitcher.baseProvider(pack));
|
||||
// TODO maybe parallel, if model stitching takes a lot of time
|
||||
return pack.models().stream()
|
||||
.map(model -> new ModelStitcher(modelProvider, model, context.logListener()).stitch())
|
||||
.toList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public BedrockModel convert(Model model, ConversionContext context) throws Exception {
|
||||
List<Element> elements = model.elements();
|
||||
if (elements.isEmpty()) {
|
||||
context.debug("Model " + model.key().key() + " has no elements");
|
||||
return null;
|
||||
}
|
||||
|
||||
String value = model.key().value();
|
||||
context.debug("Converting model " + model.key().key() + ":" + value);
|
||||
|
||||
// TODO: Convert item models but save differently?
|
||||
if (value.startsWith("item/")) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ModelEntity modelEntity = new ModelEntity();
|
||||
modelEntity.formatVersion(FORMAT_VERSION);
|
||||
|
||||
Geometry geometry = new Geometry();
|
||||
|
||||
String namespace = model.key().namespace();
|
||||
String fileName = value.substring(value.lastIndexOf('/') + 1);
|
||||
|
||||
String geoName = (namespace.equals(Key.MINECRAFT_NAMESPACE) ? "" : namespace + ".") + fileName;
|
||||
|
||||
// TODO: Don't hardcode all this
|
||||
Description description = new Description();
|
||||
description.identifier(String.format(GEOMETRY_FORMAT, geoName));
|
||||
description.textureWidth(16);
|
||||
description.textureHeight(16);
|
||||
description.visibleBoundsWidth(2);
|
||||
description.visibleBoundsHeight(2);
|
||||
description.visibleBoundsOffset(new float[] { 0.0f, 0.25f, 0.0f });
|
||||
geometry.description(description);
|
||||
|
||||
List<Bones> bones = new ArrayList<>();
|
||||
|
||||
// TODO: Should each element be its own bone rather
|
||||
// than its own cube in the same bone?
|
||||
int i = 0;
|
||||
for (Element element : elements) {
|
||||
float[] from = element.from().toArray();
|
||||
float[] to = element.to().toArray();
|
||||
|
||||
Bones bone = new Bones();
|
||||
bone.name("bone_" + i++);
|
||||
bone.pivot(new float[] { ELEMENT_OFFSET[0], ELEMENT_OFFSET[1], -ELEMENT_OFFSET[2] });
|
||||
|
||||
Cubes cube = new Cubes();
|
||||
cube.origin(new float[] { ELEMENT_OFFSET[0] - to[0], from[1], from[2] - ELEMENT_OFFSET[2] });
|
||||
cube.size(new float[] { to[0] - from[0], to[1] - from[1], to[2] - from[2] });
|
||||
|
||||
ElementRotation elementRotation = element.rotation();
|
||||
if (elementRotation != null) {
|
||||
float[] origin = elementRotation.origin().toArray();
|
||||
cube.pivot(new float[] { ELEMENT_OFFSET[0] - origin[0], ELEMENT_OFFSET[1] - origin[1], origin[2] - ELEMENT_OFFSET[2] });
|
||||
|
||||
float angle = elementRotation.angle();
|
||||
float[] rotation = new float[3];
|
||||
switch (elementRotation.axis()) {
|
||||
case X -> rotation[0] = -angle;
|
||||
case Y -> rotation[1] = -angle;
|
||||
case Z -> rotation[2] = -angle;
|
||||
}
|
||||
|
||||
cube.rotation(rotation);
|
||||
}
|
||||
|
||||
Uv uv = new Uv();
|
||||
for (Map.Entry<CubeFace, ElementFace> entry : element.faces().entrySet()) {
|
||||
CubeFace face = entry.getKey();
|
||||
ElementFace elementFace = entry.getValue();
|
||||
if (elementFace.uv0() == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The Java pack lib we use does this weird thing where it
|
||||
// divides the UV by 16, so we need to multiply it by 16
|
||||
|
||||
String texture = elementFace.texture().replace("#", "");
|
||||
applyUv(uv, face, texture, multiplyUv(elementFace.uv0(), 16f));
|
||||
}
|
||||
|
||||
cube.uv(uv);
|
||||
bone.cubes(List.of(cube));
|
||||
|
||||
bones.add(bone);
|
||||
}
|
||||
|
||||
geometry.bones(bones);
|
||||
|
||||
modelEntity.geometry(List.of(geometry));
|
||||
|
||||
if (model.key().namespace().contains("entity")) {
|
||||
return new BedrockModel(BedrockModel.ModelType.ENTITY, fileName + ".json", modelEntity);
|
||||
} else {
|
||||
// Bedrock only has a concept of entity or block models
|
||||
return new BedrockModel(BedrockModel.ModelType.BLOCK, fileName + ".json", modelEntity);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(BedrockResourcePack pack, List<BedrockModel> bedrockModels, CombineContext context) {
|
||||
List<String> entityModels = new ArrayList<>();
|
||||
List<String> blockModels = new ArrayList<>();
|
||||
|
||||
for (BedrockModel model : bedrockModels) {
|
||||
switch (model.type()) {
|
||||
case ENTITY -> {
|
||||
if (entityModels.contains(model.fileName())) {
|
||||
context.warn("Conflicting entity model " + model.fileName() + "!");
|
||||
continue;
|
||||
}
|
||||
entityModels.add(model.fileName());
|
||||
pack.addEntityModel(model.model(), model.fileName());
|
||||
}
|
||||
case BLOCK -> {
|
||||
if (blockModels.contains(model.fileName())) {
|
||||
context.warn("Conflicting entity model " + model.fileName() + "!");
|
||||
continue;
|
||||
}
|
||||
blockModels.add(model.fileName());
|
||||
pack.addBlockModel(model.model(), model.fileName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private TextureUV multiplyUv(TextureUV textureUV, float mult) {
|
||||
return TextureUV.uv(textureUV.from().multiply(mult), textureUV.to().multiply(mult));
|
||||
}
|
||||
|
||||
private static void applyUv(Uv uv, CubeFace face, String texture, TextureUV faceUv) {
|
||||
float[] uvs;
|
||||
float[] uvSize;
|
||||
|
||||
// These values are flipped for some reason
|
||||
if (face == CubeFace.DOWN || face == CubeFace.UP) {
|
||||
uvs = new float[] { faceUv.to().x(), faceUv.to().y() };
|
||||
uvSize = new float[] { faceUv.from().x() - faceUv.to().x(), faceUv.from().y() - faceUv.to().y() };
|
||||
} else {
|
||||
uvs = new float[] { faceUv.from().x(), faceUv.from().y() };
|
||||
uvSize = new float[] { faceUv.to().x() - faceUv.from().x(), faceUv.to().y() - faceUv.from().y() };
|
||||
}
|
||||
|
||||
switch (face) {
|
||||
case NORTH -> {
|
||||
North north = new North();
|
||||
north.uv(uvs);
|
||||
north.uvSize(uvSize);
|
||||
north.materialInstance(texture);
|
||||
|
||||
uv.north(north);
|
||||
}
|
||||
case SOUTH -> {
|
||||
South south = new South();
|
||||
south.uv(uvs);
|
||||
south.uvSize(uvSize);
|
||||
south.materialInstance(texture);
|
||||
|
||||
uv.south(south);
|
||||
}
|
||||
case EAST -> {
|
||||
East east = new East();
|
||||
east.uv(uvs);
|
||||
east.uvSize(uvSize);
|
||||
east.materialInstance(texture);
|
||||
|
||||
uv.east(east);
|
||||
}
|
||||
case WEST -> {
|
||||
West west = new West();
|
||||
west.uv(uvs);
|
||||
west.uvSize(uvSize);
|
||||
west.materialInstance(texture);
|
||||
|
||||
uv.west(west);
|
||||
}
|
||||
case UP -> {
|
||||
Up up = new Up();
|
||||
up.uv(uvs);
|
||||
up.uvSize(uvSize);
|
||||
up.materialInstance(texture);
|
||||
|
||||
uv.up(up);
|
||||
}
|
||||
case DOWN -> {
|
||||
Down down = new Down();
|
||||
down.uv(uvs);
|
||||
down.uvSize(uvSize);
|
||||
down.materialInstance(texture);
|
||||
|
||||
uv.down(down);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,12 +24,11 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.model;
|
||||
package org.geysermc.pack.converter.type.model;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.util.DefaultLogListener;
|
||||
import org.geysermc.pack.converter.util.LogListener;
|
||||
import org.geysermc.pack.converter.util.VanillaPackProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
@@ -39,10 +38,7 @@ import team.unnamed.creative.model.ItemTransform;
|
||||
import team.unnamed.creative.model.Model;
|
||||
import team.unnamed.creative.model.ModelTexture;
|
||||
import team.unnamed.creative.model.ModelTextures;
|
||||
import team.unnamed.creative.serialize.minecraft.MinecraftResourcePackReader;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -195,7 +191,7 @@ public class ModelStitcher {
|
||||
return pack::model;
|
||||
}
|
||||
|
||||
public static Provider vanillaProvider(@NotNull ResourcePack pack, @NotNull LogListener log, @NotNull ResourcePack vanillaPack) {
|
||||
public static Provider vanillaProvider(@NotNull ResourcePack pack, @NotNull ResourcePack vanillaPack) {
|
||||
return key -> {
|
||||
Model model = pack.model(key);
|
||||
if (model == null) {
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright (c) 2025-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.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.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.sound.Sound;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class SoundConverter implements AssetConverter<Sound, Sound>, AssetCombiner<Sound> {
|
||||
public static final SoundConverter INSTANCE = new SoundConverter();
|
||||
|
||||
@Override
|
||||
public @Nullable Sound convert(Sound sound, ConversionContext context) throws Exception {
|
||||
return sound;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(BedrockResourcePack pack, List<Sound> sounds, CombineContext context) {
|
||||
List<String> exported = new ArrayList<>();
|
||||
Path output = pack.directory().resolve(SoundRegistryConverter.BEDROCK_SOUNDS_LOCATION);
|
||||
|
||||
for (Sound sound : sounds) {
|
||||
String path = sound.key().value();
|
||||
if (exported.contains(path)) {
|
||||
context.warn("Conflicting sound file " + sound.key() + "!");
|
||||
continue;
|
||||
}
|
||||
Path file = output.resolve(path + ".ogg");
|
||||
Path directory = file.getParent();
|
||||
try {
|
||||
Files.createDirectories(directory);
|
||||
try (OutputStream outputStream = new FileOutputStream(file.toFile())) {
|
||||
sound.data().write(outputStream);
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
context.error("Failed to write sound file " + sound.key() + "!", exception);
|
||||
continue;
|
||||
}
|
||||
exported.add(path);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2025-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.type.sound;
|
||||
|
||||
import org.geysermc.pack.bedrock.resource.BedrockResourcePack;
|
||||
import org.geysermc.pack.bedrock.resource.sounds.sounddefinitions.SoundDefinitions;
|
||||
import org.geysermc.pack.bedrock.resource.sounds.sounddefinitions.Sounds;
|
||||
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.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.sound.SoundEntry;
|
||||
import team.unnamed.creative.sound.SoundEvent;
|
||||
import team.unnamed.creative.sound.SoundRegistry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SoundRegistryConverter implements AssetConverter<SoundRegistry, Map<String, SoundDefinitions>>, AssetCombiner<Map<String, SoundDefinitions>> {
|
||||
public static final SoundRegistryConverter INSTANCE = new SoundRegistryConverter();
|
||||
static final String BEDROCK_SOUNDS_LOCATION = "sounds";
|
||||
|
||||
@Override
|
||||
public @Nullable Map<String, SoundDefinitions> convert(SoundRegistry soundRegistry, ConversionContext context) throws Exception {
|
||||
Map<String, SoundDefinitions> definitions = new HashMap<>();
|
||||
|
||||
for (SoundEvent value : soundRegistry.sounds()) {
|
||||
String key = value.key().asString();
|
||||
|
||||
SoundDefinitions definition = new SoundDefinitions();
|
||||
definition.useLegacyMaxDistance(true); // TODO: Needed?
|
||||
definition.maxDistance(64); // ???
|
||||
for (SoundEntry sound : value.sounds()) {
|
||||
Sounds bedrockSound = new Sounds();
|
||||
bedrockSound.name(BEDROCK_SOUNDS_LOCATION + "/" + sound.key().value());
|
||||
bedrockSound.stream(sound.stream());
|
||||
bedrockSound.loadOnLowMemory(true);
|
||||
bedrockSound.volume(sound.volume());
|
||||
bedrockSound.pitch(sound.pitch());
|
||||
bedrockSound.weight(sound.weight());
|
||||
|
||||
definition.sounds().add(bedrockSound);
|
||||
}
|
||||
|
||||
definitions.put(key, definition);
|
||||
}
|
||||
|
||||
return definitions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(BedrockResourcePack pack, List<Map<String, SoundDefinitions>> maps, CombineContext context) {
|
||||
List<String> soundEvents = new ArrayList<>();
|
||||
|
||||
for (Map<String, SoundDefinitions> definitions : maps) {
|
||||
for (Map.Entry<String, SoundDefinitions> entry : definitions.entrySet()) {
|
||||
if (soundEvents.contains(entry.getKey())) {
|
||||
context.warn("Conflicting sound event " + entry.getKey() + "!");
|
||||
}
|
||||
pack.addSoundDefinition(entry.getKey(), entry.getValue());
|
||||
soundEvents.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture;
|
||||
package org.geysermc.pack.converter.type.texture;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -189,7 +189,7 @@ public final class PngToTgaMappings {
|
||||
};
|
||||
|
||||
@Nullable
|
||||
public static TgaMapping mapping(@NotNull String key) {
|
||||
static TgaMapping mapping(@NotNull String key) {
|
||||
return MAPPINGS.get(key);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright (c) 2019-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.type.texture;
|
||||
|
||||
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.AssetExtractor;
|
||||
import org.geysermc.pack.converter.pipeline.CombineContext;
|
||||
import org.geysermc.pack.converter.pipeline.ConversionContext;
|
||||
import org.geysermc.pack.converter.pipeline.ExtractionContext;
|
||||
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.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.AlphaComposite;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
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.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class TextureConverter implements AssetExtractor<Texture>, AssetConverter<Texture, TransformedTexture>, AssetCombiner<TransformedTexture> {
|
||||
public static final TextureConverter INSTANCE = new TextureConverter();
|
||||
public static final String BEDROCK_TEXTURES_LOCATION = "textures";
|
||||
|
||||
private final List<TextureTransformer> transformers = StreamSupport.stream(ServiceLoader.load(TextureTransformer.class).spliterator(), false)
|
||||
.sorted(Comparator.comparingInt(TextureTransformer::order))
|
||||
.toList();
|
||||
|
||||
public static final Map<String, String> DIRECTORY_LOCATIONS = Map.of(
|
||||
"block", "blocks",
|
||||
"item", "items",
|
||||
"gui", "ui"
|
||||
);
|
||||
|
||||
@Override
|
||||
public Collection<Texture> extract(ResourcePack pack, ExtractionContext context) {
|
||||
// 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();
|
||||
List<Texture> textures = new ArrayList<>(pack.textures());
|
||||
|
||||
context.info("Transforming textures...");
|
||||
TransformContext transformContext = new TransformContext(
|
||||
mappings,
|
||||
textures,
|
||||
context.bedrockResourcePack(),
|
||||
pack,
|
||||
context.vanillaPack(),
|
||||
context.logListener()
|
||||
);
|
||||
for (TextureTransformer transformer : this.transformers) {
|
||||
try {
|
||||
transformer.transform(transformContext);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
context.info("Transformed textures!");
|
||||
|
||||
return textures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable TransformedTexture convert(Texture texture, ConversionContext context) throws Exception {
|
||||
TextureMappings mappings = TextureMappings.textureMappings();
|
||||
TransformedTexture transformed = new TransformedTexture(texture);
|
||||
|
||||
String input = texture.key().value();
|
||||
String relativePath = input.replaceAll("\\.png$", "");
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return transformed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void include(BedrockResourcePack pack, List<TransformedTexture> transformedTextures, CombineContext context) {
|
||||
Path texturePath = pack.directory().resolve(BEDROCK_TEXTURES_LOCATION);
|
||||
List<String> exportedPaths = new ArrayList<>();
|
||||
|
||||
for (TransformedTexture textureToExport : transformedTextures) {
|
||||
String bedrockDirectory = "%s/%s";
|
||||
if (context.textureSubDirectory() != null) {
|
||||
bedrockDirectory = "%s/" + context.textureSubDirectory() + "/%s";
|
||||
}
|
||||
|
||||
List<Path> outputs = new ArrayList<>();
|
||||
for (String outputPath : textureToExport.output()) {
|
||||
if (exportedPaths.contains(outputPath)) {
|
||||
context.warn("Conflicting texture " + outputPath + "!");
|
||||
continue;
|
||||
}
|
||||
exportedPaths.add(outputPath);
|
||||
|
||||
String root = outputPath.substring(0, outputPath.indexOf('/'));
|
||||
String value = outputPath.substring(outputPath.indexOf('/') + 1);
|
||||
|
||||
outputs.add(texturePath.resolve((
|
||||
bedrockDirectory.formatted(root, value)
|
||||
).replace('/', File.separatorChar)));
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] bytes = textureToExport.texture().data().toByteArray();
|
||||
|
||||
BufferedImage image = ImageIO.read(new ByteArrayInputStream(bytes));
|
||||
|
||||
for (Path output : outputs) {
|
||||
if (output.getParent() != null && Files.notExists(output.getParent())) {
|
||||
Files.createDirectories(output.getParent());
|
||||
}
|
||||
|
||||
BufferedImage bedrockImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_INT_ARGB);
|
||||
|
||||
Graphics2D g = bedrockImage.createGraphics();
|
||||
g.setComposite(AlphaComposite.Src);
|
||||
g.drawImage(image, 0, 0, null);
|
||||
g.dispose();
|
||||
|
||||
String pngKey = pack.directory().relativize(output).toString().replace(File.separatorChar, '/');
|
||||
PngToTgaMappings.TgaMapping mapping = PngToTgaMappings.mapping(pngKey);
|
||||
if (mapping != null) {
|
||||
Path tgaPath = pack.directory().resolve(mapping.value());
|
||||
if (Files.notExists(tgaPath.getParent())) {
|
||||
Files.createDirectories(tgaPath.getParent());
|
||||
}
|
||||
|
||||
ImageUtil.writeTGA(tgaPath, bedrockImage);
|
||||
if (!mapping.keep()) {
|
||||
Files.deleteIfExists(output);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
try (OutputStream stream = Files.newOutputStream(output)) {
|
||||
ImageIO.write(bedrockImage, "png", stream);
|
||||
}
|
||||
}
|
||||
} catch (IOException exception) {
|
||||
context.error("Failed to write texture " + textureToExport.texture().key() + "!", exception);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture;
|
||||
package org.geysermc.pack.converter.type.texture;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import lombok.ToString;
|
||||
@@ -34,7 +34,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@ToString
|
||||
public class TextureMappings extends LinkedHashMap<String, Object> {
|
||||
@@ -24,7 +24,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer;
|
||||
package org.geysermc.pack.converter.type.texture.transformer;
|
||||
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -24,14 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer;
|
||||
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.PackConversionContext;
|
||||
import org.geysermc.pack.converter.converter.texture.TextureMappings;
|
||||
import org.geysermc.pack.converter.data.TextureConversionData;
|
||||
import org.geysermc.pack.converter.type.texture.TextureMappings;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.LogListener;
|
||||
import org.geysermc.pack.converter.util.LogListenerHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.ResourcePack;
|
||||
@@ -43,27 +43,33 @@ import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class TransformContext {
|
||||
private final PackConversionContext<TextureConversionData> conversionContext;
|
||||
public class TransformContext implements LogListenerHelper {
|
||||
private final TextureMappings 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)
|
||||
private final BedrockResourcePack bedrockPack;
|
||||
private final ResourcePack javaPack;
|
||||
private final Optional<ResourcePack> vanillaPack;
|
||||
private final LogListener logListener;
|
||||
private final Map<Key, Texture> byKey = new HashMap<>();
|
||||
|
||||
public TransformContext(
|
||||
PackConversionContext<TextureConversionData> conversionContext,
|
||||
TextureMappings mappings,
|
||||
Collection<Texture> textures,
|
||||
BedrockResourcePack bedrockPack,
|
||||
ResourcePack javaPack
|
||||
ResourcePack javaPack,
|
||||
Optional<ResourcePack> vanillaPack,
|
||||
LogListener logListener
|
||||
) {
|
||||
this.conversionContext = conversionContext;
|
||||
this.mappings = mappings;
|
||||
this.textures = textures;
|
||||
this.bedrockPack = bedrockPack;
|
||||
this.javaPack = javaPack;
|
||||
this.vanillaPack = vanillaPack;
|
||||
this.logListener = logListener;
|
||||
|
||||
for (Texture texture : textures) {
|
||||
this.byKey.put(texture.key(), texture);
|
||||
@@ -74,16 +80,17 @@ public class TransformContext {
|
||||
return this.mappings;
|
||||
}
|
||||
|
||||
@Deprecated(forRemoval = true)
|
||||
public BedrockResourcePack bedrockResourcePack() {
|
||||
return this.bedrockPack;
|
||||
return bedrockPack;
|
||||
}
|
||||
|
||||
public ResourcePack javaResourcePack() {
|
||||
return this.javaPack;
|
||||
}
|
||||
|
||||
public ResourcePack vanillaPack() {
|
||||
return this.conversionContext.data().vanillaPack();
|
||||
public Optional<ResourcePack> vanillaPack() {
|
||||
return vanillaPack;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,8 +133,7 @@ public class TransformContext {
|
||||
public Texture pollOrPeekVanilla(@NotNull Key key) {
|
||||
Texture remove = this.byKey.remove(key);
|
||||
if (remove == null) {
|
||||
// This *shouldn't* be null, but if a bad key is inputted, it is possible this value is null
|
||||
return this.conversionContext.data().vanillaPack().texture(key);
|
||||
return vanillaPack.map(pack -> pack.texture(key)).orElse(null);
|
||||
}
|
||||
|
||||
this.textures.remove(remove);
|
||||
@@ -146,8 +152,7 @@ public class TransformContext {
|
||||
public Texture peekOrVanilla(@NotNull Key key) {
|
||||
Texture texture = this.byKey.get(key);
|
||||
if (texture == null) {
|
||||
// This *shouldn't* be null, but if a bad key is inputted, it is possible this value is null
|
||||
return this.conversionContext.data().vanillaPack().texture(key);
|
||||
return vanillaPack.map(pack -> pack.texture(key)).orElse(null);
|
||||
}
|
||||
|
||||
return texture;
|
||||
@@ -186,23 +191,7 @@ public class TransformContext {
|
||||
this.byKey.put(texture.key(), texture);
|
||||
}
|
||||
|
||||
public void debug(@NotNull String message) {
|
||||
this.conversionContext.debug(message);
|
||||
}
|
||||
|
||||
public void info(@NotNull String message) {
|
||||
this.conversionContext.info(message);
|
||||
}
|
||||
|
||||
public void warn(@NotNull String message) {
|
||||
this.conversionContext.warn(message);
|
||||
}
|
||||
|
||||
public void error(@NotNull String message) {
|
||||
this.conversionContext.error(message);
|
||||
}
|
||||
|
||||
public void error(@NotNull String message, @NotNull Throwable throwable) {
|
||||
this.conversionContext.error(message, throwable);
|
||||
public LogListener logListener() {
|
||||
return logListener;
|
||||
}
|
||||
}
|
||||
@@ -24,20 +24,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer;
|
||||
package org.geysermc.pack.converter.type.texture.transformer;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TransformedTexture {
|
||||
private final Texture texture;
|
||||
private Path output;
|
||||
private final List<String> outputs = new ArrayList<>();
|
||||
|
||||
public TransformedTexture(@NotNull Texture texture, @NotNull Path output) {
|
||||
public TransformedTexture(@NotNull Texture texture) {
|
||||
this.texture = texture;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -46,11 +46,11 @@ public class TransformedTexture {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Path output() {
|
||||
return output;
|
||||
public List<String> output() {
|
||||
return outputs;
|
||||
}
|
||||
|
||||
public void output(@NotNull Path output) {
|
||||
this.output = output;
|
||||
public void output(@NotNull String output) {
|
||||
outputs.add(output);
|
||||
}
|
||||
}
|
||||
@@ -24,12 +24,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -54,7 +55,7 @@ public class AtlasTransformer implements TextureTransformer {
|
||||
|
||||
BufferedImage atlasImage = null;
|
||||
for (int i = 0; i <= atlasCount; i++) {
|
||||
Texture texture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, String.format(javaName, String.format("%1$2s", i).replace(" ", "0"))));
|
||||
Texture texture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, String.format(javaName, String.format("%1$2s", i).replace(" ", "0"))));
|
||||
if (texture == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -69,7 +70,7 @@ public class AtlasTransformer implements TextureTransformer {
|
||||
}
|
||||
|
||||
if (atlasImage != null) {
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, bedrockName), atlasImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, bedrockName), atlasImage, "png");
|
||||
context.debug(String.format("Created atlas %s", bedrockName));
|
||||
}
|
||||
}
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.geysermc.pack.converter.util.UnsafeKey;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
@@ -272,7 +273,7 @@ public class ColorizeTransformer implements TextureTransformer {
|
||||
Color color = overlay.color();
|
||||
boolean deleteOverlay = overlay.deleteOverlay();
|
||||
|
||||
Key key = Key.key(Key.MINECRAFT_NAMESPACE, overlayPath);
|
||||
Key key = KeyUtil.key(Key.MINECRAFT_NAMESPACE, overlayPath);
|
||||
Texture texture = deleteOverlay ? context.poll(key) : context.peek(key);
|
||||
if (texture == null) {
|
||||
context.debug("Missing overlay texture: " + overlayPath);
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -102,8 +103,8 @@ public class OverlayTransformer implements TextureTransformer {
|
||||
boolean noReplace = overlay.noReplace();
|
||||
boolean keep = overlay.keep();
|
||||
|
||||
Key javaKey = Key.key(Key.MINECRAFT_NAMESPACE, javaName);
|
||||
Key overlayKey = Key.key(Key.MINECRAFT_NAMESPACE, overlayName);
|
||||
Key javaKey = KeyUtil.key(Key.MINECRAFT_NAMESPACE, javaName);
|
||||
Key overlayKey = KeyUtil.key(Key.MINECRAFT_NAMESPACE, overlayName);
|
||||
|
||||
// We don't have either textures, skip this
|
||||
if (!context.isTexturePresent(javaKey) && !context.isTexturePresent(overlayKey)) continue;
|
||||
@@ -149,7 +150,7 @@ public class OverlayTransformer implements TextureTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, bedrockName), image, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, bedrockName), image, "png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -46,8 +47,8 @@ public class WeatherTransformer implements TextureTransformer {
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
Texture snowTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, SNOW_INPUT));
|
||||
Texture rainTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, RAIN_INPUT));
|
||||
Texture snowTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, SNOW_INPUT));
|
||||
Texture rainTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, RAIN_INPUT));
|
||||
if (snowTexture == null || rainTexture == null) {
|
||||
return;
|
||||
}
|
||||
@@ -69,6 +70,6 @@ public class WeatherTransformer implements TextureTransformer {
|
||||
// Rain
|
||||
graphics.drawImage(ImageUtil.cover(ImageUtil.crop(rainImage, rainImage.getWidth(), (int) (5 * factor)), weatherImage.getWidth(), (int) (5 * factor)), 0, (int) (5 * factor), null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, WEATHER_OUTPUT), weatherImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, WEATHER_OUTPUT), weatherImage, "png");
|
||||
}
|
||||
}
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.block;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.block;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -65,7 +66,7 @@ public class BedTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
for (String bedColor : BED_COLORS) {
|
||||
Texture texture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, BED_PATH + "/" + bedColor + ".png"));
|
||||
Texture texture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, BED_PATH + "/" + bedColor + ".png"));
|
||||
if (texture == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -110,7 +111,7 @@ public class BedTransformer implements TextureTransformer {
|
||||
graphics.drawImage(ImageUtil.rotate(ImageUtil.crop(bedImage, ((fromX + 9) * factor), ((fromY + 3) * factor), (3 * factor), (3 * factor)), 180), ((toX + 3) * factor), (toY * factor), null);
|
||||
}
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, BED_PATH + "/" + bedColor + ".png"), newBedImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, BED_PATH + "/" + bedColor + ".png"), newBedImage, "png");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.block;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.block;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -50,8 +51,8 @@ public class ChestDoubleTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
for (ChestData chest : CHEST_DATA) {
|
||||
Texture leftTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, chest.javaNameLeft()));
|
||||
Texture rightTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, chest.javaNameRight()));
|
||||
Texture leftTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, chest.javaNameLeft()));
|
||||
Texture rightTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, chest.javaNameRight()));
|
||||
if (leftTexture == null || rightTexture == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -101,7 +102,7 @@ public class ChestDoubleTransformer implements TextureTransformer {
|
||||
graphics.drawImage(ImageUtil.crop(leftImage, 0, 0, (6 * factor), (6 * factor)), 0, 0, null);
|
||||
graphics.drawImage(ImageUtil.crop(rightImage, 0, 0, (6 * factor), (6 * factor)), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, chest.bedrockName()), newImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, chest.bedrockName()), newImage, "png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.block;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.block;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -50,7 +51,7 @@ public class ChestFrontTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
for (ChestData chest : CHESTS) {
|
||||
Texture texture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, chest.javaName()));
|
||||
Texture texture = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, chest.javaName()));
|
||||
if (texture == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -68,7 +69,7 @@ public class ChestFrontTransformer implements TextureTransformer {
|
||||
graphics.drawImage(ImageUtil.crop(fromImage, (14 * factor), (34 * factor), (14 * factor), (9 * factor)), 0, (5 * factor), null);
|
||||
graphics.drawImage(ImageUtil.crop(fromImage , factor, factor, (2 * factor), (4 * factor)), (6 * factor), (3 * factor), null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, chest.bedrockName()), newImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, chest.bedrockName()), newImage, "png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.block;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.block;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -53,7 +54,7 @@ public class ChestNormalTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
for (String variant : VARIANTS) {
|
||||
Texture texture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, CHEST_PATH + "/" + variant + ".png"));
|
||||
Texture texture = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, CHEST_PATH + "/" + variant + ".png"));
|
||||
if (texture == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -86,7 +87,7 @@ public class ChestNormalTransformer implements TextureTransformer {
|
||||
|
||||
graphics.drawImage(ImageUtil.crop(chestImage, 0, 0, (6 * factor), (6 * factor)), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, CHEST_PATH + "/" + variant + ".png"), newChestImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, CHEST_PATH + "/" + variant + ".png"), newChestImage, "png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.block;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.block;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -49,7 +50,7 @@ public class ChestSideTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
for (ChestData chest : CHESTS) {
|
||||
Texture texture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, chest.javaName()));
|
||||
Texture texture = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, chest.javaName()));
|
||||
if (texture == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -66,7 +67,7 @@ public class ChestSideTransformer implements TextureTransformer {
|
||||
graphics.drawImage(ImageUtil.crop(fromImage, (28 * factor), (14 * factor), (14 * factor), (5 * factor)), 0, 0, null);
|
||||
graphics.drawImage(ImageUtil.crop(fromImage, (28 * factor), (34 * factor), (14 * factor), (9 * factor)), 0, (5 * factor), null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, chest.bedrockName()), newImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, chest.bedrockName()), newImage, "png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.block;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.block;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -42,7 +43,7 @@ import java.io.IOException;
|
||||
public class ConduitTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
Texture baseTexture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, "entity/conduit/base.png"));
|
||||
Texture baseTexture = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "entity/conduit/base.png"));
|
||||
if (baseTexture != null) {
|
||||
BufferedImage baseImage = this.readImage(baseTexture);
|
||||
|
||||
@@ -53,10 +54,10 @@ public class ConduitTransformer implements TextureTransformer {
|
||||
Graphics g = bedrockBaseImage.getGraphics();
|
||||
g.drawImage(ImageUtil.crop(baseImage, 0, 0, (int) (24 * scale), (int) (12 * scale)), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "blocks/conduit_base.png"), bedrockBaseImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "blocks/conduit_base.png"), bedrockBaseImage, "png");
|
||||
}
|
||||
|
||||
Texture eyeTexture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, "entity/conduit/closed_eye.png"));
|
||||
Texture eyeTexture = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "entity/conduit/closed_eye.png"));
|
||||
if (eyeTexture != null) {
|
||||
BufferedImage image = this.readImage(eyeTexture);
|
||||
|
||||
@@ -67,10 +68,10 @@ public class ConduitTransformer implements TextureTransformer {
|
||||
Graphics g = bedrockImage.getGraphics();
|
||||
g.drawImage(ImageUtil.crop(image, 0, 0, (int) (8 * scale), (int) (8 * scale)), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "blocks/conduit_closed.png"), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "blocks/conduit_closed.png"), bedrockImage, "png");
|
||||
}
|
||||
|
||||
Texture eyeOpenTexture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, "entity/conduit/open_eye.png"));
|
||||
Texture eyeOpenTexture = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "entity/conduit/open_eye.png"));
|
||||
if (eyeOpenTexture != null) {
|
||||
BufferedImage image = this.readImage(eyeOpenTexture);
|
||||
|
||||
@@ -81,7 +82,7 @@ public class ConduitTransformer implements TextureTransformer {
|
||||
Graphics g = bedrockImage.getGraphics();
|
||||
g.drawImage(ImageUtil.crop(image, 0, 0, (int) (8 * scale), (int) (8 * scale)), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "blocks/conduit_open.png"), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "blocks/conduit_open.png"), bedrockImage, "png");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.block;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.block;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -55,7 +56,7 @@ public class LiquidTransformer implements TextureTransformer {
|
||||
int minWidth = liquid.minWidth();
|
||||
boolean grayscale = liquid.grayscale();
|
||||
|
||||
Texture texture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, javaName));
|
||||
Texture texture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, javaName));
|
||||
if (texture == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -70,7 +71,7 @@ public class LiquidTransformer implements TextureTransformer {
|
||||
|
||||
liquidImage = ImageUtil.ensureMinWidth(liquidImage, minWidth);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, bedrockName), liquidImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, bedrockName), liquidImage, "png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.block;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.block;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -47,22 +48,22 @@ public class TallSeagrassTransformer implements TextureTransformer {
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
Texture javaTop = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, JAVA_TOP));
|
||||
Texture javaTop = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, JAVA_TOP));
|
||||
|
||||
if (javaTop != null) {
|
||||
BufferedImage javaImage = this.readImage(javaTop);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, BEDROCK_TOP.formatted("a")), javaImage, "png");
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, BEDROCK_TOP.formatted("b")), ImageUtil.flip(javaImage, true, false), "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, BEDROCK_TOP.formatted("a")), javaImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, BEDROCK_TOP.formatted("b")), ImageUtil.flip(javaImage, true, false), "png");
|
||||
}
|
||||
|
||||
Texture javaBottom = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, JAVA_BOTTOM));
|
||||
Texture javaBottom = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, JAVA_BOTTOM));
|
||||
|
||||
if (javaBottom != null) {
|
||||
BufferedImage javaImage = this.readImage(javaBottom);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, BEDROCK_BOTTOM.formatted("a")), javaImage, "png");
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, BEDROCK_BOTTOM.formatted("b")), ImageUtil.flip(javaImage, true, false), "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, BEDROCK_BOTTOM.formatted("a")), javaImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, BEDROCK_BOTTOM.formatted("b")), ImageUtil.flip(javaImage, true, false), "png");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.entity;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.entity;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -46,7 +47,7 @@ public class ArrowTransformer implements TextureTransformer {
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
Texture texture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, INPUT));
|
||||
Texture texture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, INPUT));
|
||||
if (texture == null) {
|
||||
return;
|
||||
}
|
||||
@@ -76,6 +77,6 @@ public class ArrowTransformer implements TextureTransformer {
|
||||
|
||||
graphics.drawImage(fromImage, 0, 10 * factor, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, OUTPUT), newArrowImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, OUTPUT), newArrowImage, "png");
|
||||
}
|
||||
}
|
||||
@@ -24,17 +24,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.entity;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.entity;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -44,7 +45,7 @@ public class DolphinTransformer implements TextureTransformer {
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
Texture javaTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, LOCATION));
|
||||
Texture javaTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, LOCATION));
|
||||
if (javaTexture == null) return;
|
||||
|
||||
BufferedImage javaImage = this.readImage(javaTexture);
|
||||
@@ -590,6 +591,6 @@ public class DolphinTransformer implements TextureTransformer {
|
||||
null
|
||||
);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, LOCATION), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, LOCATION), bedrockImage, "png");
|
||||
}
|
||||
}
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.entity;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.entity;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -47,8 +48,8 @@ public class DrownedTransformer implements TextureTransformer {
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
Texture drownedTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, String.format(TEXTURE_PATH, DROWNED_TEXTURE)));
|
||||
Texture outerLayerTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, String.format(TEXTURE_PATH, DROWNED_OUTER_LAYER_TEXTURE)));
|
||||
Texture drownedTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, String.format(TEXTURE_PATH, DROWNED_TEXTURE)));
|
||||
Texture outerLayerTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, String.format(TEXTURE_PATH, DROWNED_OUTER_LAYER_TEXTURE)));
|
||||
|
||||
if (drownedTexture == null || outerLayerTexture == null) {
|
||||
return;
|
||||
@@ -71,6 +72,6 @@ public class DrownedTransformer implements TextureTransformer {
|
||||
graphics.drawImage(ImageUtil.crop(overlayImage, (int) (16 * factor), (int) (48 * factor), (int) (16 * factor), (int) (16 * factor)), 0, (int) (48 * factor), null);
|
||||
graphics.drawImage(ImageUtil.crop(overlayImage, (int) (32 * factor), (int) (48 * factor), (int) (16 * factor), (int) (16 * factor)), (int) (48 * factor), (int) (48 * factor), null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, String.format(TEXTURE_PATH, DROWNED_TEXTURE)), newImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, String.format(TEXTURE_PATH, DROWNED_TEXTURE)), newImage, "png");
|
||||
}
|
||||
}
|
||||
@@ -24,22 +24,21 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.entity;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.entity;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
@@ -52,11 +51,11 @@ public class PaintingTransformer implements TextureTransformer {
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
// Let's check if we actually need to convert anything.
|
||||
boolean isAnyPresent = PAINTING_DATA.keySet().stream().anyMatch(key -> {
|
||||
return context.isTexturePresent(Key.key(Key.MINECRAFT_NAMESPACE, JAVA_LOCATION.formatted(key)));
|
||||
return context.isTexturePresent(KeyUtil.key(Key.MINECRAFT_NAMESPACE, JAVA_LOCATION.formatted(key)));
|
||||
});
|
||||
|
||||
// We don't map this like the others because bedrock is difficult, so it isn't in PAINTING_DATA.
|
||||
isAnyPresent = isAnyPresent || context.isTexturePresent(Key.key(Key.MINECRAFT_NAMESPACE, JAVA_LOCATION.formatted("back")));
|
||||
isAnyPresent = isAnyPresent || context.isTexturePresent(KeyUtil.key(Key.MINECRAFT_NAMESPACE, JAVA_LOCATION.formatted("back")));
|
||||
|
||||
if (!isAnyPresent) return; // we have nothing to convert, skip this
|
||||
|
||||
@@ -65,7 +64,7 @@ public class PaintingTransformer implements TextureTransformer {
|
||||
Map<String, Float> scales = new HashMap<>();
|
||||
|
||||
PAINTING_DATA.forEach((key, value) -> {
|
||||
Texture javaTexture = context.pollOrPeekVanilla(Key.key(Key.MINECRAFT_NAMESPACE, JAVA_LOCATION.formatted(key)));
|
||||
Texture javaTexture = context.pollOrPeekVanilla(KeyUtil.key(Key.MINECRAFT_NAMESPACE, JAVA_LOCATION.formatted(key)));
|
||||
if (javaTexture == null) {
|
||||
scales.put(key, 1f);
|
||||
return;
|
||||
@@ -83,7 +82,7 @@ public class PaintingTransformer implements TextureTransformer {
|
||||
});
|
||||
|
||||
// Again, bedrock being difficult with back.
|
||||
Texture backTexture = context.pollOrPeekVanilla(Key.key(Key.MINECRAFT_NAMESPACE, JAVA_LOCATION.formatted("back")));
|
||||
Texture backTexture = context.pollOrPeekVanilla(KeyUtil.key(Key.MINECRAFT_NAMESPACE, JAVA_LOCATION.formatted("back")));
|
||||
if (backTexture != null) {
|
||||
BufferedImage image = this.readImage(backTexture);
|
||||
|
||||
@@ -128,7 +127,7 @@ public class PaintingTransformer implements TextureTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "painting/kz.png"), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "painting/kz.png"), bedrockImage, "png");
|
||||
}
|
||||
|
||||
// BedrockX and BedrockY determine where the image is in kz.png (Bedrock painting atlas)
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.entity;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.entity;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -47,9 +48,9 @@ public class SheepTransformer implements TextureTransformer {
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
Key sheepKey = Key.key(Key.MINECRAFT_NAMESPACE, SHEEP);
|
||||
Key woolKey = Key.key(Key.MINECRAFT_NAMESPACE, SHEEP_WOOL);
|
||||
Key undercoatKey = Key.key(Key.MINECRAFT_NAMESPACE, SHEEP_UNDERCOAT);
|
||||
Key sheepKey = KeyUtil.key(Key.MINECRAFT_NAMESPACE, SHEEP);
|
||||
Key woolKey = KeyUtil.key(Key.MINECRAFT_NAMESPACE, SHEEP_WOOL);
|
||||
Key undercoatKey = KeyUtil.key(Key.MINECRAFT_NAMESPACE, SHEEP_UNDERCOAT);
|
||||
|
||||
if (
|
||||
!context.isTexturePresent(sheepKey) &&
|
||||
@@ -93,6 +94,6 @@ public class SheepTransformer implements TextureTransformer {
|
||||
|
||||
g.drawImage(sheepWoolImage, 0, sheepImage.getHeight(), null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, SHEEP), newImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, SHEEP), newImage, "png");
|
||||
}
|
||||
}
|
||||
@@ -24,12 +24,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.entity;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.entity;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
@@ -69,7 +70,7 @@ public class VillagerTransformer implements TextureTransformer {
|
||||
for (String entity : ENTITIES) {
|
||||
for (String profession : VILLAGER_PROFESSIONS) {
|
||||
String texturePath = String.format(TEXTURE_PATH, entity, profession);
|
||||
Texture texture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, texturePath));
|
||||
Texture texture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, texturePath));
|
||||
if (texture == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -91,7 +92,7 @@ public class VillagerTransformer implements TextureTransformer {
|
||||
}
|
||||
}
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, texturePath), newImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, texturePath), newImage, "png");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,17 +24,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.entity;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.entity;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -53,7 +54,7 @@ public class ZombieTransformer implements TextureTransformer {
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
for (ZombieData zombieData : ZOMBIES) {
|
||||
String zombie = zombieData.name();
|
||||
Key path = Key.key(Key.MINECRAFT_NAMESPACE, TEXTURE_PATH.formatted(zombie));
|
||||
Key path = KeyUtil.key(Key.MINECRAFT_NAMESPACE, TEXTURE_PATH.formatted(zombie));
|
||||
Texture texture = context.poll(path);
|
||||
if (texture == null) continue;
|
||||
|
||||
@@ -70,7 +71,7 @@ public class ZombieTransformer implements TextureTransformer {
|
||||
context.offer(path, bedrockImage, "png");
|
||||
|
||||
if (zombieData.mobHead()) {
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, MOB_HEAD_PATH.formatted(zombie)), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, MOB_HEAD_PATH.formatted(zombie)), bedrockImage, "png");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,16 +24,17 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.item;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.item;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -67,8 +68,8 @@ public class BundleTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
for (String color : COLORS) {
|
||||
Texture backTexture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, FRONT.formatted(color)));
|
||||
Texture frontTexture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, BACK.formatted(color)));
|
||||
Texture backTexture = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, FRONT.formatted(color)));
|
||||
Texture frontTexture = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, BACK.formatted(color)));
|
||||
if (backTexture == null || frontTexture == null) continue; // TODO: If one is missing, pull from vanilla pack
|
||||
|
||||
BufferedImage backImage = this.readImage(backTexture);
|
||||
@@ -81,7 +82,7 @@ public class BundleTransformer implements TextureTransformer {
|
||||
g.drawImage(backImage, 0, 0, null);
|
||||
g.drawImage(frontImage, 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, BEDROCK_OUTPUT.formatted(color)), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, BEDROCK_OUTPUT.formatted(color)), bedrockImage, "png");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,13 +24,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.particle;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.particle;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.geysermc.pack.converter.util.Spritesheet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
@@ -75,10 +76,10 @@ public class BaseParticleTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
// Create a grayscale bubble image
|
||||
Texture bubbleTexture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, PATH + "/bubble.png"));
|
||||
Texture bubbleTexture = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, PATH + "/bubble.png"));
|
||||
if (bubbleTexture != null) {
|
||||
BufferedImage bubble = this.readImage(bubbleTexture);
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, PATH + "/bubble_gray.png"), ImageUtil.grayscale(bubble), "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, PATH + "/bubble_gray.png"), ImageUtil.grayscale(bubble), "png");
|
||||
}
|
||||
|
||||
this.createSpritesheet(context);
|
||||
@@ -169,7 +170,7 @@ public class BaseParticleTransformer implements TextureTransformer {
|
||||
|
||||
context.debug(String.format("Creating particle spritesheet %s", OUTPUT));
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, PATH + "/" + OUTPUT), vanillaSprite, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, PATH + "/" + OUTPUT), vanillaSprite, "png");
|
||||
}
|
||||
|
||||
interface TextureData {
|
||||
@@ -181,7 +182,7 @@ public class BaseParticleTransformer implements TextureTransformer {
|
||||
|
||||
@NotNull
|
||||
public Key textureKey(int atlas) {
|
||||
return Key.key(Key.MINECRAFT_NAMESPACE, PATH + "/" + javaName + "_" + atlas + ".png");
|
||||
return KeyUtil.key(Key.MINECRAFT_NAMESPACE, PATH + "/" + javaName + "_" + atlas + ".png");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -207,7 +208,7 @@ public class BaseParticleTransformer implements TextureTransformer {
|
||||
continue;
|
||||
}
|
||||
|
||||
Texture texture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, textureName + ".png"));
|
||||
Texture texture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, textureName + ".png"));
|
||||
if (texture == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -24,10 +24,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.particle;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.particle;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
public class CampfireParticleTransformer extends SpritesheetParticleTransformer {
|
||||
@@ -24,10 +24,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.particle;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.particle;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
public class SculkChargeParticleTransformer extends SpritesheetParticleTransformer {
|
||||
@@ -24,10 +24,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.particle;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.particle;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
public class SculkChargePopParticleTransformer extends SpritesheetParticleTransformer {
|
||||
@@ -24,10 +24,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.particle;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.particle;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
public class SculkSoulParticleTransformer extends SpritesheetParticleTransformer {
|
||||
@@ -24,10 +24,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.particle;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.particle;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
public class SonicExplosionParticleTransformer extends SpritesheetParticleTransformer {
|
||||
@@ -24,10 +24,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.particle;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.particle;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
public class SoulParticleTransformer extends SpritesheetParticleTransformer {
|
||||
@@ -24,12 +24,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.particle;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.particle;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.geysermc.pack.converter.util.Spritesheet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
@@ -59,7 +60,7 @@ public class SpritesheetParticleTransformer implements TextureTransformer {
|
||||
BitSet occupiedSectors = new BitSet(this.atlasCount);
|
||||
Spritesheet spritesheet = new Spritesheet();
|
||||
for (int i = 0; i < this.atlasCount; i++) {
|
||||
Texture texture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, String.format(this.javaPath, i)));
|
||||
Texture texture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, String.format(this.javaPath, i)));
|
||||
if (texture == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -95,6 +96,6 @@ public class SpritesheetParticleTransformer implements TextureTransformer {
|
||||
|
||||
context.debug(String.format("Creating particle spritesheet %s", this.bedrockPath));
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, this.bedrockPath), vanillaSprite, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, this.bedrockPath), vanillaSprite, "png");
|
||||
}
|
||||
}
|
||||
@@ -24,26 +24,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.ui;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.ui;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.font.*;
|
||||
import team.unnamed.creative.font.BitMapFontProvider;
|
||||
import team.unnamed.creative.font.Font;
|
||||
import team.unnamed.creative.font.FontProvider;
|
||||
import team.unnamed.creative.font.ReferenceFontProvider;
|
||||
import team.unnamed.creative.font.SpaceFontProvider;
|
||||
import team.unnamed.creative.font.UnihexFontProvider;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HexFormat;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
public class FontTransformer implements TextureTransformer {
|
||||
@@ -69,7 +78,7 @@ public class FontTransformer implements TextureTransformer {
|
||||
|
||||
// Currently, only the default font is converted, custom fonts are not supported on bedrock
|
||||
for (Font font : context.javaResourcePack().fonts()) {
|
||||
if (!font.key().equals(Key.key(Key.MINECRAFT_NAMESPACE, "default"))) continue;
|
||||
if (!font.key().equals(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "default"))) continue;
|
||||
|
||||
for (FontProvider fontProvider : font.providers()) {
|
||||
unicodeFontData.addAll(handleFont(context, fontProvider));
|
||||
@@ -77,15 +86,15 @@ public class FontTransformer implements TextureTransformer {
|
||||
}
|
||||
|
||||
// if we have no data, don't stop yet, we may still want to generate some stuff from vanilla
|
||||
if (unicodeFontData.isEmpty()) {
|
||||
if (unicodeFontData.isEmpty() && context.vanillaPack().isPresent()) {
|
||||
if (
|
||||
!context.isTexturePresent(Key.key(Key.MINECRAFT_NAMESPACE, "font/ascii.png")) &&
|
||||
!context.isTexturePresent(Key.key(Key.MINECRAFT_NAMESPACE, "font/accented.png")) &&
|
||||
!context.isTexturePresent(Key.key(Key.MINECRAFT_NAMESPACE, "font/nonlatin_european.png"))
|
||||
!context.isTexturePresent(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "font/ascii.png")) &&
|
||||
!context.isTexturePresent(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "font/accented.png")) &&
|
||||
!context.isTexturePresent(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "font/nonlatin_european.png"))
|
||||
) return;
|
||||
|
||||
for (Font font : context.vanillaPack().fonts()) {
|
||||
if (!font.key().equals(Key.key(Key.MINECRAFT_NAMESPACE, "default"))) continue;
|
||||
for (Font font : context.vanillaPack().get().fonts()) {
|
||||
if (!font.key().equals(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "default"))) continue;
|
||||
|
||||
for (FontProvider fontProvider : font.providers()) {
|
||||
unicodeFontData.addAll(handleFont(context, fontProvider));
|
||||
@@ -225,8 +234,8 @@ public class FontTransformer implements TextureTransformer {
|
||||
} else if (fontProvider instanceof ReferenceFontProvider referenceFontProvider) {
|
||||
// Refers to other fonts, so we need to read those
|
||||
Font font = context.javaResourcePack().font(referenceFontProvider.id());
|
||||
if (font == null) { // Just maybe, the vanilla files are used
|
||||
font = context.vanillaPack().font(referenceFontProvider.id());
|
||||
if (font == null && context.vanillaPack().isPresent()) { // Just maybe, the vanilla files are used
|
||||
font = context.vanillaPack().get().font(referenceFontProvider.id());
|
||||
}
|
||||
|
||||
if (font == null) {
|
||||
@@ -247,30 +256,30 @@ public class FontTransformer implements TextureTransformer {
|
||||
private void transformDefault8(@NotNull TransformContext context) throws IOException {
|
||||
// Don't attempt to write default8 if we have no data to pull from, otherwise it's vanilla to vanilla
|
||||
if (
|
||||
!context.isTexturePresent(Key.key(Key.MINECRAFT_NAMESPACE, "font/ascii.png")) &&
|
||||
!context.isTexturePresent(Key.key(Key.MINECRAFT_NAMESPACE, "font/accented.png")) &&
|
||||
!context.isTexturePresent(Key.key(Key.MINECRAFT_NAMESPACE, "font/nonlatin_european.png"))
|
||||
!context.isTexturePresent(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "font/ascii.png")) &&
|
||||
!context.isTexturePresent(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "font/accented.png")) &&
|
||||
!context.isTexturePresent(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "font/nonlatin_european.png"))
|
||||
) return;
|
||||
|
||||
// Store the java images to prevent constant image reading
|
||||
Map<String, BufferedImage> imgs = new HashMap<>();
|
||||
Map<String, Integer> scales = new HashMap<>();
|
||||
|
||||
Texture ascii = context.peekOrVanilla(Key.key(Key.MINECRAFT_NAMESPACE, "font/ascii.png"));
|
||||
Texture ascii = context.peekOrVanilla(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "font/ascii.png"));
|
||||
if (ascii != null) {
|
||||
BufferedImage image = this.readImage(ascii);
|
||||
imgs.put("ascii", image);
|
||||
scales.put("ascii", image.getWidth() / 128);
|
||||
}
|
||||
|
||||
Texture accented = context.peekOrVanilla(Key.key(Key.MINECRAFT_NAMESPACE, "font/accented.png"));
|
||||
Texture accented = context.peekOrVanilla(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "font/accented.png"));
|
||||
if (accented != null) {
|
||||
BufferedImage image = this.readImage(accented);
|
||||
imgs.put("accented", image);
|
||||
scales.put("accented", image.getWidth() / 144);
|
||||
}
|
||||
|
||||
Texture nonlatin_european = context.peekOrVanilla(Key.key(Key.MINECRAFT_NAMESPACE, "font/nonlatin_european.png"));
|
||||
Texture nonlatin_european = context.peekOrVanilla(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "font/nonlatin_european.png"));
|
||||
if (nonlatin_european != null) {
|
||||
BufferedImage image = this.readImage(nonlatin_european);
|
||||
imgs.put("nonlatin_european", image);
|
||||
@@ -24,17 +24,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.ui;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.ui;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -45,7 +46,7 @@ public class HotbarTransformer implements TextureTransformer {
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
Texture javaHotbarTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, HOTBAR));
|
||||
Texture javaHotbarTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, HOTBAR));
|
||||
if (javaHotbarTexture == null) return;
|
||||
|
||||
BufferedImage javaHotbarImage = readImage(javaHotbarTexture);
|
||||
@@ -61,7 +62,7 @@ public class HotbarTransformer implements TextureTransformer {
|
||||
|
||||
g.drawImage(ImageUtil.crop(javaHotbarImage, 0, 0, scale, height), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "ui/hotbar_start_cap.png"), bedrockStartHotbar, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "ui/hotbar_start_cap.png"), bedrockStartHotbar, "png");
|
||||
|
||||
for (int i = 0; i <= 8; i++) {
|
||||
BufferedImage bedrockHotbarPart = new BufferedImage(scale * 20, height, BufferedImage.TYPE_INT_ARGB);
|
||||
@@ -70,7 +71,7 @@ public class HotbarTransformer implements TextureTransformer {
|
||||
|
||||
graphics.drawImage(ImageUtil.crop(javaHotbarImage, (i * 20 * scale) + scale, 0, scale * 20, height), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "ui/hotbar_" + i + ".png"), bedrockHotbarPart, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "ui/hotbar_" + i + ".png"), bedrockHotbarPart, "png");
|
||||
}
|
||||
|
||||
// The texture is 1 wide, so 1 * scale = scale
|
||||
@@ -80,9 +81,9 @@ public class HotbarTransformer implements TextureTransformer {
|
||||
|
||||
g.drawImage(ImageUtil.crop(javaHotbarImage, javaHotbarImage.getWidth() - scale, 0, scale, height), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "ui/hotbar_end_cap.png"), bedrockEndHotbar, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "ui/hotbar_end_cap.png"), bedrockEndHotbar, "png");
|
||||
|
||||
Texture javaHotbarSelectionTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, HOTBAR_SELECTION));
|
||||
Texture javaHotbarSelectionTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, HOTBAR_SELECTION));
|
||||
if (javaHotbarSelectionTexture == null) return;
|
||||
|
||||
BufferedImage javaHotbarSelectionImage = readImage(javaHotbarSelectionTexture);
|
||||
@@ -99,6 +100,6 @@ public class HotbarTransformer implements TextureTransformer {
|
||||
|
||||
g.drawImage(ImageUtil.flip(ImageUtil.crop(javaHotbarSelectionImage, 0, 0, size, selectionScale), false, true), 0, size - selectionScale, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "ui/selected_hotbar_slot.png"), bedrockHotbarSelection, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "ui/selected_hotbar_slot.png"), bedrockHotbarSelection, "png");
|
||||
}
|
||||
}
|
||||
@@ -24,20 +24,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.ui;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.ui;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
@@ -52,7 +52,7 @@ public class LocatorTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
for (Map.Entry<String, String> mapping : DOT_MAPPING.entrySet()) {
|
||||
Texture dotTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, mapping.getKey()));
|
||||
Texture dotTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, mapping.getKey()));
|
||||
if (dotTexture == null) continue;
|
||||
|
||||
BufferedImage dotImage = this.readImage(dotTexture);
|
||||
@@ -71,10 +71,10 @@ public class LocatorTransformer implements TextureTransformer {
|
||||
// Also accounts for the scale a resource pack may offer
|
||||
g.drawImage(ImageUtil.crop(dotImage, scale, scale, bedrockSize, bedrockSize), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, mapping.getValue()), bedrockDotImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, mapping.getValue()), bedrockDotImage, "png");
|
||||
}
|
||||
|
||||
Texture upArrowTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/locator_bar_arrow_up.png"));
|
||||
Texture upArrowTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/locator_bar_arrow_up.png"));
|
||||
if (upArrowTexture != null) {
|
||||
BufferedImage javaImage = this.readImage(upArrowTexture);
|
||||
|
||||
@@ -86,10 +86,10 @@ public class LocatorTransformer implements TextureTransformer {
|
||||
|
||||
g.drawImage(ImageUtil.crop(javaImage, 0, 1, javaImage.getWidth(), scale * 4), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "ui/locator_arrow_up.png"), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "ui/locator_arrow_up.png"), bedrockImage, "png");
|
||||
}
|
||||
|
||||
Texture downArrowTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/locator_bar_arrow_down.png"));
|
||||
Texture downArrowTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/locator_bar_arrow_down.png"));
|
||||
if (downArrowTexture != null) {
|
||||
BufferedImage javaImage = this.readImage(downArrowTexture);
|
||||
|
||||
@@ -101,10 +101,10 @@ public class LocatorTransformer implements TextureTransformer {
|
||||
|
||||
g.drawImage(ImageUtil.crop(javaImage, 0, 0, javaImage.getWidth(), scale * 4), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "ui/locator_arrow_down.png"), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "ui/locator_arrow_down.png"), bedrockImage, "png");
|
||||
}
|
||||
|
||||
Texture bgTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/locator_bar_background.png"));
|
||||
Texture bgTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/locator_bar_background.png"));
|
||||
if (bgTexture != null) {
|
||||
BufferedImage javaImage = this.readImage(bgTexture);
|
||||
|
||||
@@ -122,7 +122,7 @@ public class LocatorTransformer implements TextureTransformer {
|
||||
|
||||
g.drawImage(ImageUtil.crop(javaImage, javaImage.getWidth() - (scale * 5), 0, scale * 5, javaImage.getHeight()), (scale * 182) - scale * 5, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "ui/locator_bg.png"), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "ui/locator_bg.png"), bedrockImage, "png");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,17 +24,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.ui;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.ui;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -62,7 +63,7 @@ public class SignTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
for (SignData signData : SIGNS) {
|
||||
Texture javaTexture = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, JAVA_LOCATION.formatted(signData.name)));
|
||||
Texture javaTexture = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, JAVA_LOCATION.formatted(signData.name)));
|
||||
if (javaTexture == null) continue;
|
||||
|
||||
BufferedImage javaImage = this.readImage(javaTexture);
|
||||
@@ -75,7 +76,7 @@ public class SignTransformer implements TextureTransformer {
|
||||
|
||||
g.drawImage(ImageUtil.crop(javaImage, (int) (2 * scale), (int) (2 * scale), (int) (scale * 24), (int) (scale * 12)), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, BEDROCK_LOCATION.formatted(signData.bedrockName)), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, BEDROCK_LOCATION.formatted(signData.bedrockName)), bedrockImage, "png");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,17 +24,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.ui;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.ui;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -42,7 +43,7 @@ import java.io.IOException;
|
||||
public class TitleTransformer implements TextureTransformer {
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
Texture javaTexture = context.poll(Key.key(Key.MINECRAFT_NAMESPACE, "gui/title/minecraft.png"));
|
||||
Texture javaTexture = context.poll(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "gui/title/minecraft.png"));
|
||||
if (javaTexture == null) return;
|
||||
|
||||
BufferedImage javaImage = this.readImage(javaTexture);
|
||||
@@ -56,6 +57,6 @@ public class TitleTransformer implements TextureTransformer {
|
||||
|
||||
g.drawImage(ImageUtil.resize(ImageUtil.crop(javaImage, 0, 0, javaImage.getWidth(), javaImage.getHeight() - ((int) (scale * 79))), 1937, 333), 0, 0, null);
|
||||
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "ui/title.png"), bedrockImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "ui/title.png"), bedrockImage, "png");
|
||||
}
|
||||
}
|
||||
@@ -24,22 +24,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.ui;
|
||||
package org.geysermc.pack.converter.type.texture.transformer.type.ui;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.TransformContext;
|
||||
import org.geysermc.pack.converter.util.KeyUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
// This isn't really a "transformer", we just include some files if an certain UI elements are present
|
||||
// in order to get it to appear correctly, the mappings here are still done in textures.json or elsewhere
|
||||
@@ -47,29 +45,26 @@ import java.nio.charset.StandardCharsets;
|
||||
// Credit to Bedrock Tweaks, wouldn't know how to do this without their packs
|
||||
@AutoService(TextureTransformer.class)
|
||||
public class UISizeTransformer implements TextureTransformer {
|
||||
private static final Gson GSON = new GsonBuilder()
|
||||
.setPrettyPrinting()
|
||||
.create();
|
||||
|
||||
private static final JsonArray FULLBARSLICE = new JsonArray();
|
||||
|
||||
@Override
|
||||
public void transform(@NotNull TransformContext context) throws IOException {
|
||||
Texture emptyXp = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/experience_bar_background.png"));
|
||||
Texture emptyXp = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/experience_bar_background.png"));
|
||||
if (emptyXp != null) {
|
||||
writeUiJson(context, this.readImage(emptyXp), "experiencebarempty", FULLBARSLICE);
|
||||
|
||||
// Since we have the full image, we *don't* want this
|
||||
BufferedImage nubImage = new BufferedImage(11, 5, BufferedImage.TYPE_INT_ARGB);
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, "ui/experiencenub.png"), nubImage, "png");
|
||||
context.offer(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "ui/experiencenub.png"), nubImage, "png");
|
||||
}
|
||||
|
||||
Texture fullXp = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/experience_bar_progress.png"));
|
||||
Texture fullXp = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/experience_bar_progress.png"));
|
||||
if (fullXp != null) {
|
||||
writeUiJson(context, this.readImage(fullXp), "experiencebarfull", FULLBARSLICE);
|
||||
}
|
||||
|
||||
Texture locatorBg = context.peek(Key.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/locator_bar_background.png"));
|
||||
Texture locatorBg = context.peek(KeyUtil.key(Key.MINECRAFT_NAMESPACE, "gui/sprites/hud/locator_bar_background.png"));
|
||||
if (locatorBg != null) {
|
||||
BufferedImage image = this.readImage(locatorBg);
|
||||
|
||||
@@ -97,7 +92,7 @@ public class UISizeTransformer implements TextureTransformer {
|
||||
baseSize.add(customHeight);
|
||||
rootObject.add("base_size", baseSize);
|
||||
|
||||
context.bedrockResourcePack().addExtraFile(GSON.toJson(rootObject).getBytes(StandardCharsets.UTF_8), "textures/ui/%s.json".formatted(jsonName));
|
||||
context.bedrockResourcePack().addExtraFile(rootObject, "textures/ui/%s.json".formatted(jsonName));
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
* 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
|
||||
@@ -24,15 +24,22 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter;
|
||||
package org.geysermc.pack.converter.util;
|
||||
|
||||
import org.geysermc.pack.converter.data.BaseConversionData;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public abstract class BaseConverter implements Converter<BaseConversionData> {
|
||||
@SuppressWarnings("PatternValidation")
|
||||
public final class KeyUtil {
|
||||
|
||||
@Override
|
||||
public BaseConversionData createConversionData(@NotNull ConversionDataCreationContext context) {
|
||||
return new BaseConversionData(context.inputDirectory(), context.outputDirectory(), context.vanillaResourcePack());
|
||||
private KeyUtil() {
|
||||
}
|
||||
|
||||
public static @NotNull Key key(final @NotNull String string) {
|
||||
return Key.key(string);
|
||||
}
|
||||
|
||||
public static @NotNull Key key(final @NotNull String namespace, final @NotNull String value) {
|
||||
return Key.key(namespace, value);
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2023 GeyserMC. http://geysermc.org
|
||||
* Copyright (c) 2025-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
|
||||
@@ -24,22 +24,31 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter;
|
||||
package org.geysermc.pack.converter.util;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class Converters {
|
||||
public interface LogListenerHelper {
|
||||
|
||||
public static List<? extends Converter<?>> defaultConverters() {
|
||||
return defaultConverters(false);
|
||||
LogListener logListener();
|
||||
|
||||
default void debug(@NotNull String message) {
|
||||
logListener().debug(message);
|
||||
}
|
||||
|
||||
public static List<? extends Converter<?>> defaultConverters(boolean experimental) {
|
||||
return ServiceLoader.load(Converter.class).stream()
|
||||
.map(ServiceLoader.Provider::get)
|
||||
.map(c -> (Converter<?>)c)
|
||||
.filter(converter -> experimental || !converter.isExperimental())
|
||||
.toList();
|
||||
default void info(@NotNull String message) {
|
||||
logListener().info(message);
|
||||
}
|
||||
|
||||
default void warn(@NotNull String message) {
|
||||
logListener().warn(message);
|
||||
}
|
||||
|
||||
default void error(@NotNull String message) {
|
||||
logListener().error(message);
|
||||
}
|
||||
|
||||
default void error(@NotNull String message, @NotNull Throwable exception) {
|
||||
logListener().error(message, exception);
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,16 @@
|
||||
|
||||
package org.geysermc.pack.converter.util;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import lombok.Getter;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.file.PathUtils;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.type.OverlayTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.type.entity.SheepTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.type.OverlayTransformer;
|
||||
import org.geysermc.pack.converter.type.texture.transformer.type.entity.SheepTransformer;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
@@ -40,7 +44,10 @@ import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class VanillaPackProvider {
|
||||
|
||||
@@ -28,6 +28,7 @@ package org.geysermc.pack.bedrock.resource;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
import org.geysermc.pack.bedrock.resource.attachables.Attachables;
|
||||
import org.geysermc.pack.bedrock.resource.models.entity.ModelEntity;
|
||||
import org.geysermc.pack.bedrock.resource.render_controllers.RenderControllers;
|
||||
@@ -44,9 +45,9 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -91,6 +92,16 @@ public class BedrockResourcePack {
|
||||
this.terrainTexture = terrainTexture;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the directory of the resource pack.
|
||||
*
|
||||
* @return the directory of the resource pack
|
||||
*/
|
||||
@NotNull
|
||||
public Path directory() {
|
||||
return directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the manifest of the resource pack.
|
||||
*
|
||||
@@ -500,6 +511,16 @@ public class BedrockResourcePack {
|
||||
this.extraFiles.put(location, bytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an extra JSON file to the resource pack.
|
||||
*
|
||||
* @param element the contents of the file
|
||||
* @param location the location of the file
|
||||
*/
|
||||
public void addExtraFile(@NotNull JsonElement element, @NotNull String location) {
|
||||
addExtraFile(GSON.toJson(element).getBytes(StandardCharsets.UTF_8), location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Exports the resource pack to the specified directory.
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user