diff --git a/src/main/java/dev/anvilcraft/rg/api/ConfigUtil.java b/src/main/java/dev/anvilcraft/rg/api/ConfigUtil.java index 5055e48..e4259b2 100644 --- a/src/main/java/dev/anvilcraft/rg/api/ConfigUtil.java +++ b/src/main/java/dev/anvilcraft/rg/api/ConfigUtil.java @@ -10,26 +10,51 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Path; +/** + * ConfigUtil类提供文件操作实用程序,包括读取和写入JSON配置文件 + */ public class ConfigUtil { + + /** + * 从指定的文件路径检索JSON对象内容。如果文件不存在或是目录, + * 它创建一个包含空JSON对象内容的新文件,并返回一个空JsonObject + * + * @param path 文件路径,不得为空 + * @return 返回从文件读取的JSON对象,如果文件不存在,则返回一个新的空JsonObject + * @throws RGRuleException 如果读取文件失败,则抛出异常并说明原因 + */ public static @NotNull JsonObject getOrCreateContent(@NotNull Path path) { File file = path.toFile(); try { if (!file.exists() || file.isDirectory()) { + // 将空JSON对象写入不存在的或目录文件 FileUtils.writeStringToFile(file, "{}", StandardCharsets.UTF_8); return new JsonObject(); } + // 读取文件内容并将其解析为JsonObject String value = FileUtils.readFileToString(path.toFile(), StandardCharsets.UTF_8); return GsonHelper.parse(value); } catch (IOException e) { + // 如果读取文件失败,则抛出自定义异常 throw new RGRuleException("Failed to read rolling gate config file", e); } } + /** + * 将内容写入指定的文件路径 + * + * @param path 文件路径,不得为空 + * @param content 要写入的内容,不能为空 + * @throws RGRuleException 如果写入文件失败,则抛出异常并说明原因 + */ public static void writeContent(@NotNull Path path, @NotNull String content) { try { + // 将指定内容写入文件 FileUtils.writeStringToFile(path.toFile(), content, StandardCharsets.UTF_8); } catch (IOException e) { + // 如果写入文件失败,则抛出自定义异常 throw new RGRuleException("Failed to write rolling gate config file", e); } } } + diff --git a/src/main/java/dev/anvilcraft/rg/api/RGAdditional.java b/src/main/java/dev/anvilcraft/rg/api/RGAdditional.java index 945ef21..bf4bc89 100644 --- a/src/main/java/dev/anvilcraft/rg/api/RGAdditional.java +++ b/src/main/java/dev/anvilcraft/rg/api/RGAdditional.java @@ -4,10 +4,29 @@ import dev.anvilcraft.rg.api.server.ServerRGRuleManager; import net.neoforged.fml.IExtensionPoint; +/** + * RGAdditional接口扩展了IExtensionPoint接口,旨在提供一个扩展点, + * 用于在服务器和客户端加载特定规则。这个接口允许实现类 + * 在需要时自定义规则加载逻辑 + */ public interface RGAdditional extends IExtensionPoint { + + /** + * 为服务器端加载规则提供了一个默认方法。这个方法在服务器规则管理器中 + * 提供了一个接入点,实现类可以覆盖此方法以加载自定义的服务器规则 + * + * @param manager 服务器规则管理器,用于操作和管理服务器规则 + */ default void loadServerRules(ServerRGRuleManager manager) { } + /** + * 为客户端加载规则提供了一个默认方法。这个方法在客户端规则管理器中 + * 提供了一个接入点,实现类可以覆盖此方法以加载自定义的客户端规则 + * + * @param manager 客户端规则管理器,用于操作和管理客户端规则 + */ default void loadClientRules(ClientRGRuleManager manager) { } } + diff --git a/src/main/java/dev/anvilcraft/rg/api/RGCodec.java b/src/main/java/dev/anvilcraft/rg/api/RGCodec.java index 562db14..f4b66a8 100644 --- a/src/main/java/dev/anvilcraft/rg/api/RGCodec.java +++ b/src/main/java/dev/anvilcraft/rg/api/RGCodec.java @@ -1,3 +1,9 @@ +/** + * Realms of the Gods (RG) 编码解码器接口 + * 提供自定义类型与JSON之间的序列化和反序列化功能 + * + * @param 要序列化和反序列化的类型 + */ package dev.anvilcraft.rg.api; import com.google.gson.JsonDeserializationContext; @@ -12,63 +18,144 @@ import java.lang.reflect.Type; import java.util.function.Function; +/** + * RGCodec 类实现 JsonDeserializer 和 JsonSerializer 接口 + * 提供自定义类型与JSON之间的序列化和反序列化功能 + * + * @param 要序列化和反序列化的类型 + */ public class RGCodec implements JsonDeserializer, JsonSerializer { + // 类型类 private final Class clazz; + // 解码函数,将字符串转换为指定类型 private final Function decoder; + // 编码函数,将指定类型转换为字符串 private final Function encoder; - private final boolean isLock; + // 是否锁定,表示该类型是否具有固定的编解码逻辑 + private final boolean isBuiltIn; + + // 预定义的字符串类型编解码器 public static final RGCodec STRING = new RGCodec<>(String.class, String::toString, String::toString, true); + // 预定义的布尔类型编解码器 public static final RGCodec BOOLEAN = new RGCodec<>(Boolean.class, s -> s.equals("true"), Object::toString, true); + // 预定义的字节类型编解码器 public static final RGCodec BYTE = new RGCodec<>(Byte.class, Byte::parseByte, Object::toString, true); + // 预定义的短整型编解码器 public static final RGCodec SHORT = new RGCodec<>(Short.class, Short::parseShort, Object::toString, true); + // 预定义的整型编解码器 public static final RGCodec INTEGER = new RGCodec<>(Integer.class, Integer::parseInt, Object::toString, true); + // 预定义的长整型编解码器 public static final RGCodec LONG = new RGCodec<>(Long.class, Long::parseLong, Object::toString, true); + // 预定义的浮点型编解码器 public static final RGCodec FLOAT = new RGCodec<>(Float.class, Float::parseFloat, Object::toString, true); + // 预定义的双精度浮点型编解码器 public static final RGCodec DOUBLE = new RGCodec<>(Double.class, Double::parseDouble, Object::toString, true); - private RGCodec(Class clazz, Function decoder, Function encoder, boolean isLock) { + /** + * 构造一个 RGCodec 实例 + * + * @param clazz 类型类 + * @param decoder 解码函数 + * @param encoder 编码函数 + * @param isBuiltIn 是否内置 + */ + private RGCodec(Class clazz, Function decoder, Function encoder, boolean isBuiltIn) { this.clazz = clazz; this.decoder = decoder; this.encoder = encoder; - this.isLock = isLock; + this.isBuiltIn = isBuiltIn; } + /** + * 创建一个 RGCodec 实例 + * + * @param clazz 类型类 + * @param decoder 解码函数 + * @param encoder 编码函数 + * @param 类型 + * @return RGCodec 实例 + */ @SuppressWarnings("unused") public static @NotNull RGCodec of(Class clazz, Function decoder, Function encoder) { return new RGCodec<>(clazz, decoder, encoder, false); } + /** + * 获取类型类 + * + * @return 类型类 + */ public Class clazz() { return this.clazz; } - public boolean isLock() { - return isLock; + /** + * 检查编解码器是否内置 + * + * @return 是否内置 + */ + public boolean isBuiltIn() { + return isBuiltIn; } + /** + * 解码字符串为指定类型 + * + * @param str 字符串 + * @return 解码后的对象 + */ public T decode(String str) { if (str == null) return null; return this.decoder.apply(str); } + /** + * 编码对象为字符串 + * + * @param value 对象 + * @return 编码后的字符串 + */ public String encode(T value) { if (value == null) return null; return this.encoder.apply(value); } + /** + * 强制编码对象为字符串,不进行类型检查 + * + * @param value 对象 + * @return 编码后的字符串 + */ public String forceEncode(Object value) { if (value == null) return null; //noinspection unchecked return this.encoder.apply((T) value); } + /** + * 从 JsonElement 中反序列化为指定类型对象 + * + * @param json JSON元素 + * @param typeOfT 类型 + * @param context 反序列化上下文 + * @return 反序列化后的对象 + * @throws JsonParseException JSON解析异常 + */ @Override public T deserialize(@NotNull JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return this.decode(json.getAsString()); } + /** + * 序列化对象为 JsonElement + * + * @param src 对象 + * @param typeOfSrc 类型 + * @param context 序列化上下文 + * @return 序列化后的 JSON元素 + */ @Override public @NotNull JsonElement serialize(T src, Type typeOfSrc, JsonSerializationContext context) { return new JsonPrimitive(this.encode(src)); } -} \ No newline at end of file +} diff --git a/src/main/java/dev/anvilcraft/rg/api/RGEnvironment.java b/src/main/java/dev/anvilcraft/rg/api/RGEnvironment.java index 24a0c3a..d52ad44 100644 --- a/src/main/java/dev/anvilcraft/rg/api/RGEnvironment.java +++ b/src/main/java/dev/anvilcraft/rg/api/RGEnvironment.java @@ -1,13 +1,33 @@ package dev.anvilcraft.rg.api; +/** + * 枚举 RGEnvironment 表示模块可以运行的不同环境 + * 它包括两种类型:客户端和服务器。此枚举提供了确定当前环境的方法 + */ public enum RGEnvironment { + /** + * 表示客户端环境 + */ CLIENT, + /** + * 表示服务器端环境 + */ SERVER; + /** + * 检查当前环境是否为客户端. + * + * @return 如果当前环境是客户端,则为true,否则为false + */ public boolean isClient() { return this == CLIENT; } + /** + * 检查当前环境是否为服务器端 + * + * @return 如果当前环境是服务器端,则为true,否则为false + */ public boolean isServer() { return this == SERVER; } diff --git a/src/main/java/dev/anvilcraft/rg/api/RGRule.java b/src/main/java/dev/anvilcraft/rg/api/RGRule.java index ac3f3fb..803cbf0 100644 --- a/src/main/java/dev/anvilcraft/rg/api/RGRule.java +++ b/src/main/java/dev/anvilcraft/rg/api/RGRule.java @@ -14,9 +14,18 @@ import java.util.List; import java.util.Map; +/** + * RGRule类用于定义和管理配置规则它是一个泛型记录类,用于存储配置项的相关信息和操作逻辑 + * + * @param 配置项的类型 + */ public record RGRule(String namespace, Class type, RGEnvironment environment, String[] categories, String serialize, String[] allowed, List> validators, T defaultValue, Field field, RGCodec codec) { + + /** + * CODECS映射用于存储支持的类型及其对应的编解码器 + */ public static final Map> CODECS = new HashMap<>() {{ put("java.lang.Boolean", RGCodec.BOOLEAN); put("boolean", RGCodec.BOOLEAN); @@ -35,18 +44,32 @@ public record RGRule(String namespace, Class type, RGEnvironment environme put("java.lang.String", RGCodec.STRING); }}; + /** + * 创建一个新的RGRule实例 + * + * @param namespace 命名空间,用于区分不同的配置范围 + * @param field 配置项对应的Field对象 + * @param 配置项的类型 + * @return 新创建的RGRule实例 + * @throws RGRuleException 如果配置项不合法或不支持,则抛出此异常 + */ @SuppressWarnings("unchecked") public static @NotNull RGRule of(String namespace, @NotNull Field field) { String name = field.getName(); + // 检查配置项是否是静态的 if (!Modifier.isStatic(field.getModifiers())) throw RGRuleException.notStatic(name); + // 检查配置项是否是公开的 if (!Modifier.isPublic(field.getModifiers())) throw RGRuleException.notPublic(name); + // 检查配置项是否不是final的 if (Modifier.isFinal(field.getModifiers())) throw RGRuleException.beFinal(name); Class type = RGRule.checkType(field); Rule rule = field.getAnnotation(Rule.class); + // 确保配置项上有Rule注解 if (rule == null) throw RGRuleException.notAnnotated(name); String serialize = rule.serialize().isEmpty() ? RGRule.caseToSnake(name) : rule.serialize(); RGRule.checkSerialize(serialize); List> validators = new ArrayList<>(); + // 实例化所有验证器 for (Class validator : rule.validator()) { try { validators.add((RGValidator) validator.getDeclaredConstructor().newInstance()); @@ -55,11 +78,14 @@ public record RGRule(String namespace, Class type, RGEnvironment environme } } RGCodec rgCodec = RGRule.CODECS.getOrDefault(type.getTypeName(), null); + // 确保类型支持 if (rgCodec == null) { throw RGRuleException.unsupportedType(name, type); } else if (rgCodec.clazz() == Boolean.class) { + // 为Boolean类型添加默认验证器 validators.add((RGValidator) new RGValidator.BooleanValidator()); } else if (rgCodec.clazz() == String.class && validators.isEmpty()) { + // 为String类型添加默认验证器 validators.add((RGValidator) new RGValidator.StringValidator()); } try { @@ -80,10 +106,21 @@ public record RGRule(String namespace, Class type, RGEnvironment environme } } + /** + * 获取配置项的名称 + * + * @return 配置项的名称 + */ public @NotNull String name() { return this.field.getName(); } + /** + * 获取配置项的当前值 + * + * @return 配置项的值 + * @throws RGRuleException 如果无法访问配置项的值,则抛出此异常 + */ @SuppressWarnings("unchecked") public T getValue() { try { @@ -93,6 +130,7 @@ public T getValue() { } } + /** * 检查并转换字段的类型 *

diff --git a/src/main/java/dev/anvilcraft/rg/api/RGRuleException.java b/src/main/java/dev/anvilcraft/rg/api/RGRuleException.java index b292e19..89d45ae 100644 --- a/src/main/java/dev/anvilcraft/rg/api/RGRuleException.java +++ b/src/main/java/dev/anvilcraft/rg/api/RGRuleException.java @@ -2,39 +2,97 @@ import org.jetbrains.annotations.NotNull; +/** + * 自定义运行时异常类,用于表示规则引擎中的规则相关错误 + */ public class RGRuleException extends RuntimeException { + /** + * 构造函数,用于格式化异常消息 + * + * @param msg 格式化的消息字符串 + * @param args 消息中的参数 + */ public RGRuleException(String msg, Object... args) { super(String.format(msg, args)); } + /** + * 构造函数,用于处理异常消息和原因 + * + * @param msg 异常消息 + * @param e 异常原因 + */ public RGRuleException(String msg, Throwable e) { super(msg, e); } + /** + * 静态工厂方法,用于创建表示非法访问错误的异常 + * + * @param name 字段名 + * @return 创建的异常实例 + */ public static @NotNull RGRuleException illegalAccess(@NotNull String name) { return new RGRuleException("Field %s has illegal access", name); } + /** + * 静态工厂方法,用于创建表示字段非静态错误的异常 + * + * @param name 字段名 + * @return 创建的异常实例 + */ public static @NotNull RGRuleException notStatic(@NotNull String name) { return new RGRuleException("Field %s is not static", name); } + /** + * 静态工厂方法,用于创建表示字段非公共错误的异常 + * + * @param name 字段名 + * @return 创建的异常实例 + */ public static @NotNull RGRuleException notPublic(@NotNull String name) { return new RGRuleException("Field %s is not public", name); } + /** + * 静态工厂方法,用于创建表示字段为final错误的异常 + * + * @param name 字段名 + * @return 创建的异常实例 + */ public static @NotNull RGRuleException beFinal(@NotNull String name) { return new RGRuleException("Field %s can't be final", name); } + /** + * 静态工厂方法,用于创建表示字段未标注@Rule错误的异常 + * + * @param name 字段名 + * @return 创建的异常实例 + */ public static @NotNull RGRuleException notAnnotated(@NotNull String name) { return new RGRuleException("Field %s is not annotated with @Rule", name); } + /** + * 静态工厂方法,用于创建表示创建规则失败错误的异常 + * + * @param name 字段名 + * @return 创建的异常实例 + */ public static @NotNull RGRuleException createRuleFailed(@NotNull String name) { return new RGRuleException("Failed to create rule for field %s", name); } + /** + * 静态工厂方法,用于创建表示字段类型不受支持错误的异常 + * + * @param name 字段名 + * @param type 字段类型 + * @return 创建的异常实例 + */ public static @NotNull RGRuleException unsupportedType(@NotNull String name, @NotNull Class type) { return new RGRuleException("Field %s has unsupported type, this type can only be boolean, byte, int, long, float, double, String, but got %s", name, type.getTypeName()); } diff --git a/src/main/java/dev/anvilcraft/rg/api/RGRuleManager.java b/src/main/java/dev/anvilcraft/rg/api/RGRuleManager.java index e4aea0f..fba569a 100644 --- a/src/main/java/dev/anvilcraft/rg/api/RGRuleManager.java +++ b/src/main/java/dev/anvilcraft/rg/api/RGRuleManager.java @@ -16,48 +16,83 @@ import java.util.List; import java.util.Map; +/** + * RollingGate规则管理器,负责处理和存储规则配置 + */ public class RGRuleManager { + // Gson实例,用于JSON序列化和反序列化 public static final Gson GSON; + // 环境对象,用于确定当前环境(客户端或服务器) protected final RGEnvironment environment; + // 存储规则的映射表 protected final Map> rules = new HashMap<>(); + // 管理器的命名空间 protected final String managerNamespace; + // 全局配置文件路径 protected final Path globalConfigPath; + // 全局配置映射表 protected final Map, Object> globalConfig = new HashMap<>(); + // 默认命名空间 protected String namespace = "rolling_gate"; + // 存储规则类别的列表 protected final List categories = new ArrayList<>(); + // 静态代码块,初始化Gson实例 static { GsonBuilder builder = new GsonBuilder(); + // 注册自定义的Gson类型适配器 for (Map.Entry> entry : RGRule.CODECS.entrySet()) { RGCodec codec = entry.getValue(); - if (codec.isLock()) continue; + if (codec.isBuiltIn()) continue; builder.registerTypeAdapter(codec.clazz(), codec); } GSON = builder.setPrettyPrinting().create(); } + /** + * 构造函数,初始化规则管理器 + * + * @param namespace 命名空间 + * @param environment 环境对象 + */ public RGRuleManager(String namespace, @NotNull RGEnvironment environment) { this.managerNamespace = namespace; this.environment = environment; + // 根据命名空间和环境确定全局配置文件路径 this.globalConfigPath = FMLPaths.CONFIGDIR.get().resolve("%s%s.json".formatted(namespace, this.environment.isClient() ? "_client" : "")); } + /** + * 从配置文件中设置规则,并返回设置的结果 + * + * @param config 配置文件内容 + * @return 返回设置后的规则映射表 + */ protected @NotNull Map, Object> setSaveRules(@NotNull JsonObject config) { Map, Object> result = new HashMap<>(); + // 遍历配置文件中的每个规则 for (Map.Entry entry : config.entrySet()) { RGRule rule = this.rules.get(entry.getKey()); if (rule == null) { RollingGate.LOGGER.warn("{}({}) not exist.", entry.getKey(), entry.getValue()); continue; } + // 设置规则的字段值 rule.setFieldValue(entry.getValue()); result.put(rule, rule.getValue()); } return result; } + /** + * 序列化配置映射表 + * + * @param configs 配置映射表 + * @return 返回序列化后的配置映射表 + */ protected @NotNull Map getSerializedConfig(@NotNull Map, Object> configs) { Map result = new HashMap<>(); + // 遍历配置映射表,序列化每个规则 for (Map.Entry, Object> entry : configs.entrySet()) { RGRule key = entry.getKey(); result.put(key.serialize(), entry.getValue()); @@ -65,18 +100,36 @@ public RGRuleManager(String namespace, @NotNull RGEnvironment environment) { return result; } + /** + * 重新初始化全局配置 + */ public void reInit() { this.globalConfig.clear(); + // 从配置文件中重新加载并设置规则 this.globalConfig.putAll(this.setSaveRules(ConfigUtil.getOrCreateContent(globalConfigPath))); } + /** + * 添加规则到管理器 + * + * @param rule 要添加的规则 + */ public void addRule(@NotNull RGRule rule) { this.rules.put(rule.serialize(), rule); + // 添加规则的类别到类别列表 this.categories.addAll(Arrays.asList(rule.categories())); } + /** + * 根据命名空间和规则类创建规则列表 + * + * @param namespace 命名空间 + * @param rules 规则类 + * @return 返回创建的规则列表 + */ private static @NotNull List> of(String namespace, @NotNull Class rules) { List> ruleList = new ArrayList<>(); + // 遍历规则类的每个字段 for (Field field : rules.getDeclaredFields()) { RGRule.checkType(field); ruleList.add(RGRule.of(namespace, field)); @@ -84,10 +137,21 @@ public void addRule(@NotNull RGRule rule) { return ruleList; } + /** + * 注册规则类 + * + * @param rules 规则类 + */ public void register(Class rules) { + // 创建并添加规则到管理器 RGRuleManager.of(this.namespace, rules).forEach(this::addRule); } + /** + * 设置管理器的命名空间 + * + * @param namespace 命名空间 + */ public void setNamespace(String namespace) { this.namespace = namespace; } @@ -95,6 +159,7 @@ public void setNamespace(String namespace) { /** * 获取分组翻译键 * + * @param category 分组名称 * @return 返回格式化的分组翻译键字符串 */ public @NotNull String getDescriptionCategoryKey(String category) { diff --git a/src/main/java/dev/anvilcraft/rg/api/RGValidator.java b/src/main/java/dev/anvilcraft/rg/api/RGValidator.java index b67250d..0842704 100644 --- a/src/main/java/dev/anvilcraft/rg/api/RGValidator.java +++ b/src/main/java/dev/anvilcraft/rg/api/RGValidator.java @@ -4,14 +4,32 @@ import java.util.Map; +/** + * RGValidator接口用于定义验证操作的规范 + * 它允许实现类针对特定数据类型进行有效性检查 + * @param 要验证的旧值的类型 + */ @SuppressWarnings("unused") public interface RGValidator { + /** + * 验证新值是否有效 + * @param oldValue 旧值,用于比较或参考 + * @param newValue 新值,需要进行验证 + * @return 如果新值有效则返回true,否则返回false + */ boolean validate(@NotNull T oldValue, @NotNull String newValue); + /** + * 输入值非法的原因 + * @return 输入值非法的原因 + */ default String reason() { return "The input value is illegal!"; } + /** + * StringValidator类实现了RGValidator接口,专门用于字符串类型的验证 + */ class StringValidator implements RGValidator { @Override public boolean validate(@NotNull String oldValue, @NotNull String newValue) { @@ -24,6 +42,9 @@ public String reason() { } } + /** + * BooleanValidator类实现了RGValidator接口,专门用于布尔类型的验证 + */ class BooleanValidator implements RGValidator { @Override public boolean validate(@NotNull Boolean oldValue, @NotNull String newValue) { @@ -36,7 +57,16 @@ public String reason() { } } + /** + * NumberValidator抽象类实现了RGValidator接口,为数字类型提供了一个通用的验证框架 + * 它要求子类提供具体的数字解析和范围获取实现 + * @param 具体数字类型,如Integer、Float等 + */ abstract class NumberValidator implements RGValidator { + /** + * 获取数字的有效范围 + * @return 包含最小值和最大值的Map.Entry对象 + */ public abstract @NotNull Map.Entry getRange(); @Override @@ -54,39 +84,62 @@ public String reason() { return "The input value must be between " + getRange().getKey().toString() + " and " + getRange().getValue().toString() + "!"; } + /** + * 解析字符串为指定的数字类型 + * @param newValue 待解析的字符串 + * @return 解析后的数字 + */ protected abstract T parse(@NotNull String newValue); } + /** + * ByteValidator抽象类继承自NumberValidator,用于byte类型的数字验证 + */ abstract class ByteValidator extends NumberValidator { protected Byte parse(@NotNull String newValue) { return Byte.parseByte(newValue); } } + /** + * ShortValidator抽象类继承自NumberValidator,用于short类型的数字验证 + */ abstract class ShortValidator extends NumberValidator { protected Short parse(@NotNull String newValue) { return Short.parseShort(newValue); } } + /** + * IntegerValidator抽象类继承自NumberValidator,用于int类型的数字验证 + */ abstract class IntegerValidator extends NumberValidator { protected Integer parse(@NotNull String newValue) { return Integer.parseInt(newValue); } } + /** + * LongValidator抽象类继承自NumberValidator,用于long类型的数字验证 + */ abstract class LongValidator extends NumberValidator { protected Long parse(@NotNull String newValue) { return Long.parseLong(newValue); } } + /** + * FloatValidator抽象类继承自NumberValidator,用于float类型的数字验证 + */ abstract class FloatValidator extends NumberValidator { protected Float parse(@NotNull String newValue) { return Float.parseFloat(newValue); } } + /** + * DoubleValidator抽象类继承自NumberValidator,用于double类型的数字验证 + */ abstract class DoubleValidator extends NumberValidator { protected Double parse(@NotNull String newValue) { return Double.parseDouble(newValue); diff --git a/src/main/java/dev/anvilcraft/rg/api/Rule.java b/src/main/java/dev/anvilcraft/rg/api/Rule.java index 4994da6..f85a73f 100644 --- a/src/main/java/dev/anvilcraft/rg/api/Rule.java +++ b/src/main/java/dev/anvilcraft/rg/api/Rule.java @@ -5,16 +5,50 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * Rule注解用于定义配置项的规则和约束条件 + * 它提供了关于配置项如何在不同环境中处理、如何序列化、允许的值、所属类别以及验证器的信息 + */ @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface Rule { + /** + * 指定配置项适用的环境,默认为服务器环境 + * 这有助于在不同的运行环境下正确地应用配置规则 + * + * @return RGEnvironment枚举值,表示配置项适用的环境 + */ RGEnvironment env() default RGEnvironment.SERVER; + /** + * 指定配置项的序列化,默认为空字符串 + * 这允许开发者自定义配置项的序列化名称 + * + * @return 字符串,表示配置项的序列化名称 + */ String serialize() default ""; + /** + * 定义配置项允许的值列表,默认为空数组 + * 这有助于限制配置项的可能值,确保配置的有效性和一致性 + * + * @return 字符串数组,表示配置项允许的值 + */ String[] allowed() default {}; + /** + * 指定配置项所属的类别列表,默认为空数组 + * 这允许对配置项进行分类管理,便于理解和维护 + * + * @return 字符串数组,表示配置项所属的类别 + */ String[] categories() default {}; + /** + * 定义配置项使用的验证器类列表,默认为空数组 + * 验证器用于在运行时验证配置项的值,确保其符合预期的规则和约束 + * + * @return RGValidator的类数组,表示配置项使用的验证器 + */ Class[] validator() default {}; } diff --git a/src/main/java/dev/anvilcraft/rg/api/client/ClientRGRuleManager.java b/src/main/java/dev/anvilcraft/rg/api/client/ClientRGRuleManager.java index f7da966..c01ea45 100644 --- a/src/main/java/dev/anvilcraft/rg/api/client/ClientRGRuleManager.java +++ b/src/main/java/dev/anvilcraft/rg/api/client/ClientRGRuleManager.java @@ -3,8 +3,18 @@ import dev.anvilcraft.rg.api.RGEnvironment; import dev.anvilcraft.rg.api.RGRuleManager; +/** + * ClientRGRuleManager类是RGRuleManager的子类,专门用于客户端环境 + * 它通过继承RGRuleManager类并指定环境为客户端,来管理客户端特定的规则 + */ public class ClientRGRuleManager extends RGRuleManager { + /** + * 初始化ClientRGRuleManager对象,设置命名空间和环境 + * + * @param namespace 命名空间,用于区分不同的规则管理器实例 + */ public ClientRGRuleManager(String namespace) { super(namespace, RGEnvironment.CLIENT); } } + diff --git a/src/main/java/dev/anvilcraft/rg/api/event/RGRuleChangeEvent.java b/src/main/java/dev/anvilcraft/rg/api/event/RGRuleChangeEvent.java index 6e35e0a..9002c9a 100644 --- a/src/main/java/dev/anvilcraft/rg/api/event/RGRuleChangeEvent.java +++ b/src/main/java/dev/anvilcraft/rg/api/event/RGRuleChangeEvent.java @@ -5,47 +5,124 @@ import net.neoforged.bus.api.Event; import net.neoforged.bus.api.ICancellableEvent; +/** + * 当规则发生变化时触发的事件。 + * 此事件允许服务器和客户端监听和响应区域规则的更改。 + * + * @param 规则值的类型。 + */ public class RGRuleChangeEvent extends Event implements ICancellableEvent { + /** + * 发生变更的规则。 + */ private final RGRule rule; + /** + * 规则的旧值。 + */ private final T oldValue; + /** + * 规则的新值。 + */ private T newValue; + /** + * 构造一个新的规则更改事件。 + * + * @param rule 发生变更的规则。 + * @param oldValue 规则的旧值。 + * @param newValue 规则的新值。 + */ public RGRuleChangeEvent(RGRule rule, T oldValue, T newValue) { this.rule = rule; this.oldValue = oldValue; this.newValue = newValue; } + /** + * 获取发生变更的规则。 + * + * @return 发生变更的规则。 + */ public RGRule getRule() { return rule; } + /** + * 获取规则的新值。 + * + * @return 规则的新值。 + */ public T getNewValue() { return newValue; } + /** + * 获取规则的旧值。 + * + * @return 规则的旧值。 + */ public T getOldValue() { return oldValue; } + /** + * 设置规则的新值。 + * 这允许在事件处理过程中更改规则的值。 + * + * @param newValue 规则的新值。 + */ public void setNewValue(T newValue) { this.newValue = newValue; } + /** + * 针对服务器端的规则更改事件。 + * 包含对服务器实例的引用。 + * + * @param 规则值的类型。 + */ public static class Server extends RGRuleChangeEvent { + /** + * 服务器实例。 + */ private final MinecraftServer server; + /** + * 构造一个新的服务器端规则更改事件。 + * + * @param rule 发生变更的规则。 + * @param oldValue 规则的旧值。 + * @param newValue 规则的新值。 + * @param server 服务器实例。 + */ public Server(RGRule rule, T oldValue, T newValue, MinecraftServer server) { super(rule, oldValue, newValue); this.server = server; } + /** + * 获取服务器实例。 + * + * @return 服务器实例。 + */ public MinecraftServer getServer() { return server; } } + /** + * 针对客户端的规则更改事件。 + * + * @param 规则值的类型。 + */ public static class Client extends RGRuleChangeEvent { + /** + * 构造一个新的客户端规则更改事件。 + * + * @param rule 发生变更的规则。 + * @param oldValue 规则的旧值。 + * @param newValue 规则的新值。 + */ public Client(RGRule rule, T oldValue, T newValue) { super(rule, oldValue, newValue); } diff --git a/src/main/java/dev/anvilcraft/rg/api/server/ServerRGRuleManager.java b/src/main/java/dev/anvilcraft/rg/api/server/ServerRGRuleManager.java index 0716f50..4921438 100644 --- a/src/main/java/dev/anvilcraft/rg/api/server/ServerRGRuleManager.java +++ b/src/main/java/dev/anvilcraft/rg/api/server/ServerRGRuleManager.java @@ -35,20 +35,47 @@ import java.util.Optional; import java.util.concurrent.CompletableFuture; +/** + * 服务器端RGRule管理器类,继承自RGRuleManager + * 用于管理服务器端的规则,包括规则的设置、重新初始化以及命令生成 + */ public class ServerRGRuleManager extends RGRuleManager { + // 世界配置文件路径 private final LevelResource worldConfigPath; + // 用于存储世界特定规则配置的映射 private final Map, Object> worldConfig = new HashMap<>(); + /** + * 构造函数 + * 初始化ServerRGRuleManager实例,设置其命名空间和环境为服务器端 + * + * @param namespace 命名空间,用于标识规则管理器 + */ public ServerRGRuleManager(String namespace) { super(namespace, RGEnvironment.SERVER); this.worldConfigPath = new LevelResource("%s.json".formatted(namespace)); } + /** + * 设置世界配置 + * 将指定规则的值存储到世界配置中,并更新配置文件 + * + * @param server 服务器实例,用于访问世界路径 + * @param rule 要设置的规则 + * @param value 规则的值 + * @param 规则值的类型 + */ public void setWorldConfig(@NotNull MinecraftServer server, @NotNull RGRule rule, T value) { this.worldConfig.put(rule, value); ConfigUtil.writeContent(server.getWorldPath(worldConfigPath), GSON.toJson(this.getSerializedConfig(this.worldConfig))); } + /** + * 重新初始化世界配置 + * 清空当前世界配置,并从配置文件中重新加载配置 + * + * @param server 服务器实例,用于访问世界路径 + */ public void reInit(@NotNull MinecraftServer server) { super.reInit(); this.worldConfig.clear(); @@ -59,16 +86,32 @@ public void reInit(@NotNull MinecraftServer server) { } } + /** + * 生成命令 + * 根据提供的字面量在命令调度器中注册命令 + * + * @param dispatcher 命令调度器,用于注册命令 + * @param literal 命令的字面量 + */ @SuppressWarnings("unused") public void generateCommand(CommandDispatcher dispatcher, @NotNull String literal) { this.generateCommand(dispatcher, literal, null); } + /** + * 生成命令 + * 根据提供的字面量和重定向路径在命令调度器中注册命令 + * + * @param dispatcher 命令调度器,用于注册命令 + * @param literal 命令的字面量 + * @param redirect 命令的重定向路径,可以为null + */ @SuppressWarnings("unused") public void generateCommand(CommandDispatcher dispatcher, @NotNull String literal, String redirect) { new Command(dispatcher, literal, redirect).generateCommand(); } + private class Command { @NotNull CommandDispatcher dispatcher; @NotNull String literal; @@ -80,7 +123,7 @@ private Command(@NotNull CommandDispatcher dispatcher, @NotN this.redirect = redirect; } - public void generateCommand() { + private void generateCommand() { LiteralArgumentBuilder root = Commands.literal(literal) .requires(this::checkPermission) .executes(this::listCommand) diff --git a/src/main/java/dev/anvilcraft/rg/api/server/TranslationUtil.java b/src/main/java/dev/anvilcraft/rg/api/server/TranslationUtil.java index fb0dee9..6eaa059 100644 --- a/src/main/java/dev/anvilcraft/rg/api/server/TranslationUtil.java +++ b/src/main/java/dev/anvilcraft/rg/api/server/TranslationUtil.java @@ -13,10 +13,26 @@ import java.util.HashMap; import java.util.Map; +/** + * 翻译实用程序类,用于处理语言翻译相关功能 + */ public class TranslationUtil { + /** + * Gson实例用于JSON解析 + */ public static final Gson GSON = new Gson(); + /** + * 存储所有语言及其相应的翻译 + */ public static final Map> LANGUAGES = new HashMap<>(); + /** + * 将密钥转换为相应的文本,并可选择格式替换 + * + * @param key 翻译键 + * @param args 可选格式替换参数 + * @return 翻译和格式化的文本 + */ public static @NotNull MutableComponent trans(String key, Object... args) { return Component.translatableWithFallback( key, @@ -27,16 +43,29 @@ public class TranslationUtil { ); } + /** + * 为指定语言添加一组翻译 + * + * @param language 语言代码 + * @param translations 包含翻译的Map + */ public static void addLanguage(String language, Map translations) { Map languages = LANGUAGES.getOrDefault(language, new HashMap<>()); languages.putAll(translations); LANGUAGES.putIfAbsent(language, languages); } + /** + * 从指定的命名空间和语言代码加载语言文件 + * + * @param clazz 用于加载资源的类 + * @param namespace 资源命名空间 + * @param language 语言代码 + */ @SuppressWarnings("unchecked") public static void loadLanguage(Class clazz, String namespace, String language) { try ( - InputStream stream = clazz.getResourceAsStream("/assets/%s/lang/%s.json".formatted(namespace, language)); + InputStream stream = clazz.getResourceAsStream("/assets/%s/lang/%s.json".formatted(namespace, language)) ) { if (stream == null) { RollingGate.LOGGER.error("Can't find language {}/{}.", namespace, language);