Updated Pneumaticraft compatibility to 1.12.2 (wip)

Due to outstanding meta/state conversion issues in the mod, support is a bit weird, notably Pneumatic doors
This commit is contained in:
Unknown 2018-12-02 23:24:47 +01:00 committed by unknown
parent 24d552b418
commit 9b26c48286

View file

@ -1,11 +1,16 @@
package cr0s.warpdrive.compat;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBlockTransformer;
import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.api.WarpDriveText;
import cr0s.warpdrive.config.WarpDriveConfig;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
@ -15,20 +20,31 @@ import net.minecraft.world.World;
public class CompatPneumaticCraft implements IBlockTransformer {
private static Class<?> classTileEntityBase;
private static Class<?> classBlockPneumaticCraft;
private static Method methodBlockPneumaticCraft_isRotatable; // many blocks are rotatable, many are not => it's more efficient to read the property to differentiate them
private static Class<?> classBlockPneumaticDoor;
private static Class<?> classBlockPressureChamberWall;
private static Class<?> classBlockPressureChamberValve;
public static void register() {
try {
classTileEntityBase = Class.forName("pneumaticCraft.common.tileentity.TileEntityBase");
classBlockPneumaticCraft = Class.forName("me.desht.pneumaticcraft.common.block.BlockPneumaticCraft");
methodBlockPneumaticCraft_isRotatable = classBlockPneumaticCraft.getMethod("isRotatable");
classBlockPneumaticDoor = Class.forName("me.desht.pneumaticcraft.common.block.BlockPneumaticDoor");
classBlockPressureChamberWall = Class.forName("me.desht.pneumaticcraft.common.block.BlockPressureChamberWall");
classBlockPressureChamberValve = Class.forName("me.desht.pneumaticcraft.common.block.BlockPressureChamberValve");
WarpDriveConfig.registerBlockTransformer("pneumaticcraft", new CompatPneumaticCraft());
} catch(final ClassNotFoundException exception) {
} catch(final ClassNotFoundException | NoSuchMethodException exception) {
exception.printStackTrace();
}
}
@Override
public boolean isApplicable(final Block block, final int metadata, final TileEntity tileEntity) {
return classTileEntityBase.isInstance(tileEntity);
return classBlockPneumaticCraft.isInstance(block);
}
@Override
@ -48,9 +64,12 @@ public class CompatPneumaticCraft implements IBlockTransformer {
// nothing to do
}
private static final byte[] mrotForgeDirection = { 0, 1, 5, 4, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
private static final byte[] mrotTextRotation = { 1, 2, 3, 0 };
private static final byte[] mrotDoor = { 0, 1, 5, 4, 2, 3, 6, 7, 11, 10, 8, 9, 12, 13, 14, 15 };
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
private static final byte[] mrotFacing = { 0, 1, 5, 4, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; // Chamber interface & Omnidirectional hopper
private static final byte[] mrotChamberWall = { 0, 1, 3, 2, 4, 8, 5, 6, 7, 9, 10, 11, 12, 13, 14, 15 }; // Chamber wall
private static final byte[] mrotChamberValve = { 0, 1, 5, 4, 2, 3, 6, 7, 11, 10, 8, 9, 12, 13, 14, 15 }; // Chamber valve
private static final byte[] mrotPneumaticDoor = { 0, 1, 5, 4, 2, 3, 6, 7, 11, 10, 8, 9, 12, 13, 14, 15 }; // Pressure door
private static final byte[] mrotTextRotation = { 1, 2, 3, 0 };
@Override
public int rotate(final Block block, final int metadata, final NBTTagCompound nbtTileEntity, final ITransformation transformation) {
@ -61,75 +80,75 @@ public class CompatPneumaticCraft implements IBlockTransformer {
return metadata;
}
// hoppers
// Aphorism signs
// @todo the sign has no text after ship movement in single player until chunk is reloaded?
if (nbtTileEntity.hasKey("textRot")) {
if (metadata == 0 || metadata == 1) {// sign is horizontal, only the text needs to be rotated
final int textRotation = nbtTileEntity.getInteger("textRot");
switch (rotationSteps) {
case 1:
nbtTileEntity.setInteger("textRot", mrotTextRotation[textRotation]);
return metadata;
case 2:
nbtTileEntity.setInteger("textRot", mrotTextRotation[mrotTextRotation[textRotation]]);
return metadata;
case 3:
nbtTileEntity.setInteger("textRot", mrotTextRotation[mrotTextRotation[mrotTextRotation[textRotation]]]);
return metadata;
default:
return metadata;
}
} else {// sign is vertical, only the block itself is rotating
switch (rotationSteps) {
case 1:
return mrotFacing[metadata];
case 2:
return mrotFacing[mrotFacing[metadata]];
case 3:
return mrotFacing[mrotFacing[mrotFacing[metadata]]];
default:
return metadata;
}
}
}
// Omnidirectional hoppers
if (nbtTileEntity.hasKey("inputDir")) {
final int inputDir = nbtTileEntity.getInteger("inputDir");
final int outputDir = nbtTileEntity.getInteger("outputDir");
switch (rotationSteps) {
case 1:
nbtTileEntity.setInteger("inputDir", mrotForgeDirection[inputDir]);
return mrotForgeDirection[metadata];
nbtTileEntity.setInteger("inputDir", mrotFacing[inputDir]);
nbtTileEntity.setInteger("outputDir", mrotFacing[outputDir]);
return mrotFacing[metadata];
case 2:
nbtTileEntity.setInteger("inputDir", mrotForgeDirection[mrotForgeDirection[inputDir]]);
return mrotForgeDirection[mrotForgeDirection[metadata]];
nbtTileEntity.setInteger("inputDir", mrotFacing[mrotFacing[inputDir]]);
nbtTileEntity.setInteger("outputDir", mrotFacing[mrotFacing[outputDir]]);
return mrotFacing[mrotFacing[metadata]];
case 3:
nbtTileEntity.setInteger("inputDir", mrotForgeDirection[mrotForgeDirection[mrotForgeDirection[inputDir]]]);
return mrotForgeDirection[mrotForgeDirection[mrotForgeDirection[metadata]]];
nbtTileEntity.setInteger("inputDir", mrotFacing[mrotFacing[mrotFacing[inputDir]]]);
nbtTileEntity.setInteger("outputDir", mrotFacing[mrotFacing[mrotFacing[outputDir]]]);
return mrotFacing[mrotFacing[mrotFacing[metadata]]];
default:
return metadata;
}
}
// Aphorism signs
if (nbtTileEntity.hasKey("textRotation")) {
final int textRotation = nbtTileEntity.getInteger("textRotation");
// Pneumatic door is facing + top/down on modulo (6 or 8 ?)
if (classBlockPneumaticDoor.isInstance(block)) {
switch (rotationSteps) {
case 1:
nbtTileEntity.setInteger("textRotation", mrotTextRotation[textRotation]);
return mrotForgeDirection[metadata];
return mrotPneumaticDoor[metadata];
case 2:
nbtTileEntity.setInteger("textRotation", mrotTextRotation[mrotTextRotation[textRotation]]);
return mrotForgeDirection[mrotForgeDirection[metadata]];
return mrotPneumaticDoor[mrotPneumaticDoor[metadata]];
case 3:
nbtTileEntity.setInteger("textRotation", mrotTextRotation[mrotTextRotation[mrotTextRotation[textRotation]]]);
return mrotForgeDirection[mrotForgeDirection[mrotForgeDirection[metadata]]];
return mrotPneumaticDoor[mrotPneumaticDoor[mrotPneumaticDoor[metadata]]];
default:
return metadata;
}
}
// door base
if (nbtTileEntity.hasKey("orientation")) {
final int orientation = nbtTileEntity.getInteger("orientation");
switch (rotationSteps) {
case 1:
nbtTileEntity.setInteger("orientation", mrotTextRotation[orientation]);
return metadata;
case 2:
nbtTileEntity.setInteger("orientation", mrotTextRotation[mrotTextRotation[orientation]]);
return metadata;
case 3:
nbtTileEntity.setInteger("orientation", mrotTextRotation[mrotTextRotation[mrotTextRotation[orientation]]]);
return metadata;
default:
return metadata;
}
}
// door
if (nbtTileEntity.getString("id").equals("TileEntityPneumaticDoor")) {
switch (rotationSteps) {
case 1:
return mrotDoor[metadata];
case 2:
return mrotDoor[mrotDoor[metadata]];
case 3:
return mrotDoor[mrotDoor[mrotDoor[metadata]]];
default:
return metadata;
}
}
// pressure chamber wall, pressure chamber window, pressure chamber interface
// pressure chamber blocks (wall, glass, valve, interface)
if (nbtTileEntity.hasKey("valveX")) {
final BlockPos target = transformation.apply(
nbtTileEntity.getInteger("valveX"),
@ -143,21 +162,25 @@ public class CompatPneumaticCraft implements IBlockTransformer {
// pressure chamber valve
if (nbtTileEntity.hasKey("multiBlockX")) {
final BlockPos sourceMin = new BlockPos(
nbtTileEntity.getInteger("multiBlockX"),
nbtTileEntity.getInteger("multiBlockY"),
nbtTileEntity.getInteger("multiBlockZ"));
// multiBlockXYZ only makes sense when size is non null, even if they are part of the multiblock (yes, it's weird)
final int multiBlockSize = nbtTileEntity.getInteger("multiBlockSize");
final BlockPos sourceMax = new BlockPos(
sourceMin.getX() + multiBlockSize - 1,
sourceMin.getY() + multiBlockSize - 1,
sourceMin.getZ() + multiBlockSize - 1);
final BlockPos target1 = transformation.apply(sourceMin);
final BlockPos target2 = transformation.apply(sourceMax);
nbtTileEntity.setInteger("multiBlockX", Math.min(target1.getX(), target2.getX()));
nbtTileEntity.setInteger("multiBlockY", Math.min(target1.getY(), target2.getY()));
nbtTileEntity.setInteger("multiBlockZ", Math.min(target1.getZ(), target2.getZ()));
if (multiBlockSize != 0) {
final BlockPos sourceMin = new BlockPos(
nbtTileEntity.getInteger("multiBlockX"),
nbtTileEntity.getInteger("multiBlockY"),
nbtTileEntity.getInteger("multiBlockZ"));
final BlockPos sourceMax = new BlockPos(
sourceMin.getX() + multiBlockSize - 1,
sourceMin.getY() + multiBlockSize - 1,
sourceMin.getZ() + multiBlockSize - 1);
final BlockPos target1 = transformation.apply(sourceMin);
final BlockPos target2 = transformation.apply(sourceMax);
nbtTileEntity.setInteger("multiBlockX", Math.min(target1.getX(), target2.getX()));
nbtTileEntity.setInteger("multiBlockY", Math.min(target1.getY(), target2.getY()));
nbtTileEntity.setInteger("multiBlockZ", Math.min(target1.getZ(), target2.getZ()));
}
// Valves coordinates to each valves
final NBTTagList tagListOld = nbtTileEntity.getTagList("Valves", 10);
final NBTTagList tagListNew = new NBTTagList();
for (int index = 0; index < tagListOld.tagCount(); index++) {
@ -177,22 +200,117 @@ public class CompatPneumaticCraft implements IBlockTransformer {
// use default metadata rotation
}
// all other tile entities: security station, programmer, pneumatic dynamo, charging station, air cannon, elevator caller, air compressor
switch (rotationSteps) {
case 1:
return mrotForgeDirection[metadata];
case 2:
return mrotForgeDirection[mrotForgeDirection[metadata]];
case 3:
return mrotForgeDirection[mrotForgeDirection[mrotForgeDirection[metadata]]];
default:
// elevator base, pipe
if (nbtTileEntity.hasKey("sideConnected0")) {
final byte[] connectedOldSides = new byte[6];
for (int side = 2; side < 6; side++) {
connectedOldSides[side] = nbtTileEntity.getByte("sideConnected" + side);
}
for (int side = 2; side < 6; side++) {
final byte connected = connectedOldSides[side];
switch (rotationSteps) {
case 1:
nbtTileEntity.setByte("sideConnected" + mrotFacing[side], connected);
break;
case 2:
nbtTileEntity.setByte("sideConnected" + mrotFacing[mrotFacing[side]], connected);
break;
case 3:
nbtTileEntity.setByte("sideConnected" + mrotFacing[mrotFacing[mrotFacing[side]]], connected);
break;
default:
break;
}
}
if (nbtTileEntity.hasKey("sideClosed0")) {
final byte[] closedOldSides = new byte[6];
for (int side = 2; side < 6; side++) {
closedOldSides[side] = nbtTileEntity.getByte("sideClosed" + side);
}
for (int side = 2; side < 6; side++) {
final byte connected = closedOldSides[side];
switch (rotationSteps) {
case 1:
nbtTileEntity.setByte("sideClosed" + mrotFacing[side], connected);
break;
case 2:
nbtTileEntity.setByte("sideClosed" + mrotFacing[mrotFacing[side]], connected);
break;
case 3:
nbtTileEntity.setByte("sideClosed" + mrotFacing[mrotFacing[mrotFacing[side]]], connected);
break;
default:
break;
}
}
}
}
// Pressure chamber wall has its own logic: NONE, CENTER, XEDGE, ZEDGE, YEDGE, XMIN_YMIN_ZMIN, XMIN_YMIN_ZMAX, XMIN_YMAX_ZMIN, XMIN_YMAX_ZMAX
if (classBlockPressureChamberWall.isInstance(block)) {
switch (rotationSteps) {
case 1:
return mrotChamberWall[metadata];
case 2:
return mrotChamberWall[mrotChamberWall[metadata]];
case 3:
return mrotChamberWall[mrotChamberWall[mrotChamberWall[metadata]]];
default:
return metadata;
}
}
if (classBlockPressureChamberValve.isInstance(block)) {
switch (rotationSteps) {
case 1:
return mrotChamberValve[metadata];
case 2:
return mrotChamberValve[mrotChamberValve[metadata]];
case 3:
return mrotChamberValve[mrotChamberValve[mrotChamberValve[metadata]]];
default:
return metadata;
}
}
// all other tile entities we need to check the Rotatable state
// this includes many blocks like security station, programmer, pneumatic dynamo, charging station, air cannon, elevator caller, air compressor, etc.
final boolean isRotatable;
try {
final Object object = methodBlockPneumaticCraft_isRotatable.invoke(block);
if (object instanceof Boolean) {
isRotatable = (Boolean) object;
} else {
WarpDrive.logger.error(String.format("Block %s has invalid non-Boolean return value to isRotatable: %s",
block.getRegistryName(), object));
return metadata;
}
} catch (final IllegalAccessException | InvocationTargetException exception) {
exception.printStackTrace();
return metadata;
}
WarpDrive.logger.info(String.format("Block %s isRotatable %s",
block.getRegistryName(), isRotatable));
if (isRotatable) {
switch (rotationSteps) {
case 1:
return mrotFacing[metadata];
case 2:
return mrotFacing[mrotFacing[metadata]];
case 3:
return mrotFacing[mrotFacing[mrotFacing[metadata]]];
default:
return metadata;
}
} else {
return metadata;
}
}
@Override
public void restoreExternals(final World world, final int x, final int y, final int z,
final Block block, final int blockMeta, final TileEntity tileEntity,
public void restoreExternals(final World world, final BlockPos blockPos,
final IBlockState blockState, final TileEntity tileEntity,
final ITransformation transformation, final NBTBase nbtBase) {
// nothing to do
}