Skip to content

Commit

Permalink
修改规则管理器单例位置
Browse files Browse the repository at this point in the history
  • Loading branch information
Gu-ZT committed Sep 17, 2024
1 parent cbe0e05 commit 83eab2c
Show file tree
Hide file tree
Showing 9 changed files with 231 additions and 67 deletions.
138 changes: 137 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,144 @@
# 卷帘门 | Rolling Gate

> 一个NeoForge模组,控制Minecraft技术选项
>
>
> A NeoForge mod that controls Minecraft technology options
[![Development Builds](https://github.com/Anvil-Dev/RollingGate/actions/workflows/ci.yml/badge.svg)](https://github.com/Anvil-Dev/RollingGate/actions/workflows/ci.yml)
[![GitHub downloads](https://img.shields.io/github/downloads/Anvil-Dev/RollingGate/total?label=Github%20downloads&logo=github)](https://github.com/Anvil-Dev/RollingGate/releases)

## 声明 | Disclaimer

> 本模组仅支持 Minecraft 1.21+ ,暂无向更低版本兼容的计划。
>
> This mod only supports Minecraft 1.21+ and has no plans to be compatible with lower versions at the moment.
>
> 本模组代码基于 [LGPL-3.0](./LICENSE) 协议开源,其它资产基于 [CC-BY-NC-ND 4.0](./LICENSE_ASSETS) 发布,请遵守协议。
>
> This module code is open source based on the [LGPL-3.0](./LICENSE) protocol, while other assets are released based on
> the [CC-BY-NC-ND 4.0](./LICENSE_ASSETS) protocol. Please comply with the protocol.
## 快速开始 | Quick Start

1. 下载模组,放置到 `.minecraft/mods``.minecraft/versions/{version}/mods` 文件夹
2. 进入存档,使用 `/rg` 命令显示模组控制面板以调整规则的启用状态

## 配置 | Configuration

*`configs/rolling-gate.json` 中修改默认配置,该配置将影响所有存档
* 在存档目录中创建 `rolling-gate.json` 文件以覆盖默认配置
* 配置文件格式为 JSON,示例如下:

```json5
{
// string
"rule1": "value",
// int
"rule2": 1,
// double
"rule3": 1.0,
// boolean
"rule4": true
}
```

## 命令 | Command

* `/rg` - 显示模组控制面板
* `reload` - 重新加载配置文件
* `list` - 列出所有修改过的规则
* `[rule]` - 查看规则的详细信息
* `category [category]` - 查看分组下的所有规则
* `set [rule] [value]` - 设置规则的值
* `default [rule] [value]` - 设置当前存档的规则默认值

* `/rg` - Display mod control panel
* `reload` - Reload configuration file
* `list` - List all modified rules
* `[rule]` - View detailed information of rules
* `category [category]` - View all rules under the group
* `set [rule] [value]` - Set the value of the rule
* `default [rule] [value]` - Set default rules for the current save

## 规则 | Rules

| 规则 | 类型 | 默认值 | 允许值 | 描述 |
|------------|--------|---------|------------------|------------|
| `language` | String | `zh_cn` | `en_us`, `zh_cn` | 设置卷帘门的默认语言 |

| Rule | Type | Default Value | Allowed Value | Description |
|------------|--------|---------------|------------------|------------------------------------------|
| `language` | String | `zh_cn` | `en_us`, `zh_cn` | Set the default language for RollingGate |

## 贡献 | Contribution

* Fork 仓库 | Fork Repository
* [![Fork Repository](https://img.shields.io/badge/Fork%20Repository-blue?logo=github)](https://github.com/Anvil-Dev/RollingGate/fork)

* 提交 PR | Submit PR
* [![Submit PR](https://img.shields.io/badge/Submit%20PR-green?logo=github)](https://github.com/Anvil-Dev/RollingGate/pulls)

## 贡献者 | Contributors

<!--suppress ALL -->
<table>
<tr>
<td align="center">
<a href="https://github.com/Gu-ZT">
<img src="https://avatars.githubusercontent.com/u/34372427?v=100&s=100" width="100px" height="100px" alt=""/><br />
<sub><b>Gugle</b></sub>
</a><br />
<a title="Code">💻</a><br />
<a href="https://space.bilibili.com/19822751">19822751</a>
</td>
<td align="center">
<a href="https://github.com/Cjsah">
<img src="https://avatars.githubusercontent.com/u/46415647?v=100&s=100" width="100px" height="100px" alt=""/><br />
<sub><b>꧁[C̲̅j̲̅s̲̅a̲̅h̲̅]꧂</b></sub>
</a><br />
<a title="Code">💻</a><br />
<a href="https://space.bilibili.com/19170004">19170004</a>
</td>
</tr>
</table>

## 联系我们 | Contact Us

* [![Contact Us](https://img.shields.io/badge/Contact%20Us-white?logo=tencentqq)](https://qm.qq.com/q/alOmGR4G6k)

## 赞助我们 | Sponsor Us

* [![Sponsor Us](https://img.shields.io/badge/Sponsor%20Us-blue?logo=githubsponsors)](https://www.anvilcraft.dev/#/support)

## 赞助者 | Sponsors

## 编写附属 | Write Additional

* 编写一个类实现 `dev.anvilcraft.rg.api.RGAdditional`
* Write a class implement `dev.anvilcraft.rg.api.RGAdditional`

```java
public class YourAdditional implements RGAdditional {
@Override
public void loadRules(@NotNull RGRuleManager manager) {
manager.register(YourRules.class);
}
}
```

* 亦可以让你的模组主类实现 `dev.anvilcraft.rg.api.RGAdditional`
* You can also enable your mod main class to implement `dev.anvilcraft.rg.api.RGAdditional`

```java
@Mod('your_mod_id')
public class YourMod implements RGAdditional {
public YourMod(IEventBus modEventBus, ModContainer modContainer) {
// ...
}

@Override
public void loadRules(@NotNull RGRuleManager manager) {
manager.register(YourRules.class);
}
}
```
6 changes: 0 additions & 6 deletions dev.md

This file was deleted.

61 changes: 58 additions & 3 deletions src/main/java/dev/anvilcraft/rg/RollingGate.java
Original file line number Diff line number Diff line change
@@ -1,21 +1,76 @@
package dev.anvilcraft.rg;

import com.google.gson.JsonObject;
import com.mojang.logging.LogUtils;
import dev.anvilcraft.rg.api.RGAdditional;
import dev.anvilcraft.rg.api.RGRuleException;
import dev.anvilcraft.rg.api.RGRuleManager;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.level.storage.LevelResource;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.ModList;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.event.lifecycle.FMLLoadCompleteEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.event.server.ServerStartingEvent;
import org.apache.commons.io.FileUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.spongepowered.include.com.google.common.base.Charsets;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Optional;

@Mod(RollingGate.MODID)
public class RollingGate {
public class RollingGate implements RGAdditional {
public static final String MODID = "rolling_gate";
private static final Logger LOGGER = LogUtils.getLogger();
private static final RGRuleManager RULE_MANAGER = new RGRuleManager();
private static final LevelResource RULE_PATH = new LevelResource("rolling_gate.json");

public RollingGate(@NotNull IEventBus modEventBus, ModContainer modContainer) {
NeoForge.EVENT_BUS.addListener(this::reInitRules);
modEventBus.addListener(this::loadRGRules);
}

@Override
public void loadRules(@NotNull RGRuleManager manager) {
manager.register(RollingGateRules.class);
}

@SubscribeEvent
public void loadRGRules(FMLLoadCompleteEvent event) {
ModList.get().forEachModContainer((modId, modContainer) -> {
RollingGate.RULE_MANAGER.setNamespace(modId);
Optional<RGAdditional> additional = modContainer.getCustomExtension(RGAdditional.class);
additional.ifPresent(add -> add.loadRules(RollingGate.RULE_MANAGER));
});
}

public RollingGate(IEventBus modEventBus, ModContainer modContainer) {
NeoForge.EVENT_BUS.addListener((ServerStartingEvent event) -> RGRuleManager.reInitSaveRules(event.getServer()));
@SubscribeEvent
public void reInitRules(@NotNull ServerStartingEvent event) {
MinecraftServer server = event.getServer();
Path path = server.getWorldPath(RollingGate.RULE_PATH);
JsonObject config = getOrCreateContent(path);
RollingGate.RULE_MANAGER.reInit(config);
}

private static @NotNull JsonObject getOrCreateContent(@NotNull Path path) {
File file = path.toFile();
try {
if (!file.exists() || file.isDirectory()) {
FileUtils.writeStringToFile(file, "{}", Charsets.UTF_8);
return new JsonObject();
}
String value = FileUtils.readFileToString(path.toFile(), Charsets.UTF_8);
return GsonHelper.parse(value);
} catch (IOException e) {
throw new RGRuleException("Failed to read rolling gate config file", e);
}
}
}
5 changes: 5 additions & 0 deletions src/main/java/dev/anvilcraft/rg/RollingGateCategories.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package dev.anvilcraft.rg;

public class RollingGateCategories {
public static final String DISABLED = "DISABLED";
}
8 changes: 8 additions & 0 deletions src/main/java/dev/anvilcraft/rg/RollingGateRules.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package dev.anvilcraft.rg;

import dev.anvilcraft.rg.api.Rule;

public class RollingGateRules {
@Rule(allowed = {"true", "false"}, categories = {RollingGateCategories.DISABLED})
public static final boolean antiCheatDisabled = false;
}
7 changes: 7 additions & 0 deletions src/main/java/dev/anvilcraft/rg/api/RGAdditional.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package dev.anvilcraft.rg.api;

import net.neoforged.fml.IExtensionPoint;

public interface RGAdditional extends IExtensionPoint {
void loadRules(RGRuleManager manager);
}
29 changes: 5 additions & 24 deletions src/main/java/dev/anvilcraft/rg/api/RGRule.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,8 @@
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;

public class RGRule<T> {
final String namespace;
final Class<T> type;
final RGEnvironment environment;
final String serialize;
final String[] preset;
final RGValidator<T> validator;
final T defaultValue;
final Field field;

public RGRule(String namespace, Class<T> type, RGEnvironment environment, String serialize, String[] preset, RGValidator<T> validator, T defaultValue, Field field) {
this.namespace = namespace;
this.type = type;
this.environment = environment;
this.serialize = serialize;
this.preset = preset;
this.validator = validator;
this.defaultValue = defaultValue;
this.field = field;
}

public record RGRule<T>(String namespace, Class<T> type, RGEnvironment environment, String serialize, String[] allowed,
RGValidator<T> validator, T defaultValue, Field field) {
@SuppressWarnings("unchecked")
public static <T> @NotNull RGRule<T> of(String namespace, @NotNull Field field) {
if (!Modifier.isStatic(field.getModifiers())) throw RGRuleException.notStatic(field.getName());
Expand All @@ -43,7 +24,7 @@ public RGRule(String namespace, Class<T> type, RGEnvironment environment, String
(Class<T>) type,
rule.env(),
serialize,
rule.preset(),
rule.allowed(),
rule.validator().getDeclaredConstructor().newInstance(),
(T) field.get(null),
field
Expand Down Expand Up @@ -135,7 +116,7 @@ public void setFieldValue(T value) {
*/
@SuppressWarnings("unchecked")
public void setFieldValue(JsonElement primitive) {
Object value = switch (field.getType().getTypeName()) {
Object value = switch (this.field.getType().getTypeName()) {
case "boolean", "java.lang.Boolean" -> primitive.getAsBoolean();
case "byte", "java.lang.Byte" -> primitive.getAsByte();
case "short", "java.lang.Short" -> primitive.getAsShort();
Expand All @@ -145,7 +126,7 @@ public void setFieldValue(JsonElement primitive) {
case "double", "java.lang.Double" -> primitive.getAsDouble();
case "java.lang.String" -> primitive.getAsString();
default ->
throw new RGRuleException("Field %s has unsupported type %s", field.getName(), field.getType().getTypeName());
throw new RGRuleException("Field %s has unsupported type %s", this.field.getName(), this.field.getType().getTypeName());
};
this.setFieldValue((T) value);
}
Expand Down
38 changes: 8 additions & 30 deletions src/main/java/dev/anvilcraft/rg/api/RGRuleManager.java
Original file line number Diff line number Diff line change
@@ -1,60 +1,39 @@
package dev.anvilcraft.rg.api;

import com.google.gson.JsonObject;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.GsonHelper;
import net.minecraft.world.level.storage.LevelResource;
import org.apache.commons.io.FileUtils;
import org.jetbrains.annotations.NotNull;
import org.spongepowered.include.com.google.common.base.Charsets;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class RGRuleManager {
private static final RGRuleManager INSTANCE = new RGRuleManager();
private static final LevelResource path = new LevelResource("rolling_gate.json");
private final Map<String, RGRule<?>> rules;
private String namespace = "rolling_gate";

public RGRuleManager() {
this.rules = new HashMap<>();
}

public static void reInitSaveRules(MinecraftServer server) {
Path path = server.getWorldPath(RGRuleManager.path);
JsonObject config = getOrCreateContent(path);
public void reInit(@NotNull JsonObject config) {
config.entrySet().forEach((entry) -> {
RGRule<?> rule = INSTANCE.rules.get(entry.getKey());
RGRule<?> rule = this.rules.get(entry.getKey());
if (rule != null) rule.setFieldValue(entry.getValue());
});
}

public void register(RGRule<?> rule) {
this.rules.put(rule.namespace, rule);
public void register(Class<?> rules) {
RGRuleManager.of(this.namespace, rules).forEach(rule -> this.rules.put(rule.serialize(), rule));
}

private static JsonObject getOrCreateContent(Path path) {
File file = path.toFile();
try {
if (!file.exists() || file.isDirectory()) {
FileUtils.writeStringToFile(file, "{}", Charsets.UTF_8);
return new JsonObject();
}
String value = FileUtils.readFileToString(path.toFile(), Charsets.UTF_8);
return GsonHelper.parse(value);
} catch (IOException e) {
throw new RGRuleException("Failed to read rolling gate config file", e);
}
public void setNamespace(String namespace) {
this.namespace = namespace;
}

public static @NotNull List<RGRule<?>> of(String namespace, @NotNull Class<?> rules) {
private static @NotNull List<RGRule<?>> of(String namespace, @NotNull Class<?> rules) {
List<RGRule<?>> ruleList = new ArrayList<>();
for (Field field : rules.getDeclaredFields()) {
if (!Modifier.isStatic(field.getModifiers())) continue;
Expand All @@ -65,5 +44,4 @@ private static JsonObject getOrCreateContent(Path path) {
}
return ruleList;
}

}
Loading

0 comments on commit 83eab2c

Please sign in to comment.