• 200金粒签到奖励和周年纪念勋章(4/5/6/7周年)销售将于 4月13日晚结束,不要错过噢!【点我去看看】

讨论 【Bukkit插件开发】读取配置,把 getMapList 变成 getSectionList

MrXiaoM

【Lv:4】

VIP
开发者
正式会员
注册
2021/08/13
消息
165
金粒
6,405金粒
各位除非是自动序列化的,或多或少应该都是用 Bukkit 自带的 YamlConfiguration 来读写 yml 配置的,一般如无必要都是直接使用内置的来得快一些。
但是,有一天,我遇上了要读取下面这个玩意的需求

YAML:
rewards:
  - type: mythic
    mythic: ExampleItem
    rate: 0.05
    amount: 1
  - type: vanilla
    material: DIAMOND
    rate: 0.1
    amount: 1
  - type: vanilla
    material: IRON_INGOT
    rate: 0.5
    amount: 1
以防脑子一时没转过弯来,提醒一下,这是一个列表 (List),列表里面套配置 (ConfigurationSection)。

但是 Bukkit 只给了一个 getMapList 用来读取这种格式,返回的是 List<Map<?, ?>>
如果你要用这玩意,恭喜你,你要写额外空检查、类型检查等等一大堆乱七八糟的玩意,ConfigurationSection 提供的便利全都没有啦。

Java:
for (Map<?, ?> map : config.getMapList("rewards")) {
    String type = (String) map.get("type");
    Object amountRaw = map.get("amount"); // 看着就烦
    int amount = amountRaw instance Integer ? (int) amountRaw : 1;
    // ...
}

这只是配置相对简单的场景,要是列表下套的配置还有子项,比如
YAML:
rewards:
  - type: mythic
    mythic:
      type: ExampleItem
      level: 10

甚至于还有可能列表套配置再套列表,那就非常麻烦了…

我的解决方法是想办法把它返回的这个 List<Map<?, ?>> 给转换成 List<ConfigurationSection>,下面是实现代码,唯一的缺点是保存会丢注释,如果这个配置只读不写,那问题不大。

Java:
    @NotNull
    public static List<ConfigurationSection> getSectionList(ConfigurationSection parent, String key) {
        List<ConfigurationSection> list = new ArrayList<>();
        List<Map<?, ?>> rawList = parent.getMapList(key);
        for (Map<?, ?> map : rawList) {
            MemoryConfiguration section = new MemoryConfiguration();
            for (Map.Entry<?, ?> entry : map.entrySet()) {
                String sectionKey = entry.getKey().toString();
                section.set(sectionKey, processValue(section, sectionKey, entry.getValue()));
            }
            list.add(section);
        }
        return list;
    }

    private static Object processValue(ConfigurationSection parent, String key, Object value) {
        if (value instanceof Map<?, ?>) {
            Map<?, ?> map = (Map<?, ?>) value;
            ConfigurationSection section;
            if (parent == null || key == null) { // 兼容 List
                section = new MemoryConfiguration();
            } else { // 兼容 Map
                section = parent.createSection(key);
            }
            for (Map.Entry<?, ?> entry : map.entrySet()) {
                String mapKey = entry.getKey().toString();
                section.set(mapKey, processValue(section, mapKey, entry.getValue()));
            }
            return section;
        }
        if (value instanceof List<?>) {
            List<?> list = (List<?>) value;
            List<Object> result = new ArrayList<>();
            for (Object object : list) {
                result.add(processValue(null, null, object));
            }
            return result;
        }
        return value;
    }

这样读取起来就会相对舒适一点了。

Java:
for (ConfigurationSection section : getSectionList(config, "rewards")) {
    String type = section.getString("type");
    int amount = section.getInt("amount", 1);
    // ...
}


本文代码来自我的仓库 PluginBase
与仓库共用许可证 MIT License
 

在线会员

  • Starry
  • Superhero_JZ
  • ccccyyyyy
  • ou150654
  • xuantianzhilin
  • yekina
  • RMiracle
  • 炸鸡大王
  • 青菜白玉汤
  • 星铸笑
  • Satona
  • Caldron
  • 诗音
  • 2016
  • Nico6719
  • YSYERROR
  • 伊希娅
  • 溥翠韵
  • Edithfus
  • 钛歌
...和 39 更多。
后退
顶部 底部