Rotation support
LemADEC opened this issue ยท 28 comments
I wanted to add rotation support for LittleTiles with my WarpDrive mod.
Is there an existing rotation method/code I can use on the TileEntities NBT data? or should I make individual rotation of each boxes in there?
I could add rotate(Axis axis, boolean clockwise)
and flip(Axis axis)
to ILittleTileTE
(source). This interface is implemented by my TileEntity
. Would that be enough?
For other mods, rotation happens on the NBT data, before placing in the world. Doing so avoid conflicts since surrounding blocks aren't all rotated yet.
I could postpone rotation after TileEntity creation just for LittleTiles blocks, but other incompatibilities may happen like torch placements and such. So it'll have to be tested.
Either place the blocks first and then rotate them or we can also do it different (it's not that difficult to modify the nbt data itself). Is there some kind of block rotation handler?
Correction: I've already fixed the API to support rotation after placing the TileEntity, so your proposal would work.
I wonder how that'll work with LittleTiles' doors, especially if they are in movement at that time. Should we prevent rotating/moving the block while the block is animated?
The BlockTransformer API is defined here: https://github.com/LemADEC/WarpDrive/blob/MC1.12/src/main/java/cr0s/warpdrive/api/IBlockTransformer.java
You can see existing implementations in https://github.com/LemADEC/WarpDrive/tree/MC1.12/src/main/java/cr0s/warpdrive/compat .
I see the general idea, however it won't work properly.
@Override
public int rotate(Block block, int metadata, NBTTagCompound nbtTileEntity, ITransformation transformation) {
TileEntityLittleTiles te = new TileEntityLittleTiles();
te.readFromNBT(nbtTileEntity);
for (LittleTile tile : te.getTiles()) {
tile.transform(transformation);
}
te.writeToNBT(nbtTileEntity);
return 0;
}
should be more like so
@Override
public int rotate(Block block, int metadata, NBTTagCompound nbtTileEntity, ITransformation transformation) {
final byte rotationSteps = transformation.getRotationSteps();
if (rotationSteps == 0) {
return metadata;
}
TileEntityLittleTiles te = new TileEntityLittleTiles();
te.readFromNBT(nbtTileEntity);
for (LittleTile tile : te.getTiles()) {
for (int rotationStep = 0; rotationStep< rotationSteps, rotationStep++) {
tile.transform(transformation);
}
}
te.writeToNBT(nbtTileEntity);
return metadata;
}
and I should probably add a proper API for registering external transformers.
Added support for it, unfortunately I can't test it yet. It will be part of the upcoming pre-release, which might take a few more days/ weeks.
If you want to you can take a look at the code:https://github.com/CreativeMD/LittleTiles/blob/1.12/src/main/java/com/creativemd/littletiles/common/mods/warpdrive/TileEntityLittleTilesTransformer.java
Oh right just realized I was using ITransformation from forge ... thanks! Hopefully it looks better this time.
That looks much better indeed :).
Please note ITransformation.apply() works on world coordinates, assuming rotation around the Ship core.
From the look of it, LittleTileBox holds internal coordinates to the block, so we need to scale them to the block size, then translate them to world coordinates, before applying the transformation.
Not sure how to compute the scaling factor here, but here's quick example inspired from another compatibility class:
public static void transformTile(LittleTile tile, ITransformation transformation) {
final BlockPos blockPosOld = new BlockPos(
nbtTileEntity.getInteger("x"),
nbtTileEntity.getInteger("y"),
nbtTileEntity.getInteger("z") );
final BlockPos blockPosNew = transformation.apply(blockPosOld);
final double scaling = ???;
Vec3d min = transformation.apply(
blockPosOld.getX() + box.minX * scaling,
blockPosOld.getY() + box.minY * scaling,
blockPosOld.getZ() + box.minZ * scaling );
Vec3d max = transformation.apply(
blockPosOld.getX() + box.maxX * scaling,
blockPosOld.getY() + box.maxY * scaling,
blockPosOld.getZ() + box.maxZ * scaling );
box.minX = (int) ((Math.min(min.x, max.x) - blockPosNew.getX()) / scaling);
box.minY = (int) ((Math.min(min.y, max.y) - blockPosNew.getY()) / scaling);
box.minZ = (int) ((Math.min(min.z, max.z) - blockPosNew.getZ()) / scaling);
box.maxX = (int) ((Math.max(min.x, max.x) - blockPosNew.getX()) / scaling);
box.maxY = (int) ((Math.max(min.y, max.y) - blockPosNew.getY()) / scaling);
box.maxZ = (int) ((Math.max(min.z, max.z) - blockPosNew.getZ()) / scaling);
...
}
I've added some documentation to ITransformation so it's more explicit.
Does apply rotate around a center? I thought there would be no difference for the block itself. Is there a way to do it different (ignore rotation center?
rotation is always around a center, it could default to (0 0 0) but in most cases you want to rotate around the center of the block (0.5 0.5 0.5).
I could add a ITransformation.rotate() to rotate around the center of the block, but that doesn't save you from scaling up and down.
Does it really matter? The scale is completely irrelevant if it's rotated around 0 0 0. Is there a way to get access to the rotation matrix?
Rotating around 0 0 0 means all the coordinates will be on the negative axis, is that ok with the rest of LittleTiles handling?
There's only 3 possible rotations, there's no rotation matrix for that, just a switch case, like so: https://github.com/LemADEC/WarpDrive/blob/MC1.12/src/main/java/cr0s/warpdrive/data/Transformation.java#L89
Hm, I have some code which could handle all this stuff very easily, but your class is rather confusing to me. Is there some kind of rotation degree or a rotation axis?
Ok thanks :D
Fixed it now for sure (hopefully) assuming rotation is clockwise: https://github.com/CreativeMD/LittleTiles/blob/1.12/src/main/java/com/creativemd/littletiles/common/mods/warpdrive/TileEntityLittleTilesTransformer.java
It is out, can you test it? (don't know how work with your mod) If not I can do it as well.
As of LittleTiles_v1.5.0-pre145_mc1.12.2 + WarpDrive-1.12.2-1.5.5, block transformer is registered, but rotation is happening backwards for simple blocks:
- left turn is turning right,
- 180 deg turn works,
- right turn is turning left.
I'm not sure how to make more advanced blocks like doors, etc. Here's a simple test modpack for Twitch launcher/MCPC:
Littletiles+WarpDrive integration-1.0.0.zip
right click the computer, press 1, press m to choose your movement, press Y to confirm the jump.
Nice! Looks like it's counter clockwise. Easy to fix!
Unfortunately can't test it at the moment. If you really want to you can place down a simple door and see if it still works.
Fixed version: https://www.curseforge.com/minecraft/mc-mods/littletiles/files/2736125
How to:
Go into creative mode. Type in /lt-import
, copy the content of https://pastebin.com/VTQD72Kr to your clipboard. Hit paste and then place the recipe down.
CreativeCore_v1.9.52_mc1.12.2 did fix the simple blocks rotation.
The Simple door model turns but door interaction no longer works and reports "Cannot interact with door (not all tiles are loaded)". If I come back to original orientation, then the door works again.
Okay ... things are a lot more complicated as I found out, but it works now ... kinda.
I had to use the externals in order to make it work, unfortunately those are not used by the client, because it only works on server side. So if you leave the world and join again the structure works. Is there a way to fix that?
Assuming you're talking about the externals from the IBlockTransformer, those are intended to carry data not saved inside the TileEntity NBT. For example, ImmersiveEngineering wires or ArsMagica2 links are saved that way.
Those externals are part of the ship schematic: your IBlockTransformer defines how to saveExternals, delete them and restore them, while WarpDrive will manage how to write and read the related data into a ship schematic.
See ImmersiveEngineering compatibility module for an example: https://github.com/LemADEC/WarpDrive/blob/MC1.12/src/main/java/cr0s/warpdrive/compat/CompatImmersiveEngineering.java#L58
Fixed it, I just thought restore externals would also be called on client side. A simple update notification did the job. Thanks for your time!!! Glad we could finally solve this.
Indeed, IBlockTransformer only runs server side. restoreExternals() is good spot to push your custom client update update notifications that might be required.
As of CreativeCore_v1.9.54_mc1.12.2 + LittleTiles_v1.5.0-pre149_mc1.12.2, doors rotation point seems to be offset after turning the ship. Doing 4 consecutive ship turns to the right does restore the original door's rotation point.
It's fixed, I don't know when I will release it (maybe next week). Feel free to test it yourself: https://www.dropbox.com/s/fmv3g4vhy7vwflv/LittleTiles_v1.5.0-pre150_mc1.12.2.jar?dl=1