Custom Dimensions
See original GitHub issueCustom Dimensions
After messing around with dims for the last day or so I have found a few places that might be a good candidate to be handled by fabric.
TL;DR at bottom of this issue
Creation of the SecondaryServerWorld
In MinecraftServer.createWorlds
, SecondaryServerWorld
’s are created for the end and the neather. As well as adding them to the MinecraftServer.worlds
map. This would be an easy thing to patch. An API would need to be created to allow modders to register their DimensionType’s to be created
Creating a new DimensionType
Currently DimensionType has a protected constructor, I think the best solution to this is to create a builder (similar to the item groups) This builder would take an identifier and handle some things the modder shouldn’t need to touch such as the saveDir
One possible idea would be to remove the need to speicfy a unique dim id, this needs to be looked into some more as the dim id’s would need to be synced from the server to the client on connection. The id’s seem to be used in very few places so I think this could be feasible without too much work.
ChunkGeneratorType
ChunkGeneratorType is used by the Dimension to create generate chunks, easy enough. ChunkGeneratorType.register
could do with an AT, this is the least of the issues however.
ChunkGeneratorFactory is package private, this makes creating ChunkGeneratorType’s a pain, to work around this I moved this code into the net.minecraft.world.gen.chunk
package, however this is bad on a few levels, and will not work outside of dev. This class should be AT’ed to be public.
Entity Teleportation and Portal Creation (Very WIP)
One area that I think would befit from an API in fabric would be allowing a way to bypass the code located in class_1946
. class_1946
is currently hard coded to handle the nether portal, however it gets called when traveling to custom dimensions.
To slove this issue I came up with the following interface: (Very rough API and bad java docs)
public interface PlayerPlacementHandler {
/**
*
* This is used to create a portal if needed, as well as set the player location in the new dim
*
* when you return true no other placement handlers will be called when the player is moving
*
* @param entity the entity that is traveling between 2 dims
* @param previousWorld the world that the entity is traveling from
* @param newWorld the world that the entity is traveling true
* @return if the placement handler handled this movement
*/
boolean placeInPortal(Entity entity, ServerWorld previousWorld, ServerWorld newWorld);
//TODO move out of this?
default void setEntityLocation(Entity entity, BlockPos pos){
if (entity instanceof ServerPlayerEntity) {
((ServerPlayerEntity)entity).networkHandler.method_14363(pos.getX(), pos.getY(), pos.getZ(), 0, 0);
((ServerPlayerEntity)entity).networkHandler.method_14372();
} else {
entity.setPositionAndAngles(pos.getX(), pos.getY(), pos.getZ(), 0, 0);
}
}
}
The placeInPortal method is called whenever an entity changes dimension (including vanilla), this idea is to allow mods to handle teleporting to and from their own dims, as well enabling mods to replace the functionality of telporting to vanilla dims if required.
The setEntityLocation
is added as a helper method to set the player’s location correctly, this was based of the code found in class_1946
Bellow is the example mixin targeting PlayerManager
to implement PlayerPlacementHandler
@Mixin(PlayerManager.class)
public class MixinPlayerManager {
@Inject(method = "method_14558", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/Profiler;begin(Ljava/lang/String;)V", shift = At.Shift.BEFORE), cancellable = true)
public void method_14558(Entity entity, DimensionType dimensionType, ServerWorld previousWorld, ServerWorld newWorld, CallbackInfo info) {
for (PlayerPlacementHandler playerPlacementHandler : DimAPI.playerPlacementHandlerList) {
if (playerPlacementHandler.placeInPortal(entity, previousWorld, newWorld)) {
newWorld.spawnEntity(entity);
newWorld.method_8553(entity, false);
entity.setWorld(newWorld);
info.cancel();
break;
}
}
}
}
Issues with this idea:
If a mod does not handle the teleportation it will pass it onto class_1946
and the game will most likely crash. Do we need an API that holds the hand of the modder a bit more? (For example requiring them to handle all teleport to their dim?)
TL;DR
-
Patch
MinecraftServer.createWorlds
to handle the creation ofSecondaryServerWorld
-
Create a builder around
DimensionType
, and possibly handle auto dim id assigning? -
Add some AT’s to
ChunkGeneratorType
andChunkGeneratorFactory
to make them easily accessible -
Create an API in fabric to allow modder’s to handle entity location and portal creation. Possibly find a way to stop it crashing if not handled correctly?
Conclusion
I think there are a few places where Fabric can help with the creation of modded dims, however im not sure if all of these places should be handled by fabric, or handled by the mods (Mainly thinking about the places I suggest AT’ing when possible)
One of the things that I think needs more thinking over is the placement / teleportation code as right now it is very easy to get it wrong and crash the game.
Finally, all feedback will be greatly appreciated, thanks for spending your time reading this.
Issue Analytics
- State:
- Created 5 years ago
- Comments:6 (4 by maintainers)
Top GitHub Comments
This has been done for ages.
People keep failing at getting dimension apis merged lol