Added ForgeMultipart rotation support

This includes microblocks and Wireless redstone (Chickenbones edition)
Other parts will not rotate and may corrupt your world, use at your own
risk.
This commit is contained in:
LemADEC 2016-04-22 22:44:52 +02:00
parent 41a8dfafea
commit 6752ec16e5
3 changed files with 177 additions and 28 deletions

View file

@ -0,0 +1,171 @@
package cr0s.warpdrive.compat;
import java.lang.reflect.Method;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBlockTransformer;
import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.config.WarpDriveConfig;
public class CompatForgeMultipart implements IBlockTransformer {
public static Method methodMultipartHelper_createTileFromNBT = null;
public static Method methodMultipartHelper_sendDescPacket = null;
public static Method tileMultipart_onChunkLoad = null;
private static Class<?> classBlockMultipart;
public static boolean register() {
try {
Class forgeMultipart_helper = Class.forName("codechicken.multipart.MultipartHelper");
methodMultipartHelper_createTileFromNBT = forgeMultipart_helper.getDeclaredMethod("createTileFromNBT", World.class, NBTTagCompound.class);
methodMultipartHelper_sendDescPacket = forgeMultipart_helper.getDeclaredMethod("sendDescPacket", World.class, TileEntity.class);
Class forgeMultipart_tileMultipart = Class.forName("codechicken.multipart.TileMultipart");
tileMultipart_onChunkLoad = forgeMultipart_tileMultipart.getDeclaredMethod("onChunkLoad");
classBlockMultipart = Class.forName("codechicken.multipart.BlockMultipart");
WarpDriveConfig.registerBlockTransformer("ForgeMultipart", new CompatForgeMultipart());
} catch(ClassNotFoundException | SecurityException | NoSuchMethodException exception) {
exception.printStackTrace();
return false;
}
return true;
}
@Override
public boolean isApplicable(final Block block, final int metadata, final TileEntity tileEntity) {
return classBlockMultipart.isInstance(block);
}
@Override
public boolean isJumpReady(final Block block, final int metadata, final TileEntity tileEntity, StringBuilder reason) {
return true;
}
@Override
public NBTBase saveExternals(final TileEntity tileEntity) {
// nothing to do
return null;
}
@Override
public void remove(TileEntity tileEntity) {
// nothing to do
}
private static final byte NBTTagCompoundId = 10; // new NBTTagCompound().getId();
// Microblocks shape is bits 0-3 for shape/slot, bits 4-7 for size:
// - mcr_cnr (nook, corner, notch): 16 20 22 18 / 17 21 23 19 => shape/slot: 0 4 6 2 / 1 5 7 3
// - mcr_face (cover, panel, slab): 16 / 17 / 18 21 19 20 => shape/slot: 0 / 1 / 2 5 3 4
// - mcr_hllw (hollow cover, panel, slab): same as mcr_face
// - mcr_edge (strip, post, pillar): 16 18 19 17 / 20 24 21 26 / 22 25 23 27 => shape/slot: 0 2 3 1 / 4 8 5 10 / 6 9 7 11
// - mcr_post (post, pillar): 32 / 33 34 => shape/slot: 0 / 1 2
// = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
private static final byte[] rotMicroblockCorner = { 4, 5, 0, 1, 6, 7, 2, 3, 8, 9, 10, 11, 12, 13, 14, 15 };
private static final byte[] rotMicroblockFace = { 0, 1, 5, 4, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
private static final byte[] rotMicroblockEdge = { 2, 0, 3, 1, 8, 10, 9, 11, 5, 7, 4, 6, 12, 13, 14, 15 };
private static final byte[] rotMicroblockPost = { 0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
// WRCBE state is bits 0-1 for rotation, bits 2-4 for face:
// - wrcbe-recv, wrcbe-tran, wrcbe-jamm: 0 1 2 3 / 4 7 6 5 / 8 20 12 16 / 9 21 13 17 / 10 22 14 18 / 11 23 15 19
private static final byte[] rotWRCBEstate = { 1, 2, 3, 0, 7, 4, 5, 6,
20, 21, 22, 23, 16, 17, 18, 19, 8, 9, 10, 11, 12, 13, 14, 15,
24, 25, 26, 27, 28, 29, 30, 31 };
private NBTTagCompound rotate_part(final byte rotationSteps, NBTTagCompound nbtPart) {
NBTTagCompound nbtNewPart = (NBTTagCompound) nbtPart.copy();
if (!nbtNewPart.hasKey("id")) {
WarpDrive.logger.error("Ignoring ForgeMultipart with missing id: " + nbtPart);
} else {
String id = nbtPart.getString("id");
String propertyName = null;
byte mask = (byte) 0xFF;
byte[] rot = null;
// microblocks
if (id.equals("mcr_cnr")) {
propertyName = "shape";
mask = (byte) 0x0F;
rot = rotMicroblockCorner;
} else if (id.equals("mcr_face") || id.equals("mcr_hllw")) {
propertyName = "shape";
mask = (byte) 0x0F;
rot = rotMicroblockFace;
} else if (id.equals("mcr_edge")) {
propertyName = "shape";
mask = (byte) 0x0F;
rot = rotMicroblockEdge;
} else if (id.equals("mcr_post")) {
propertyName = "shape";
mask = (byte) 0x0F;
rot = rotMicroblockPost;
// wireless redstone
} else if (id.equals("wrcbe-recv") || id.equals("wrcbe-tran") || id.equals("wrcbe-jamm")) {
propertyName = "state";
mask = (byte) 0x1F;
rot = rotWRCBEstate;
} else {
WarpDrive.logger.error("Ignoring part of ForgeMultipart with unknown id: " + nbtPart);
}
// actual rotation
if (propertyName != null && rot != null) {
if (nbtPart.hasKey(propertyName)) {
byte value = nbtPart.getByte(propertyName);
byte masked = (byte) (value & mask);
byte notmasked = (byte) (value - masked);
switch (rotationSteps) {
case 1:
nbtNewPart.setByte(propertyName, (byte) (notmasked | rot[masked]));
break;
case 2:
nbtNewPart.setByte(propertyName, (byte) (notmasked | rot[rot[masked]]));
break;
case 3:
nbtNewPart.setByte(propertyName, (byte) (notmasked | rot[rot[rot[masked]]]));
break;
default:
break;
}
}
}
}
return nbtNewPart;
}
@Override
public int rotate(final Block block, final int metadata, NBTTagCompound nbtTileEntity, final ITransformation transformation) {
byte rotationSteps = transformation.getRotationSteps();
if (rotationSteps == 0 || nbtTileEntity == null) {
return metadata;
}
// Parts
if (nbtTileEntity.hasKey("parts")) {
NBTTagList nbtParts = nbtTileEntity.getTagList("parts", NBTTagCompoundId);
NBTTagList nbtNewParts = new NBTTagList();
for (int index = 0; index < nbtParts.tagCount(); index++) {
NBTTagCompound nbtPart = nbtParts.getCompoundTagAt(index);
NBTTagCompound nbtNewPart = rotate_part(rotationSteps, nbtPart);
nbtNewParts.appendTag(nbtNewPart);
}
nbtTileEntity.setTag("parts", nbtNewParts);
} else {
WarpDrive.logger.error("Ignoring ForgeMultipart with no 'parts': " + nbtTileEntity);
}
return metadata;
}
@Override
public void restoreExternals(TileEntity tileEntity, ITransformation transformation, NBTBase nbtBase) {
// nothing to do
}
}

View file

@ -5,7 +5,6 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
@ -29,6 +28,7 @@ import cr0s.warpdrive.compat.CompatBotania;
import cr0s.warpdrive.compat.CompatComputerCraft;
import cr0s.warpdrive.compat.CompatEnderIO;
import cr0s.warpdrive.compat.CompatEvilCraft;
import cr0s.warpdrive.compat.CompatForgeMultipart;
import cr0s.warpdrive.compat.CompatImmersiveEngineering;
import cr0s.warpdrive.compat.CompatIndustrialCraft2;
import cr0s.warpdrive.compat.CompatJABBA;
@ -47,9 +47,6 @@ import cr0s.warpdrive.data.Planet;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.config.ConfigCategory;
import net.minecraftforge.common.config.Configuration;
@ -83,11 +80,6 @@ public class WarpDriveConfig {
public static boolean isEnderIOloaded = false;
public static boolean isAdvancedRepulsionSystemLoaded = false;
// ForgeMultipart (microblocks) support
public static Method forgeMultipart_helper_createTileFromNBT = null;
public static Method forgeMultipart_helper_sendDescPacket = null;
public static Method forgeMultipart_tileMultipart_onChunkLoad = null;
public static ItemStack IC2_compressedAir;
public static ItemStack IC2_emptyCell;
public static Block IC2_rubberWood;
@ -761,7 +753,7 @@ public class WarpDriveConfig {
public static void onFMLInitialization() {
isForgeMultipartLoaded = Loader.isModLoaded("ForgeMultipart");
if (isForgeMultipartLoaded) {
loadForgeMultipart();
isForgeMultipartLoaded = CompatForgeMultipart.register();
}
isIndustrialCraft2Loaded = Loader.isModLoaded("IC2");
@ -876,20 +868,6 @@ public class WarpDriveConfig {
Dictionary.apply();
}
private static void loadForgeMultipart() {
try {
Class forgeMultipart_helper = Class.forName("codechicken.multipart.MultipartHelper");
forgeMultipart_helper_createTileFromNBT = forgeMultipart_helper.getDeclaredMethod("createTileFromNBT", World.class, NBTTagCompound.class);
forgeMultipart_helper_sendDescPacket = forgeMultipart_helper.getDeclaredMethod("sendDescPacket", World.class, TileEntity.class);
Class forgeMultipart_tileMultipart = Class.forName("codechicken.multipart.TileMultipart");
forgeMultipart_tileMultipart_onChunkLoad = forgeMultipart_tileMultipart.getDeclaredMethod("onChunkLoad");
} catch (Exception exception) {
isForgeMultipartLoaded = false;
WarpDrive.logger.error("Error loading ForgeMultipart classes");
exception.printStackTrace();
}
}
private static void loadIC2() {
try {
IC2_emptyCell = getModItemStack("IC2", "itemCellEmpty", -1);

View file

@ -43,11 +43,11 @@ import net.minecraft.util.ChunkCoordinates;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBlockTransformer;
import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.block.detection.BlockMonitor;
import cr0s.warpdrive.compat.CompatForgeMultipart;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.config.filler.Filler;
@ -299,7 +299,7 @@ public class JumpBlock {
boolean isForgeMultipart = false;
if (WarpDriveConfig.isForgeMultipartLoaded && nbtToDeploy.hasKey("id") && nbtToDeploy.getString("id") == "savedMultipart") {
isForgeMultipart = true;
newTileEntity = (TileEntity) WarpDriveConfig.forgeMultipart_helper_createTileFromNBT.invoke(null, targetWorld, nbtToDeploy);
newTileEntity = (TileEntity) CompatForgeMultipart.methodMultipartHelper_createTileFromNBT.invoke(null, targetWorld, nbtToDeploy);
} else if (block == WarpDriveConfig.CC_Computer || block == WarpDriveConfig.CC_peripheral
|| block == WarpDriveConfig.CCT_Turtle || block == WarpDriveConfig.CCT_Expanded || block == WarpDriveConfig.CCT_Advanced) {
@ -327,8 +327,8 @@ public class JumpBlock {
targetWorld.setTileEntity(target.posX, target.posY, target.posZ, newTileEntity);
if (isForgeMultipart) {
WarpDriveConfig.forgeMultipart_tileMultipart_onChunkLoad.invoke(newTileEntity);
WarpDriveConfig.forgeMultipart_helper_sendDescPacket.invoke(null, targetWorld, newTileEntity);
CompatForgeMultipart.tileMultipart_onChunkLoad.invoke(newTileEntity);
CompatForgeMultipart.methodMultipartHelper_sendDescPacket.invoke(null, targetWorld, newTileEntity);
}
return;
} else {