Skip to content

Commit d4d4122

Browse files
authored
Allow registration of data resource reloader using a factory and provide a store to store data reload results. (#4944)
* Allow once again to register data resource reloader using a factory, and provide a mechanism to store data in `MinecraftServer` once a resource reload completes. * Remove dead code, add access to advancement and recipe loaders. * Fix import order of `DataResourceLoader`. * Fix interface injection of `DataResourceStore` into `MinecraftServer`.
1 parent bee81f0 commit d4d4122

File tree

17 files changed

+415
-103
lines changed

17 files changed

+415
-103
lines changed

fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/api/resource/ResourceManagerHelper.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ default void addReloadListener(IdentifiableResourceReloadListener listener) {
6262
*
6363
* @param identifier The identifier of the listener.
6464
* @param listenerFactory A function that creates a new instance of the listener with a given registry lookup.
65-
* @deprecated Use {@link net.fabricmc.fabric.api.resource.v1.ResourceLoader#RELOADER_REGISTRY_LOOKUP_KEY} with {@link net.minecraft.resource.ResourceReloader.Store} instead.
65+
* @deprecated Use {@link net.fabricmc.fabric.api.resource.v1.ResourceLoader#RELOADER_REGISTRY_LOOKUP_KEY} with {@link net.minecraft.resource.ResourceReloader.Store},
66+
* or {@link net.fabricmc.fabric.api.resource.v1.DataResourceLoader#registerReloader(Identifier, Function)} instead.
6667
*/
6768
@Deprecated
6869
void registerReloadListener(Identifier identifier, Function<RegistryWrapper.WrapperLookup, IdentifiableResourceReloadListener> listenerFactory);

fabric-resource-loader-v1/build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
version = getSubprojectVersion(project)
22

3+
loom {
4+
accessWidenerPath = file("src/main/resources/fabric-resource-loader-v1.accesswidener")
5+
}
6+
37
moduleDependencies(project, ['fabric-api-base'])
48

59
testDependencies(project, [
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package net.fabricmc.fabric.api.resource.v1;
18+
19+
import java.util.function.Function;
20+
21+
import org.jetbrains.annotations.ApiStatus;
22+
23+
import net.minecraft.recipe.ServerRecipeManager;
24+
import net.minecraft.registry.RegistryWrapper;
25+
import net.minecraft.resource.ResourceReloader;
26+
import net.minecraft.resource.ResourceType;
27+
import net.minecraft.server.ServerAdvancementLoader;
28+
import net.minecraft.util.Identifier;
29+
30+
import net.fabricmc.fabric.impl.resource.v1.DataResourceLoaderImpl;
31+
32+
/**
33+
* Provides various hooks into the {@linkplain net.minecraft.resource.ResourceType#SERVER_DATA server data} resource loader.
34+
*/
35+
@ApiStatus.NonExtendable
36+
public interface DataResourceLoader extends ResourceLoader {
37+
/**
38+
* The resource reloader store key for the recipe manager.
39+
*
40+
* @apiNote The recipe manager is only available in {@linkplain ResourceType#SERVER_DATA server data} resource reloaders.
41+
* <br/>
42+
* It should <b>only</b> be accessed in the application phase of the resource reloader,
43+
* and you should depend on {@link net.fabricmc.fabric.api.resource.v1.reloader.ResourceReloaderKeys.Server#RECIPES}.
44+
*/
45+
ResourceReloader.Key<ServerRecipeManager> RECIPE_MANAGER_KEY = new ResourceReloader.Key<>();
46+
/**
47+
* The resource reloader store key for the advancement loader.
48+
*
49+
* @apiNote The advancement loader is only available in {@linkplain ResourceType#SERVER_DATA server data} resource reloaders.
50+
* <br/>
51+
* It should <b>only</b> be accessed in the application phase of the resource reloader,
52+
* and you should depend on {@link net.fabricmc.fabric.api.resource.v1.reloader.ResourceReloaderKeys.Server#ADVANCEMENTS}.
53+
*/
54+
ResourceReloader.Key<ServerAdvancementLoader> ADVANCEMENT_LOADER_KEY = new ResourceReloader.Key<>();
55+
/**
56+
* The resource reloader store key for the data resource store.
57+
*
58+
* @apiNote The data resource store is only available in {@linkplain ResourceType#SERVER_DATA server data} resource reloaders.
59+
* <br/>
60+
* It should <b>only</b> be mutated in the application phase of the resource reloader.
61+
*/
62+
ResourceReloader.Key<DataResourceStore.Mutable> DATA_RESOURCE_STORE_KEY = new ResourceReloader.Key<>();
63+
64+
static DataResourceLoader get() {
65+
return DataResourceLoaderImpl.INSTANCE;
66+
}
67+
68+
/**
69+
* Registers a data resource reloader.
70+
*
71+
* @param id the identifier of the resource reloader
72+
* @param factory the factory function of the resource reloader
73+
* @see #registerReloader(Identifier, ResourceReloader)
74+
* @see #addReloaderOrdering(Identifier, Identifier)
75+
*
76+
* @apiNote In most cases {@link #registerReloader(Identifier, ResourceReloader)} is sufficient and should be preferred,
77+
* but for some resource reloaders like {@link net.minecraft.resource.JsonDataLoader} constructing the resource reloader
78+
* with a known instance of the wrapper lookup is required.
79+
* <br/>
80+
* While this may encourage stateful resource reloaders, it is best to primarily use resource reloaders as stateless loaders,
81+
* as storing a state may easily lead to incomplete or leaking data.
82+
*/
83+
void registerReloader(
84+
Identifier id,
85+
Function<RegistryWrapper.WrapperLookup, ResourceReloader> factory
86+
);
87+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package net.fabricmc.fabric.api.resource.v1;
18+
19+
/**
20+
* Represents a resource store for data.
21+
*
22+
* <p>Such resource store can be filled in the application phase of data {@linkplain net.minecraft.resource.ResourceReloader resource reloaders}.
23+
* And queried through an instance of {@link net.minecraft.server.MinecraftServer}.
24+
*/
25+
public interface DataResourceStore {
26+
/**
27+
* Represents a typed key for {@linkplain DataResourceStore the data resource store}.
28+
*
29+
* @param <T> the type of this key
30+
*/
31+
final class Key<T> {
32+
}
33+
34+
/**
35+
* Gets data stored at the given key, or throws if not found.
36+
*
37+
* @param key the key
38+
* @return the data stored at the given key
39+
* @param <T> the type of data
40+
*/
41+
<T> T getOrThrow(Key<T> key);
42+
43+
interface Mutable extends DataResourceStore {
44+
/**
45+
* Puts data at the given key.
46+
*
47+
* @param key the key to store at
48+
* @param data the data to store
49+
* @param <T> the type of data
50+
*/
51+
<T> void put(Key<T> key, T data);
52+
}
53+
}

fabric-resource-loader-v1/src/main/java/net/fabricmc/fabric/api/resource/v1/ResourceLoader.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ static ResourceLoader get(ResourceType type) {
4949
}
5050

5151
/**
52-
* Register a resource reloader for a given resource manager type.
52+
* Registers a resource reloader for a given resource manager type.
5353
*
5454
* @param id the identifier of the resource reloader
5555
* @param reloader the resource reloader
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package net.fabricmc.fabric.impl.resource.v1;
18+
19+
import java.util.LinkedHashMap;
20+
import java.util.Map;
21+
import java.util.Objects;
22+
import java.util.Set;
23+
import java.util.function.Function;
24+
25+
import org.jetbrains.annotations.Nullable;
26+
27+
import net.minecraft.registry.RegistryWrapper;
28+
import net.minecraft.resource.ResourceReloader;
29+
import net.minecraft.resource.ResourceType;
30+
import net.minecraft.util.Identifier;
31+
32+
import net.fabricmc.fabric.api.resource.v1.DataResourceLoader;
33+
34+
public final class DataResourceLoaderImpl extends ResourceLoaderImpl implements DataResourceLoader {
35+
public static final DataResourceLoaderImpl INSTANCE = new DataResourceLoaderImpl();
36+
private final Map<Identifier, Function<RegistryWrapper.WrapperLookup, ResourceReloader>> addedReloaderFactories
37+
= new LinkedHashMap<>();
38+
39+
private DataResourceLoaderImpl() {
40+
super(ResourceType.SERVER_DATA);
41+
}
42+
43+
@Override
44+
protected boolean hasResourceReloader(Identifier id) {
45+
return super.hasResourceReloader(id) || this.addedReloaderFactories.containsKey(id);
46+
}
47+
48+
@Override
49+
public void registerReloader(Identifier id, Function<RegistryWrapper.WrapperLookup, ResourceReloader> factory) {
50+
Objects.requireNonNull(id, "The reloader identifier should not be null.");
51+
Objects.requireNonNull(factory, "The reloader factory should not be null.");
52+
this.checkUniqueResourceReloader(id);
53+
54+
for (Map.Entry<Identifier, Function<RegistryWrapper.WrapperLookup, ResourceReloader>> entry
55+
: this.addedReloaderFactories.entrySet()
56+
) {
57+
if (entry.getValue() == factory) {
58+
throw new IllegalStateException(
59+
"Resource reloader factory with ID %s already in resource reloader factory set with ID %s!"
60+
.formatted(id, entry.getKey())
61+
);
62+
}
63+
}
64+
65+
this.addedReloaderFactories.put(id, factory);
66+
}
67+
68+
@Override
69+
protected Set<Map.Entry<Identifier, ResourceReloader>> collectReloadersToAdd(
70+
@Nullable SetupMarkerResourceReloader setupMarker
71+
) {
72+
if (setupMarker == null) {
73+
throw new IllegalStateException("The setup marker should not be null for data resource loading.");
74+
}
75+
76+
RegistryWrapper.WrapperLookup registries = setupMarker.dataPackContents().getReloadableRegistries().createRegistryLookup();
77+
Set<Map.Entry<Identifier, ResourceReloader>> reloadersToAdd = super.collectReloadersToAdd(setupMarker);
78+
79+
for (Map.Entry<Identifier, Function<RegistryWrapper.WrapperLookup, ResourceReloader>> entry
80+
: this.addedReloaderFactories.entrySet()
81+
) {
82+
ResourceReloader reloader = entry.getValue().apply(registries);
83+
reloadersToAdd.add(Map.entry(entry.getKey(), reloader));
84+
}
85+
86+
return reloadersToAdd;
87+
}
88+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package net.fabricmc.fabric.impl.resource.v1;
18+
19+
import java.util.IdentityHashMap;
20+
import java.util.Map;
21+
import java.util.Objects;
22+
23+
import net.fabricmc.fabric.api.resource.v1.DataResourceStore;
24+
25+
public final class DataResourceStoreImpl implements DataResourceStore.Mutable {
26+
private final Map<Key<?>, Object> store = new IdentityHashMap<>();
27+
28+
@Override
29+
public <T> void put(Key<T> key, T data) {
30+
this.store.put(key, data);
31+
}
32+
33+
@SuppressWarnings("unchecked")
34+
@Override
35+
public <T> T getOrThrow(Key<T> key) {
36+
return Objects.requireNonNull((T) this.store.get(key));
37+
}
38+
}
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616

1717
package net.fabricmc.fabric.impl.resource.v1;
1818

19-
import net.minecraft.registry.RegistryWrapper;
19+
import net.fabricmc.fabric.api.resource.v1.DataResourceStore;
2020

21-
public interface FabricRecipeManager {
22-
RegistryWrapper.WrapperLookup fabric$getRegistries();
21+
public interface FabricDataResourceStoreHolder {
22+
DataResourceStore.Mutable fabric$getDataResourceStore();
2323
}

0 commit comments

Comments
 (0)