mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 09:59:20 +00:00
添加物品名称和描述的预解析
This commit is contained in:
@@ -47,7 +47,6 @@ import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.block.BlockType;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -80,9 +79,6 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
private Map<Integer, Object> stateId2BlockHolder;
|
||||
// This map is used to change the block states that are not necessarily needed into a certain block state
|
||||
private Map<Integer, Integer> blockAppearanceMapper;
|
||||
// Used to automatically arrange block states for strings such as minecraft:note_block:0
|
||||
private Map<Key, List<Integer>> blockAppearanceArranger;
|
||||
private Map<Key, List<Integer>> realBlockArranger;
|
||||
// Record the amount of real blocks by block type
|
||||
private Map<Key, Integer> registeredRealBlockSlots;
|
||||
// A set of blocks that sounds have been removed
|
||||
@@ -125,6 +121,11 @@ public final class BukkitBlockManager extends AbstractBlockManager {
|
||||
this.resetPacketConsumers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String stateRegistryIdToStateSNBT(int id) {
|
||||
return BlockStateUtils.idToBlockState(id).toString();
|
||||
}
|
||||
|
||||
public static BukkitBlockManager instance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@@ -177,7 +177,6 @@ public final class WorldStorageInjector {
|
||||
return section;
|
||||
}
|
||||
|
||||
|
||||
public static class SetBlockStateInterceptor {
|
||||
public static final SetBlockStateInterceptor INSTANCE = new SetBlockStateInterceptor();
|
||||
|
||||
@@ -215,7 +214,7 @@ public final class WorldStorageInjector {
|
||||
}
|
||||
}
|
||||
|
||||
protected static void compareAndUpdateBlockState(int x, int y, int z, Object newState, Object previousState, InjectedHolder holder) {
|
||||
private static void compareAndUpdateBlockState(int x, int y, int z, Object newState, Object previousState, InjectedHolder holder) {
|
||||
try {
|
||||
Optional<ImmutableBlockState> optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(newState);
|
||||
CESection section = holder.ceSection();
|
||||
|
||||
@@ -188,6 +188,7 @@ public class BukkitServerPlayer extends Player {
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
@Override
|
||||
public void setGameMode(GameMode gameMode) {
|
||||
platformPlayer().setGameMode(Objects.requireNonNull(org.bukkit.GameMode.getByValue(gameMode.id())));
|
||||
|
||||
@@ -380,10 +380,10 @@ chunk-system:
|
||||
compression-method: 4
|
||||
# Settings for injection
|
||||
injection:
|
||||
# Requires a restart to apply
|
||||
# Requires a restart to apply.
|
||||
# SECTION: Inject the LevelChunkSection
|
||||
# PALETTE: Inject the PalettedContainer
|
||||
target: SECTION
|
||||
target: PALETTE
|
||||
# Enables faster injection method
|
||||
# Note: May not work with certain server forks that alter chunk class structure (In most cases it won't conflict)
|
||||
use-fast-method: true
|
||||
|
||||
@@ -239,7 +239,6 @@ warning.config.block.state.unavailable_vanilla: "<yellow>Problem in Datei <arg:0
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen Vanilla-Blockzustand '<arg:2>', der den verfügbaren Slot-Bereich '0~<arg:3>' überschreitet.</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen Vanilla-Blockzustand '<arg:2>', der bereits von '<arg:3>' belegt ist.</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' konnte den echten Blockzustand für '<arg:2>' nicht binden, da der Zustand von '<arg:3>' belegt ist.</yellow>"
|
||||
warning.config.block.state.missing_model: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt das erforderliche 'model' oder 'models'-Argument.</yellow>"
|
||||
warning.config.block.state.invalid_real_id: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' verwendet einen echten Blockzustand '<arg:2>', der den verfügbaren Slot-Bereich '0~<arg:3>' überschreitet. Erwägen Sie, weitere echte Zustände in 'additional-real-blocks.yml' hinzuzufügen, wenn die Slots aufgebraucht sind.</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow>Problem in Datei <arg:0> gefunden - Dem Block '<arg:1>' fehlt die erforderliche 'path'-Option für 'model'.</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow>Problem in Datei <arg:0> gefunden - Der Block '<arg:1>' hat ein 'path'-Argument '<arg:2>', das illegale Zeichen enthält. Bitte lesen Sie https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
|
||||
|
||||
@@ -261,7 +261,6 @@ warning.config.block.state.unavailable_vanilla: "<yellow>Issue found in file <ar
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using a vanilla block state '<arg:2>' that exceeds the available slot range '0~<arg:3>'.</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using a vanilla block state '<arg:2>' that has been occupied by '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' failed to bind real block state for '<arg:2>' as the state has been occupied by '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.missing_model: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'model' or 'models' argument.</yellow>"
|
||||
warning.config.block.state.invalid_real_id: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is using a real block state '<arg:2>' that exceeds the available slot range '0~<arg:3>'. Consider adding more real states in 'additional-real-blocks.yml' if the slots are used up.</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' is missing the required 'path' option for 'model'.</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow>Issue found in file <arg:0> - The block '<arg:1>' has a 'path' argument '<arg:2>' that contains illegal characters. Please read https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
|
||||
|
||||
@@ -187,7 +187,6 @@ warning.config.block.state.unavailable_vanilla: "<yellow>Problema encontrado en
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un estado de bloque vanilla '<arg:2>' que excede el rango de slots disponible '0~<arg:3>'.</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un estado de bloque vanilla '<arg:2>' que está ocupado por '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' falló al vincular el estado de bloque real para '<arg:2>' porque está ocupado por el estado '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.missing_model: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' carece del argumento requerido 'model' o 'models'.</yellow>"
|
||||
warning.config.block.state.invalid_real_id: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' está usando un estado de bloque real '<arg:2>' que excede el rango de slots disponible '0~<arg:3>'. Si los slots están usados, considera agregar más estados reales a 'additional-real-blocks.yml'.</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' carece de la opción requerida 'path' para 'model'.</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow>Problema encontrado en el archivo <arg:0> - El bloque '<arg:1>' tiene un argumento 'path' '<arg:2>' que contiene caracteres prohibidos. Por favor lee https://minecraft.wiki/w/Resource_location#Legal_characters</yellow>"
|
||||
|
||||
@@ -237,7 +237,6 @@ warning.config.block.state.unavailable_vanilla: "<yellow>Проблема най
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' использует состояние ванильного блока '<arg:2>', что превышает доступный диапазон слотов '0~<arg:3>'.</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' использует состояние ванильного блока '<arg:2>' которое занято '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow>Проблема найдена в файле <arg:0> - Блоку '<arg:1>' не удалось привязать реальное состояние блока для '<arg:2>', так как состояние занято '<arg:3>'.</yellow>"
|
||||
warning.config.block.state.missing_model: "<yellow>Проблема найдена в файле <arg:0> - В блоке '<arg:1>' отсутствует необходимый 'model' или 'models' аргумент.</yellow>"
|
||||
warning.config.block.state.invalid_real_id: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' использует реальное состояние блока '<arg:2>', которое превышает доступный диапазон слотов '0~<arg:3>'. Рассмотрите возможность добавления большего количества реальных состояний в 'additional-real-blocks.yml' если слоты израсходованы.</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow>Проблема найдена в файле <arg:0> - В блоке '<arg:1>' отсутствует необходимый 'path' опция для 'model'.</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow>Проблема найдена в файле <arg:0> - Блок '<arg:1>' имеет 'path' аргумент '<arg:2>' содержит недопустимые символы. Пожалуйста, прочтите https://minecraft.wiki/w/Resource_location#Legal_characters.</yellow>"
|
||||
|
||||
@@ -185,7 +185,6 @@ warning.config.block.state.unavailable_vanilla: "<yellow><arg:0> dosyasında sor
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, mevcut yuva aralığı '0~<arg:3>' aşan bir vanilya blok durumu '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, '<arg:3>' tarafından işgal edilmiş bir vanilya blok durumu '<arg:2>' kullanıyor.</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, durum '<arg:3>' tarafından işgal edildiği için '<arg:2>' için gerçek blok durumu bağlamada başarısız oldu.</yellow>"
|
||||
warning.config.block.state.missing_model: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu gerekli 'model' veya 'models' argümanı eksik.</yellow>"
|
||||
warning.config.block.state.invalid_real_id: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, mevcut yuva aralığı '0~<arg:3>' aşan bir gerçek blok durumu '<arg:2>' kullanıyor. Yuvalar kullanılmışsa, 'additional-real-blocks.yml' dosyasına daha fazla gerçek durum eklemeyi düşünün.</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğu, 'model' için gerekli 'path' seçeneği eksik.</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow><arg:0> dosyasında sorun bulundu - '<arg:1>' bloğunun, yasak karakterler içeren bir 'path' argümanı '<arg:2>' var. Lütfen https://minecraft.wiki/w/Resource_location#Legal_characters sayfasını okuyun.</yellow>"
|
||||
|
||||
@@ -261,7 +261,6 @@ warning.config.block.state.unavailable_vanilla: "<yellow>在文件 <arg:0> 发
|
||||
warning.config.block.state.invalid_vanilla_id: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 使用的原版方块状态 '<arg:2>' 超出可用槽位范围 '0~<arg:3>'</yellow>"
|
||||
warning.config.block.state.conflict: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 使用的原版方块状态 '<arg:2>' 已被 '<arg:3>' 占用</yellow>"
|
||||
warning.config.block.state.bind_failed: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 无法为 '<arg:2>' 绑定真实方块状态 因该状态已被 '<arg:3>' 占用</yellow>"
|
||||
warning.config.block.state.missing_model: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 缺少必需的 'model' 或 'models' 参数</yellow>"
|
||||
warning.config.block.state.invalid_real_id: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 使用的真实方块状态 '<arg:2>' 超出可用槽位范围 '0~<arg:3>' 如果槽位已用尽 请在 additional-real-blocks.yml 中添加更多真实状态</yellow>"
|
||||
warning.config.block.state.model.missing_path: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'model' 缺少必需的 'path' 选项</yellow>"
|
||||
warning.config.block.state.model.invalid_path: "<yellow>在文件 <arg:0> 发现问题 - 方块 '<arg:1>' 的 'path' 参数 '<arg:2>' 包含非法字符 请参考 https://zh.minecraft.wiki/w/%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4ID#%E5%90%88%E6%B3%95%E5%AD%97%E7%AC%A6</yellow>"
|
||||
|
||||
@@ -1,18 +1,24 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.momirealms.craftengine.core.block.properties.Properties;
|
||||
import net.momirealms.craftengine.core.block.properties.Property;
|
||||
import net.momirealms.craftengine.core.pack.LoadingSequence;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.pack.ResourceLocation;
|
||||
import net.momirealms.craftengine.core.pack.model.generation.AbstractModelGenerator;
|
||||
import net.momirealms.craftengine.core.pack.model.generation.ModelGeneration;
|
||||
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.locale.LocalizedResourceConfigException;
|
||||
import net.momirealms.craftengine.core.util.GsonHelper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
import org.incendo.cloud.suggestion.Suggestion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
@@ -41,6 +47,9 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
// client side block tags
|
||||
protected Map<Integer, List<String>> clientBoundTags = Map.of();
|
||||
protected Map<Integer, List<String>> previousClientBoundTags = Map.of();
|
||||
// Used to automatically arrange block states for strings such as minecraft:note_block:0
|
||||
protected Map<Key, List<Integer>> blockAppearanceArranger;
|
||||
protected Map<Key, List<Integer>> realBlockArranger;
|
||||
|
||||
protected AbstractBlockManager(CraftEngine plugin) {
|
||||
super(plugin);
|
||||
@@ -139,6 +148,8 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
|
||||
protected abstract int getBlockRegistryId(Key id);
|
||||
|
||||
public abstract String stateRegistryIdToStateSNBT(int id);
|
||||
|
||||
public class BlockParser implements ConfigParser {
|
||||
public static final String[] CONFIG_SECTION_NAME = new String[]{"blocks", "block"};
|
||||
|
||||
@@ -179,7 +190,161 @@ public abstract class AbstractBlockManager extends AbstractModelGenerator implem
|
||||
private void parseCustomBlock(Pack pack, Path path, Key id, Map<String, Object> section) {
|
||||
// 获取方块设置
|
||||
BlockSettings settings = BlockSettings.fromMap(id, MiscUtils.castToMap(section.get("settings"), true));
|
||||
//
|
||||
// 读取基础外观配置
|
||||
Map<String, Property<?>> properties;
|
||||
Map<String, Integer> appearances;
|
||||
Map<String, BlockStateVariant> variants;
|
||||
// 读取states区域
|
||||
Map<String, Object> stateSection = MiscUtils.castToMap(ResourceConfigUtils.requireNonNullOrThrow(
|
||||
ResourceConfigUtils.get(section, "state", "states"), "warning.config.block.missing_state"), true);
|
||||
boolean singleState = !stateSection.containsKey("properties");
|
||||
// 单方块状态
|
||||
if (singleState) {
|
||||
int internalId = ResourceConfigUtils.getAsInt(ResourceConfigUtils.requireNonNullOrThrow(
|
||||
stateSection.get("id"), "warning.config.block.state.missing_real_id"), "id");
|
||||
// 获取原版外观的注册表id
|
||||
int appearanceId = pluginFormattedBlockStateToRegistryId(ResourceConfigUtils.requireNonEmptyStringOrThrow(
|
||||
stateSection.get("state"), "warning.config.block.state.missing_state"));
|
||||
// 为原版外观赋予外观模型并检查模型冲突
|
||||
this.arrangeModelForStateAndVerify(appearanceId, ResourceConfigUtils.get(stateSection, "model", "models"));
|
||||
// 设置参数
|
||||
properties = Map.of();
|
||||
appearances = Map.of("", appearanceId);
|
||||
variants = Map.of("", new BlockStateVariant("", settings, internalId));
|
||||
}
|
||||
// 多方块状态
|
||||
else {
|
||||
properties = parseBlockProperties(ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("properties"), "warning.config.block.state.missing_properties"), "properties"));
|
||||
appearances = parseBlockAppearances(ResourceConfigUtils.getAsMap(ResourceConfigUtils.requireNonNullOrThrow(stateSection.get("appearances"), "warning.config.block.state.missing_appearances"), "appearances"));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, Integer> parseBlockAppearances(Map<String, Object> appearancesSection) {
|
||||
Map<String, Integer> appearances = new HashMap<>();
|
||||
for (Map.Entry<String, Object> entry : appearancesSection.entrySet()) {
|
||||
Map<String, Object> appearanceSection = ResourceConfigUtils.getAsMap(entry.getValue(), entry.getKey());
|
||||
int appearanceId = pluginFormattedBlockStateToRegistryId(ResourceConfigUtils.requireNonEmptyStringOrThrow(
|
||||
appearanceSection.get("state"), "warning.config.block.state.missing_state"));
|
||||
this.arrangeModelForStateAndVerify(appearanceId, ResourceConfigUtils.get(appearanceSection, "model", "models"));
|
||||
appearances.put(entry.getKey(), appearanceId);
|
||||
}
|
||||
return appearances;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Map<String, Property<?>> parseBlockProperties(Map<String, Object> propertiesSection) {
|
||||
Map<String, Property<?>> properties = new HashMap<>();
|
||||
for (Map.Entry<String, Object> entry : propertiesSection.entrySet()) {
|
||||
Property<?> property = Properties.fromMap(entry.getKey(), ResourceConfigUtils.getAsMap(entry.getValue(), entry.getKey()));
|
||||
properties.put(entry.getKey(), property);
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
private void arrangeModelForStateAndVerify(int registryId, Object modelOrModels) {
|
||||
// 如果没有配置models
|
||||
if (modelOrModels == null) {
|
||||
return;
|
||||
}
|
||||
// 获取variants
|
||||
List<JsonObject> variants;
|
||||
if (modelOrModels instanceof String model) {
|
||||
JsonObject json = new JsonObject();
|
||||
json.addProperty("model", model);
|
||||
variants = Collections.singletonList(json);
|
||||
} else {
|
||||
variants = ResourceConfigUtils.parseConfigAsList(modelOrModels, this::parseAppearanceModelSectionAsJson);
|
||||
if (variants.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 拆分方块id与属性
|
||||
String blockState = stateRegistryIdToStateSNBT(registryId);
|
||||
Key blockId = Key.of(blockState.substring(blockState.indexOf('{') + 1, blockState.lastIndexOf('}')));
|
||||
String propertyNBT = blockState.substring(blockState.indexOf('[') + 1, blockState.lastIndexOf(']'));
|
||||
// 结合variants
|
||||
JsonElement combinedVariant = GsonHelper.combine(variants);
|
||||
JsonElement previous = AbstractBlockManager.this.blockStateOverrides.computeIfAbsent(blockId, k -> new HashMap<>()).put(propertyNBT, combinedVariant);
|
||||
if (previous != null && !previous.equals(combinedVariant)) {
|
||||
// todo 播报可能的冲突
|
||||
plugin.logger().warn("warning 1");
|
||||
}
|
||||
}
|
||||
|
||||
private JsonObject parseAppearanceModelSectionAsJson(Map<String, Object> section) {
|
||||
JsonObject json = new JsonObject();
|
||||
String modelPath = ResourceConfigUtils.requireNonEmptyStringOrThrow(section.get("path"), "warning.config.block.state.model.missing_path");
|
||||
if (!ResourceLocation.isValid(modelPath)) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.model.invalid_path", modelPath);
|
||||
}
|
||||
json.addProperty("model", modelPath);
|
||||
if (section.containsKey("x"))
|
||||
json.addProperty("x", ResourceConfigUtils.getAsInt(section.get("x"), "x"));
|
||||
if (section.containsKey("y"))
|
||||
json.addProperty("y", ResourceConfigUtils.getAsInt(section.get("y"), "y"));
|
||||
if (section.containsKey("uvlock")) json.addProperty("uvlock", ResourceConfigUtils.getAsBoolean(section.get("uvlock"), "uvlock"));
|
||||
if (section.containsKey("weight"))
|
||||
json.addProperty("weight", ResourceConfigUtils.getAsInt(section.get("weight"), "weight"));
|
||||
Map<String, Object> generationMap = MiscUtils.castToMap(section.get("generation"), true);
|
||||
if (generationMap != null) {
|
||||
prepareModelGeneration(ModelGeneration.of(Key.of(modelPath), generationMap));
|
||||
}
|
||||
return json;
|
||||
}
|
||||
|
||||
// 从方块外观的state里获取其原版方块的state id
|
||||
private int pluginFormattedBlockStateToRegistryId(String blockState) {
|
||||
// 五种合理情况
|
||||
// minecraft:note_block:10
|
||||
// note_block:10
|
||||
// minecraft:note_block[xxx=xxx]
|
||||
// note_block[xxx=xxx]
|
||||
// minecraft:barrier
|
||||
String[] split = blockState.split(":", 3);
|
||||
if (split.length >= 4) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", blockState);
|
||||
}
|
||||
int registryId;
|
||||
String stateOrId = split[split.length - 1];
|
||||
boolean isId = false;
|
||||
int arrangerIndex = 0;
|
||||
try {
|
||||
arrangerIndex = Integer.parseInt(stateOrId);
|
||||
if (arrangerIndex < 0) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", blockState);
|
||||
}
|
||||
isId = true;
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
// 如果末尾是id,则至少长度为2
|
||||
if (isId) {
|
||||
if (split.length == 1) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", blockState);
|
||||
}
|
||||
// 获取原版方块的id
|
||||
Key block = split.length == 2 ? Key.of(split[0]) : Key.of(split[0], split[1]);
|
||||
try {
|
||||
List<Integer> arranger = blockAppearanceArranger.get(block);
|
||||
if (arranger == null) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.unavailable_vanilla", blockState);
|
||||
}
|
||||
if (arrangerIndex >= arranger.size()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla_id", blockState, String.valueOf(arranger.size() - 1));
|
||||
}
|
||||
registryId = arranger.get(arrangerIndex);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", e, blockState);
|
||||
}
|
||||
} else {
|
||||
// 其他情况则是完整的方块
|
||||
BlockStateWrapper packedBlockState = createPackedBlockState(blockState);
|
||||
if (packedBlockState == null || !packedBlockState.isVanillaBlock()) {
|
||||
throw new LocalizedResourceConfigException("warning.config.block.state.invalid_vanilla", blockState);
|
||||
}
|
||||
registryId = packedBlockState.registryId();
|
||||
}
|
||||
return registryId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.text.minimessage.FormattedLine;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -12,6 +13,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class CustomNameModifier<I> implements SimpleNetworkItemDataModifier<I> {
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
private final String argument;
|
||||
private final FormattedLine line;
|
||||
|
||||
public CustomNameModifier(String argument) {
|
||||
if (Config.addNonItalicTag()) {
|
||||
@@ -23,6 +25,7 @@ public class CustomNameModifier<I> implements SimpleNetworkItemDataModifier<I> {
|
||||
} else {
|
||||
this.argument = argument;
|
||||
}
|
||||
this.line = FormattedLine.create(this.argument);
|
||||
}
|
||||
|
||||
public String customName() {
|
||||
@@ -36,7 +39,7 @@ public class CustomNameModifier<I> implements SimpleNetworkItemDataModifier<I> {
|
||||
|
||||
@Override
|
||||
public Item<I> apply(Item<I> item, ItemBuildContext context) {
|
||||
item.customNameComponent(AdventureHelper.miniMessage().deserialize(this.argument, context.tagResolvers()));
|
||||
item.customNameComponent(this.line.parse(context));
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package net.momirealms.craftengine.core.item.modifier;
|
||||
|
||||
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
||||
import net.momirealms.craftengine.core.item.modifier.lore.OverwritableLoreModifier;
|
||||
import net.momirealms.craftengine.core.item.modifier.lore.DynamicLoreModifier;
|
||||
import net.momirealms.craftengine.core.item.modifier.lore.LoreModifier;
|
||||
import net.momirealms.craftengine.core.item.modifier.lore.OverwritableLoreModifier;
|
||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.registry.Registries;
|
||||
import net.momirealms.craftengine.core.registry.WritableRegistry;
|
||||
|
||||
@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.item.ComponentKeys;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
||||
import net.momirealms.craftengine.core.plugin.text.minimessage.FormattedLine;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -11,9 +12,11 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class ItemNameModifier<I> implements SimpleNetworkItemDataModifier<I> {
|
||||
public static final Factory<?> FACTORY = new Factory<>();
|
||||
private final String argument;
|
||||
private final FormattedLine line;
|
||||
|
||||
public ItemNameModifier(String argument) {
|
||||
this.argument = argument;
|
||||
this.line = FormattedLine.create(argument);
|
||||
}
|
||||
|
||||
public String itemName() {
|
||||
@@ -27,7 +30,7 @@ public class ItemNameModifier<I> implements SimpleNetworkItemDataModifier<I> {
|
||||
|
||||
@Override
|
||||
public Item<I> apply(Item<I> item, ItemBuildContext context) {
|
||||
item.itemNameComponent(AdventureHelper.miniMessage().deserialize(this.argument, context.tagResolvers()));
|
||||
item.itemNameComponent(this.line.parse(context));
|
||||
return item;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,28 +2,28 @@ package net.momirealms.craftengine.core.item.modifier.lore;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.plugin.text.minimessage.FormattedLine;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import net.momirealms.craftengine.core.util.TriFunction;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
// todo 可以考虑未来添加条件系统
|
||||
public record LoreModification(Operation operation, boolean split, String[] content) {
|
||||
public record LoreModification(Operation operation, boolean split, FormattedLine[] content) {
|
||||
|
||||
public Stream<Component> apply(Stream<Component> lore, ItemBuildContext context) {
|
||||
return this.operation.function.apply(lore, context, this);
|
||||
}
|
||||
|
||||
public Stream<Component> parseAsStream(ItemBuildContext context) {
|
||||
Stream<Component> parsed = Arrays.stream(this.content).map(string -> AdventureHelper.miniMessage().deserialize(string, context.tagResolvers()));
|
||||
Stream<Component> parsed = Arrays.stream(this.content).map(line -> line.parse(context));
|
||||
return this.split ? parsed.map(AdventureHelper::splitLines).flatMap(List::stream) : parsed;
|
||||
}
|
||||
|
||||
public List<Component> parseAsList(ItemBuildContext context) {
|
||||
return this.parseAsStream(context).collect(Collectors.toList());
|
||||
return this.parseAsStream(context).toList();
|
||||
}
|
||||
|
||||
public enum Operation {
|
||||
|
||||
@@ -8,6 +8,8 @@ import net.momirealms.craftengine.core.item.ItemDataModifierFactory;
|
||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifier;
|
||||
import net.momirealms.craftengine.core.item.modifier.ItemDataModifiers;
|
||||
import net.momirealms.craftengine.core.item.modifier.SimpleNetworkItemDataModifier;
|
||||
import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.plugin.text.minimessage.FormattedLine;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||
@@ -63,7 +65,9 @@ public sealed interface LoreModifier<I> extends SimpleNetworkItemDataModifier<I>
|
||||
rawLore[i] = o.toString();
|
||||
}
|
||||
}
|
||||
return new SingleLoreModifier<>(new LoreModification(LoreModification.Operation.APPEND, false, rawLore));
|
||||
return new SingleLoreModifier<>(new LoreModification(LoreModification.Operation.APPEND, false,
|
||||
Arrays.stream(rawLore).map(line -> Config.addNonItalicTag() ? FormattedLine.create("<!i>" + line) : FormattedLine.create(line))
|
||||
.toArray(FormattedLine[]::new)));
|
||||
}
|
||||
|
||||
List<LoreModificationHolder> modifications = new ArrayList<>(rawLoreData.size() + 1);
|
||||
@@ -74,7 +78,9 @@ public sealed interface LoreModifier<I> extends SimpleNetworkItemDataModifier<I>
|
||||
LoreModification.Operation operation = ResourceConfigUtils.getAsEnum(Optional.ofNullable(complexLore.get("operation")).map(String::valueOf).orElse(null), LoreModification.Operation.class, LoreModification.Operation.APPEND);
|
||||
lastPriority = Optional.ofNullable(complexLore.get("priority")).map(it -> ResourceConfigUtils.getAsInt(it, "priority")).orElse(lastPriority);
|
||||
boolean split = ResourceConfigUtils.getAsBoolean(complexLore.get("split-lines"), "split-lines");
|
||||
modifications.add(new LoreModificationHolder(new LoreModification(operation, split, content), lastPriority));
|
||||
modifications.add(new LoreModificationHolder(new LoreModification(operation, split,
|
||||
Arrays.stream(content).map(line -> Config.addNonItalicTag() ? FormattedLine.create("<!i>" + line) : FormattedLine.create(line))
|
||||
.toArray(FormattedLine[]::new)), lastPriority));
|
||||
}
|
||||
}
|
||||
modifications.sort(LoreModificationHolder::compareTo);
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package net.momirealms.craftengine.core.plugin.text.minimessage;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.minimessage.Context;
|
||||
import net.kyori.adventure.text.minimessage.ParsingException;
|
||||
import net.kyori.adventure.text.minimessage.tag.Tag;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.ArgumentQueue;
|
||||
import net.kyori.adventure.text.minimessage.tag.resolver.TagResolver;
|
||||
import net.momirealms.craftengine.core.util.AdventureHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface FormattedLine {
|
||||
TagResolver[] CUSTOM_RESOLVERS = new TagResolver[]{
|
||||
createDummyResolvers("expr"),
|
||||
createDummyResolvers("image"),
|
||||
createDummyResolvers("arg"),
|
||||
createDummyResolvers("shift"),
|
||||
createDummyResolvers("i18n"),
|
||||
createDummyResolvers("global"),
|
||||
createDummyResolvers("papi"),
|
||||
createDummyResolvers("rel_papi")
|
||||
};
|
||||
|
||||
Component parse(net.momirealms.craftengine.core.plugin.context.Context context);
|
||||
|
||||
private static TagResolver createDummyResolvers(String tag) {
|
||||
return new TagResolver() {
|
||||
@Override
|
||||
public boolean has(@NotNull String name) {
|
||||
return tag.equals(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Tag resolve(@NotNull String name, @NotNull ArgumentQueue arguments, @NotNull Context ctx) throws ParsingException {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static FormattedLine create(String line) {
|
||||
if (line.equals(AdventureHelper.customMiniMessage().stripTags(line, CUSTOM_RESOLVERS))) {
|
||||
return new PreParsedLine(AdventureHelper.miniMessage().deserialize(line));
|
||||
} else {
|
||||
return new DynamicLine(line);
|
||||
}
|
||||
}
|
||||
|
||||
class PreParsedLine implements FormattedLine {
|
||||
private final Component parsed;
|
||||
|
||||
public PreParsedLine(Component parsed) {
|
||||
this.parsed = parsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component parse(net.momirealms.craftengine.core.plugin.context.Context context) {
|
||||
return this.parsed;
|
||||
}
|
||||
}
|
||||
|
||||
class DynamicLine implements FormattedLine {
|
||||
private final String content;
|
||||
|
||||
public DynamicLine(String content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component parse(net.momirealms.craftengine.core.plugin.context.Context context) {
|
||||
return AdventureHelper.miniMessage().deserialize(this.content, context.tagResolvers());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user