mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-19 15:09:15 +00:00
支持参数默认值嵌套
This commit is contained in:
@@ -114,7 +114,7 @@ public abstract class CraftEngine implements Plugin {
|
|||||||
LegacyRecipeTypes.init();
|
LegacyRecipeTypes.init();
|
||||||
|
|
||||||
// 初始化模板管理器
|
// 初始化模板管理器
|
||||||
this.templateManager = new TemplateManagerImpl();
|
this.templateManager = TemplateManager.INSTANCE;
|
||||||
// 初始化全局变量管理器
|
// 初始化全局变量管理器
|
||||||
this.globalVariableManager = new GlobalVariableManager();
|
this.globalVariableManager = new GlobalVariableManager();
|
||||||
// 初始化物品浏览器
|
// 初始化物品浏览器
|
||||||
|
|||||||
@@ -0,0 +1,303 @@
|
|||||||
|
package net.momirealms.craftengine.core.plugin.config.template;
|
||||||
|
|
||||||
|
import net.momirealms.craftengine.core.plugin.config.template.argument.TemplateArgument;
|
||||||
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
|
import net.momirealms.craftengine.core.util.SNBTReader;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface ArgumentString {
|
||||||
|
String rawValue();
|
||||||
|
|
||||||
|
Object get(Map<String, TemplateArgument> arguments);
|
||||||
|
|
||||||
|
final class Literal implements ArgumentString {
|
||||||
|
private final String value;
|
||||||
|
|
||||||
|
public Literal(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Literal literal(String value) {
|
||||||
|
return new Literal(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String rawValue() {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(Map<String, TemplateArgument> arguments) {
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof Literal literal)) return false;
|
||||||
|
return this.value.equals(literal.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.value.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Literal(" + this.value + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Placeholder implements ArgumentString {
|
||||||
|
private final String placeholder;
|
||||||
|
private final String rawText;
|
||||||
|
private final Object defaultValue;
|
||||||
|
private final boolean hasDefaultValue;
|
||||||
|
|
||||||
|
public Placeholder(String placeholderContent) {
|
||||||
|
this.rawText = "${" + placeholderContent + "}";
|
||||||
|
int separatorIndex = placeholderContent.indexOf(":-");
|
||||||
|
if (separatorIndex == -1) {
|
||||||
|
this.placeholder = placeholderContent;
|
||||||
|
this.defaultValue = null;
|
||||||
|
this.hasDefaultValue = false;
|
||||||
|
} else {
|
||||||
|
this.placeholder = placeholderContent.substring(0, separatorIndex);
|
||||||
|
String defaultValueString = placeholderContent.substring(separatorIndex + 2);
|
||||||
|
try {
|
||||||
|
this.defaultValue = ((TemplateManagerImpl) TemplateManager.INSTANCE).preprocessUnknownValue(new SNBTReader(defaultValueString).deserializeAsJava());
|
||||||
|
} catch (LocalizedResourceConfigException e) {
|
||||||
|
e.appendTailArgument(this.placeholder);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
this.hasDefaultValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Placeholder placeholder(String placeholder) {
|
||||||
|
return new Placeholder(placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(Map<String, TemplateArgument> arguments) {
|
||||||
|
TemplateArgument replacement = arguments.get(this.placeholder);
|
||||||
|
if (replacement != null) {
|
||||||
|
return replacement.get(arguments);
|
||||||
|
}
|
||||||
|
if (this.hasDefaultValue) {
|
||||||
|
if (this.defaultValue == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return ((TemplateManagerImpl) TemplateManager.INSTANCE).processUnknownValue(this.defaultValue, arguments);
|
||||||
|
}
|
||||||
|
throw new LocalizedResourceConfigException("warning.config.template.argument.missing_value", this.rawText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String rawValue() {
|
||||||
|
return this.rawText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof Placeholder that)) return false;
|
||||||
|
return this.placeholder.equals(that.placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.placeholder.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Placeholder(" + this.placeholder + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Complex2 implements ArgumentString {
|
||||||
|
private final String rawText;
|
||||||
|
private final ArgumentString arg1;
|
||||||
|
private final ArgumentString arg2;
|
||||||
|
|
||||||
|
public Complex2(String rawText, ArgumentString arg1, ArgumentString arg2) {
|
||||||
|
this.arg1 = arg1;
|
||||||
|
this.arg2 = arg2;
|
||||||
|
this.rawText = rawText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(Map<String, TemplateArgument> arguments) {
|
||||||
|
Object arg1 = this.arg1.get(arguments);
|
||||||
|
Object arg2 = this.arg2.get(arguments);
|
||||||
|
if (arg1 == null && arg2 == null) return null;
|
||||||
|
if (arg1 == null) return String.valueOf(arg2);
|
||||||
|
if (arg2 == null) return String.valueOf(arg1);
|
||||||
|
return String.valueOf(arg1) + arg2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String rawValue() {
|
||||||
|
return this.rawText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof Complex that)) return false;
|
||||||
|
return this.rawText.equals(that.rawText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.rawText.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Complex2(" + this.rawText + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class Complex implements ArgumentString {
|
||||||
|
private final List<ArgumentString> parts;
|
||||||
|
private final String rawText;
|
||||||
|
|
||||||
|
public Complex(String rawText, List<ArgumentString> parts) {
|
||||||
|
this.parts = parts;
|
||||||
|
this.rawText = rawText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object get(Map<String, TemplateArgument> arguments) {
|
||||||
|
StringBuilder result = new StringBuilder();
|
||||||
|
boolean hasValue = false;
|
||||||
|
for (ArgumentString part : this.parts) {
|
||||||
|
Object arg = part.get(arguments);
|
||||||
|
if (arg != null) {
|
||||||
|
result.append(arg);
|
||||||
|
hasValue = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasValue) return null;
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String rawValue() {
|
||||||
|
return this.rawText;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof Complex that)) return false;
|
||||||
|
return this.rawText.equals(that.rawText);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.rawText.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Complex(" + this.rawText + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static ArgumentString preParse(String input) {
|
||||||
|
if (input == null || input.isEmpty()) {
|
||||||
|
return Literal.literal("");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ArgumentString> arguments = new ArrayList<>();
|
||||||
|
StringBuilder currentLiteral = new StringBuilder();
|
||||||
|
final int n = input.length();
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
while (i < n) {
|
||||||
|
char c = input.charAt(i);
|
||||||
|
|
||||||
|
// --- 1. 优先检测占位符触发器 ---
|
||||||
|
if (c == '$' && i + 1 < n && input.charAt(i + 1) == '{') {
|
||||||
|
|
||||||
|
// a. 提交之前的普通文本
|
||||||
|
if (!currentLiteral.isEmpty()) {
|
||||||
|
arguments.add(Literal.literal(currentLiteral.toString()));
|
||||||
|
currentLiteral.setLength(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// b. 解析占位符内部,此处的逻辑拥有自己的转义规则
|
||||||
|
int contentStartIndex = i + 2;
|
||||||
|
StringBuilder keyBuilder = new StringBuilder();
|
||||||
|
int depth = 1;
|
||||||
|
int j = contentStartIndex;
|
||||||
|
boolean foundMatch = false;
|
||||||
|
|
||||||
|
while (j < n) {
|
||||||
|
char innerChar = input.charAt(j);
|
||||||
|
|
||||||
|
// --- 占位符内部的转义逻辑 ---
|
||||||
|
if (innerChar == '\\') {
|
||||||
|
if (j + 1 < n && (input.charAt(j + 1) == '{' || input.charAt(j + 1) == '}')) {
|
||||||
|
keyBuilder.append(input.charAt(j + 1));
|
||||||
|
j += 2;
|
||||||
|
} else {
|
||||||
|
// 在占位符内部,一个无法识别的转义\依旧被当作普通\处理
|
||||||
|
keyBuilder.append(innerChar);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
} else if (innerChar == '{') {
|
||||||
|
depth++;
|
||||||
|
keyBuilder.append(innerChar);
|
||||||
|
j++;
|
||||||
|
} else if (innerChar == '}') {
|
||||||
|
depth--;
|
||||||
|
if (depth == 0) { // 找到匹配的闭合括号
|
||||||
|
arguments.add(Placeholder.placeholder(keyBuilder.toString()));
|
||||||
|
i = j + 1;
|
||||||
|
foundMatch = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
keyBuilder.append(innerChar);
|
||||||
|
j++;
|
||||||
|
} else {
|
||||||
|
keyBuilder.append(innerChar);
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (foundMatch) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// 未找到闭合括号,将 '$' 视为普通字符
|
||||||
|
currentLiteral.append(c);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// --- 2. 其次,只处理对触发器'$'的转义 ---
|
||||||
|
else if (c == '\\' && i + 1 < n && input.charAt(i + 1) == '$') {
|
||||||
|
currentLiteral.append('$'); // 直接添加 '$'
|
||||||
|
i += 2; // 跳过 '\' 和 '$'
|
||||||
|
}
|
||||||
|
// --- 3. 处理所有其他字符(包括独立的'\'和'{')为普通文本 ---
|
||||||
|
else {
|
||||||
|
currentLiteral.append(c);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!currentLiteral.isEmpty()) {
|
||||||
|
arguments.add(Literal.literal(currentLiteral.toString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return switch (arguments.size()) {
|
||||||
|
case 0 -> Literal.literal("");
|
||||||
|
case 1 -> arguments.getFirst();
|
||||||
|
case 2 -> new Complex2(input, arguments.get(0), arguments.get(1));
|
||||||
|
default -> new Complex(input, arguments);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package net.momirealms.craftengine.core.plugin.config.template;
|
|||||||
|
|
||||||
import net.momirealms.craftengine.core.plugin.Manageable;
|
import net.momirealms.craftengine.core.plugin.Manageable;
|
||||||
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
||||||
|
import net.momirealms.craftengine.core.plugin.config.template.argument.TemplateArgument;
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.SNBTReader;
|
import net.momirealms.craftengine.core.util.SNBTReader;
|
||||||
@@ -12,299 +13,9 @@ import java.util.Map;
|
|||||||
|
|
||||||
public interface TemplateManager extends Manageable {
|
public interface TemplateManager extends Manageable {
|
||||||
|
|
||||||
|
TemplateManager INSTANCE = new TemplateManagerImpl();
|
||||||
|
|
||||||
ConfigParser parser();
|
ConfigParser parser();
|
||||||
|
|
||||||
Object applyTemplates(Key id, Object input);
|
Object applyTemplates(Key id, Object input);
|
||||||
|
|
||||||
interface ArgumentString {
|
|
||||||
|
|
||||||
String rawValue();
|
|
||||||
|
|
||||||
Object get(Map<String, TemplateArgument> arguments);
|
|
||||||
}
|
|
||||||
|
|
||||||
final class Literal implements ArgumentString {
|
|
||||||
private final String value;
|
|
||||||
|
|
||||||
public Literal(String value) {
|
|
||||||
this.value = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Literal literal(String value) {
|
|
||||||
return new Literal(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String rawValue() {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object get(Map<String, TemplateArgument> arguments) {
|
|
||||||
return this.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof Literal literal)) return false;
|
|
||||||
return this.value.equals(literal.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.value.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Literal(" + this.value + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class Placeholder implements ArgumentString {
|
|
||||||
private final String placeholder;
|
|
||||||
private final String rawText;
|
|
||||||
private final Object defaultValue;
|
|
||||||
private final boolean hasDefaultValue;
|
|
||||||
|
|
||||||
public Placeholder(String placeholderContent) {
|
|
||||||
this.rawText = "${" + placeholderContent + "}";
|
|
||||||
int separatorIndex = placeholderContent.indexOf(":-");
|
|
||||||
if (separatorIndex == -1) {
|
|
||||||
this.placeholder = placeholderContent;
|
|
||||||
this.defaultValue = null;
|
|
||||||
this.hasDefaultValue = false;
|
|
||||||
} else {
|
|
||||||
this.placeholder = placeholderContent.substring(0, separatorIndex);
|
|
||||||
String defaultValueString = placeholderContent.substring(separatorIndex + 2);
|
|
||||||
try {
|
|
||||||
this.defaultValue = new SNBTReader(defaultValueString).deserializeAsJava();
|
|
||||||
} catch (LocalizedResourceConfigException e) {
|
|
||||||
e.appendTailArgument(this.placeholder);
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
this.hasDefaultValue = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Placeholder placeholder(String placeholder) {
|
|
||||||
return new Placeholder(placeholder);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object get(Map<String, TemplateArgument> arguments) {
|
|
||||||
TemplateArgument replacement = arguments.get(this.placeholder);
|
|
||||||
if (replacement != null) {
|
|
||||||
return replacement.get(arguments);
|
|
||||||
}
|
|
||||||
if (this.hasDefaultValue) {
|
|
||||||
return this.defaultValue;
|
|
||||||
}
|
|
||||||
throw new LocalizedResourceConfigException("warning.config.template.argument.missing_value", this.rawText);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String rawValue() {
|
|
||||||
return this.rawText;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof Placeholder that)) return false;
|
|
||||||
return this.placeholder.equals(that.placeholder);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.placeholder.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Placeholder(" + this.placeholder + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class Complex2 implements ArgumentString {
|
|
||||||
private final String rawText;
|
|
||||||
private final ArgumentString arg1;
|
|
||||||
private final ArgumentString arg2;
|
|
||||||
|
|
||||||
public Complex2(String rawText, ArgumentString arg1, ArgumentString arg2) {
|
|
||||||
this.arg1 = arg1;
|
|
||||||
this.arg2 = arg2;
|
|
||||||
this.rawText = rawText;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object get(Map<String, TemplateArgument> arguments) {
|
|
||||||
Object arg1 = this.arg1.get(arguments);
|
|
||||||
Object arg2 = this.arg2.get(arguments);
|
|
||||||
if (arg1 == null && arg2 == null) return null;
|
|
||||||
if (arg1 == null) return String.valueOf(arg2);
|
|
||||||
if (arg2 == null) return String.valueOf(arg1);
|
|
||||||
return String.valueOf(arg1) + arg2;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String rawValue() {
|
|
||||||
return this.rawText;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof Complex that)) return false;
|
|
||||||
return this.rawText.equals(that.rawText);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.rawText.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Complex2(" + this.rawText + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final class Complex implements ArgumentString {
|
|
||||||
private final List<ArgumentString> parts;
|
|
||||||
private final String rawText;
|
|
||||||
|
|
||||||
public Complex(String rawText, List<ArgumentString> parts) {
|
|
||||||
this.parts = parts;
|
|
||||||
this.rawText = rawText;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object get(Map<String, TemplateArgument> arguments) {
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
boolean hasValue = false;
|
|
||||||
for (ArgumentString part : this.parts) {
|
|
||||||
Object arg = part.get(arguments);
|
|
||||||
if (arg != null) {
|
|
||||||
result.append(arg);
|
|
||||||
hasValue = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!hasValue) return null;
|
|
||||||
return result.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String rawValue() {
|
|
||||||
return this.rawText;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (!(o instanceof Complex that)) return false;
|
|
||||||
return this.rawText.equals(that.rawText);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return this.rawText.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "Complex(" + this.rawText + ")";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static ArgumentString preParse(String input) {
|
|
||||||
if (input == null || input.isEmpty()) {
|
|
||||||
return Literal.literal("");
|
|
||||||
}
|
|
||||||
|
|
||||||
List<ArgumentString> arguments = new ArrayList<>();
|
|
||||||
StringBuilder currentLiteral = new StringBuilder();
|
|
||||||
final int n = input.length();
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
while (i < n) {
|
|
||||||
char c = input.charAt(i);
|
|
||||||
|
|
||||||
// --- 1. 优先检测占位符触发器 ---
|
|
||||||
if (c == '$' && i + 1 < n && input.charAt(i + 1) == '{') {
|
|
||||||
|
|
||||||
// a. 提交之前的普通文本
|
|
||||||
if (!currentLiteral.isEmpty()) {
|
|
||||||
arguments.add(Literal.literal(currentLiteral.toString()));
|
|
||||||
currentLiteral.setLength(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// b. 解析占位符内部,此处的逻辑拥有自己的转义规则
|
|
||||||
int contentStartIndex = i + 2;
|
|
||||||
StringBuilder keyBuilder = new StringBuilder();
|
|
||||||
int depth = 1;
|
|
||||||
int j = contentStartIndex;
|
|
||||||
boolean foundMatch = false;
|
|
||||||
|
|
||||||
while (j < n) {
|
|
||||||
char innerChar = input.charAt(j);
|
|
||||||
|
|
||||||
// --- 占位符内部的转义逻辑 ---
|
|
||||||
if (innerChar == '\\') {
|
|
||||||
if (j + 1 < n && (input.charAt(j + 1) == '{' || input.charAt(j + 1) == '}')) {
|
|
||||||
keyBuilder.append(input.charAt(j + 1));
|
|
||||||
j += 2;
|
|
||||||
} else {
|
|
||||||
// 在占位符内部,一个无法识别的转义\依旧被当作普通\处理
|
|
||||||
keyBuilder.append(innerChar);
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
} else if (innerChar == '{') {
|
|
||||||
depth++;
|
|
||||||
keyBuilder.append(innerChar);
|
|
||||||
j++;
|
|
||||||
} else if (innerChar == '}') {
|
|
||||||
depth--;
|
|
||||||
if (depth == 0) { // 找到匹配的闭合括号
|
|
||||||
arguments.add(Placeholder.placeholder(keyBuilder.toString()));
|
|
||||||
i = j + 1;
|
|
||||||
foundMatch = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
keyBuilder.append(innerChar);
|
|
||||||
j++;
|
|
||||||
} else {
|
|
||||||
keyBuilder.append(innerChar);
|
|
||||||
j++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (foundMatch) {
|
|
||||||
continue;
|
|
||||||
} else {
|
|
||||||
// 未找到闭合括号,将 '$' 视为普通字符
|
|
||||||
currentLiteral.append(c);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// --- 2. 其次,只处理对触发器'$'的转义 ---
|
|
||||||
else if (c == '\\' && i + 1 < n && input.charAt(i + 1) == '$') {
|
|
||||||
currentLiteral.append('$'); // 直接添加 '$'
|
|
||||||
i += 2; // 跳过 '\' 和 '$'
|
|
||||||
}
|
|
||||||
// --- 3. 处理所有其他字符(包括独立的'\'和'{')为普通文本 ---
|
|
||||||
else {
|
|
||||||
currentLiteral.append(c);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!currentLiteral.isEmpty()) {
|
|
||||||
arguments.add(Literal.literal(currentLiteral.toString()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return switch (arguments.size()) {
|
|
||||||
case 0 -> Literal.literal("");
|
|
||||||
case 1 -> arguments.getFirst();
|
|
||||||
case 2 -> new Complex2(input, arguments.get(0), arguments.get(1));
|
|
||||||
default -> new Complex(input, arguments);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.pack.LoadingSequence;
|
|||||||
import net.momirealms.craftengine.core.pack.Pack;
|
import net.momirealms.craftengine.core.pack.Pack;
|
||||||
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
import net.momirealms.craftengine.core.plugin.config.ConfigParser;
|
||||||
import net.momirealms.craftengine.core.plugin.config.IdObjectConfigParser;
|
import net.momirealms.craftengine.core.plugin.config.IdObjectConfigParser;
|
||||||
|
import net.momirealms.craftengine.core.plugin.config.template.argument.*;
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||||
@@ -14,16 +15,16 @@ import java.util.*;
|
|||||||
|
|
||||||
@SuppressWarnings("DuplicatedCode")
|
@SuppressWarnings("DuplicatedCode")
|
||||||
public class TemplateManagerImpl implements TemplateManager {
|
public class TemplateManagerImpl implements TemplateManager {
|
||||||
private static final ArgumentString TEMPLATE = Literal.literal("template");
|
private static final ArgumentString TEMPLATE = ArgumentString.Literal.literal("template");
|
||||||
private static final ArgumentString OVERRIDES = Literal.literal("overrides");
|
private static final ArgumentString OVERRIDES = ArgumentString.Literal.literal("overrides");
|
||||||
private static final ArgumentString ARGUMENTS = Literal.literal("arguments");
|
private static final ArgumentString ARGUMENTS = ArgumentString.Literal.literal("arguments");
|
||||||
private static final ArgumentString MERGES = Literal.literal("merges");
|
private static final ArgumentString MERGES = ArgumentString.Literal.literal("merges");
|
||||||
private final static Set<ArgumentString> NON_TEMPLATE_ARGUMENTS = new HashSet<>(Set.of(TEMPLATE, ARGUMENTS, OVERRIDES, MERGES));
|
private final static Set<ArgumentString> NON_TEMPLATE_ARGUMENTS = new HashSet<>(Set.of(TEMPLATE, ARGUMENTS, OVERRIDES, MERGES));
|
||||||
|
|
||||||
private final Map<Key, Object> templates = new HashMap<>();
|
private final Map<Key, Object> templates = new HashMap<>();
|
||||||
private final TemplateParser templateParser;
|
private final TemplateParser templateParser;
|
||||||
|
|
||||||
public TemplateManagerImpl() {
|
protected TemplateManagerImpl() {
|
||||||
this.templateParser = new TemplateParser();
|
this.templateParser = new TemplateParser();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,13 +70,13 @@ public class TemplateManagerImpl implements TemplateManager {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object preprocessUnknownValue(Object value) {
|
public Object preprocessUnknownValue(Object value) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case Map<?, ?> map -> {
|
case Map<?, ?> map -> {
|
||||||
Map<String, Object> in = MiscUtils.castToMap(map, false);
|
Map<String, Object> in = MiscUtils.castToMap(map, false);
|
||||||
Map<ArgumentString, Object> out = new LinkedHashMap<>(map.size());
|
Map<ArgumentString, Object> out = new LinkedHashMap<>(map.size());
|
||||||
for (Map.Entry<String, Object> entry : in.entrySet()) {
|
for (Map.Entry<String, Object> entry : in.entrySet()) {
|
||||||
out.put(TemplateManager.preParse(entry.getKey()), preprocessUnknownValue(entry.getValue()));
|
out.put(ArgumentString.preParse(entry.getKey()), preprocessUnknownValue(entry.getValue()));
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
@@ -87,7 +88,7 @@ public class TemplateManagerImpl implements TemplateManager {
|
|||||||
return objList;
|
return objList;
|
||||||
}
|
}
|
||||||
case String string -> {
|
case String string -> {
|
||||||
return TemplateManager.preParse(string);
|
return ArgumentString.preParse(string);
|
||||||
}
|
}
|
||||||
case null, default -> {
|
case null, default -> {
|
||||||
return value;
|
return value;
|
||||||
@@ -188,8 +189,8 @@ public class TemplateManagerImpl implements TemplateManager {
|
|||||||
|
|
||||||
// 处理一个类型未知的值,本方法只管将member处理好后,传递回调用者a
|
// 处理一个类型未知的值,本方法只管将member处理好后,传递回调用者a
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Object processUnknownValue(Object value,
|
public Object processUnknownValue(Object value,
|
||||||
Map<String, TemplateArgument> arguments) {
|
Map<String, TemplateArgument> arguments) {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case Map<?, ?> innerMap ->
|
case Map<?, ?> innerMap ->
|
||||||
// map下面还是个map吗?这并不一定
|
// map下面还是个map吗?这并不一定
|
||||||
@@ -237,7 +238,7 @@ public class TemplateManagerImpl implements TemplateManager {
|
|||||||
// 如果模板id被用了参数,则应先应用参数后再查询模板
|
// 如果模板id被用了参数,则应先应用参数后再查询模板
|
||||||
Object actualTemplate = templateId.get(parentArguments);
|
Object actualTemplate = templateId.get(parentArguments);
|
||||||
if (actualTemplate == null) continue; // 忽略被null掉的模板
|
if (actualTemplate == null) continue; // 忽略被null掉的模板
|
||||||
Object template = Optional.ofNullable(this.templates.get(Key.of(actualTemplate.toString())))
|
Object template = Optional.ofNullable(((TemplateManagerImpl) INSTANCE).templates.get(Key.of(actualTemplate.toString())))
|
||||||
.orElseThrow(() -> new LocalizedResourceConfigException("warning.config.template.invalid", actualTemplate.toString()));
|
.orElseThrow(() -> new LocalizedResourceConfigException("warning.config.template.invalid", actualTemplate.toString()));
|
||||||
Object processedTemplate = processUnknownValue(template, arguments);
|
Object processedTemplate = processUnknownValue(template, arguments);
|
||||||
if (processedTemplate != null) templateList.add(processedTemplate);
|
if (processedTemplate != null) templateList.add(processedTemplate);
|
||||||
@@ -294,7 +295,7 @@ public class TemplateManagerImpl implements TemplateManager {
|
|||||||
// 合并参数
|
// 合并参数
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private Map<String, TemplateArgument> mergeArguments(@NotNull Map<ArgumentString, Object> childArguments,
|
private Map<String, TemplateArgument> mergeArguments(@NotNull Map<ArgumentString, Object> childArguments,
|
||||||
@NotNull Map<String, TemplateArgument> parentArguments) {
|
@NotNull Map<String, TemplateArgument> parentArguments) {
|
||||||
Map<String, TemplateArgument> result = new LinkedHashMap<>(parentArguments);
|
Map<String, TemplateArgument> result = new LinkedHashMap<>(parentArguments);
|
||||||
for (Map.Entry<ArgumentString, Object> argumentEntry : childArguments.entrySet()) {
|
for (Map.Entry<ArgumentString, Object> argumentEntry : childArguments.entrySet()) {
|
||||||
Object placeholderObj = argumentEntry.getKey().get(result);
|
Object placeholderObj = argumentEntry.getKey().get(result);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import com.ezylang.evalex.Expression;
|
import com.ezylang.evalex.Expression;
|
||||||
import com.ezylang.evalex.data.EvaluationValue;
|
import com.ezylang.evalex.data.EvaluationValue;
|
||||||
|
import net.momirealms.craftengine.core.plugin.config.template.ArgumentString;
|
||||||
|
import net.momirealms.craftengine.core.plugin.config.template.TemplateManager;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -11,11 +13,11 @@ import java.util.function.Function;
|
|||||||
|
|
||||||
public class ExpressionTemplateArgument implements TemplateArgument {
|
public class ExpressionTemplateArgument implements TemplateArgument {
|
||||||
public static final Factory FACTORY = new Factory();
|
public static final Factory FACTORY = new Factory();
|
||||||
private final TemplateManager.ArgumentString expression;
|
private final ArgumentString expression;
|
||||||
private final ValueType valueType;
|
private final ValueType valueType;
|
||||||
|
|
||||||
protected ExpressionTemplateArgument(String expression, ValueType valueType) {
|
protected ExpressionTemplateArgument(String expression, ValueType valueType) {
|
||||||
this.expression = TemplateManager.preParse(expression);
|
this.expression = ArgumentString.preParse(expression);
|
||||||
this.valueType = valueType;
|
this.valueType = valueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.MiscUtils;
|
import net.momirealms.craftengine.core.util.MiscUtils;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
import net.momirealms.craftengine.core.registry.BuiltInRegistries;
|
||||||
import net.momirealms.craftengine.core.registry.Registries;
|
import net.momirealms.craftengine.core.registry.Registries;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
|
import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
import net.momirealms.craftengine.core.plugin.locale.LocalizedResourceConfigException;
|
||||||
import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
|
import net.momirealms.craftengine.core.plugin.locale.TranslationManager;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package net.momirealms.craftengine.core.plugin.config.template;
|
package net.momirealms.craftengine.core.plugin.config.template.argument;
|
||||||
|
|
||||||
import net.momirealms.craftengine.core.util.Key;
|
import net.momirealms.craftengine.core.util.Key;
|
||||||
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
import net.momirealms.craftengine.core.util.ResourceConfigUtils;
|
||||||
@@ -37,7 +37,7 @@ import net.momirealms.craftengine.core.pack.model.special.SpecialModelFactory;
|
|||||||
import net.momirealms.craftengine.core.pack.model.special.SpecialModelReader;
|
import net.momirealms.craftengine.core.pack.model.special.SpecialModelReader;
|
||||||
import net.momirealms.craftengine.core.pack.model.tint.TintFactory;
|
import net.momirealms.craftengine.core.pack.model.tint.TintFactory;
|
||||||
import net.momirealms.craftengine.core.pack.model.tint.TintReader;
|
import net.momirealms.craftengine.core.pack.model.tint.TintReader;
|
||||||
import net.momirealms.craftengine.core.plugin.config.template.TemplateArgumentFactory;
|
import net.momirealms.craftengine.core.plugin.config.template.argument.TemplateArgumentFactory;
|
||||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||||
import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory;
|
import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory;
|
||||||
import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory;
|
import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ import net.momirealms.craftengine.core.pack.model.special.SpecialModelFactory;
|
|||||||
import net.momirealms.craftengine.core.pack.model.special.SpecialModelReader;
|
import net.momirealms.craftengine.core.pack.model.special.SpecialModelReader;
|
||||||
import net.momirealms.craftengine.core.pack.model.tint.TintFactory;
|
import net.momirealms.craftengine.core.pack.model.tint.TintFactory;
|
||||||
import net.momirealms.craftengine.core.pack.model.tint.TintReader;
|
import net.momirealms.craftengine.core.pack.model.tint.TintReader;
|
||||||
import net.momirealms.craftengine.core.plugin.config.template.TemplateArgumentFactory;
|
import net.momirealms.craftengine.core.plugin.config.template.argument.TemplateArgumentFactory;
|
||||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||||
import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory;
|
import net.momirealms.craftengine.core.plugin.context.condition.ConditionFactory;
|
||||||
import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory;
|
import net.momirealms.craftengine.core.plugin.context.function.FunctionFactory;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
org.gradle.jvmargs=-Xmx1G
|
org.gradle.jvmargs=-Xmx1G
|
||||||
|
|
||||||
# Project settings
|
# Project settings
|
||||||
project_version=0.0.65.13
|
project_version=0.0.65.13.1
|
||||||
config_version=58
|
config_version=58
|
||||||
lang_version=40
|
lang_version=40
|
||||||
project_group=net.momirealms
|
project_group=net.momirealms
|
||||||
|
|||||||
Reference in New Issue
Block a user