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

Add event phases #1669

Merged
merged 9 commits into from
Nov 5, 2021
Merged

Add event phases #1669

merged 9 commits into from
Nov 5, 2021

Conversation

Technici4n
Copy link
Member

@Technici4n Technici4n commented Aug 25, 2021

This is an extension of the event system to allow ordering constraints between event listeners.

Design points

  • No direct ordering constraints between listeners, as they cannot be identified reliably.
  • No integer priorities, and no fixed EventPriority enum (or a similar limited and hardcoded set of priorities).
  • An arbitrary number of event phases may be added, with soft ordering constraints w.r.t. other phases (a failure to resolve the constraints should not crash the game). Adding both soft and hard ordering constraints might also be possible, but I wasn't able to figure out how to implement them.
  • Listeners may be added to any phase.
  • This ordering system should only be used as a last resort. When it is clear from the start that multiple phases are necessary (for example ALLOW, ADD, MODIFY), multiple events should still be created as usual. However, the phase system allows adding ordering constraints beyond what the API author originally thought of.

Examples

Damage canceling

An example use case: some potion mod registers an AllowDamage handler for an invincibility potion, and some tech mod registers an AllowDamage handler for its powered armor. Ideally, the powered armor callback should be executed later, to avoid consuming energy when the potion already prevents the damage. This is impossible to predict when adding this kind of event.
This is how this PR would address it:

// Define a set of standard phases in the API (names just for illustration).
public static final Identifier
  FREE = new Identifier("fabric", "free"), // for free damage cancel (no cost).
  RENEWABLE = new Identifier("fabric", "renewable"), // for renewable damage cancel (e.g. power armor)
  DEFAULT = Event.DEFAULT_PHASE,// default
  SINGLE_USE = new Identifier("fabric", "single_use"); // for single use expensive cancel
// Define the event
Event<AllowDamage> ALLOW_DAMAGE = EventFactory.createWithPhases(AllowDamage.class, factory, FREE, RENEWABLE, DEFAULT, SINGLE_USE);
// Register a few listeners:
ALLOW_DAMAGE.register(FREE, (player, damage) -> return !player.hasPotion(INVINCIBILITY)); // potion handler
ALLOW_DAMAGE.register(RENEWABLE, (player, damage) -> return !(isWearingPoweredArmor(player) && tryUseEnergy(player, damage))); // powered armor
// etc...

Override the transfer API's item fallback

A somewhat involved use case, that would be useful to port TechReborn to the item transfer API: if API Lookup fallback providers were exposed as an Event<BlockApiProvider<A, C>>, a mod could override the default wrapping of Inventory as Storage<ItemVariant> in the item transfer API by registering its own fallback provider in an early event phase.

interface BlockApiLookup<A, C> {
    // Assume this is added:
    Event<BlockApiProvider<A, C>> fallback();
    default void registerFallback(BlockApiProvider<A, C> provider) {
        fallback().register(provider);
    }
}
// Default behavior:
ItemStorage.SIDED.registerFallback((world, pos, be, state, direction) -> {
    if (be instanceof MyModBe) {
        // runs after fabric's compat with Inventory, this will never run if MyModBe implements Inventory
    }
});
// With event phases:
Identifier phase = new Identifier("mymod", "before_fabric");
ItemStorage.SIDED.fallback().addPhaseOrdering(phase, Event.DEFAULT_PHASE);
ItemStorage.SIDED.fallback().register(phase, (world, pos, be, state, direction) -> {
    if (be instanceof MyModBe) {
        // runs BEFORE fabric's compat with Inventory, this will run even if MyModBe implements Inventory!
    }
});
// In practice fabric would provide this early phase, for this exact use case.

Any comment is welcome! 😄

@Technici4n Technici4n added enhancement New feature or request priority:low Low priority PRs that don't immediately need to be resolved reviews needed This PR needs more reviews labels Aug 25, 2021
@Technici4n Technici4n marked this pull request as ready for review August 27, 2021 18:22
@Technici4n Technici4n requested review from sfPlayer1 and a team August 28, 2021 10:29
@liach
Copy link
Contributor

liach commented Aug 28, 2021

Should we create a new interface for these phased events? Some callbacks don't need phases, and it is a somewhat expensive feature.

For the phase ordering, maybe we can find out strongly connected components first, group them equally, and then do topological sort? So if phase a and phase b have a loop dependency, the order of execution among a and b is arbitrary, but a and b will be ran before any of their descendant phases (that is not in a loop, or descendant loops).

Also this reminds me of the strategy where you create two anchors for the beginning and the end of the phase; you create one for start of free blocking damage and one for end of free blocking. Then, when you register your listener, you order it to go after the start and before the end. In your example, you do:

ALLOW_DAMAGE.register(FREE, INVINCIBILITY_POTION_HANDLER);

except you still need to guarantee that INVINCIBILITY_POTION_HANDLER runs before RENEWABLE.

@Technici4n
Copy link
Member Author

Should we create a new interface for these phased events? Some callbacks don't need phases, and it is a somewhat expensive feature.

That would prevent the feature from being adopted on day 1 though, and would require that we somehow expose the new type for most existing events.
What makes you say this is an expensive feature? I just noticed that this doubles the asymptotic memory footprint of events when many listeners are registered... I'll push a fix for this in a bit. But other than that, events with a single phase should have essentially the same performance as non-phased events.

For the phase ordering, maybe we can find out strongly connected components first, group them equally, and then do topological sort? So if phase a and phase b have a loop dependency, the order of execution among a and b is arbitrary, but a and b will be ran before any of their descendant phases (that is not in a loop, or descendant loops).

Yes that's a good idea! Doing a visit, reversing the list and then doing another visit should be enough! (That's more or less Kosaraju's algorithm, but we don't need to group SCCs together at the end). :)

Also this reminds me of the strategy where you create two anchors for the beginning and the end of the phase; you create one for start of free blocking damage and one for end of free blocking. Then, when you register your listener, you order it to go after the start and before the end.

Not sure what you mean exactly with these anchors? Do you build an ordered tree of handlers this way?
This may be similar to the "hookchain"... I've seen some commits but I'm really not familiar with how it worked.

except you still need to guarantee that INVINCIBILITY_POTION_HANDLER runs before RENEWABLE.

This is handled by createWithPhases directly, that's the point! Centralizing event phases in the event declaration (when possible) avoids each mod having to specify ordering wrt. the N-1 other mods. :)

@liach
Copy link
Contributor

liach commented Aug 28, 2021

Hmm, now I have an alternative idea, given we can split an event phase into a start and an end:
event phases may be hierarchical; when a phase Y is enclosed in X, we have ordering like X.start -> Y.start -> Y.end -> X.end.

We can have

public interface EventPhase<T> {
  // get or create another enclosed phase within this phase/event
  // may use the same phase if non-phased, but the new listener should have the given path prefix
  EventPhase<T> subPhase(String path);
  // adds ordering between two elements (phase/listener) in this phase/event
  // may be noop if not supported
  void order(String from, String to);
  // register a listener within this event/phase
  // maybe just straight register if no phase support
  void register(String path, T listener);
  // we can optionally have a pathless register, and the listener registered is 
  // only guaranteed to be called during this phase, and order with other
  // components of the phase is arbitrary; or we can direct the register to a custom subpath by default
  default void register(T listener) {
    subPhase("default").register(/* make a path */, listener);
  }
}

Was writing the comment when you replied; now I think we can actually add these 3 methods to the default Event if you see fit, and in the default impl we will just disrespect these soft orders.

So the usages are like:

EventPhase<AllowDamage> FREE = ALLOW_DAMAGE.subPhase("free");

and we don't need to add two calls to link a listener registered to the beginning and the end of the free subsection.

@liach
Copy link
Contributor

liach commented Aug 28, 2021

What makes you say this is an expensive feature?

Oh right, you compile an array of the actual invoked listeners after that, so ain't that slow

@liach
Copy link
Contributor

liach commented Aug 28, 2021

except you still need to guarantee that INVINCIBILITY_POTION_HANDLER runs before RENEWABLE.

This is handled by createWithPhases directly, that's the point! Centralizing event phases in the event declaration (when possible) avoids each mod having to specify ordering wrt. the N-1 other mods. :)

Um, I think you misunderstood this part. So we have 3 tasks, A, B, and C, and orderings A -> B and A -> C. Then ABC or ACB are both valid execution orders for the tasks. Now, plug in FREE for A, and INVINCIBILITY_POTION_HANDLER for B, and RENEWABLE for C. In your example, the A -> C is defined by event itself, and user defines A -> B. You need another B -> C link to prevent INVINCIBILITY_POTION_HANDLER from running before anything from RENEWABLE.

Hence, I proposed that nested EventPhase model above, as to avoid such user errors.

@Technici4n
Copy link
Member Author

Um, I think you misunderstood this part. So we have 3 tasks, A, B, and C, and orderings A -> B and A -> C. Then ABC or ACB are both valid execution orders for the tasks. Now, plug in FREE for A, and INVINCIBILITY_POTION_HANDLER for B, and RENEWABLE for C. In your example, the A -> C is defined by event itself, and user defines A -> B. You need another B -> C link to prevent INVINCIBILITY_POTION_HANDLER from running before anything from RENEWABLE.

Hence, I proposed that nested EventPhase model above, as to avoid such user errors.

Hmmm, in my example INVINCIBILITY_POTION_HANDLER is not an id but rather the callback, which I just register to the FREE phase. That might have been a little bit confusing, so I've updated the PR description.

@Technici4n
Copy link
Member Author

Nested phases may be an option as well. The default phase list with the option to insert some phases should be good enough for 95% of the cases where you'd need event phases, so I'm a bit hesitant. I need to think about this a little bit more. 😄
Note that we can easily extend this PR's event phase system to subphases in the future if that is necessary.

I've noticed you used String instead of Identifier in your example. I've also considered that, but I'm not sure what is better.

@liach
Copy link
Contributor

liach commented Aug 29, 2021

Here is another vision if we only allow one level of phase nesting (like as is)

public interface Event<T> {
  EventPhase<T> subPhase(String path);
  void order(String from, String to);
  default void register(T listener) {
    subPhase("default").register(listener);
  }
}

// we can later enhance this api to support nested phases (for easier sorting, etc)
public interface EventPhase<T> {
  void register(T listener);
}

Imo, creating an EventPhase<T> for registering events is more visible than specifying the phase in register.

@sfPlayer1
Copy link
Contributor

IMO nested phases don't really add much, they are only slightly more expressive than flat ordering and that's in very specific corner cases. In general phases shouldn't see that much use overall, only a few operations like damage application really need them.

Damage handling may even need a more powerful scheme, something like IC2 armor using can't be computed properly in successive steps but needs linear distribution taking all armor pieces and other effects into account. This acts as if a later handler has to influence an earlier handler, so it really needs a property gathering step followed by computation to spread the damage across the absorbing elements and then application.

@Technici4n
Copy link
Member Author

Hmmm separating EventPhase will make the overall structure clearer, and give me a place where I can put the javadoc for event phases. We can also use a more expressive syntax for ordering:

event.phase("whatever").runBefore("otherphase"); // replaces the current event.addPhaseOrdering("whatever", "otherphase");
event.phase("whatever").runAfter("otherphase"); // replaces the current event.addPhaseOrdering("otherphase", "whatever");

What about String vs Identifier? In most cases, a static final constant will be used, so it shouldn't make a big difference.

EventPhaseData<T> second = getOrCreatePhase(secondPhase);
first.subsequentPhases.add(second);
second.previousPhases.add(first);
sortPhases();
Copy link
Contributor

Choose a reason for hiding this comment

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

Given these sorts are quite expensive, can we have an option to add multiple orderings at once (so the sort is only done after adding all of those ordering definitions)

Copy link
Member Author

Choose a reason for hiding this comment

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

If P is the number of phases and C is the number of constraints, the sort is only O(P+C), so it shouldn't be a big bottleneck. Event registrations themselves are O(N) each after all.

Copy link
Contributor

Choose a reason for hiding this comment

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

But if we try to register C constraints, the current model has a total time complexity of O(C(P+C)) as you do such a calculation after registering each constraint. Often you would register multiple constraints at once, such as when declaring the default phases of an event.

Copy link
Member Author

Choose a reason for hiding this comment

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

Imo if this is a bottleneck then we should provide a way to register multiple constraints at once. But otherwise I'd like to keep the API changes minimal.

@Technici4n
Copy link
Member Author

Ok so I've just split EventPhase into a separate class, which allows registering multiple dependencies at once (even though that shouldn't have a big performance impact @liach ). But I feel like it makes the API worse so I'll just revert it. You can look at the corresponding commit if you are interested.

@Technici4n Technici4n mentioned this pull request Aug 31, 2021
@modmuss50 modmuss50 self-requested a review October 27, 2021 09:52
@modmuss50 modmuss50 added the last call If you care, make yourself heard right away! label Oct 28, 2021
@modmuss50 modmuss50 added the merge me please Pull requests that are ready to merge label Nov 5, 2021
@modmuss50 modmuss50 merged commit 2cff307 into FabricMC:1.17 Nov 5, 2021
modmuss50 pushed a commit that referenced this pull request Nov 5, 2021
* Proof of concept

* Simplify and document

* Allow events to be registered with default phases

* Use modified Kosaraju for the toposort, and add test for cyclic dependency graphs

* Separate phase-related functionality in an EventPhase class

* Revert "Separate phase-related functionality in an EventPhase class"

This reverts commit e433f34.

* Ensure that the phase order is deterministic

* Add pretty graphs

* Add a test, fix a bug, only do one sort for every constraint registration
modmuss50 pushed a commit that referenced this pull request Nov 5, 2021
* Proof of concept

* Simplify and document

* Allow events to be registered with default phases

* Use modified Kosaraju for the toposort, and add test for cyclic dependency graphs

* Separate phase-related functionality in an EventPhase class

* Revert "Separate phase-related functionality in an EventPhase class"

This reverts commit e433f34.

* Ensure that the phase order is deterministic

* Add pretty graphs

* Add a test, fix a bug, only do one sort for every constraint registration
modmuss50 added a commit that referenced this pull request May 20, 2022
* TooltipComponent API (#1695)

* TooltipComponent API

* Add warning

* Fix handling of orphaned registry entries (#1759)

* Fix handling of orphaned registry entries

* Fix handling of orphaned registry entries in RegistrySyncManager

* Transfer API: bugfixes and improvements (#1762)

* Fix SingleVariantItemStorage extraction bug

* Inventory wrappers: reuse the original stack more aggressively

* Add some filtered overloads to StorageUtil methods

* Override PlayerInventoryStorage#insert to call #offer

* Add small comment regarding predicates

* Bump version

* Fix refamp generation for gametest API. Fixes #1722

* Bump version.

* Add two more sleep events (#1755)

* Add event for setting bed occupation state

* Add wake up pos event and update tests

* Bump version

Just in case. I have a bad feeling that
this could become a patch version otherwise.

* Add code tags for true/false/null in EntitySleepEvents jd

* Add Dynamic annotations for lambda body mixins

* Update class javadoc to contain the new events

* Bump version

* Fix Registry.GAME_EVENT not being synced.

* Updated mappings to yarn 1.17.1+build.63 (#1786)

* Updated mappings to yarn 1.17.1+build.63

* Forgot some bits.

* Forgot to reeable

* Make biome & dimension api stable. And change usage around @deprecated (#1783)

* Make biome & dimension api stable (for 1.17). Remove the usage of @deprecated for other experimental modules.

The @deprecated should be used for experimental/volatile APIs that are highly likely to change.

* Apply suggestions from code review

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* ItemGroup API: Remove return and call super so all others ItemStack's get appended (#1617)

* Remove return and call super so all others ItemStack's get appended

* Add method to FabricItemGroupBuilder to pass ItemGroup with appendItems and change stacksForDisplay to a BiConsumer

* Update ItemGroupBuilder javadoc and add example to testmod

* Remove leftover aw

* Update fabric-item-groups-v0/src/main/java/net/fabricmc/fabric/api/client/itemgroup/FabricItemGroupBuilder.java

Co-authored-by: liach <7806504+liach@users.noreply.github.com>

* Update fabric-item-groups-v0/src/testmod/java/net/fabricmc/fabric/test/item/group/ItemGroupTest.java

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>

* Remove used import in ItemGroupTest

* Clean up

* Fix damn checkstyle

* Change version to 0.3.0

Co-authored-by: liach <7806504+liach@users.noreply.github.com>
Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>

* Bump version

* Add tag-based mining level API, fix and deprecate FabricBlockSettings.breakByTool (#1629)

* Mining Level API, part 1

* Fix incorrect netherite mining level in MiningLevelManager docs

* Add some format checks in dynamic mining level tag checking

* Add mining level API test mod

* Grammar

* Add cursed basic support for the tool attribute api

* Fix tool attribute JD

* Add proper compat for tool attribute api

Also fixes the remaining bugs in it!

* Update license headers

* stuff

* better comments

* more test mod work

* more

* Fix test mod

* i'm done with this module

* Address some code review things

* Use Reference2IntMap (basically IdentityHashMap for int values)

* Prefix mixin handlers with fabric$

* Add missing license header

* Update fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/FabricBlockSettings.java

* Resolve liach's comment

* Update to use TagFactory

* Add event phases (#1669)

* Proof of concept

* Simplify and document

* Allow events to be registered with default phases

* Use modified Kosaraju for the toposort, and add test for cyclic dependency graphs

* Separate phase-related functionality in an EventPhase class

* Revert "Separate phase-related functionality in an EventPhase class"

This reverts commit e433f34.

* Ensure that the phase order is deterministic

* Add pretty graphs

* Add a test, fix a bug, only do one sort for every constraint registration

* Environmental renderers (#1727)

* Environmental Renderers

* Remove defunt hideClouds and hideWeather

* Pushed missing License

* Push checkstyle fixes

* remove unused

* Unwrapped the test mod sky rendering.

* Added a first attempt at javadoc.

* Forgot a blank line

* Moved Environment references out of class

* Moved Lamda functions for fog override, thick fog usage and fog color adjustment to their own interfaces and gave them proper javadoc.

* Made FabricSkyProperties private

* PURGE THE H...I mean FabricSkyPropertyBuilder and FabricSkyProperties.

- Reverted unintentional mixin changes
- Fix various typo errors that were pointed out.
- Added missing javadocs and added the ability to override.

* Forgot some pluggin in some overrides.

* Added missing javadoc suggestion

* Changed api a bit so that it fires a exception if renderer not being overridden and one already exists.

* Split Implemtnation and Interface

* Forgot a license

* Added WorldRenderContext to Renderers

* Added logging

* Added missing javadocs and removed the override option.

* Removed INSTANCE

* Environmental Renderers

* Remove defunt hideClouds and hideWeather

* Pushed missing License

* Push checkstyle fixes

* remove unused

* Unwrapped the test mod sky rendering.

* Added a first attempt at javadoc.

* Forgot a blank line

* Moved Environment references out of class

* Moved Lamda functions for fog override, thick fog usage and fog color adjustment to their own interfaces and gave them proper javadoc.

* Made FabricSkyProperties private

* PURGE THE H...I mean FabricSkyPropertyBuilder and FabricSkyProperties.

- Reverted unintentional mixin changes
- Fix various typo errors that were pointed out.
- Added missing javadocs and added the ability to override.

* Forgot some pluggin in some overrides.

* Added missing javadoc suggestion

* Changed api a bit so that it fires a exception if renderer not being overridden and one already exists.

* Split Implemtnation and Interface

* Forgot a license

* Added WorldRenderContext to Renderers

* Added logging

* Added missing javadocs and removed the override option.

* Removed INSTANCE

* Fixed Issues

* Fixed formatting issue.

* completed Juuxl's suggestions and removed null check on adding skyproperties. Changed SkyProperties registering to take an Identifier. Registration turns out to be only adding new options to the "effects" entry of dimension type jsonjson.

* Forgot to reenable this.

* Just did suggested tweaks

* Changed SkyProperties to DimensionEffects

* Pushed suggestions of Haykam and apple502j

* Added missing changes from sky properties to dimension effects.

* Corrected me being inconsistent.

* Forgot to remove import.

* Impliments 

#1727 (comment)
#1727 (comment)

* Implements #1727 (comment)

* Last minute tweak. Runnable that controls fog runs right before dimension spefific rendering is done. Based on more subtle issues discovered while working api with twilight forest.

Co-authored-by: AlphaMode <AlphaModeYT@gmail.com>

* Another wave of transfer API improvements (#1801)

* Another wave of transfer API improvements

* Cleaner implementation of FilteringStorage#...Of

* Undo colored name for water and lava variants

* Custom fluid renderers and enhanced vanilla fluid renderer customization (#1687)

* Implement custom fluid rendering

* Move custom renderers in FluidRenderer mixin and add overlay sprite support to FluidRenderHandlers

* Add vanilla-like fluid renderer. Maybe very unnecessary, might remove.

* Optimize imports

* Allow custom fluid renderers to call the default renderer. Re-add DEFAULT.

* Add interface to implement by blocks that enforces overlay texture on fluids

* Some comments

* Simplify API and remove DefaultLikeFluidRenderer

* Make simple renderer overlay texture nullable

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>

* Expand test mod

* Checkstyle and licenses

* Easy shortcut for custom colored vanilla water fluids

* Easy way to register a renderer for two (still+flowing) fluids

* Update fabric-rendering-fluids-v1/src/main/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandlerRegistry.java

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* Update fabric-rendering-fluids-v1/src/main/java/net/fabricmc/fabric/mixin/client/rendering/fluid/MixinFluidRenderer.java

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>
Co-authored-by: modmuss50 <modmuss50@gmail.com>
Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* Bump versions

All of the version need to be bumped due to fabric-api-base being updated, this highlights the need for a better solution.

* Target the void world in the DimensionalRenderingTest

It's a bit too obnoxious for the overworld.

* Fix shears being the ultimate mining tool (#1809)

* Add detail about default value to MiningLevelManager jd

* Fix shears being the ultimate mining tool

In more technical terms, fix an invalid
comparison in TaggedToolsModdedBlocksToolHandler.
The code was supposed to check if the tool's
mining level was at least the block's minimum
mining level. Instead, the check succeeded
whenever the block required a tool
(min level >= 0).

* WIP fixing tool attribute api bugs

* Fix mostly everything

* Simplify to (== 0) with explanation

* A less breaking workaround for #1806 (#1811)

* A less breaking workaround for #1806

* Checkstyle

* Bump version

* Update Loom and Loader. Cleanup/improve buildscript. (#1802)

Co-authored-by: shartte <shartte@users.noreply.github.com>

* Fix missing some chunk unloads events leading to a possible memory leak. (#1820)

* Fix crash when loading resources from a UNC (windows) network share.

See: https://bugs.openjdk.java.net/browse/JDK-8178726

* Update ResourceManagerHelper.java

* Update ResourceManagerHelperImpl.java

* Update ResourceManagerHelperImpl.java

* attempt to get rid of trailing whitespace

* works

* Update the test mod

* Split TestPack to check if unnamed packs still load and display correctly

* update javadoc

* bump testmod version

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

Co-authored-by: LambdAurora <aurora42lambda@gmail.com>

* Use modid in description

* Add lang

Co-Authored-By: LambdAurora <email@lambdaurora.dev>

* Update fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourceManagerHelperImpl.java

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* Fix optional server resource loading

* small changes and adhere to checkstyle

* Remove ResourcePackProfileAccessor from mixin json

* bump pack_format

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>
Co-authored-by: BasiqueEvangelist <basiqueevangelist@yandex.ru>
Co-authored-by: modmuss50 <modmuss50@gmail.com>
Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>
Co-authored-by: Waterpicker <Waterpickerenternity@gmail.com>
Co-authored-by: AlphaMode <AlphaModeYT@gmail.com>
Co-authored-by: liach <7806504+liach@users.noreply.github.com>
Co-authored-by: Shadew <11669132+FoxShadew@users.noreply.github.com>
Co-authored-by: shartte <shartte@users.noreply.github.com>
Co-authored-by: LambdAurora <aurora42lambda@gmail.com>
Co-authored-by: LambdAurora <email@lambdaurora.dev>
Co-authored-by: deirn <deirn@bai.lol>
modmuss50 pushed a commit that referenced this pull request May 20, 2022
* TooltipComponent API (#1695)

* TooltipComponent API

* Add warning

* Fix handling of orphaned registry entries (#1759)

* Fix handling of orphaned registry entries

* Fix handling of orphaned registry entries in RegistrySyncManager

* Transfer API: bugfixes and improvements (#1762)

* Fix SingleVariantItemStorage extraction bug

* Inventory wrappers: reuse the original stack more aggressively

* Add some filtered overloads to StorageUtil methods

* Override PlayerInventoryStorage#insert to call #offer

* Add small comment regarding predicates

* Bump version

* Fix refamp generation for gametest API. Fixes #1722

* Bump version.

* Add two more sleep events (#1755)

* Add event for setting bed occupation state

* Add wake up pos event and update tests

* Bump version

Just in case. I have a bad feeling that
this could become a patch version otherwise.

* Add code tags for true/false/null in EntitySleepEvents jd

* Add Dynamic annotations for lambda body mixins

* Update class javadoc to contain the new events

* Bump version

* Fix Registry.GAME_EVENT not being synced.

* Updated mappings to yarn 1.17.1+build.63 (#1786)

* Updated mappings to yarn 1.17.1+build.63

* Forgot some bits.

* Forgot to reeable

* Make biome & dimension api stable. And change usage around @deprecated (#1783)

* Make biome & dimension api stable (for 1.17). Remove the usage of @deprecated for other experimental modules.

The @deprecated should be used for experimental/volatile APIs that are highly likely to change.

* Apply suggestions from code review

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* ItemGroup API: Remove return and call super so all others ItemStack's get appended (#1617)

* Remove return and call super so all others ItemStack's get appended

* Add method to FabricItemGroupBuilder to pass ItemGroup with appendItems and change stacksForDisplay to a BiConsumer

* Update ItemGroupBuilder javadoc and add example to testmod

* Remove leftover aw

* Update fabric-item-groups-v0/src/main/java/net/fabricmc/fabric/api/client/itemgroup/FabricItemGroupBuilder.java

Co-authored-by: liach <7806504+liach@users.noreply.github.com>

* Update fabric-item-groups-v0/src/testmod/java/net/fabricmc/fabric/test/item/group/ItemGroupTest.java

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>

* Remove used import in ItemGroupTest

* Clean up

* Fix damn checkstyle

* Change version to 0.3.0

Co-authored-by: liach <7806504+liach@users.noreply.github.com>
Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>

* Bump version

* Add tag-based mining level API, fix and deprecate FabricBlockSettings.breakByTool (#1629)

* Mining Level API, part 1

* Fix incorrect netherite mining level in MiningLevelManager docs

* Add some format checks in dynamic mining level tag checking

* Add mining level API test mod

* Grammar

* Add cursed basic support for the tool attribute api

* Fix tool attribute JD

* Add proper compat for tool attribute api

Also fixes the remaining bugs in it!

* Update license headers

* stuff

* better comments

* more test mod work

* more

* Fix test mod

* i'm done with this module

* Address some code review things

* Use Reference2IntMap (basically IdentityHashMap for int values)

* Prefix mixin handlers with fabric$

* Add missing license header

* Update fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/FabricBlockSettings.java

* Resolve liach's comment

* Update to use TagFactory

* Add event phases (#1669)

* Proof of concept

* Simplify and document

* Allow events to be registered with default phases

* Use modified Kosaraju for the toposort, and add test for cyclic dependency graphs

* Separate phase-related functionality in an EventPhase class

* Revert "Separate phase-related functionality in an EventPhase class"

This reverts commit e433f34.

* Ensure that the phase order is deterministic

* Add pretty graphs

* Add a test, fix a bug, only do one sort for every constraint registration

* Environmental renderers (#1727)

* Environmental Renderers

* Remove defunt hideClouds and hideWeather

* Pushed missing License

* Push checkstyle fixes

* remove unused

* Unwrapped the test mod sky rendering.

* Added a first attempt at javadoc.

* Forgot a blank line

* Moved Environment references out of class

* Moved Lamda functions for fog override, thick fog usage and fog color adjustment to their own interfaces and gave them proper javadoc.

* Made FabricSkyProperties private

* PURGE THE H...I mean FabricSkyPropertyBuilder and FabricSkyProperties.

- Reverted unintentional mixin changes
- Fix various typo errors that were pointed out.
- Added missing javadocs and added the ability to override.

* Forgot some pluggin in some overrides.

* Added missing javadoc suggestion

* Changed api a bit so that it fires a exception if renderer not being overridden and one already exists.

* Split Implemtnation and Interface

* Forgot a license

* Added WorldRenderContext to Renderers

* Added logging

* Added missing javadocs and removed the override option.

* Removed INSTANCE

* Environmental Renderers

* Remove defunt hideClouds and hideWeather

* Pushed missing License

* Push checkstyle fixes

* remove unused

* Unwrapped the test mod sky rendering.

* Added a first attempt at javadoc.

* Forgot a blank line

* Moved Environment references out of class

* Moved Lamda functions for fog override, thick fog usage and fog color adjustment to their own interfaces and gave them proper javadoc.

* Made FabricSkyProperties private

* PURGE THE H...I mean FabricSkyPropertyBuilder and FabricSkyProperties.

- Reverted unintentional mixin changes
- Fix various typo errors that were pointed out.
- Added missing javadocs and added the ability to override.

* Forgot some pluggin in some overrides.

* Added missing javadoc suggestion

* Changed api a bit so that it fires a exception if renderer not being overridden and one already exists.

* Split Implemtnation and Interface

* Forgot a license

* Added WorldRenderContext to Renderers

* Added logging

* Added missing javadocs and removed the override option.

* Removed INSTANCE

* Fixed Issues

* Fixed formatting issue.

* completed Juuxl's suggestions and removed null check on adding skyproperties. Changed SkyProperties registering to take an Identifier. Registration turns out to be only adding new options to the "effects" entry of dimension type jsonjson.

* Forgot to reenable this.

* Just did suggested tweaks

* Changed SkyProperties to DimensionEffects

* Pushed suggestions of Haykam and apple502j

* Added missing changes from sky properties to dimension effects.

* Corrected me being inconsistent.

* Forgot to remove import.

* Impliments

#1727 (comment)
#1727 (comment)

* Implements #1727 (comment)

* Last minute tweak. Runnable that controls fog runs right before dimension spefific rendering is done. Based on more subtle issues discovered while working api with twilight forest.

Co-authored-by: AlphaMode <AlphaModeYT@gmail.com>

* Another wave of transfer API improvements (#1801)

* Another wave of transfer API improvements

* Cleaner implementation of FilteringStorage#...Of

* Undo colored name for water and lava variants

* Custom fluid renderers and enhanced vanilla fluid renderer customization (#1687)

* Implement custom fluid rendering

* Move custom renderers in FluidRenderer mixin and add overlay sprite support to FluidRenderHandlers

* Add vanilla-like fluid renderer. Maybe very unnecessary, might remove.

* Optimize imports

* Allow custom fluid renderers to call the default renderer. Re-add DEFAULT.

* Add interface to implement by blocks that enforces overlay texture on fluids

* Some comments

* Simplify API and remove DefaultLikeFluidRenderer

* Make simple renderer overlay texture nullable

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>

* Expand test mod

* Checkstyle and licenses

* Easy shortcut for custom colored vanilla water fluids

* Easy way to register a renderer for two (still+flowing) fluids

* Update fabric-rendering-fluids-v1/src/main/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandlerRegistry.java

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* Update fabric-rendering-fluids-v1/src/main/java/net/fabricmc/fabric/mixin/client/rendering/fluid/MixinFluidRenderer.java

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>
Co-authored-by: modmuss50 <modmuss50@gmail.com>
Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* Bump versions

All of the version need to be bumped due to fabric-api-base being updated, this highlights the need for a better solution.

* Target the void world in the DimensionalRenderingTest

It's a bit too obnoxious for the overworld.

* Fix shears being the ultimate mining tool (#1809)

* Add detail about default value to MiningLevelManager jd

* Fix shears being the ultimate mining tool

In more technical terms, fix an invalid
comparison in TaggedToolsModdedBlocksToolHandler.
The code was supposed to check if the tool's
mining level was at least the block's minimum
mining level. Instead, the check succeeded
whenever the block required a tool
(min level >= 0).

* WIP fixing tool attribute api bugs

* Fix mostly everything

* Simplify to (== 0) with explanation

* A less breaking workaround for #1806 (#1811)

* A less breaking workaround for #1806

* Checkstyle

* Bump version

* Update Loom and Loader. Cleanup/improve buildscript. (#1802)

Co-authored-by: shartte <shartte@users.noreply.github.com>

* Fix missing some chunk unloads events leading to a possible memory leak. (#1820)

* Fix crash when loading resources from a UNC (windows) network share.

See: https://bugs.openjdk.java.net/browse/JDK-8178726

* Update ResourceManagerHelper.java

* Update ResourceManagerHelperImpl.java

* Update ResourceManagerHelperImpl.java

* attempt to get rid of trailing whitespace

* works

* Update the test mod

* Split TestPack to check if unnamed packs still load and display correctly

* update javadoc

* bump testmod version

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

Co-authored-by: LambdAurora <aurora42lambda@gmail.com>

* Use modid in description

* Add lang

Co-Authored-By: LambdAurora <email@lambdaurora.dev>

* Update fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourceManagerHelperImpl.java

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* Fix optional server resource loading

* small changes and adhere to checkstyle

* Remove ResourcePackProfileAccessor from mixin json

* bump pack_format

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>
Co-authored-by: BasiqueEvangelist <basiqueevangelist@yandex.ru>
Co-authored-by: modmuss50 <modmuss50@gmail.com>
Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>
Co-authored-by: Waterpicker <Waterpickerenternity@gmail.com>
Co-authored-by: AlphaMode <AlphaModeYT@gmail.com>
Co-authored-by: liach <7806504+liach@users.noreply.github.com>
Co-authored-by: Shadew <11669132+FoxShadew@users.noreply.github.com>
Co-authored-by: shartte <shartte@users.noreply.github.com>
Co-authored-by: LambdAurora <aurora42lambda@gmail.com>
Co-authored-by: LambdAurora <email@lambdaurora.dev>
Co-authored-by: deirn <deirn@bai.lol>
(cherry picked from commit 2afceb2)
ThalusA pushed a commit to ThalusA/fabric that referenced this pull request May 31, 2022
* Proof of concept

* Simplify and document

* Allow events to be registered with default phases

* Use modified Kosaraju for the toposort, and add test for cyclic dependency graphs

* Separate phase-related functionality in an EventPhase class

* Revert "Separate phase-related functionality in an EventPhase class"

This reverts commit e433f34.

* Ensure that the phase order is deterministic

* Add pretty graphs

* Add a test, fix a bug, only do one sort for every constraint registration
ThalusA pushed a commit to ThalusA/fabric that referenced this pull request May 31, 2022
* TooltipComponent API (FabricMC#1695)

* TooltipComponent API

* Add warning

* Fix handling of orphaned registry entries (FabricMC#1759)

* Fix handling of orphaned registry entries

* Fix handling of orphaned registry entries in RegistrySyncManager

* Transfer API: bugfixes and improvements (FabricMC#1762)

* Fix SingleVariantItemStorage extraction bug

* Inventory wrappers: reuse the original stack more aggressively

* Add some filtered overloads to StorageUtil methods

* Override PlayerInventoryStorage#insert to call #offer

* Add small comment regarding predicates

* Bump version

* Fix refamp generation for gametest API. Fixes FabricMC#1722

* Bump version.

* Add two more sleep events (FabricMC#1755)

* Add event for setting bed occupation state

* Add wake up pos event and update tests

* Bump version

Just in case. I have a bad feeling that
this could become a patch version otherwise.

* Add code tags for true/false/null in EntitySleepEvents jd

* Add Dynamic annotations for lambda body mixins

* Update class javadoc to contain the new events

* Bump version

* Fix Registry.GAME_EVENT not being synced.

* Updated mappings to yarn 1.17.1+build.63 (FabricMC#1786)

* Updated mappings to yarn 1.17.1+build.63

* Forgot some bits.

* Forgot to reeable

* Make biome & dimension api stable. And change usage around @deprecated (FabricMC#1783)

* Make biome & dimension api stable (for 1.17). Remove the usage of @deprecated for other experimental modules.

The @deprecated should be used for experimental/volatile APIs that are highly likely to change.

* Apply suggestions from code review

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* ItemGroup API: Remove return and call super so all others ItemStack's get appended (FabricMC#1617)

* Remove return and call super so all others ItemStack's get appended

* Add method to FabricItemGroupBuilder to pass ItemGroup with appendItems and change stacksForDisplay to a BiConsumer

* Update ItemGroupBuilder javadoc and add example to testmod

* Remove leftover aw

* Update fabric-item-groups-v0/src/main/java/net/fabricmc/fabric/api/client/itemgroup/FabricItemGroupBuilder.java

Co-authored-by: liach <7806504+liach@users.noreply.github.com>

* Update fabric-item-groups-v0/src/testmod/java/net/fabricmc/fabric/test/item/group/ItemGroupTest.java

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>

* Remove used import in ItemGroupTest

* Clean up

* Fix damn checkstyle

* Change version to 0.3.0

Co-authored-by: liach <7806504+liach@users.noreply.github.com>
Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>

* Bump version

* Add tag-based mining level API, fix and deprecate FabricBlockSettings.breakByTool (FabricMC#1629)

* Mining Level API, part 1

* Fix incorrect netherite mining level in MiningLevelManager docs

* Add some format checks in dynamic mining level tag checking

* Add mining level API test mod

* Grammar

* Add cursed basic support for the tool attribute api

* Fix tool attribute JD

* Add proper compat for tool attribute api

Also fixes the remaining bugs in it!

* Update license headers

* stuff

* better comments

* more test mod work

* more

* Fix test mod

* i'm done with this module

* Address some code review things

* Use Reference2IntMap (basically IdentityHashMap for int values)

* Prefix mixin handlers with fabric$

* Add missing license header

* Update fabric-object-builder-api-v1/src/main/java/net/fabricmc/fabric/api/object/builder/v1/block/FabricBlockSettings.java

* Resolve liach's comment

* Update to use TagFactory

* Add event phases (FabricMC#1669)

* Proof of concept

* Simplify and document

* Allow events to be registered with default phases

* Use modified Kosaraju for the toposort, and add test for cyclic dependency graphs

* Separate phase-related functionality in an EventPhase class

* Revert "Separate phase-related functionality in an EventPhase class"

This reverts commit e433f34.

* Ensure that the phase order is deterministic

* Add pretty graphs

* Add a test, fix a bug, only do one sort for every constraint registration

* Environmental renderers (FabricMC#1727)

* Environmental Renderers

* Remove defunt hideClouds and hideWeather

* Pushed missing License

* Push checkstyle fixes

* remove unused

* Unwrapped the test mod sky rendering.

* Added a first attempt at javadoc.

* Forgot a blank line

* Moved Environment references out of class

* Moved Lamda functions for fog override, thick fog usage and fog color adjustment to their own interfaces and gave them proper javadoc.

* Made FabricSkyProperties private

* PURGE THE H...I mean FabricSkyPropertyBuilder and FabricSkyProperties.

- Reverted unintentional mixin changes
- Fix various typo errors that were pointed out.
- Added missing javadocs and added the ability to override.

* Forgot some pluggin in some overrides.

* Added missing javadoc suggestion

* Changed api a bit so that it fires a exception if renderer not being overridden and one already exists.

* Split Implemtnation and Interface

* Forgot a license

* Added WorldRenderContext to Renderers

* Added logging

* Added missing javadocs and removed the override option.

* Removed INSTANCE

* Environmental Renderers

* Remove defunt hideClouds and hideWeather

* Pushed missing License

* Push checkstyle fixes

* remove unused

* Unwrapped the test mod sky rendering.

* Added a first attempt at javadoc.

* Forgot a blank line

* Moved Environment references out of class

* Moved Lamda functions for fog override, thick fog usage and fog color adjustment to their own interfaces and gave them proper javadoc.

* Made FabricSkyProperties private

* PURGE THE H...I mean FabricSkyPropertyBuilder and FabricSkyProperties.

- Reverted unintentional mixin changes
- Fix various typo errors that were pointed out.
- Added missing javadocs and added the ability to override.

* Forgot some pluggin in some overrides.

* Added missing javadoc suggestion

* Changed api a bit so that it fires a exception if renderer not being overridden and one already exists.

* Split Implemtnation and Interface

* Forgot a license

* Added WorldRenderContext to Renderers

* Added logging

* Added missing javadocs and removed the override option.

* Removed INSTANCE

* Fixed Issues

* Fixed formatting issue.

* completed Juuxl's suggestions and removed null check on adding skyproperties. Changed SkyProperties registering to take an Identifier. Registration turns out to be only adding new options to the "effects" entry of dimension type jsonjson.

* Forgot to reenable this.

* Just did suggested tweaks

* Changed SkyProperties to DimensionEffects

* Pushed suggestions of Haykam and apple502j

* Added missing changes from sky properties to dimension effects.

* Corrected me being inconsistent.

* Forgot to remove import.

* Impliments

FabricMC#1727 (comment)
FabricMC#1727 (comment)

* Implements FabricMC#1727 (comment)

* Last minute tweak. Runnable that controls fog runs right before dimension spefific rendering is done. Based on more subtle issues discovered while working api with twilight forest.

Co-authored-by: AlphaMode <AlphaModeYT@gmail.com>

* Another wave of transfer API improvements (FabricMC#1801)

* Another wave of transfer API improvements

* Cleaner implementation of FilteringStorage#...Of

* Undo colored name for water and lava variants

* Custom fluid renderers and enhanced vanilla fluid renderer customization (FabricMC#1687)

* Implement custom fluid rendering

* Move custom renderers in FluidRenderer mixin and add overlay sprite support to FluidRenderHandlers

* Add vanilla-like fluid renderer. Maybe very unnecessary, might remove.

* Optimize imports

* Allow custom fluid renderers to call the default renderer. Re-add DEFAULT.

* Add interface to implement by blocks that enforces overlay texture on fluids

* Some comments

* Simplify API and remove DefaultLikeFluidRenderer

* Make simple renderer overlay texture nullable

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>

* Expand test mod

* Checkstyle and licenses

* Easy shortcut for custom colored vanilla water fluids

* Easy way to register a renderer for two (still+flowing) fluids

* Update fabric-rendering-fluids-v1/src/main/java/net/fabricmc/fabric/api/client/render/fluid/v1/FluidRenderHandlerRegistry.java

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* Update fabric-rendering-fluids-v1/src/main/java/net/fabricmc/fabric/mixin/client/rendering/fluid/MixinFluidRenderer.java

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>
Co-authored-by: modmuss50 <modmuss50@gmail.com>
Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* Bump versions

All of the version need to be bumped due to fabric-api-base being updated, this highlights the need for a better solution.

* Target the void world in the DimensionalRenderingTest

It's a bit too obnoxious for the overworld.

* Fix shears being the ultimate mining tool (FabricMC#1809)

* Add detail about default value to MiningLevelManager jd

* Fix shears being the ultimate mining tool

In more technical terms, fix an invalid
comparison in TaggedToolsModdedBlocksToolHandler.
The code was supposed to check if the tool's
mining level was at least the block's minimum
mining level. Instead, the check succeeded
whenever the block required a tool
(min level >= 0).

* WIP fixing tool attribute api bugs

* Fix mostly everything

* Simplify to (== 0) with explanation

* A less breaking workaround for FabricMC#1806 (FabricMC#1811)

* A less breaking workaround for FabricMC#1806

* Checkstyle

* Bump version

* Update Loom and Loader. Cleanup/improve buildscript. (FabricMC#1802)

Co-authored-by: shartte <shartte@users.noreply.github.com>

* Fix missing some chunk unloads events leading to a possible memory leak. (FabricMC#1820)

* Fix crash when loading resources from a UNC (windows) network share.

See: https://bugs.openjdk.java.net/browse/JDK-8178726

* Update ResourceManagerHelper.java

* Update ResourceManagerHelperImpl.java

* Update ResourceManagerHelperImpl.java

* attempt to get rid of trailing whitespace

* works

* Update the test mod

* Split TestPack to check if unnamed packs still load and display correctly

* update javadoc

* bump testmod version

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

Co-authored-by: LambdAurora <aurora42lambda@gmail.com>

* Use modid in description

* Add lang

Co-Authored-By: LambdAurora <email@lambdaurora.dev>

* Update fabric-resource-loader-v0/src/main/java/net/fabricmc/fabric/impl/resource/loader/ResourceManagerHelperImpl.java

Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>

* Fix optional server resource loading

* small changes and adhere to checkstyle

* Remove ResourcePackProfileAccessor from mixin json

* bump pack_format

Co-authored-by: Technici4n <13494793+Technici4n@users.noreply.github.com>
Co-authored-by: BasiqueEvangelist <basiqueevangelist@yandex.ru>
Co-authored-by: modmuss50 <modmuss50@gmail.com>
Co-authored-by: Juuxel <6596629+Juuxel@users.noreply.github.com>
Co-authored-by: Waterpicker <Waterpickerenternity@gmail.com>
Co-authored-by: AlphaMode <AlphaModeYT@gmail.com>
Co-authored-by: liach <7806504+liach@users.noreply.github.com>
Co-authored-by: Shadew <11669132+FoxShadew@users.noreply.github.com>
Co-authored-by: shartte <shartte@users.noreply.github.com>
Co-authored-by: LambdAurora <aurora42lambda@gmail.com>
Co-authored-by: LambdAurora <email@lambdaurora.dev>
Co-authored-by: deirn <deirn@bai.lol>
(cherry picked from commit 07a90aabcbb95acf2aaba97a203723df2550479a)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request last call If you care, make yourself heard right away! merge me please Pull requests that are ready to merge priority:low Low priority PRs that don't immediately need to be resolved reviews needed This PR needs more reviews
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants