自定义数据包/资源包资源

自定义数据包/资源包资源

我们已经说完了注册 reload listener 的过程,但是你仍然还是需要写一个,这个过程的那一部分会在本段讨论(换句话说,本段将会讨论 SimpleSynchronousResourceReloadListener,然后再讨论async listeners)。

在所有的编程法则中,你应该无法在Java中实例化一个接口,因为其方法太抽象难以调用。然而,模组编写者并不关心实际的编程者觉得怎样,所以我们仍旧这么做。

new SimpleSynchronousResourceReloadListener() { @Override public Identifier getFabricId() { return new Identifier("tutorial", "my_resources"); } @Override public void apply(ResourceManager manager) { [...] }}

你在这里看到的是将要通过 ResourceManagerHelper 注册的实际上的资源reload listener(技术上讲,是一个资源reload listener,然而这不是唯一的类型,不过是最容易实现的)。如你所见,这里有两个重要的部分:getFabricId 和 apply 方法。getFabricId 方法是这两个中间相似的,你只需要返回一个独一无二的标识符来让 reload listener 考虑,没什么稀奇的。然而,apply方法是主角。

apply 方法为你提供一个 ResourceManager,有了它,就可以在注册表的资源类型的限制范围内加载任何你想加载的数据(记住,SERVER_DATA 只能访问数据包,CLIENT_RESOURCES 只能访问资源包)。你对resource manager做的事情取决于你, if you are making some aspect of your mod data-driven then you probably want to read from a specific folder. 这样做很简单,但是需要多留意一点。

首先,你会需要清除或者准备更新任何存储你准备去通过这个manager获取的信息的东西,否则你的模组一到 /reload 或 F3+T 的时候就有可能崩掉。完成之后,你应该使用 ResourceManager#findResources(String path, Predicate pathPredicate) 来获取包含在你想要的任意文件夹的文件(注意:这个路径是从所有处理过的数据包/资源包地data或者assets文件夹开始的)。这会给你一个所有在指定路径范围内且符合谓词准则(meet the predicate's criteria,你很有可能想要筛选特定的文件类型,例如在本教程中,筛选出所有的 .json)的文件的路径(path)的集合(collection),然后你会遍历这个集合然后对这些路径做些事情。

@Override public void apply(ResourceManager manager) { // 在这里清除缓存 for(Identifier id : manager.findResources("my_resource_folder", path -> path.endsWith(".json"))) { try(InputStream stream = manager.getResource(id).getInputStream()) { // Consume the stream however you want, medium, rare, or well done. } catch(Exception e) { TUTORIAL_LOG.error("Error occurred while loading resource json " + id.toString(), e); } } [...] }}

这里注意两点。首先,所有的资源都必须作为 InputStreams(输入流)处理。这意味着,你需要在处理之后关闭(close)这些资源,忘掉这样做的结果就是导致资源泄漏。要确保所有处理过的资源都关闭,最简单的方法是,使用 try-with-resource 语句块来处理,就像上面展示的那样。第二点,注意你没办法获取你处理的原始文件,所以“所有的资源都必须作为 InputStreams 处理”中的“必须”事实上是“必须”而不是“应该”。不过,有很多的解析器(parser)能够从这个输入流中获得你想要的文件,尤其是对于json。

完成之后,你的代码应该看上去像这样。此时,恭喜你已经成功地让你的模组的一部分由数据驱动了!任何包含在数据包或模组数据中的 “my_resource_folder” 文件夹中的所有文件 will get picked up by the this.

public class ExampleMod implements ModInitializer { ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(new SimpleSynchronousResourceReloadListener() { @Override public Identifier getFabricId() { return new Identifier("tutorial", "my_resources"); } @Override public void apply(ResourceManager manager) { // Clear Caches Here for(Identifier id : manager.findResources("my_resource_folder", path -> path.endsWith(".json"))) { try(IntputStream stream = manager.getResource(id).getInputStream()) { // Consume the stream however you want, medium, rare, or well done. } catch(Exception e) ( TUTORIAL_LOG.error("Error occurred while loading resource json " + id.toString(), e); } } } }); [...]}

相关推荐