Skip to content

Commit e041ddc

Browse files
committed
[resource loader] initial work on V2
1 parent 3819212 commit e041ddc

229 files changed

Lines changed: 9715 additions & 3802 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 159 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,161 @@
11
# Resource Loader API
22

3-
The Resource Loader API allows mods to load their own resources into the game. The mod's resources are wrapped in a "built-in resource pack" which allows the game to find them.
3+
The Resource Loader API allows mods to load their own resources into the game. On top of that, it provides its own access layer for resource packs and resource management.
4+
5+
## Loading Your Mod's Resources
6+
7+
Mods do not need to manually load their resources into the game. OSL wraps each mod's resources in a resource pack and loads all those resource packs in under the `fabric-mod-resources` pack. You can check that this is working by opening the Resource Packs screen and checking that `fabric-mod-resources` appears in the selected packs list.
8+
9+
## Resource Loader Events
10+
11+
The API provides several events for both the client and server, for initializing resource management and listening for resource reloads. Event listeners for these events should be registered in your mod's entrypoint.
12+
13+
```java
14+
package com.example;
15+
16+
import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer;
17+
import net.ornithemc.osl.networking.api.client.ClientPlayNetworking;
18+
19+
public class ExampleInitializer implements ClientModInitializer {
20+
21+
@Override
22+
public void initClient() {
23+
ClientResourceLoaderEvents.INIT_RESOURCE_PACK_REPOSITORY.register(packRepository -> {
24+
// register resource pack repository sources here
25+
});
26+
ClientResourceLoaderEvents.INIT_RESOURCE_MANAGER.register(resourceManager -> {
27+
// register resource reloaders and reload listeners here
28+
});
29+
ClientResourceLoaderEvents.START_RESOURCE_PACKS_RELOAD.register(() -> {
30+
// this code is run before the resource pack repository is reloaded
31+
});
32+
ClientResourceLoaderEvents.START_RESOURCE_RELOAD.register(() -> {
33+
// this code is run before a resource reload is started
34+
});
35+
}
36+
}
37+
```
38+
39+
## Bundled Mod Resource Packs
40+
41+
The API provides a way for mods to provide multiple bundled resource packs. You can do this by using sub-directories in your project resources. This is useful if you want to separate client assets from server data, or if you want to organize resources into bundles for specific feature sets or project modules.
42+
43+
To ensure these resources are loaded properly, register them in your mod's entrypoint.
44+
45+
```java
46+
package com.example;
47+
48+
import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer;
49+
import net.ornithemc.osl.networking.api.client.ClientPlayNetworking;
50+
51+
public class ExampleInitializer implements ClientModInitializer {
52+
53+
private static final ModContainer MOD = FabricLoader.getInstance().getModContainer("example").get()
54+
55+
@Override
56+
public void initClient() {
57+
ResourcePackRepository.registerBundledModResources("cookie-assets", MOD, "client/cookies/")
58+
}
59+
}
60+
```
61+
62+
## Resource Pack Repositories
63+
64+
The client and server each have their own resource pack repositories. You can add a custom source to load in custom resource packs.
65+
66+
```java
67+
package com.example;
68+
69+
import net.ornithemc.osl.entrypoints.api.client.ClientModInitializer;
70+
import net.ornithemc.osl.networking.api.client.ClientPlayNetworking;
71+
72+
public class ExampleRepositorySource implements ResourcePackRepository.Source {
73+
74+
@Override
75+
public void loadResourcePacks(Consumer<ResourcePack> consumer) {
76+
// Load your custom resource packs here.
77+
// These can be virtual resource packs, or packs loaded
78+
// from a special file directory.
79+
...
80+
}
81+
}
82+
```
83+
84+
```java
85+
ClientResourceLoaderEvents.INIT_RESOURCE_PACK_REPOSITORY.register(packRepository -> {
86+
packRepository.addSource(new ExampleRepositorySource());
87+
});
88+
```
89+
90+
## Resource Management
91+
92+
The client and server each has their own resource manager. You can use this to access resources and register resource reloaders or reload listeners.
93+
94+
95+
```java
96+
ResourceManager resourceManager = ResourceManager.client();
97+
98+
// Get resource as an InputStream using a direct String path.
99+
// Use this to access Vanilla resources in versions before 1.6.
100+
// For custom resources you add, it is recommended to lay them
101+
// out in namespaced directories like Vanilla in 1.6 and later.
102+
resourceManager.getResource("/path/to/resource");
103+
104+
// Get resource as an Optional<Resource> using a namespaced location.
105+
// Use this to access Vanilla resources in versions 1.6 and later.
106+
// It is recommended to lay out custom resources in namespaced
107+
// directories for improved compatibility and extra features.
108+
resourceManager.getResource(NamespacedIdentifiers.from("example", "path/to/resource"));
109+
110+
// Get all resources as a Map<NamespacedIdentifier, Resource>
111+
// in the specified directory that match the specified filter.
112+
// NOTE: the specified directory is not resolved from the root
113+
// of the resource packs, but from the namespaced directories!
114+
// For example: a file at /directory/to/resources/example.json
115+
// will NOT be found, but
116+
// a file at `/assets/example/directory/to/resources/example.json
117+
// WILL be found.`
118+
resourceManager.findResources("directory/to/resources/", FileNameFilter.JSON);
119+
```
120+
121+
```java
122+
public class CookiesManager implements SimpleResourceReloader<Cookies> {
123+
124+
private Cookies cookies;
125+
126+
@Override
127+
public Cookies reloadResources(ResourceManager manager) {
128+
// Load resources from the resource manager here, parse them
129+
// as necessary, and package them up. This code may not run
130+
// on the main game thread, so it is imperative that you do
131+
// not modify the world or render state here!
132+
Cookies cookies = ...
133+
return cookies;
134+
}
135+
136+
@Override
137+
public void applyResources(Cookies cookies, ResourceManager manager) {
138+
// Use the resources you loaded, and parsed above to modify
139+
// the world or render state as necessary.
140+
this.cookies = cookies;
141+
}
142+
}
143+
```
144+
145+
```java
146+
public class ExampleReloadListener implements ResourceReloadListener {
147+
148+
@Override
149+
public void resourcesReloaded(ResourceManager manager) {
150+
//
151+
...
152+
}
153+
}
154+
```
155+
156+
```java
157+
ClientResourceLoaderEvents.INIT_RESOURCE_MANAGER.register(resourceManager -> {
158+
resourceManager.addReloader(new CookiesManager());
159+
resourceManager.addReloader(new ExampleReloadListener());
160+
});
161+
```
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,5 @@
11
setUpLibrary(project)
2+
3+
dependencies {
4+
implementation 'com.google.code.gson:gson:2.8.0'
5+
}

libraries/resource-loader/gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,4 @@ library_name = Resource Loader
33
library_description = Resource loading API and events.
44
library_version = 0.6.1
55

6-
osl_dependencies = core:>=0.7.0
6+
osl_dependencies = core:>=0.7.0,executors:>=0.1.0-,text-components:>=0.1.0-

libraries/resource-loader/resource-loader-mc11w49a-mc1.2.5/build.gradle renamed to libraries/resource-loader/resource-loader-mc1.8.2-pre5-mc1.12.2/build.gradle

File renamed without changes.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
environment = client
2+
min_mc_version = 1.8.2-pre5
3+
max_mc_version = 1.12.2
4+
minecraft_dependency = >=1.8.2-rc.5 <=1.12.2
5+
6+
minecraft_version = 1.12.2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package net.ornithemc.osl.resource.loader.impl;
2+
3+
import java.util.function.Consumer;
4+
5+
import net.minecraft.client.resource.pack.ResourcePacks;
6+
7+
import net.ornithemc.osl.resource.loader.api.resource.pack.PackPosition;
8+
import net.ornithemc.osl.resource.loader.api.resource.pack.ResourcePack;
9+
import net.ornithemc.osl.resource.loader.api.resource.repository.ResourcePackRepository;
10+
import net.ornithemc.osl.resource.loader.api.resource.repository.ResourcePackSummary;
11+
import net.ornithemc.osl.resource.loader.impl.adapter.WrappedResourcePack;
12+
13+
public class ClientResourcePacks implements ResourcePackRepository.Source {
14+
15+
private final ResourcePacks resourcePacks;
16+
17+
public ClientResourcePacks(ResourcePacks resourcePacks) {
18+
this.resourcePacks = resourcePacks;
19+
}
20+
21+
@Override
22+
public void loadResourcePacks(Consumer<ResourcePackSummary> consumer) {
23+
ResourcePack pack = new WrappedResourcePack(this.resourcePacks.defaultPack);
24+
ResourcePackSummary summary = ResourcePackSummary.create(
25+
pack,
26+
true,
27+
false,
28+
PackPosition.BOTTOM
29+
);
30+
31+
consumer.accept(summary);
32+
33+
if (this.resourcePacks.getServerPack() != null) {
34+
ResourcePack serverPack = new WrappedResourcePack(this.resourcePacks.getServerPack());
35+
ResourcePackSummary serverSummary = ResourcePackSummary.create(
36+
serverPack,
37+
true,
38+
true,
39+
PackPosition.TOP
40+
);
41+
42+
if (serverSummary != null) {
43+
consumer.accept(serverSummary);
44+
}
45+
}
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package net.ornithemc.osl.resource.loader.impl.adapter;
2+
3+
import java.io.FileNotFoundException;
4+
import java.io.IOException;
5+
import java.util.ArrayList;
6+
import java.util.Collections;
7+
import java.util.List;
8+
import java.util.Optional;
9+
import java.util.stream.Collectors;
10+
11+
import net.minecraft.client.resource.metadata.ResourceMetadataSerializerRegistry;
12+
import net.minecraft.resource.Identifier;
13+
14+
import net.ornithemc.osl.core.api.util.NamespacedIdentifier;
15+
import net.ornithemc.osl.resource.loader.api.resource.Resource;
16+
import net.ornithemc.osl.resource.loader.api.resource.pack.ResourcePack;
17+
18+
class Adapters {
19+
20+
static Identifier identifier(NamespacedIdentifier id) {
21+
return id instanceof Identifier ? (Identifier) id : new Identifier(id.namespace(), id.identifier());
22+
}
23+
24+
static net.minecraft.client.resource.Resource resource(ResourceMetadataSerializerRegistry metadataSerializers, Resource resource) throws IOException {
25+
return new ResourceAdapter(metadataSerializers, resource);
26+
}
27+
28+
static net.minecraft.client.resource.Resource resource(ResourceMetadataSerializerRegistry metadataSerializers, NamespacedIdentifier location, Optional<Resource> resource) throws IOException {
29+
if (resource.isPresent()) {
30+
return resource(metadataSerializers, resource.get());
31+
}
32+
33+
throw new FileNotFoundException(location.toString());
34+
}
35+
36+
static List<net.minecraft.client.resource.Resource> resources(ResourceMetadataSerializerRegistry metadataSerializers, List<Resource> resources) throws IOException {
37+
List<net.minecraft.client.resource.Resource> rs = new ArrayList<>();
38+
39+
for (Resource resource : resources) {
40+
rs.add(resource(metadataSerializers, resource));
41+
}
42+
43+
return Collections.unmodifiableList(rs);
44+
}
45+
46+
static net.minecraft.client.resource.pack.ResourcePack resourcePack(ResourcePack pack) {
47+
if (pack instanceof WrappedResourcePack) {
48+
return ((WrappedResourcePack) pack).pack;
49+
} else {
50+
return new ResourcePackAdapter(pack);
51+
}
52+
}
53+
54+
static ResourcePack resourcePack(net.minecraft.client.resource.pack.ResourcePack pack) {
55+
if (pack instanceof ResourcePackAdapter) {
56+
return ((ResourcePackAdapter) pack).pack;
57+
} else {
58+
return new WrappedResourcePack(pack);
59+
}
60+
}
61+
62+
static List<net.minecraft.client.resource.pack.ResourcePack> packs(List<ResourcePack> packs) {
63+
return packs.stream().map(Adapters::resourcePack).collect(Collectors.toList());
64+
}
65+
66+
static List<ResourcePack> resourcePacks(List<net.minecraft.client.resource.pack.ResourcePack> packs) {
67+
return packs.stream().map(Adapters::resourcePack).collect(Collectors.toList());
68+
}
69+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package net.ornithemc.osl.resource.loader.impl.adapter;
2+
3+
import java.io.IOException;
4+
import java.io.InputStream;
5+
6+
import com.google.gson.JsonObject;
7+
8+
import net.minecraft.client.resource.metadata.ResourceMetadataSection;
9+
import net.minecraft.client.resource.metadata.ResourceMetadataSerializerRegistry;
10+
import net.minecraft.resource.Identifier;
11+
12+
import net.ornithemc.osl.resource.loader.api.resource.Resource;
13+
import net.ornithemc.osl.resource.loader.api.resource.ResourceMetadata;
14+
import net.ornithemc.osl.resource.loader.impl.resource.JsonResourceMetadata;
15+
16+
class ResourceAdapter implements net.minecraft.client.resource.Resource {
17+
18+
private final ResourceMetadataSerializerRegistry metadataSerializers;
19+
private final Identifier location;
20+
private final InputStream resource;
21+
private final ResourceMetadata metadata;
22+
private String sourceName;
23+
24+
ResourceAdapter(ResourceMetadataSerializerRegistry metadataSerializers, Resource resource) throws IOException {
25+
ResourceMetadata metadata;
26+
27+
try {
28+
metadata = resource.metadata();
29+
} catch (IOException e) {
30+
metadata = ResourceMetadata.EMPTY;
31+
}
32+
33+
this.metadataSerializers = metadataSerializers;
34+
this.location = Adapters.identifier(resource.location());
35+
this.resource = resource.open();
36+
this.metadata = metadata;
37+
this.sourceName = resource.sourceName();
38+
}
39+
40+
@Override
41+
public Identifier getLocation() {
42+
return this.location;
43+
}
44+
45+
@Override
46+
public InputStream asStream() {
47+
return this.resource;
48+
}
49+
50+
@Override
51+
public <T extends ResourceMetadataSection> T getMetadata(String name) {
52+
if (this.metadata instanceof JsonResourceMetadata) {
53+
JsonResourceMetadata meta = (JsonResourceMetadata) this.metadata;
54+
JsonObject metadataJson = meta.asJsonObject();
55+
56+
return this.metadataSerializers.readMetadata(name, metadataJson);
57+
} else {
58+
return null;
59+
}
60+
}
61+
62+
@Override
63+
public boolean hasMetadata() {
64+
return this.metadata != ResourceMetadata.EMPTY;
65+
}
66+
67+
@Override
68+
public String getSourceName() {
69+
return this.sourceName;
70+
}
71+
72+
@Override
73+
public void close() throws IOException {
74+
this.resource.close();
75+
}
76+
}

0 commit comments

Comments
 (0)