Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ default void addReloadListener(IdentifiableResourceReloadListener listener) {
*
* @param identifier The identifier of the listener.
* @param listenerFactory A function that creates a new instance of the listener with a given registry lookup.
* @deprecated Use {@link net.fabricmc.fabric.api.resource.v1.ResourceLoader#RELOADER_REGISTRY_LOOKUP_KEY} with {@link net.minecraft.resource.ResourceReloader.Store} instead.
* @deprecated Use {@link net.fabricmc.fabric.api.resource.v1.ResourceLoader#RELOADER_REGISTRY_LOOKUP_KEY} with {@link net.minecraft.resource.ResourceReloader.Store},
* or {@link net.fabricmc.fabric.api.resource.v1.DataResourceLoader#registerReloader(Identifier, Function)} instead.
*/
@Deprecated
void registerReloadListener(Identifier identifier, Function<RegistryWrapper.WrapperLookup, IdentifiableResourceReloadListener> listenerFactory);
Expand Down
4 changes: 4 additions & 0 deletions fabric-resource-loader-v1/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
version = getSubprojectVersion(project)

loom {
accessWidenerPath = file("src/main/resources/fabric-resource-loader-v1.accesswidener")
}

moduleDependencies(project, ['fabric-api-base'])

testDependencies(project, [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.resource.v1;

import java.util.function.Function;

import org.jetbrains.annotations.ApiStatus;

import net.minecraft.recipe.ServerRecipeManager;
import net.minecraft.registry.RegistryWrapper;
import net.minecraft.resource.ResourceReloader;
import net.minecraft.resource.ResourceType;
import net.minecraft.server.ServerAdvancementLoader;
import net.minecraft.util.Identifier;

import net.fabricmc.fabric.impl.resource.v1.DataResourceLoaderImpl;

/**
* Provides various hooks into the {@linkplain net.minecraft.resource.ResourceType#SERVER_DATA server data} resource loader.
*/
@ApiStatus.NonExtendable
public interface DataResourceLoader extends ResourceLoader {
/**
* The resource reloader store key for the recipe manager.
*
* @apiNote The recipe manager is only available in {@linkplain ResourceType#SERVER_DATA server data} resource reloaders.
* <br/>
* It should <b>only</b> be accessed in the application phase of the resource reloader,
* and you should depend on {@link net.fabricmc.fabric.api.resource.v1.reloader.ResourceReloaderKeys.Server#RECIPES}.
*/
ResourceReloader.Key<ServerRecipeManager> RECIPE_MANAGER_KEY = new ResourceReloader.Key<>();
/**
* The resource reloader store key for the advancement loader.
*
* @apiNote The advancement loader is only available in {@linkplain ResourceType#SERVER_DATA server data} resource reloaders.
* <br/>
* It should <b>only</b> be accessed in the application phase of the resource reloader,
* and you should depend on {@link net.fabricmc.fabric.api.resource.v1.reloader.ResourceReloaderKeys.Server#ADVANCEMENTS}.
*/
ResourceReloader.Key<ServerAdvancementLoader> ADVANCEMENT_LOADER_KEY = new ResourceReloader.Key<>();
/**
* The resource reloader store key for the data resource store.
*
* @apiNote The data resource store is only available in {@linkplain ResourceType#SERVER_DATA server data} resource reloaders.
* <br/>
* It should <b>only</b> be mutated in the application phase of the resource reloader.
*/
ResourceReloader.Key<DataResourceStore.Mutable> DATA_RESOURCE_STORE_KEY = new ResourceReloader.Key<>();

static DataResourceLoader get() {
return DataResourceLoaderImpl.INSTANCE;
}

/**
* Registers a data resource reloader.
*
* @param id the identifier of the resource reloader
* @param factory the factory function of the resource reloader
* @see #registerReloader(Identifier, ResourceReloader)
* @see #addReloaderOrdering(Identifier, Identifier)
*
* @apiNote In most cases {@link #registerReloader(Identifier, ResourceReloader)} is sufficient and should be preferred,
* but for some resource reloaders like {@link net.minecraft.resource.JsonDataLoader} constructing the resource reloader
* with a known instance of the wrapper lookup is required.
* <br/>
* While this may encourage stateful resource reloaders, it is best to primarily use resource reloaders as stateless loaders,
* as storing a state may easily lead to incomplete or leaking data.
*/
void registerReloader(
Identifier id,
Function<RegistryWrapper.WrapperLookup, ResourceReloader> factory
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit confused why we are using a WrapperLookup here, rather than the DataResourceStore. Is there a good reason?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, the main need for this overload is for JsonDataLoader and it only needs WrapperLookup, I'm a bit concerned about how confusing the DataResourceStore might be here.
Also the DataResourceStore does not contain the WrapperLookup, the lookup and other reloaders are also available through the Vanilla ResourceReloader shared state store.

);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package net.fabricmc.fabric.api.resource.v1;

/**
* Represents a resource store for data.
*
* <p>Such resource store can be filled in the application phase of data {@linkplain net.minecraft.resource.ResourceReloader resource reloaders}.
* And queried through an instance of {@link net.minecraft.server.MinecraftServer}.
*/
public interface DataResourceStore {
/**
* Represents a typed key for {@linkplain DataResourceStore the data resource store}.
*
* @param <T> the type of this key
*/
final class Key<T> {
}

/**
* Gets data stored at the given key, or throws if not found.
*
* @param key the key
* @return the data stored at the given key
* @param <T> the type of data
*/
<T> T getOrThrow(Key<T> key);

interface Mutable extends DataResourceStore {
/**
* Puts data at the given key.
*
* @param key the key to store at
* @param data the data to store
* @param <T> the type of data
*/
<T> void put(Key<T> key, T data);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ static ResourceLoader get(ResourceType type) {
}

/**
* Register a resource reloader for a given resource manager type.
* Registers a resource reloader for a given resource manager type.
*
* @param id the identifier of the resource reloader
* @param reloader the resource reloader
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

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

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;

import org.jetbrains.annotations.Nullable;

import net.minecraft.registry.RegistryWrapper;
import net.minecraft.resource.ResourceReloader;
import net.minecraft.resource.ResourceType;
import net.minecraft.util.Identifier;

import net.fabricmc.fabric.api.resource.v1.DataResourceLoader;

public final class DataResourceLoaderImpl extends ResourceLoaderImpl implements DataResourceLoader {
public static final DataResourceLoaderImpl INSTANCE = new DataResourceLoaderImpl();
private final Map<Identifier, Function<RegistryWrapper.WrapperLookup, ResourceReloader>> addedReloaderFactories
= new LinkedHashMap<>();

private DataResourceLoaderImpl() {
super(ResourceType.SERVER_DATA);
}

@Override
protected boolean hasResourceReloader(Identifier id) {
return super.hasResourceReloader(id) || this.addedReloaderFactories.containsKey(id);
}

@Override
public void registerReloader(Identifier id, Function<RegistryWrapper.WrapperLookup, ResourceReloader> factory) {
Objects.requireNonNull(id, "The reloader identifier should not be null.");
Objects.requireNonNull(factory, "The reloader factory should not be null.");
this.checkUniqueResourceReloader(id);

for (Map.Entry<Identifier, Function<RegistryWrapper.WrapperLookup, ResourceReloader>> entry
: this.addedReloaderFactories.entrySet()
) {
if (entry.getValue() == factory) {
throw new IllegalStateException(
"Resource reloader factory with ID %s already in resource reloader factory set with ID %s!"
.formatted(id, entry.getKey())
);
}
}

this.addedReloaderFactories.put(id, factory);
}

@Override
protected Set<Map.Entry<Identifier, ResourceReloader>> collectReloadersToAdd(
@Nullable SetupMarkerResourceReloader setupMarker
) {
if (setupMarker == null) {
throw new IllegalStateException("The setup marker should not be null for data resource loading.");
}

RegistryWrapper.WrapperLookup registries = setupMarker.dataPackContents().getReloadableRegistries().createRegistryLookup();
Set<Map.Entry<Identifier, ResourceReloader>> reloadersToAdd = super.collectReloadersToAdd(setupMarker);

for (Map.Entry<Identifier, Function<RegistryWrapper.WrapperLookup, ResourceReloader>> entry
: this.addedReloaderFactories.entrySet()
) {
ResourceReloader reloader = entry.getValue().apply(registries);
reloadersToAdd.add(Map.entry(entry.getKey(), reloader));
}

return reloadersToAdd;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

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

import java.util.IdentityHashMap;
import java.util.Map;
import java.util.Objects;

import net.fabricmc.fabric.api.resource.v1.DataResourceStore;

public final class DataResourceStoreImpl implements DataResourceStore.Mutable {
private final Map<Key<?>, Object> store = new IdentityHashMap<>();

@Override
public <T> void put(Key<T> key, T data) {
this.store.put(key, data);
}

@SuppressWarnings("unchecked")
@Override
public <T> T getOrThrow(Key<T> key) {
return Objects.requireNonNull((T) this.store.get(key));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@

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

import net.minecraft.registry.RegistryWrapper;
import net.fabricmc.fabric.api.resource.v1.DataResourceStore;

public interface FabricRecipeManager {
RegistryWrapper.WrapperLookup fabric$getRegistries();
public interface FabricDataResourceStoreHolder {
DataResourceStore.Mutable fabric$getDataResourceStore();
}
Loading
Loading