diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PlayPacketIdHelper.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PlayPacketIdHelper.java index 83fdfd05b..2748aa4a5 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PlayPacketIdHelper.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/id/PlayPacketIdHelper.java @@ -6,7 +6,9 @@ import net.momirealms.craftengine.core.plugin.network.ConnectionState; import net.momirealms.craftengine.core.plugin.network.PacketFlow; import net.momirealms.craftengine.core.util.VersionHelper; -import java.util.*; +import java.util.Collections; +import java.util.EnumMap; +import java.util.Map; public class PlayPacketIdHelper { // 1.20.5-latest diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java index a0f6da658..962c8a4d9 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/AbstractPackManager.java @@ -5,7 +5,6 @@ import com.google.common.collect.Multimap; import com.google.common.jimfs.Configuration; import com.google.common.jimfs.Jimfs; import com.google.gson.*; -import net.kyori.adventure.text.Component; import net.momirealms.craftengine.core.font.BitmapImage; import net.momirealms.craftengine.core.font.Font; import net.momirealms.craftengine.core.item.equipment.ComponentBasedEquipment; @@ -28,6 +27,7 @@ import net.momirealms.craftengine.core.pack.revision.Revisions; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.config.Config; import net.momirealms.craftengine.core.plugin.config.ConfigParser; +import net.momirealms.craftengine.core.plugin.config.SectionConfigParser; import net.momirealms.craftengine.core.plugin.config.StringKeyConstructor; import net.momirealms.craftengine.core.plugin.locale.LangData; import net.momirealms.craftengine.core.plugin.locale.LocalizedException; @@ -60,7 +60,6 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.function.BiConsumer; import java.util.function.Consumer; import java.util.function.Predicate; -import java.util.stream.Collectors; import static net.momirealms.craftengine.core.util.MiscUtils.castToMap; @@ -105,6 +104,7 @@ public abstract class AbstractPackManager implements PackManager { private Map cachedAssetFiles = Collections.emptyMap(); protected BiConsumer zipGenerator; protected ResourcePackHost resourcePackHost; + private final SkipOptimizationParser parser = new SkipOptimizationParser(); public AbstractPackManager(CraftEngine plugin, Consumer cacheEventDispatcher, BiConsumer generationEventDispatcher) { this.plugin = plugin; @@ -242,6 +242,7 @@ public abstract class AbstractPackManager implements PackManager { @Override public void unload() { + this.parser.clearCache(); this.loadedPacks.clear(); } @@ -858,8 +859,10 @@ public abstract class AbstractPackManager implements PackManager { List imagesToOptimize = new ArrayList<>(); List commonJsonToOptimize = new ArrayList<>(); List modelJsonToOptimize = new ArrayList<>(); - Set excludeTexture = Config.optimizeTextureExclude(); - Set excludeJson = Config.optimizeJsonExclude(); + Set excludeTexture = new HashSet<>(Config.optimizeTextureExclude()); + Set excludeJson = new HashSet<>(Config.optimizeJsonExclude()); + excludeTexture.addAll(this.parser.excludeTexture()); + excludeJson.addAll(this.parser.excludeJson()); Predicate texturePathPredicate = p -> !excludeTexture.contains(CharacterUtils.replaceBackslashWithSlash(path.relativize(p).toString())); Predicate jsonPathPredicate = p -> !excludeJson.contains(CharacterUtils.replaceBackslashWithSlash(path.relativize(p).toString())); @@ -2755,4 +2758,66 @@ public abstract class AbstractPackManager implements PackManager { } } } + + @Override + public ConfigParser parser() { + return this.parser; + } + + public static class SkipOptimizationParser extends SectionConfigParser { + private static final String[] SECTION_ID = new String[] {"skip-optimization"}; + private final Set excludeTexture = new HashSet<>(); + private final Set excludeJson = new HashSet<>(); + + public SkipOptimizationParser() { + } + + public void clearCache() { + this.excludeTexture.clear(); + this.excludeJson.clear(); + } + + public Set excludeTexture() { + return excludeTexture; + } + + public Set excludeJson() { + return excludeJson; + } + + @Override + protected void parseSection(Pack pack, Path path, Map section) throws LocalizedException { + if (!Config.optimizeResourcePack()) return; + List textures = MiscUtils.getAsStringList(section.get("texture")); + if (!textures.isEmpty()) { + for (String texture : textures) { + if (texture.endsWith(".png")) { + this.excludeTexture.add(texture); + } else { + this.excludeTexture.add(texture + ".png"); + } + } + } + List jsons = MiscUtils.getAsStringList(section.get("json")); + if (!jsons.isEmpty()) { + for (String json : jsons) { + if (json.endsWith(".json") || json.endsWith(".mcmeta")) { + this.excludeJson.add(json); + } else { + this.excludeJson.add(json + ".json"); + } + } + } + } + + @Override + public String[] sectionId() { + return SECTION_ID; + } + + @Override + public int loadingSequence() { + return LoadingSequence.SKIP_OPTIMIZATION; + } + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/LoadingSequence.java b/core/src/main/java/net/momirealms/craftengine/core/pack/LoadingSequence.java index f8928a7ef..1cee9fe7e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/LoadingSequence.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/LoadingSequence.java @@ -21,4 +21,5 @@ public final class LoadingSequence { public static final int EMOJI = 140; public static final int ADVANCEMENT = 150; public static final int LANG = 160; + public static final int SKIP_OPTIMIZATION = 170; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/pack/PackManager.java b/core/src/main/java/net/momirealms/craftengine/core/pack/PackManager.java index 839de5886..df44b1845 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/pack/PackManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/pack/PackManager.java @@ -12,6 +12,8 @@ import java.util.Collection; public interface PackManager extends Manageable { + ConfigParser parser(); + void loadResources(boolean recipe); void initCachedAssets(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java index 4e25c0c6f..23e168c72 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/CraftEngine.java @@ -298,6 +298,8 @@ public abstract class CraftEngine implements Plugin { this.packManager.registerConfigSectionParser(this.vanillaLootManager.parser()); // register advancement parser this.packManager.registerConfigSectionParser(this.advancementManager.parser()); + // register skip-optimization parser + this.packManager.registerConfigSectionParser(this.packManager.parser()); } public void applyDependencies() { diff --git a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java index c04987e6f..1da73e545 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java +++ b/core/src/main/java/net/momirealms/craftengine/core/plugin/config/Config.java @@ -333,9 +333,15 @@ public class Config { resource_pack$protection$obfuscation$resource_location$bypass_equipments = config.getStringList("resource-pack.protection.obfuscation.resource-location.bypass-equipments"); resource_pack$optimization$enable = config.getBoolean("resource-pack.optimization.enable", false); resource_pack$optimization$texture$enable = config.getBoolean("resource-pack.optimization.texture.enable", true); - resource_pack$optimization$texture$exlude = new HashSet<>(config.getStringList("resource-pack.optimization.texture.exclude")); + resource_pack$optimization$texture$exlude = config.getStringList("resource-pack.optimization.texture.exclude").stream().map(p -> { + if (!p.endsWith(".png")) return p + ".png"; + return p; + }).collect(Collectors.toSet()); resource_pack$optimization$json$enable = config.getBoolean("resource-pack.optimization.json.enable", true); - resource_pack$optimization$json$exclude = new HashSet<>(config.getStringList("resource-pack.optimization.json.exclude")); + resource_pack$optimization$json$exclude = config.getStringList("resource-pack.optimization.json.exclude").stream().map(p -> { + if (!p.endsWith(".json") && !p.endsWith(".mcmeta")) return p + ".json"; + return p; + }).collect(Collectors.toSet()); resource_pack$validation$enable = config.getBoolean("resource-pack.validation.enable", true); resource_pack$validation$fix_atlas = VersionHelper.PREMIUM && config.getBoolean("resource-pack.validation.fix-atlas", true); resource_pack$exclude_core_shaders = config.getBoolean("resource-pack.exclude-core-shaders", false); diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/PngWriter.java b/core/src/main/java/net/momirealms/craftengine/core/util/PngWriter.java index f8a716f97..e2b9780a4 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/PngWriter.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/PngWriter.java @@ -29,6 +29,7 @@ import org.apache.commons.imaging.formats.png.PngConstants; import org.apache.commons.imaging.palette.Palette; import org.apache.commons.imaging.palette.PaletteFactory; +import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -64,6 +65,8 @@ public class PngWriter { public void write(BufferedImage src, OutputStream os, PaletteFactory paletteFactory) throws IOException { final int width = src.getWidth(); final int height = src.getHeight(); + src = convertTo8BitRGB(src); + final boolean hasAlpha = paletteFactory.hasTransparency(src); boolean isGrayscale = paletteFactory.isGrayscale(src); @@ -86,6 +89,27 @@ public class PngWriter { os.close(); } + public static BufferedImage convertTo8BitRGB(BufferedImage sourceImage) { + int type = sourceImage.getType(); + if (type == BufferedImage.TYPE_INT_ARGB || + type == BufferedImage.TYPE_INT_RGB || + type == BufferedImage.TYPE_BYTE_INDEXED) { + return sourceImage; + } + + BufferedImage eightBitImage = new BufferedImage( + sourceImage.getWidth(), + sourceImage.getHeight(), + sourceImage.getColorModel().hasAlpha() ? BufferedImage.TYPE_INT_ARGB : BufferedImage.TYPE_INT_RGB + ); + + Graphics2D g2d = eightBitImage.createGraphics(); + g2d.drawImage(sourceImage, 0, 0, null); + g2d.dispose(); + + return eightBitImage; + } + private Pair findBestCompressMethod(BufferedImage src, PaletteFactory paletteFactory, boolean hasAlpha, boolean isGrayscale) throws IOException { byte[] paletteSize = tryPalette(src, paletteFactory, hasAlpha); byte[] normalSize = tryNormal(src, hasAlpha, isGrayscale);