LittleTiles

LittleTiles

12M Downloads

Rotation support

LemADEC opened this issue ยท 28 comments

commented

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?

commented

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?

commented

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.

commented

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?

commented

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 .

commented

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.

commented

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

commented

Oh right just realized I was using ITransformation from forge ... thanks! Hopefully it looks better this time.

commented

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.

commented

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?

commented

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.

commented

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?

commented

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

commented

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?

commented

Rotation axis is always Y.
Rotation angle is rotationStep * 90 deg.

commented

Yes, it's a clockwise rotation.
Looks much better now, to be tested :)

commented

It is out, can you test it? (don't know how work with your mod) If not I can do it as well.

commented

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.

commented

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.

commented

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.

commented

How do I get the newest version from ComputerCraft?

commented

Use CC:Tweaked, it's the updated fork

commented

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?

commented

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

commented

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.

commented

Indeed, IBlockTransformer only runs server side. restoreExternals() is good spot to push your custom client update update notifications that might be required.

commented

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.

commented

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