-
-
Notifications
You must be signed in to change notification settings - Fork 216
Implementation Policy: Bridges and Mixins
In the past, Sponge had no distinct structural policy beyond a couple of followed "rules" when adding new mixins/interfaces to the various projects. One of these rules, IMixin-style interfaces, served us well and is followed by many projects out there but leads to hard-to-maintain code when it isn't clear where things are coming from and going to. Likewise prefixing or lack thereof in several Mixins and their injectors/redirectors/etc makes for hard to decipher logs of exactly where problems are at and, on a more alarming level, general comprehension of the codebase. After discussion and coming to terms with this, @gabizou and @Zidane have decided to iron this out with a policy once and for all.
- Package root for
Mixinconfig trees should bemixin.-
SpongeCommon(org.spongepowered.common.mixin). -
SpongeForge(org.spongepowered.mod.mixin). -
SpongeVanilla(org.spongepowered.server.mixin).
-
- Package trees for mixins should begin with the
Mixinconfig`s name.-
SpongeCommon(org.spongepowered.common.mixin.core). -
SpongeForge(org.spongepowered.mod.mixin.core). -
SpongeVanilla(org.spongepowered.server.mixin.core).
-
- Package branches should follow their target's package structure 1:1.
- Branches starting with
com,net, or other widely used top-level domains as well asnet.minecraftare exempted and should be omitted.- Based on this exemption, if you are mixing into
net.minecraft.world.chunk.Chunkfrom core, the mixin would be located inorg.spongepowered.common.mixin.core.world.chunk.
- Based on this exemption, if you are mixing into
- Branches starting with
- For multi-target mixins1, it is at the discretion of the team on the most applicable spot to place the mixin.
-
Mixinclass names should be prefixed with the Mixin target's name then the wordMixinfollowed by_and finally the Mixin config's name.- Only one config is exempt from this and that is mixins originating from the
coreconfig in SpongeCommon as that is the baseline for the entire Sponge implementation.
- Only one config is exempt from this and that is mixins originating from the
- For multi-target mixins1, names should be prefixed with the most relevant name then the word
Mixinfollowed by_and finally the Mixin config's name.- Only one config is exempt from this and that is mixins originating from the
coreconfig in SpongeCommon as that is the baseline for the entire Sponge implementation.- Based on this rule, if you are mixing into
EntityandTileEntityto implementDataHolderfrom core, the mixin would beDataHolderMixin2. - Based on this rule, if you are mixing into
EntityandTileEntityto implementDataHolderfrom forge, the mixin would beDataHolderMixin_Forge.
- Based on this rule, if you are mixing into
- Only one config is exempt from this and that is mixins originating from the
Bridges bridge the gap between Minecraft classes (ex. net.minecraft.world.chunk.Chunk) and the Sponge implemented code via Mixins (ex. MixinChunk. There are many times where we need to call methods to perform logic off of those classes and can do so via these distinct interfaces. Replaces legacy IMixin interfaces (ex. IMixinChunk).
- Bridge class names should be prefixed with the
Mixin's target name then the word "Bridge" followed by an underscore and finally the Mixin config's name.- Only one config is exempt from this and that is bridges originating from the
coreconfig in SpongeCommon as that is the baseline for the entire Sponge implementation.- Based on this exemption, if you are writing a bridge for
ChunkMixinfrom core, the bridge would beChunkBridge. - Based on this rule, if you are writing a bridge for
ChunkMixin_Forgefrom forge, the bridge would beChunkBridge_Forge.
- Based on this exemption, if you are writing a bridge for
- Only one config is exempt from this and that is bridges originating from the
- For multi-target bridges, names should be prefixed with the most relevant name then the word
Bridgefollowed by_and finally theMixinconfig's name.- Only one config is exempt from this and that is bridges originating from the
coreconfig in SpongeCommon as that is the baseline for the entire Sponge implementation.- Based on this rule, if you are mixing into
EntityandTileEntityto implement Creator tracking in core, the bridge would beOwnershipTrackableBridge. - Based on this rule, if you are mixing into
EntityandTileEntityto implement Creator tracking in forge, the bridge would beOwnershipTrackableBridge_Forge.
- Based on this rule, if you are mixing into
- Only one config is exempt from this and that is bridges originating from the
- Bridge method names should be prefixed with the
Mixinconfig's name followed by the wordbridgefollowed by an additional$.- Only one config is exempt from this and that is bridges originating from the
coreconfig in SpongeCommon as that is the baseline for the entire Sponge implementation.- Based on this rule,
setTransforminEntityBridgefrom core would be namedbridge$setTransform. - Based on this rule,
setTransforminEntityBridge_Forgefrom forge would be namedforgeBridge$setTransform.
- Based on this rule,
- Only one config is exempt from this and that is bridges originating from the
- Bridges are not allowed to extend from other bridges, even if the bridge is effectively a subclass of another bridge (ex.
ChunkBridge_Forgeis effectively a child ofChunkBridge)- The reasoning for this is to prevent potential corner cases where a developer inadvertently performs a cast on code that will not exist on the platform currently running it.
- For example, casting
ChunkProviderClienttoChunkProviderServerBridgesimply to call a method inherited fromChunkProviderBridge.
- For example, casting
- The reasoning for this is to prevent potential corner cases where a developer inadvertently performs a cast on code that will not exist on the platform currently running it.
Injections "inject" Sponge logic into classes at explictly defined targets.
- Injection method names should be prefixed with the Mixin config's name followed by an appropriate method name for the context.
- Only one config is exempt from this and that is injections originating from the
coreconfig in SpongeCommon as that is the baseline for the entire Sponge implementation. Instead we make this impl.- Based on this rule, an injection into
onUpdateofEntityinEntityMixinin core would be namedimpl$onUpdate. - Based on this rule, an injection into
onUpdateofEntityinEntityMixinin forge would be namedforge$onUpdate.
- Based on this rule, an injection into
- Only one config is exempt from this and that is injections originating from the
Accessor and Invoker mixins allow Sponge logic to access fields in Minecraft classes whose visibility would not be available otherwise.
-
Accessorclass names should be prefixed with the Mixin target's name then the wordAccessor.- Based on this rule, if you are accessing a field/method in
Entitythe accessor would be namedEntityAccessor.
- Based on this rule, if you are accessing a field/method in
- Accessor fields should be prefixed with the word
accessorfollowed by an additional$and finally the name of the field being targeted.- Based on this rule, a getter for the
randfield inEntitywould be namedaccessor$rand(). - Based on this rule, a setter for the
randfield inEntitywould be namedaccessor$rand(Random random).
- Based on this rule, a getter for the
- Invoker method names should be prefixed with the word
invokerfollowed by an additional$and finally the name of the method being targeted.- Based on this rule, method
getRandominEntitywould be namedinvoker$getRandom().
- Based on this rule, method