9
0
mirror of https://github.com/Xiao-MoMi/craft-engine.git synced 2025-12-19 15:09:15 +00:00

优化验证速度

This commit is contained in:
XiaoMoMi
2025-12-16 20:52:43 +08:00
parent 7af13286eb
commit 75c5555fe5
10 changed files with 84 additions and 75 deletions

View File

@@ -8,8 +8,8 @@ import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.context.NetworkTextReplaceContext;
import net.momirealms.craftengine.core.plugin.network.event.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.event.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.text.component.ComponentProvider;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;

View File

@@ -11,8 +11,8 @@ import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.context.NetworkTextReplaceContext;
import net.momirealms.craftengine.core.plugin.network.event.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.event.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.text.component.ComponentProvider;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;

View File

@@ -8,8 +8,8 @@ import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer;
import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.network.event.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.event.ByteBufPacketEvent;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import org.bukkit.inventory.ItemStack;

View File

@@ -11,8 +11,8 @@ import net.momirealms.craftengine.core.entity.player.Player;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.plugin.config.Config;
import net.momirealms.craftengine.core.plugin.context.NetworkTextReplaceContext;
import net.momirealms.craftengine.core.plugin.network.event.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.event.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.text.component.ComponentProvider;
import net.momirealms.craftengine.core.util.AdventureHelper;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;

View File

@@ -11,10 +11,10 @@ import net.momirealms.craftengine.core.entity.projectile.ProjectileMeta;
import net.momirealms.craftengine.core.item.CustomItem;
import net.momirealms.craftengine.core.item.Item;
import net.momirealms.craftengine.core.item.ItemBuildContext;
import net.momirealms.craftengine.core.plugin.network.event.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.EntityPacketHandler;
import net.momirealms.craftengine.core.plugin.network.event.NMSPacketEvent;
import net.momirealms.craftengine.core.plugin.network.NetWorkUser;
import net.momirealms.craftengine.core.plugin.network.event.ByteBufPacketEvent;
import net.momirealms.craftengine.core.plugin.network.event.NMSPacketEvent;
import net.momirealms.craftengine.core.util.FriendlyByteBuf;
import net.momirealms.craftengine.core.util.MiscUtils;
import net.momirealms.craftengine.core.util.VersionHelper;

View File

@@ -94,12 +94,13 @@ resource-pack:
resolution:
type: merge_font
# Validate if there is any error in the resource pack, such as missing textures or models.
# Validation may not always be accurate due to the presence of overlays, and it is time-consuming for plugins to simulate multiple client versions for testing.
# Validation may not always be accurate due to the presence of resource pack overlays.
# If your resource pack is compliant with the standard, you can disable validation to improve the resource pack generation speed.
validation:
enable: true
# Fix images that are not within the texture atlas. It is unreasonable to always rely on plugins to fix your mistakes.
# Fix textures that are not within the atlas. It is unreasonable to always rely on plugins to fix your mistakes.
# You should strive to make your resource pack more standardized after gaining some experience with resource packs.
# When a model file mixes textures from both the blocks atlas and the items atlas, you must manually fix the issue.
fix-atlas: true
# Optimize your resource pack by reducing its size without any quality loss.
optimization:

View File

@@ -1,8 +1,6 @@
package net.momirealms.craftengine.core.pack;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.jimfs.Configuration;
import com.google.common.jimfs.Jimfs;
@@ -1186,12 +1184,12 @@ public abstract class AbstractPackManager implements PackManager {
return;
}
Multimap<Key, Key> glyphToFonts = ArrayListMultimap.create(); // 图片到字体的映射
Multimap<Key, Key> modelToItemDefinitions = ArrayListMultimap.create(); // 模型到物品的映射
Multimap<Key, String> modelToBlockStates = ArrayListMultimap.create(); // 模型到方块的映射
Multimap<Key, Key> textureToModels = ArrayListMultimap.create(); // 纹理到模型的映射
Multimap<Key, Key> textureToEquipments = ArrayListMultimap.create(); // 纹理到盔甲的映射
Multimap<Key, Key> oggToSoundEvents = ArrayListMultimap.create(); // 音频到声音的映射
Multimap<Key, Key> glyphToFonts = HashMultimap.create(128, 32); // 图片到字体的映射
Multimap<Key, Key> modelToItemDefinitions = HashMultimap.create(128, 4); // 模型到物品的映射
Multimap<Key, String> modelToBlockStates = HashMultimap.create(128, 32); // 模型到方块的映射
Multimap<Key, Key> textureToModels = HashMultimap.create(128, 8); // 纹理到模型的映射
Multimap<Key, Key> textureToEquipments = HashMultimap.create(128, 8); // 纹理到盔甲的映射
Multimap<Key, Key> oggToSoundEvents = HashMultimap.create(128, 4); // 音频到声音的映射
Map<Path, JsonObject> blockAtlasJsons = new LinkedHashMap<>();
Map<Path, JsonObject> itemAtlasJsons = new LinkedHashMap<>();
@@ -1239,16 +1237,17 @@ public abstract class AbstractPackManager implements PackManager {
/*
构建Atlas文件
构建Atlas文件
验证只使用默认的atlas否则整个过程将会变成非常复杂
*/
Atlas blockAtlas = new Atlas(MiscUtils.make(new ArrayList<>(), k -> {
Atlas blockAtlas = new Atlas(MiscUtils.make(new ArrayList<>(4), k -> {
k.add(blockAtlasJsons.get(defaultBlockAtlas));
k.add(this.vanillaBlockAtlas);
return k;
}));
Atlas itemAtlas = new Atlas(MiscUtils.make(new ArrayList<>(), k -> {
Atlas itemAtlas = new Atlas(MiscUtils.make(new ArrayList<>(4), k -> {
k.add(itemAtlasJsons.get(defaultItemAtlas));
k.add(this.vanillaItemAtlas);
return k;
@@ -1289,16 +1288,18 @@ public abstract class AbstractPackManager implements PackManager {
if (providers != null) {
Key fontName = Key.of(namespace, FileUtils.pathWithoutExtension(file.getFileName().toString()));
for (JsonElement provider : providers) {
if (provider instanceof JsonObject providerJO && providerJO.has("type")) {
String type = providerJO.get("type").getAsString();
if (type.equals("bitmap") && providerJO.has("file")) {
String pngFile = providerJO.get("file").getAsString();
if (!(provider instanceof JsonObject providerJO)) continue;
JsonPrimitive typePrimitive = providerJO.getAsJsonPrimitive("type");
if (typePrimitive == null) continue;
String type = typePrimitive.getAsString();
if (!type.equals("bitmap")) continue;
JsonPrimitive filePrimitive = providerJO.getAsJsonPrimitive("file");
if (filePrimitive == null) continue;
String pngFile = filePrimitive.getAsString();
Key resourceLocation = Key.of(FileUtils.pathWithoutExtension(pngFile));
glyphToFonts.put(resourceLocation, fontName);
}
}
}
}
return FileVisitResult.CONTINUE;
}
});
@@ -1383,7 +1384,8 @@ public abstract class AbstractPackManager implements PackManager {
if (layer.getValue() instanceof JsonArray equipmentLayer) {
for (JsonElement lay : equipmentLayer) {
if (lay instanceof JsonObject layObj) {
Key rawTexture = Key.of(layObj.get("texture").getAsString());
if (layObj.get("texture") instanceof JsonPrimitive layerTexture) {
Key rawTexture = Key.of(layerTexture.getAsString());
Key fullPath = Key.of(rawTexture.namespace(), "entity/equipment/" + type + "/" + rawTexture.value());
textureToEquipments.put(fullPath, Key.of(namespace, equipmentId));
}
@@ -1391,6 +1393,7 @@ public abstract class AbstractPackManager implements PackManager {
}
}
}
}
return FileVisitResult.CONTINUE;
}
});
@@ -1411,9 +1414,7 @@ public abstract class AbstractPackManager implements PackManager {
if (soundArray != null) {
for (JsonElement sound : soundArray) {
if (sound instanceof JsonPrimitive primitive) {
if (primitive.isString()) {
oggToSoundEvents.put(Key.of(primitive.getAsString()), soundKey);
}
} else if (sound instanceof JsonObject soundObj && soundObj.has("name")) {
if (soundObj.has("type")) {
String type = soundObj.get("type").getAsString();
@@ -1481,12 +1482,12 @@ public abstract class AbstractPackManager implements PackManager {
*/
// 获取所有带贴图的模型以及自定义父模型
Map<Key, TexturedModel> blockModels = new LinkedHashMap<>();
Map<Key, TexturedModel> itemModels = new LinkedHashMap<>();
Map<Key, TexturedModel> blockModels = new HashMap<>(256);
Map<Key, TexturedModel> itemModels = new HashMap<>(256);
// 此map仅用于缓存遇到过的路径上的模型
Map<Key, TexturedModel> blockModelsCache = new LinkedHashMap<>();
Map<Key, TexturedModel> itemModelsCache = new LinkedHashMap<>();
Set<Key> checkedModels = new HashSet<>();
Map<Key, TexturedModel> blockModelsCache = new HashMap<>(256);
Map<Key, TexturedModel> itemModelsCache = new HashMap<>(256);
Set<Key> checkedModels = new HashSet<>(256);
// 收集全部方块状态的模型贴图
label: for (Map.Entry<Key, Collection<String>> entry : modelToBlockStates.asMap().entrySet()) {
@@ -1510,7 +1511,7 @@ public abstract class AbstractPackManager implements PackManager {
}
// 提示方块状态缺少模型
if (!VANILLA_MODELS.contains(modelPath)) {
TranslationManager.instance().log("warning.config.resource_pack.generation.missing_block_model", entry.getValue().stream().distinct().toList().toString(), modelStringPath);
TranslationManager.instance().log("warning.config.resource_pack.generation.missing_block_model", entry.getValue().toString(), modelStringPath);
}
}
@@ -1535,7 +1536,7 @@ public abstract class AbstractPackManager implements PackManager {
}
}
if (!VANILLA_MODELS.contains(modelPath)) {
TranslationManager.instance().log("warning.config.resource_pack.generation.missing_item_model", entry.getValue().stream().distinct().toList().toString(), modelStringPath);
TranslationManager.instance().log("warning.config.resource_pack.generation.missing_item_model", entry.getValue().toString(), modelStringPath);
}
}
@@ -1547,9 +1548,9 @@ public abstract class AbstractPackManager implements PackManager {
*/
Multimap<Key, Key> blockAtlasesToFix = LinkedHashMultimap.create();
Multimap<Key, Key> itemAtlasesToFix = LinkedHashMultimap.create();
Multimap<Key, Key> anyAtlasesToFix = LinkedHashMultimap.create();
Multimap<Key, Key> blockAtlasesToFix = HashMultimap.create(64, 4);
Multimap<Key, Key> itemAtlasesToFix = HashMultimap.create(64, 4);
Multimap<Key, Key> anyAtlasesToFix = HashMultimap.create(64, 4);
// 验证方块贴图是否在图集里
Iterator<Map.Entry<Key, TexturedModel>> iterator1 = blockModels.entrySet().iterator();
@@ -1560,19 +1561,9 @@ public abstract class AbstractPackManager implements PackManager {
boolean shouldRemove = false;
for (Map.Entry<String, Key> texture : textures.entrySet()) {
Key spritePath = texture.getValue();
boolean definedInBlockAtlas = blockAtlas.isDefined(spritePath);
boolean definedInItemAtlas = itemAtlas.isDefined(spritePath);
// 双重定义
if (definedInItemAtlas && definedInBlockAtlas) {
TranslationManager.instance().log("warning.config.resource_pack.generation.duplicated_sprite",
entry.getKey().asString(), spritePath.asString(),
"minecraft:textures/atlas/blocks.png", "minecraft:textures/atlas/items.png");
shouldRemove = true;
break;
}
// 方块纹理不应该在item图集内这样必然出问题
boolean definedInItemAtlas = itemAtlas.isDefined(spritePath);
if (definedInItemAtlas) {
TranslationManager.instance().log("warning.config.resource_pack.generation.multiple_atlases",
entry.getKey().asString(), "minecraft:textures/atlas/blocks.png",
@@ -1582,7 +1573,7 @@ public abstract class AbstractPackManager implements PackManager {
}
// 未在方块图集内定义
if (!definedInBlockAtlas) {
if (!blockAtlas.isDefined(spritePath)) {
// 如果尝试修复
if (Config.fixTextureAtlas()) {
// 只能在方块图集
@@ -1649,16 +1640,15 @@ public abstract class AbstractPackManager implements PackManager {
textureToModels.put(spritePath, entry.getKey());
}
}
}
} else {
// 那么就至少有一个定义
if (definedInBlockAtlas) {
blockAtlasInUse = true;
}
if (definedInItemAtlas) {
} else /* if (definedInItemAtlas) */ {
itemAtlasInUse = true;
}
}
}
// 如果之前已经标记为需要移除,直接跳过后续处理
if (shouldRemove) {
@@ -1745,7 +1735,7 @@ public abstract class AbstractPackManager implements PackManager {
}
if (!itemAtlasesToFix.isEmpty()) {
List<JsonObject> sourcesToAdd = new ArrayList<>();
List<JsonObject> sourcesToAdd = new ArrayList<>(itemAtlasesToFix.size());
for (Key itemTexture : itemAtlasesToFix.keySet()) {
itemAtlas.addSingle(itemTexture);
JsonObject source = new JsonObject();
@@ -1773,7 +1763,7 @@ public abstract class AbstractPackManager implements PackManager {
}
if (!blockAtlasesToFix.isEmpty()) {
List<JsonObject> sourcesToAdd = new ArrayList<>();
List<JsonObject> sourcesToAdd = new ArrayList<>(blockAtlasesToFix.size());
for (Key blockTexture : blockAtlasesToFix.keySet()) {
blockAtlas.addSingle(blockTexture);
JsonObject source = new JsonObject();
@@ -1845,11 +1835,16 @@ public abstract class AbstractPackManager implements PackManager {
}
}
}
// todo 验证 unstitch 和 paletted permutations
}
// 经过这一步拿到的模型为包含全部父贴图的模型
@SuppressWarnings("all")
public TexturedModel getTexturedModel(Key path, JsonObject modelJson, Path[] rootPaths, Map<Key, TexturedModel> models) {
TexturedModel texturedModel = new TexturedModel(modelJson);
// 放这里防止parent互相引用造成死循环
models.put(path, texturedModel);
if (modelJson.has("parent")) {
Key parentModelPath = Key.from(modelJson.get("parent").getAsString());
TexturedModel parent = models.get(parentModelPath);
@@ -1863,17 +1858,25 @@ public abstract class AbstractPackManager implements PackManager {
} else {
// 否则只从缓存里拿一份用于归并
if (VANILLA_MODELS.contains(parentModelPath)) {
// 可能为空因为存在built-in模型
parent = PRESET_MODELS.get(parentModelPath);
if (parent == null) {
parent = TexturedModel.BUILTIN;
}
models.put(parentModelPath, parent);
} else {
parent = TexturedModel.EMPTY;
models.put(parentModelPath, parent);
}
}
}
if (parent == TexturedModel.EMPTY) {
String parentModelStringPath = "assets/" + parentModelPath.namespace() + "/models/" + parentModelPath.value() + ".json";
TranslationManager.instance().log("warning.config.resource_pack.generation.missing_parent_model", path.asString(), parentModelStringPath);
}
}
}
if (parent != null) {
} else {
texturedModel.addParent(parent);
}
}
models.put(path, texturedModel);
return texturedModel;
}

View File

@@ -15,6 +15,7 @@ import java.util.stream.Collectors;
public final class Atlas {
private final Map<String, String> directory;
private final String[] prefixes;
// 已经被包含在图集内的贴图
private final Set<Key> defined;
// 单独添加的
@@ -109,6 +110,7 @@ public final class Atlas {
}
}
this.filtered = MiscUtils.anyOf(filtered);
this.prefixes = this.directory.keySet().toArray(new String[0]);
}
public Atlas(List<JsonObject> atlasJsons) {
@@ -135,10 +137,8 @@ public final class Atlas {
if (this.filtered.test(texture)) return false;
if (this.defined.contains(texture)) return true;
String path = texture.value();
for (Map.Entry<String, String> entry : this.directory.entrySet()) {
if (path.startsWith(entry.getKey())) {
return true;
}
for (String prefix : this.prefixes) {
if (path.startsWith(prefix)) return true;
}
return false;
}
@@ -156,8 +156,9 @@ public final class Atlas {
String path = texture.value();
// 路径匹配
for (Map.Entry<String, String> entry : this.directory.entrySet()) {
if (path.startsWith(entry.getKey())) {
return Key.of(texture.namespace(), entry.getValue() + path.substring(entry.getKey().length()));
String prefix = entry.getKey();
if (path.startsWith(prefix)) {
return Key.of(texture.namespace(), entry.getValue() + path.substring(prefix.length()));
}
}
return null;

View File

@@ -9,6 +9,7 @@ import java.util.Map;
public class TexturedModel {
public static final TexturedModel EMPTY = new TexturedModel(Map.of());
public static final TexturedModel BUILTIN = new TexturedModel(Map.of());
public final Map<String, Key> textures;
private TexturedModel(Map<String, Key> textures) {

View File

@@ -1,7 +1,10 @@
package net.momirealms.craftengine.core.pack.conflict.resolution;
import com.google.common.collect.ImmutableSet;
import com.google.gson.*;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonPrimitive;
import net.momirealms.craftengine.core.pack.conflict.PathContext;
import net.momirealms.craftengine.core.plugin.CraftEngine;
import net.momirealms.craftengine.core.util.AdventureHelper;