-
-
Notifications
You must be signed in to change notification settings - Fork 211
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
Mixin
config 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
Mixin
config`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.minecraft
are exempted and should be omitted.- Based on this exemption, if you are mixing into
net.minecraft.world.chunk.Chunk
from 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.
-
Mixin
class names should be prefixed with the Mixin target's name then the wordMixin
followed by_
and finally the Mixin config's name.- Only one config is exempt from this and that is mixins originating from the
core
config 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
Mixin
followed by_
and finally the Mixin config's name.- Only one config is exempt from this and that is mixins originating from the
core
config in SpongeCommon as that is the baseline for the entire Sponge implementation.- Based on this rule, if you are mixing into
Entity
andTileEntity
to implementDataHolder
from core, the mixin would beDataHolderMixin
2. - Based on this rule, if you are mixing into
Entity
andTileEntity
to implementDataHolder
from 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
core
config in SpongeCommon as that is the baseline for the entire Sponge implementation.- Based on this exemption, if you are writing a bridge for
ChunkMixin
from core, the bridge would beChunkBridge
. - Based on this rule, if you are writing a bridge for
ChunkMixin_Forge
from 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
Bridge
followed by_
and finally theMixin
config's name.- Only one config is exempt from this and that is bridges originating from the
core
config in SpongeCommon as that is the baseline for the entire Sponge implementation.- Based on this rule, if you are mixing into
Entity
andTileEntity
to implement Creator tracking in core, the bridge would beOwnershipTrackableBridge
. - Based on this rule, if you are mixing into
Entity
andTileEntity
to 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
Mixin
config's name followed by the wordbridge
followed by an additional$
.- Only one config is exempt from this and that is bridges originating from the
core
config in SpongeCommon as that is the baseline for the entire Sponge implementation.- Based on this rule,
setTransform
inEntityBridge
from core would be namedbridge$setTransform
. - Based on this rule,
setTransform
inEntityBridge_Forge
from 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_Forge
is 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
ChunkProviderClient
toChunkProviderServerBridge
simply 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
core
config in SpongeCommon as that is the baseline for the entire Sponge implementation. Instead we make this impl.- Based on this rule, an injection into
onUpdate
ofEntity
inEntityMixin
in core would be namedimpl$onUpdate
. - Based on this rule, an injection into
onUpdate
ofEntity
inEntityMixin
in 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.
-
Accessor
class 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
Entity
the accessor would be namedEntityAccessor
.
- Based on this rule, if you are accessing a field/method in
- Accessor fields should be prefixed with the word
accessor
followed by an additional$
and finally the name of the field being targeted.- Based on this rule, a getter for the
rand
field inEntity
would be namedaccessor$rand()
. - Based on this rule, a setter for the
rand
field inEntity
would be namedaccessor$rand(Random random)
.
- Based on this rule, a getter for the
- Invoker method names should be prefixed with the word
invoker
followed by an additional$
and finally the name of the method being targeted.- Based on this rule, method
getRandom
inEntity
would be namedinvoker$getRandom()
.
- Based on this rule, method