Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resource Loader v1 #3083

Draft
wants to merge 7 commits into
base: 1.20
Choose a base branch
from
Draft

Conversation

Technici4n
Copy link
Member

@Technici4n Technici4n commented May 27, 2023

A much needed update to resource loader.

Resource Reload Events

  • ClientResourceReloadEvents and ServerResourceReloadEvents are added to hold new events.
  • START_RELOAD fires right before resource reloaders start running, and can for example be used to invalidate a cache before the resource reloader recomputes it.
  • END_RELOAD fires right when the reload completes (successfully or with a failure).
  • The exact place where the start event should be invoked is up for debate. Currently it is invoked after the resource reloaders are collected on the server side. Note that it's technically possible for END_RELOAD to fire without START_RELOAD having fired, if case something fails before START_RELOAD.
  • REGISTER_RELOADERS: see below.

Resource Reloaders

  • Resource reloader registration now happens in the REGISTER_RELOADERS events.
  • They still have an ID, however the ID is passed alongside the resource reloader at registration time. (Previously getFabricId had to be overridden).
  • Resource reloaders are instantiated once per reload on the server and stored inside DataPackContents; on the client they are instantiated once and then stored inside MinecraftClient.
  • Resource reloaders can be accessed from the data pack contents, the client and the server thanks to interface injection of ResourceReloaderHolder.
  • The event allows DataPackContents and MinecraftClient to be captured for cross-reloader talk during the apply phase.
  • Arbitrary ordering of reloaders was implemented (will use the same backend as event phases). Previously it was not possible to order modded reloaders before vanilla's. This was added in a fully backwards-compatible way.
  • Note 1: the client-side REGISTER_RELOADERS event only fires exactly once at the start of the game, but I figured it would still be nicer for consistency to have an event.
  • Note 2: the v0 API is bridged via LegacyReloaderHolder because the new client event is client-only, whereas the old API was side agnostic (since it did not provide any context whatsoever).

Here is an example of using this new API for a client reloader. I am not fully convinced by this usage pattern yet:

ClientResourceReloadEvents.REGISTER_RELOADERS.register(context -> {
	context.addReloader(SpecificModelReloadListener.ID, new SpecificModelReloadListener());
	context.addReloaderOrdering(ResourceReloaderKeys.BAKED_MODELS, SpecificModelReloadListener.ID);
	context.addReloaderOrdering(SpecificModelReloadListener.ID, ResourceReloaderKeys.ENTITY_RENDER_DISPATCHER);
});

// Later on:
SpecificModelReloadListener myListener = (SpecificModelReloadListener) MinecraftClient.getInstance().getResourceReloader(SpecificModelReloadListener.ID);

For server reloaders however, this matches what vanilla does, and is much nicer than what the v0 API provides today.

Resource Packs

  • Builtin packs: functionality is kept unchanged, however providing a display name is now required.
  • Currently they are registered by calling ResourcePackHelper, perhaps a better name should be found?
  • Add new events to directly register ResourcePack instances. See ResourcePackRegistrationEvents#afterMods(ResourceType) and afterAll(ResourceType).
  • These events are side-agnostic. Should we provide more (side-dependent) context to them? I am not convinced that this would be necessary.
  • These events provide a ResourceManager that allows inspecting the previous packs. This can be useful for virtual resource packs, among other things, however note that this API does not provide the virtual resource pack implementation itself.
  • Add ResourcePackHelper#createModResourcePack to directly instantiate mod nio resource packs. This can be useful to access resources in a mod JAR outside of the normal resource loading lifecycle.

Further possibilities

  • We could add an API to register custom ResourcePackProviders or ResourcePackProfiles. This can be left for a future PR imo. This would either be an event (maybe in ResourcePackRegistrationEvents), or a static registration in ResourcePackHelper.

TODO items

  • Does v1 need to implement ModResourcePack on its builtin packs too?
  • Possibly find a better name for ResourcePackHelper.
  • Possibly eliminate the action type from ModNioResourcePack entirely. Or can also be left for a future PR.
  • Add tests for ResourcePackRegistrationEvents
  • Consider adding isFirst to the context of ResourcePackRegistrationEvents. I think it can be left for later, it's a bit annoying.
  • Should we add ResourceReloaderKeys for all the vanilla reloaders? Many are missing on the client side.
  • The old resource reloader API broke ties by registration order, whereas the new APIs break ties by identifier. This is a potential breaking changes for mods. However they were not correctly specifying dependencies as required by the API, so this might be acceptable. A workaround might be to break ties by registration order when using the legacy bridge, and by identifier when using the new API.
  • Add javadoc note saying that END_RELOAD can technically fire even if START_RELOAD did not fire.

@Technici4n Technici4n force-pushed the resource-loader-v1 branch 2 times, most recently from fdc66ad to 614ad84 Compare June 9, 2023 14:47
@Technici4n Technici4n force-pushed the resource-loader-v1 branch from 614ad84 to 294923f Compare June 9, 2023 15:29
import net.fabricmc.fabric.api.event.EventFactory;
import net.fabricmc.fabric.api.resource.loader.v1.ResourceReloaderHolder;

public final class ClientResourceReloadEvents {
Copy link
Contributor

Choose a reason for hiding this comment

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

All classes should have a javadoc, IMO.


public final class ClientResourceReloadEvents {
/**
* Event to register resource reloaders for client resource packs (i.e. {@link ResourceType#CLIENT_RESOURCES}).
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this gets cut at i.e. when in summary.

});

/**
* Event that fires right when the resource reloaders finish running, but before subsequent cleanup has been performed.
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think "has been performed" is appropriate here, you can just use "occurs"

});

@FunctionalInterface
public interface RegisterReloaders {
Copy link
Contributor

Choose a reason for hiding this comment

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

Needs javadoc.

}

@FunctionalInterface
public interface StartReload {
Copy link
Contributor

Choose a reason for hiding this comment

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

Needs javadoc.

import net.fabricmc.fabric.api.event.Event;
import net.fabricmc.fabric.api.event.EventFactory;

public final class ServerResourceReloadEvents {
Copy link
Contributor

Choose a reason for hiding this comment

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

Classes should have javadocs.

@ApiStatus.NonExtendable
public interface RegisterContext extends Context {
/**
* Register a new resource reloader.
Copy link
Contributor

Choose a reason for hiding this comment

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

Registers.

void addReloader(Identifier identifier, ResourceReloader reloader);

/**
* Request that <b>the apply phase</b> of one reloader be executed before <b>the apply phase</b> of another reloader.
Copy link
Contributor

Choose a reason for hiding this comment

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

Requests.

Comment on lines +136 to +137
* @param firstReloader The identifier of the reloader that should run before the other.
* @param secondReloader The identifier of the reloader that should run after the other.
Copy link
Contributor

Choose a reason for hiding this comment

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

Param javadoc should be lowercase, no period

@@ -4,3 +4,7 @@ accessible method net/minecraft/resource/NamespaceResourceManager getMetadataPat
accessible method net/minecraft/resource/NamespaceResourceManager loadMetadata (Lnet/minecraft/resource/InputSupplier;)Lnet/minecraft/resource/metadata/ResourceMetadata;
accessible field net/minecraft/resource/FileResourcePackProvider source Lnet/minecraft/resource/ResourcePackSource;
accessible field net/minecraft/resource/ResourcePackManager providers Ljava/util/Set;
accessible class net/minecraft/server/MinecraftServer$ResourceManagerHolder
accessible field net/minecraft/resource/ReloadableResourceManagerImpl reloaders Ljava/util/List;

Copy link
Contributor

Choose a reason for hiding this comment

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

Extraneous line?

@dima-dencep
Copy link

@Technici4n any progress?

@Technici4n
Copy link
Member Author

No, I don't think I will be finishing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants