mirror of
https://github.com/GeyserMC/PackConverter.git
synced 2026-01-04 15:31:36 +00:00
Add support for bulk converters
This commit is contained in:
@@ -30,6 +30,10 @@ import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.PackConverter;
|
||||
import org.geysermc.pack.converter.converter.Converter;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformedTexture;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.bulk.BulkTextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.bulk.BulkTransformContext;
|
||||
import org.geysermc.pack.converter.data.TextureConversionData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
@@ -37,7 +41,7 @@ import team.unnamed.creative.texture.Texture;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
import java.util.stream.StreamSupport;
|
||||
@@ -46,11 +50,17 @@ import java.util.stream.StreamSupport;
|
||||
public class TextureConverter implements Converter<TextureConversionData> {
|
||||
public static final String BEDROCK_TEXTURES_LOCATION = "textures";
|
||||
|
||||
private final List<BulkTextureTransformer> bulkTransformers = StreamSupport.stream(ServiceLoader.load(BulkTextureTransformer.class).spliterator(), false).toList();
|
||||
private final List<TextureTransformer> transformers = StreamSupport.stream(ServiceLoader.load(TextureTransformer.class).spliterator(), false).toList();
|
||||
|
||||
@Override
|
||||
public void convert(@NotNull PackConversionContext<TextureConversionData> context) throws Exception {
|
||||
Collection<Texture> textures = context.javaResourcePack().textures();
|
||||
List<Texture> textures = new ArrayList<>(context.javaResourcePack().textures());
|
||||
|
||||
BulkTransformContext bulkContext = new BulkTransformContext(context, textures);
|
||||
for (BulkTextureTransformer bulkTransformer : this.bulkTransformers) {
|
||||
bulkTransformer.transform(bulkContext);
|
||||
}
|
||||
|
||||
for (Texture texture : textures) {
|
||||
String output = texture.key().value();
|
||||
@@ -63,7 +73,6 @@ public class TextureConverter implements Converter<TextureConversionData> {
|
||||
}
|
||||
|
||||
transformedTexture = transformer.transform(context, transformedTexture);
|
||||
|
||||
if (transformedTexture == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture;
|
||||
package org.geysermc.pack.converter.converter.texture.transformer;
|
||||
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.data.TextureConversionData;
|
||||
@@ -24,7 +24,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture;
|
||||
package org.geysermc.pack.converter.converter.texture.transformer;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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.transformer.bulk;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public interface BulkTextureTransformer {
|
||||
|
||||
void transform(@NotNull BulkTransformContext context) throws IOException;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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.transformer.bulk;
|
||||
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.data.TextureConversionData;
|
||||
import org.geysermc.pack.converter.util.ImageUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import team.unnamed.creative.base.Writable;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class BulkTransformContext {
|
||||
private final PackConversionContext<TextureConversionData> conversionContext;
|
||||
private final Collection<Texture> textures;
|
||||
private final Map<Key, Texture> byKey = new HashMap<>();
|
||||
|
||||
public BulkTransformContext(PackConversionContext<TextureConversionData> conversionContext, Collection<Texture> textures) {
|
||||
this.conversionContext = conversionContext;
|
||||
this.textures = textures;
|
||||
|
||||
for (Texture texture : textures) {
|
||||
this.byKey.put(texture.key(), texture);
|
||||
}
|
||||
}
|
||||
|
||||
public void info(@NotNull String message) {
|
||||
this.conversionContext.info(message);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Texture poll(@NotNull Key key) {
|
||||
Texture remove = this.byKey.remove(key);
|
||||
if (remove == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
this.textures.remove(remove);
|
||||
return remove;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public Texture peek(@NotNull Key key) {
|
||||
return this.byKey.get(key);
|
||||
}
|
||||
|
||||
public void offer(@NotNull Key key, @NotNull BufferedImage image, @NotNull String format) throws IOException {
|
||||
this.offer(Texture.of(key, Writable.bytes(ImageUtil.toByteArray(image, format))));
|
||||
}
|
||||
|
||||
public void offer(@NotNull Texture texture) {
|
||||
this.textures.add(texture);
|
||||
this.byKey.put(texture.key(), texture);
|
||||
}
|
||||
|
||||
public boolean containsKey(@NotNull Key key) {
|
||||
return this.byKey.containsKey(key);
|
||||
}
|
||||
}
|
||||
@@ -24,71 +24,58 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.packconverter.converters;
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.bulk.type;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import lombok.Getter;
|
||||
import org.geysermc.packconverter.PackConversionContext;
|
||||
import org.geysermc.packconverter.PackConverter;
|
||||
import org.geysermc.packconverter.utils.ImageUtils;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.bulk.BulkTextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.bulk.BulkTransformContext;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import team.unnamed.creative.texture.Texture;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@AutoService(Converter.class)
|
||||
public class AtlasConverter extends AbstractConverter {
|
||||
|
||||
@Getter
|
||||
public static final List<Object[]> defaultData = new ArrayList<>();
|
||||
|
||||
static {
|
||||
defaultData.add(new Object[] {"textures/items/clock_", 63, "textures/items/watch_atlas.png"});
|
||||
defaultData.add(new Object[] {"textures/items/compass_", 31, "textures/items/compass_atlas.png"});
|
||||
}
|
||||
@AutoService(BulkTextureTransformer.class)
|
||||
public class AtlasTransformer implements BulkTextureTransformer {
|
||||
private static final List<AtlasData> ATLASES = List.of(
|
||||
new AtlasData("item/clock_%s.png", "items/watch_atlas.png", 63),
|
||||
new AtlasData("item/compass_%s.png", "items/compass_atlas.png", 31)
|
||||
);
|
||||
|
||||
@Override
|
||||
public void convert(@NotNull PackConversionContext context) {
|
||||
List<AbstractConverter> delete = new ArrayList<>();
|
||||
public void transform(@NotNull BulkTransformContext context) throws IOException {
|
||||
for (AtlasData atlas : ATLASES) {
|
||||
String javaName = atlas.javaName();
|
||||
String bedrockName = atlas.bedrockName();
|
||||
int atlasCount = atlas.altasCount();
|
||||
|
||||
try {
|
||||
String base = (String) context.data()[0];
|
||||
int count = (int) context.data()[1];
|
||||
String to = (String) context.data()[2];
|
||||
|
||||
BufferedImage atlasImage = null;
|
||||
|
||||
for (int i = 0; i <= count; i++) {
|
||||
String step = base + String.format("%1$2s", i).replace(" ", "0") + ".png";
|
||||
File stepFile = context.storage().resolve(step).toFile();
|
||||
|
||||
if (!stepFile.exists()) {
|
||||
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"))));
|
||||
if (texture == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
BufferedImage stepImage = ImageIO.read(stepFile);
|
||||
|
||||
BufferedImage stepImage = ImageIO.read(new ByteArrayInputStream(texture.data().toByteArray()));
|
||||
if (atlasImage == null) {
|
||||
context.log(String.format("Create atlas %s", to));
|
||||
|
||||
atlasImage = new BufferedImage(stepImage.getWidth(), stepImage.getHeight() * (count + 1), BufferedImage.TYPE_INT_ARGB);
|
||||
context.info(String.format("Creating atlas %s", bedrockName));
|
||||
atlasImage = new BufferedImage(stepImage.getWidth(), stepImage.getHeight() * (atlasCount + 1), BufferedImage.TYPE_INT_ARGB);
|
||||
}
|
||||
|
||||
atlasImage.getGraphics().drawImage(stepImage, 0, (stepImage.getHeight() * i), null);
|
||||
|
||||
delete.add(new DeleteConverter(packConverter, storage, new Object[] {step}));
|
||||
}
|
||||
|
||||
if (atlasImage != null) {
|
||||
ImageUtils.write(atlasImage, "png", storage.resolve(to).toFile());
|
||||
context.offer(Key.key(Key.MINECRAFT_NAMESPACE, bedrockName), atlasImage, "png");
|
||||
context.info(String.format("Created atlas %s", bedrockName));
|
||||
}
|
||||
} catch (IOException e) { }
|
||||
}
|
||||
}
|
||||
|
||||
return delete;
|
||||
record AtlasData(String javaName, String bedrockName, int altasCount) {
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.path;
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.path;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.converter.texture.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
public class BlockTextureTransformer extends PathTransformer {
|
||||
@@ -24,10 +24,10 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.path;
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.path;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
import org.geysermc.pack.converter.converter.texture.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
|
||||
@AutoService(TextureTransformer.class)
|
||||
public class ItemTextureTransformer extends PathTransformer {
|
||||
@@ -24,12 +24,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.path;
|
||||
package org.geysermc.pack.converter.converter.texture.transformer.type.path;
|
||||
|
||||
import org.geysermc.pack.converter.PackConversionContext;
|
||||
import org.geysermc.pack.converter.converter.texture.TextureConverter;
|
||||
import org.geysermc.pack.converter.converter.texture.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.TransformedTexture;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TextureTransformer;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformedTexture;
|
||||
import org.geysermc.pack.converter.data.TextureConversionData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -48,7 +48,7 @@ public class PathTransformer implements TextureTransformer {
|
||||
|
||||
@Override
|
||||
public boolean filter(@NotNull Texture texture) {
|
||||
return texture.key().value().startsWith(this.input);
|
||||
return texture.key().value().startsWith(this.input + "/");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
package org.geysermc.pack.converter.data;
|
||||
|
||||
import org.geysermc.pack.converter.converter.texture.TransformedTexture;
|
||||
import org.geysermc.pack.converter.converter.texture.transformer.TransformedTexture;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
@@ -30,8 +30,11 @@ import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.image.*;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class ImageUtil {
|
||||
|
||||
@@ -183,6 +186,32 @@ public class ImageUtil {
|
||||
ImageIO.write(img, format, output);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link BufferedImage} to an {@link InputStream}
|
||||
*
|
||||
* @param img Image to use
|
||||
* @param format Format to use
|
||||
* @return InputStream of the image
|
||||
* @throws IOException
|
||||
*/
|
||||
public static InputStream toInputStream(BufferedImage img, String format) throws IOException {
|
||||
return new ByteArrayInputStream(toByteArray(img, format));
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link BufferedImage} to a byte array
|
||||
*
|
||||
* @param img Image to use
|
||||
* @param format Format to use
|
||||
* @return Byte array of the image
|
||||
* @throws IOException
|
||||
*/
|
||||
public static byte[] toByteArray(BufferedImage img, String format) throws IOException {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
ImageIO.write(img, format, os);
|
||||
return os.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a {@link BufferedImage} to grayscale
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user