Skip to content

Warn on mixin plugin classloads from the game layer#410

Draft
lukebemish wants to merge 3 commits into
neoforged:mainfrom
lukebemish:warn-on-tcl-mixin-plugins
Draft

Warn on mixin plugin classloads from the game layer#410
lukebemish wants to merge 3 commits into
neoforged:mainfrom
lukebemish:warn-on-tcl-mixin-plugins

Conversation

@lukebemish

Copy link
Copy Markdown
Contributor

Long term, it would be a good idea to limit mixin plugins to be in FMLModType=LIBRARY jars and not be pulled up from the game layer during transformation.

I've mentioned this before but the fact that this works this way is the last major footgun in the transformation system and leads to a lot of wacky behaviour. Most notably -- it's generally intended that part of the contract of a ClassProcessor is that its actions will only affect processors after it. This is not the case for mixin -- a ClassProcessor's actions, even if that processor is after mixin, can affect what mixin does if it processes a class loaded (indirectly or directly) from a mixin plugin.

IMO it's a reasonable solution to limit mixin plugins (and anything mixin loads, for that matter) to LIBRARY -- after all, everything else out there that could be involved in transforming classes, that someone might write, would be loaded above the game layer (Mostly just ClassProcessors now).

Last this was brought up there were worried about it causing extra complexity for people writing their own mixin plugins. My take is that this is (and ought to be!) a minority of modders -- even a minority of modders with mixins -- and is rarely needed for the things people say it is:

  • configuring mixins with a config -- this can often be handled by a static block within the mixin itself, short-circuiting the logic depending on the config value. Cases where it can't exist, but they are the minority.
  • enabling mixins only when certain mods are present -- there's already an option for this in the mixins block of your neoforge.mods.toml, no need for a mixin config plugin at all (and I've opened a PR to make sure that is documented).
  • doing literally nothing -- a surprising number of mixin plugins out in the wild appear to be empty. Obviously, these can be removed.
  • probably involves details of transformation, so it should be assumed that if you're doing it you understand the game/library layer distinction and can write a LIBRARY jar for your config plugin.

Even a case that does require moving the plugin to a LIBRARY jar shouldn't be that difficult -- in fact, doing so is already documented for MDG.

This PR (a draft for now as I work out some details) would be the first step in this process, making mixin plugins loaded from the TCL during load log errors but allowing load to continue.


For additional justification as to why this change should be made: currently, there is no entrypoint during which a classprocessor running after mixin may, before it needs to decide whether it is processing any class, look at the mixin-transformed bytecode (which it has available to it, as it is running after mixin) of a particular vanilla class. Were you to do so in handlesClass (at the last possible moment that is), the first times that is queried would be for mixin plugin classes and you would be unable to see the mixin-transformed bytecode for anything as it is recursively hidden inside mixin transformation. This is bad; classprocessors should be independent from one another. They're well-ordered for a reason.

@neoforged-pr-publishing

Copy link
Copy Markdown
  • Publish PR to GitHub Packages

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.

1 participant