Refactored jump logic

Added separate structures for ship definition
Added separate structures for compatibility with ArsMagica2,
OpenComputers and ImmersiveEngineering
Added rotation support for blocks, tile entities, entities and
chunkloading
This commit is contained in:
LemADEC 2016-03-09 03:14:23 +01:00
parent 33dbd82837
commit 68f050235e
14 changed files with 1260 additions and 501 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,39 @@
package cr0s.warpdrive.api;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
public interface IBlockTransformer {
// Return true if this transformer is applicable to that TileEntity.
boolean isApplicable(final Block block, final int metadata, final TileEntity tileEntity);
// Called when preparing to save a ship structure.
// Use this to prevent jump during critical events/animations.
@Deprecated
boolean isJumpReady(final TileEntity tileEntity);
// Called when saving a ship structure.
// Use this to save external data in the ship schematic.
// You don't need to save Block and TileEntity data here, it's already covered.
// Warning: do NOT assume that the ship will be removed!
NBTBase saveExternals(final TileEntity tileEntity);
// Called when removing the original ship structure.
// Use this to prevents drops, clear energy networks, etc.
// Block and TileEntity will be removed right after this call.
// When moving, the new ship is placed first.
void remove(TileEntity tileEntity);
// Called when restoring a ship in the world.
// Use this to apply metadata & NBT rotation, right before block & tile entity placement.
// Use priority placement to ensure dependent blocks are placed first.
// Warning: do NOT place the block or tile entity!
int rotate(final Block block, int metadata, NBTTagCompound nbtTileEntity, final byte rotationSteps, final float rotationYaw);
// Called when placing back a ship in the world.
// Use this to restore external data from the ship schematic, right after block & tile entity placement.
// Use priority placement to ensure dependent blocks are placed first.
void restoreExternals(TileEntity tileEntity, ITransformation transformation, NBTBase nbtBase);
}

View file

@ -0,0 +1,35 @@
package cr0s.warpdrive.api;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.NBTBase;
@Deprecated
public interface IEntityTransformer {
// Return true if this transformer is applicable to that Entity.
boolean isApplicable(Entity entity);
// Called when preparing to save a ship structure.
// Use this to prevent jump during critical events/animations.
boolean isJumpReady(Entity entity);
// Called when saving a ship structure.
// Use this to save external data in the ship schematic.
// You don't need to save entity data here, it's already covered.
// Warning: do NOT assume that the ship will be removed!
NBTBase saveExternals(Entity entity);
// Called when removing the original ship structure.
// Use this to prevents drops, clear energy networks, etc.
// Entity will be removed right after this call.
void remove(Entity entity);
// Called when restoring a ship in the world.
// Use this to apply entity rotation, right before entity placement.
// Warning: do NOT spawn the entity!
short rotate(NBTBase nbtEntity, final byte rotationSteps, final float rotationYaw);
// Called when placing back a ship in the world.
// Use this to restore external data from the ship schematic, right after entity placement.
// Use priority placement to ensure dependent blocks are placed first.
void restoreExternals(Entity entity, ITransformation transformation, NBTBase nbtBase);
}

View file

@ -0,0 +1,23 @@
package cr0s.warpdrive.api;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
public interface ITransformation {
World getTargetWorld();
byte getRotationSteps();
float getRotationYaw();
Vec3 apply(final double sourceX, final double sourceY, final double sourceZ);
ChunkCoordinates apply(final int sourceX, final int sourceY, final int sourceZ);
ChunkCoordinates apply(final TileEntity tileEntity);
ChunkCoordinates apply(final ChunkCoordinates chunkCoordinates);
}

View file

@ -25,6 +25,7 @@ import cr0s.warpdrive.block.movement.TileEntityShipCore;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.config.WarpDriveConfig;
import cr0s.warpdrive.data.JumpBlock;
import cr0s.warpdrive.data.Transformation;
import cr0s.warpdrive.data.Vector3;
import cr0s.warpdrive.network.PacketHandler;
import dan200.computercraft.api.lua.ILuaContext;
@ -159,25 +160,26 @@ public class TileEntityShipScanner extends TileEntityAbstractEnergy {
for (int index = 0; index < blocks; index++) {
if (currentDeployIndex >= blocksToDeployCount) {
isDeploying = false;
isDeploying = false;
setActive(false); // disable scanner
break;
}
// Deploy single block
JumpBlock jb = blocksToDeploy[currentDeployIndex];
JumpBlock jumpBlock = blocksToDeploy[currentDeployIndex];
if (jb != null && !Dictionary.BLOCKS_ANCHOR.contains(jb.block)) {
Block blockAtTarget = worldObj.getBlock(targetX + jb.x, targetY + jb.y, targetZ + jb.z);
if (jumpBlock != null && !Dictionary.BLOCKS_ANCHOR.contains(jumpBlock.block)) {
Block blockAtTarget = worldObj.getBlock(targetX + jumpBlock.x, targetY + jumpBlock.y, targetZ + jumpBlock.z);
if (blockAtTarget == Blocks.air || Dictionary.BLOCKS_EXPANDABLE.contains(blockAtTarget)) {
jb.deploy(worldObj, targetX, targetY, targetZ);
Transformation transformation = new Transformation(null, worldObj, targetX, targetY, targetZ, (byte) 0); // FIXME: need proper ship object here
jumpBlock.deploy(worldObj, transformation);
if (worldObj.rand.nextInt(100) <= 10) {
worldObj.playSoundEffect(xCoord + 0.5f, yCoord, zCoord + 0.5f, "warpdrive:lowlaser", 4F, 1F);
PacketHandler.sendBeamPacket(worldObj,
new Vector3(this).translate(0.5D),
new Vector3(targetX + jb.x, targetY + jb.y, targetZ + jb.z).translate(0.5D),
new Vector3(targetX + jumpBlock.x, targetY + jumpBlock.y, targetZ + jumpBlock.z).translate(0.5D),
0f, 1f, 0f, 15, 0, 100);
}
}

View file

@ -113,7 +113,7 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy {
if (cooldownTime > 0) {
cooldownTime--;
warmupTime = 0;
if (cooldownTime == 0) {
if (cooldownTime == 0 && controller != null) {
controller.cooldownDone();
}
}
@ -601,12 +601,12 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy {
if (consumeEnergy(calculateRequiredEnergy(currentMode, shipMass, controller.getDistance()), false)) {
WarpDrive.logger.info(this + " Moving ship to beacon (" + beaconX + "; " + yCoord + "; " + beaconZ + ")");
EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, dx, dz, this, false, 1, 0, true, beaconX, yCoord, beaconZ);
jump.maxX = maxX;
jump.minX = minX;
jump.maxZ = maxZ;
jump.minZ = minZ;
jump.maxY = maxY;
jump.minY = minY;
jump.ship.maxX = maxX;
jump.ship.minX = minX;
jump.ship.maxZ = maxZ;
jump.ship.minZ = minZ;
jump.ship.maxY = maxY;
jump.ship.minY = minY;
jump.shipLength = shipLength;
jump.on = true;
worldObj.spawnEntityInWorld(jump);
@ -771,12 +771,12 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy {
if (consumeEnergy(calculateRequiredEnergy(currentMode, shipMass, controller.getDistance()), false)) {
WarpDrive.logger.info(this + " Moving ship to a place around gate '" + targetGate.name + "' (" + destX + "; " + destY + "; " + destZ + ")");
EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, dx, dz, this, false, 1, 0, true, destX, destY, destZ);
jump.maxX = maxX;
jump.minX = minX;
jump.maxZ = maxZ;
jump.minZ = minZ;
jump.maxY = maxY;
jump.minY = minY;
jump.ship.maxX = maxX;
jump.ship.minX = minX;
jump.ship.maxZ = maxZ;
jump.ship.minZ = minZ;
jump.ship.maxY = maxY;
jump.ship.minY = minY;
jump.shipLength = shipLength;
jump.on = true;
worldObj.spawnEntityInWorld(jump);
@ -854,12 +854,12 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy {
}
EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, dx, dz, this, (currentMode == ShipCoreMode.HYPERSPACE), distance, direction,
false, 0, 0, 0);
jump.maxX = maxX;
jump.minX = minX;
jump.maxZ = maxZ;
jump.minZ = minZ;
jump.maxY = maxY;
jump.minY = minY;
jump.ship.maxX = maxX;
jump.ship.minX = minX;
jump.ship.maxZ = maxZ;
jump.ship.minZ = minZ;
jump.ship.maxY = maxY;
jump.ship.minY = minY;
jump.shipLength = shipLength;
jump.on = true;
worldObj.spawnEntityInWorld(jump);
@ -1150,7 +1150,7 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy {
@Override
public String toString() {
return String.format(
"%s \'%s\' @ \'%s\' %d, %d, %d",
"%s \'%s\' @ \'%s\' (%d %d %d)",
new Object[] { getClass().getSimpleName(), shipName, worldObj == null ? "~NULL~" : worldObj.getWorldInfo().getWorldName(),
Integer.valueOf(xCoord), Integer.valueOf(yCoord), Integer.valueOf(zCoord) });
}

View file

@ -0,0 +1,104 @@
package cr0s.warpdrive.compat;
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.util.ChunkCoordinates;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants;
import am2.api.power.IPowerNode;
import am2.power.PowerNodeRegistry;
import cpw.mods.fml.common.Optional;
import cr0s.warpdrive.api.IBlockTransformer;
import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.config.WarpDriveConfig;
public class CompatArsMagica2 implements IBlockTransformer {
public static void register() {
WarpDriveConfig.registerBlockTransformer("arsmagica2", new CompatArsMagica2());
}
@Override
public boolean isApplicable(final Block block, final int metadata, final TileEntity tileEntity) {
return tileEntity instanceof IPowerNode;
}
@Override
public boolean isJumpReady(final TileEntity tileEntity) {
return true;
}
@Override
@Optional.Method(modid = "arsmagica2")
public NBTBase saveExternals(final TileEntity tileEntity) {
if (tileEntity instanceof IPowerNode) {
NBTBase nbtArsMagica2 = PowerNodeRegistry.For(tileEntity.getWorldObj()).getDataCompoundForNode((IPowerNode) tileEntity);
return nbtArsMagica2;
}
return null;
}
@Override
@Optional.Method(modid = "arsmagica2")
public void remove(TileEntity tileEntity) {
PowerNodeRegistry.For(tileEntity.getWorldObj()).removePowerNode((IPowerNode) tileEntity);
}
@Override
public int rotate(final Block block, final int metadata, NBTTagCompound nbtTileEntity, final byte rotationSteps, final float rotationYaw) {
return metadata;
}
@Override
@Optional.Method(modid = "arsmagica2")
public void restoreExternals(TileEntity tileEntity, ITransformation transformation, NBTBase nbtBase) {
NBTTagCompound nbtTagCompound = (NBTTagCompound) nbtBase;
// powerAmounts
// (no changes)
// powerPathList
NBTTagList powerPathList = nbtTagCompound.getTagList("powerPathList", Constants.NBT.TAG_COMPOUND);
if (powerPathList != null) {
for (int powerPathIndex = 0; powerPathIndex < powerPathList.tagCount(); powerPathIndex++) {
NBTTagCompound powerPathEntry = (NBTTagCompound) powerPathList.removeTag(0);
// powerPathList[powerPathIndex].powerType
// (no change)
// powerPathList[powerPathIndex].nodePaths
NBTTagList nodePaths = powerPathEntry.getTagList("nodePaths", Constants.NBT.TAG_LIST);
if (nodePaths != null) {
for (int nodePathIndex = 0; nodePathIndex < nodePaths.tagCount(); nodePathIndex++) {
// we can't directly access it, hence removing then adding back later on
NBTTagList nodeList = (NBTTagList) nodePaths.removeTag(0);
if (nodeList != null) {
for (int nodeIndex = 0; nodeIndex < nodeList.tagCount(); nodeIndex++) {
NBTTagCompound node = (NBTTagCompound) nodeList.removeTag(0);
// read coordinates
Vec3 target = transformation.apply(node.getFloat("Vec3_x"), node.getFloat("Vec3_y"), node.getFloat("Vec3_z"));
node.setFloat("Vec3_x", (float)target.xCoord);
node.setFloat("Vec3_y", (float)target.yCoord);
node.setFloat("Vec3_z", (float)target.zCoord);
//tack the node on to the power path
nodeList.appendTag(node);
}
nodePaths.appendTag(nodeList);
}
}
powerPathEntry.setTag("nodePaths", nodePaths);
}
powerPathList.appendTag(powerPathEntry);
}
nbtTagCompound.setTag("powerPathList", powerPathList);
}
World targetWorld = transformation.getTargetWorld();
ChunkCoordinates target = transformation.apply(tileEntity);
PowerNodeRegistry.For(targetWorld).setDataCompoundForNode((IPowerNode) targetWorld.getTileEntity(target.posX, target.posY, target.posZ), nbtTagCompound);
}
}

View file

@ -0,0 +1,109 @@
package cr0s.warpdrive.compat;
import java.util.Collection;
import blusunrize.immersiveengineering.api.energy.IImmersiveConnectable;
import blusunrize.immersiveengineering.api.energy.ImmersiveNetHandler;
import blusunrize.immersiveengineering.api.energy.ImmersiveNetHandler.Connection;
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.util.ChunkCoordinates;
import net.minecraft.world.World;
import cpw.mods.fml.common.Optional;
import cr0s.warpdrive.api.IBlockTransformer;
import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.config.WarpDriveConfig;
public class CompatImmersiveEngineering implements IBlockTransformer {
private static Class<?> classTileEntityIEBase;
public static void register() {
try {
classTileEntityIEBase = Class.forName("blusunrize.immersiveengineering.common.blocks.TileEntityIEBase");
WarpDriveConfig.registerBlockTransformer("ImmersiveEngineering", new CompatImmersiveEngineering());
} catch(ClassNotFoundException exception) {
exception.printStackTrace();
}
}
@Override
public boolean isApplicable(final Block block, final int metadata, final TileEntity tileEntity) {
return tileEntity instanceof IImmersiveConnectable || classTileEntityIEBase.isInstance(tileEntity);
}
@Override
public boolean isJumpReady(TileEntity tileEntity) {
return true;
}
@Override
@Optional.Method(modid = "ImmersiveEngineering")
public NBTBase saveExternals(final TileEntity tileEntity) {
if (tileEntity instanceof IImmersiveConnectable) {
ChunkCoordinates node = new ChunkCoordinates(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord);
Collection<Connection> connections = ImmersiveNetHandler.INSTANCE.getConnections(tileEntity.getWorldObj(), node);
if (connections != null) {
NBTTagList nbtImmersiveEngineering = new NBTTagList();
for (Connection connection : connections) {
nbtImmersiveEngineering.appendTag(connection.writeToNBT());
}
ImmersiveNetHandler.INSTANCE.clearConnectionsOriginatingFrom(node, tileEntity.getWorldObj());
return nbtImmersiveEngineering;
}
}
return null;
}
@Override
@Optional.Method(modid = "ImmersiveEngineering")
public void remove(TileEntity tileEntity) {
// nothing to do
}
@Override
public int rotate(final Block block, final int metadata, NBTTagCompound nbtTileEntity, final byte rotationSteps, final float rotationYaw) {
if (rotationSteps == 0 || !nbtTileEntity.hasKey("facing")) {
return metadata;
}
int facing = nbtTileEntity.getInteger("facing");
final int[] mrot = { 0, 1, 5, 4, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
switch (rotationSteps) {
case 1:
nbtTileEntity.setInteger("facing", mrot[facing]);
return metadata;
case 2:
nbtTileEntity.setInteger("facing", mrot[mrot[facing]]);
return metadata;
case 3:
nbtTileEntity.setInteger("facing", mrot[mrot[mrot[facing]]]);
return metadata;
default:
return metadata;
}
}
@Override
@Optional.Method(modid = "ImmersiveEngineering")
public void restoreExternals(TileEntity tileEntity, ITransformation transformation, NBTBase nbtBase) {
NBTTagList nbtImmersiveEngineering = (NBTTagList) nbtBase;
if (nbtImmersiveEngineering == null) {
return;
}
World targetWorld = transformation.getTargetWorld();
// powerPathList
for (int connectionIndex = 0; connectionIndex < nbtImmersiveEngineering.tagCount(); connectionIndex++) {
Connection connection = Connection.readFromNBT(nbtImmersiveEngineering.getCompoundTagAt(connectionIndex));
connection.start = transformation.apply(connection.start);
connection.end = transformation.apply(connection.end);
ImmersiveNetHandler.INSTANCE.addConnection(targetWorld, new ChunkCoordinates(connection.start.posX, connection.start.posY, connection.start.posZ), connection);
}
}
}

View file

@ -0,0 +1,76 @@
package cr0s.warpdrive.compat;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import cpw.mods.fml.common.Optional;
import cr0s.warpdrive.api.IBlockTransformer;
import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.config.WarpDriveConfig;
public class CompatIndustrialCraft2 implements IBlockTransformer {
private static Class<?> classIC2tileEntity;
public static void register() {
try {
classIC2tileEntity = Class.forName("ic2.core.block.TileEntityBlock");
WarpDriveConfig.registerBlockTransformer("IC2", new CompatIndustrialCraft2());
} catch (ClassNotFoundException exception) {
exception.printStackTrace();
}
}
@Override
public boolean isApplicable(final Block block, final int metadata, final TileEntity tileEntity) {
return classIC2tileEntity.isInstance(tileEntity);
}
@Override
public boolean isJumpReady(TileEntity tileEntity) {
return true;
}
@Override
@Optional.Method(modid = "IC2")
public NBTBase saveExternals(final TileEntity tileEntity) {
// nothing to do
return null;
}
@Override
@Optional.Method(modid = "IC2")
public void remove(TileEntity tileEntity) {
// nothing to do
}
@Override
public int rotate(final Block block, final int metadata, NBTTagCompound nbtTileEntity, final byte rotationSteps, final float rotationYaw) {
if (rotationSteps == 0 || !nbtTileEntity.hasKey("facing")) {
return metadata;
}
short facing = nbtTileEntity.getShort("facing");
final short[] mrot = { 0, 1, 5, 4, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
switch (rotationSteps) {
case 1:
nbtTileEntity.setShort("facing", mrot[facing]);
return metadata;
case 2:
nbtTileEntity.setShort("facing", mrot[mrot[facing]]);
return metadata;
case 3:
nbtTileEntity.setShort("facing", mrot[mrot[mrot[facing]]]);
return metadata;
default:
return metadata;
}
}
@Override
@Optional.Method(modid = "IC2")
public void restoreExternals(TileEntity tileEntity, ITransformation transformation, NBTBase nbtBase) {
// nothing to do
}
}

View file

@ -0,0 +1,77 @@
package cr0s.warpdrive.compat;
import net.minecraft.block.Block;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import cpw.mods.fml.common.Optional;
import cr0s.warpdrive.api.IBlockTransformer;
import cr0s.warpdrive.api.ITransformation;
import cr0s.warpdrive.config.WarpDriveConfig;
public class CompatOpenComputers implements IBlockTransformer {
private static Class<?> classTileEntityRotatable;
public static void register() {
try {
classTileEntityRotatable = Class.forName("li.cil.oc.common.tileentity.traits.Rotatable");
WarpDriveConfig.registerBlockTransformer("OpenComputers", new CompatOpenComputers());
} catch(ClassNotFoundException exception) {
exception.printStackTrace();
}
}
@Override
public boolean isApplicable(final Block block, final int metadata, final TileEntity tileEntity) {
return classTileEntityRotatable.isInstance(tileEntity);
}
@Override
public boolean isJumpReady(TileEntity tileEntity) {
return true;
}
@Override
@Optional.Method(modid = "OpenComputers")
public NBTBase saveExternals(final TileEntity tileEntity) {
// nothing to do
return null;
}
@Override
@Optional.Method(modid = "OpenComputers")
public void remove(TileEntity tileEntity) {
// nothing to do
}
@Override
public int rotate(final Block block, final int metadata, NBTTagCompound nbtTileEntity, final byte rotationSteps, final float rotationYaw) {
if (rotationSteps == 0 || !nbtTileEntity.hasKey("oc:yaw")) {
return metadata;
}
int facing = nbtTileEntity.getInteger("oc:yaw");
final int[] mrot = { 0, 1, 5, 4, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
switch (rotationSteps) {
case 1:
nbtTileEntity.setInteger("oc:yaw", mrot[facing]);
return metadata;
case 2:
nbtTileEntity.setInteger("oc:yaw", mrot[mrot[facing]]);
return metadata;
case 3:
nbtTileEntity.setInteger("oc:yaw", mrot[mrot[mrot[facing]]]);
return metadata;
default:
return metadata;
}
}
@Override
@Optional.Method(modid = "OpenComputers")
public void restoreExternals(TileEntity tileEntity, ITransformation transformation, NBTBase nbtBase) {
// nothing to do
}
}

View file

@ -7,6 +7,7 @@ import java.io.FilenameFilter;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@ -20,6 +21,11 @@ import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.registry.GameRegistry;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.api.IBlockTransformer;
import cr0s.warpdrive.compat.CompatArsMagica2;
import cr0s.warpdrive.compat.CompatImmersiveEngineering;
import cr0s.warpdrive.compat.CompatIndustrialCraft2;
import cr0s.warpdrive.compat.CompatOpenComputers;
import cr0s.warpdrive.config.filler.FillerManager;
import cr0s.warpdrive.config.structures.StructureManager;
import cr0s.warpdrive.config.structures.StructureReference;
@ -287,6 +293,8 @@ public class WarpDriveConfig {
public static float[] HULL_HARDNESS = { 25.0F, 50.0F, 80.0F };
public static float[] HULL_BLAST_RESISTANCE = { 60.0F, 90.0F, 120.0F };
// Block transformers library
public static HashMap<String, IBlockTransformer> blockTransformers = null;
public static Block getModBlock(final String mod, final String id) {
@ -695,9 +703,16 @@ public class WarpDriveConfig {
// Dictionary
Dictionary.loadConfig(config);
// Block transformers library
blockTransformers = new HashMap();
config.save();
}
public static void registerBlockTransformer(final String modId, IBlockTransformer blockTransformer) {
blockTransformers.put(modId, blockTransformer);
}
public static int clamp(final int min, final int max, final int value) {
return Math.min(max, Math.max(value, min));
}
@ -715,6 +730,7 @@ public class WarpDriveConfig {
isIndustrialCraft2loaded = Loader.isModLoaded("IC2");
if (isIndustrialCraft2loaded) {
loadIC2();
CompatIndustrialCraft2.register();
}
isComputerCraftLoaded = Loader.isModLoaded("ComputerCraft");
@ -726,8 +742,17 @@ public class WarpDriveConfig {
isThermalExpansionLoaded = Loader.isModLoaded("ThermalExpansion");
isAppliedEnergistics2Loaded = Loader.isModLoaded("appliedenergistics2");
isOpenComputersLoaded = Loader.isModLoaded("OpenComputers");
if (isOpenComputersLoaded) {
CompatOpenComputers.register();
}
isArsMagica2Loaded = Loader.isModLoaded("arsmagica2");
if (isArsMagica2Loaded) {
CompatArsMagica2.register();
}
isImmersiveEngineeringLoaded = Loader.isModLoaded("ImmersiveEngineering");
if (isImmersiveEngineeringLoaded) {
CompatImmersiveEngineering.register();
}
isGregTech5loaded = false;
if (Loader.isModLoaded("gregtech")) {
String gregTechVersion = FMLCommonHandler.instance().findContainerFor("gregtech").getVersion();

View file

@ -1,17 +1,53 @@
package cr0s.warpdrive.data;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import net.minecraft.block.Block;
import net.minecraft.block.BlockBed;
import net.minecraft.block.BlockButton;
import net.minecraft.block.BlockChest;
import net.minecraft.block.BlockCocoa;
import net.minecraft.block.BlockDispenser;
import net.minecraft.block.BlockDoor;
import net.minecraft.block.BlockEndPortalFrame;
import net.minecraft.block.BlockEnderChest;
import net.minecraft.block.BlockFenceGate;
import net.minecraft.block.BlockFurnace;
import net.minecraft.block.BlockHopper;
import net.minecraft.block.BlockHugeMushroom;
import net.minecraft.block.BlockLadder;
import net.minecraft.block.BlockLever;
import net.minecraft.block.BlockLog;
import net.minecraft.block.BlockPistonBase;
import net.minecraft.block.BlockPistonExtension;
import net.minecraft.block.BlockPistonMoving;
import net.minecraft.block.BlockPortal;
import net.minecraft.block.BlockPumpkin;
import net.minecraft.block.BlockRailBase;
import net.minecraft.block.BlockRedstoneDiode;
import net.minecraft.block.BlockSign;
import net.minecraft.block.BlockSkull;
import net.minecraft.block.BlockStairs;
import net.minecraft.block.BlockTorch;
import net.minecraft.block.BlockTrapDoor;
import net.minecraft.block.BlockTripWireHook;
import net.minecraft.block.BlockVine;
import net.minecraft.init.Blocks;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.tileentity.TileEntity;
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.config.WarpDriveConfig;
import cr0s.warpdrive.config.filler.Filler;
@ -23,8 +59,7 @@ public class JumpBlock {
public int x;
public int y;
public int z;
public NBTTagCompound nbtArsMagica2;
public NBTTagList nbtImmersiveEngineering;
public HashMap<String, NBTBase> externals;
public JumpBlock() {
}
@ -45,6 +80,14 @@ public class JumpBlock {
this.x = x;
this.y = y;
this.z = z;
// save externals
for (Entry<String, IBlockTransformer> entryBlockTransformer : WarpDriveConfig.blockTransformers.entrySet()) {
if (entryBlockTransformer.getValue().isApplicable(block, blockMeta, tileEntity)) {
NBTBase nbtBase = entryBlockTransformer.getValue().saveExternals(tileEntity);
setExternal(entryBlockTransformer.getKey(), nbtBase);
}
}
}
public JumpBlock(Filler filler, int x, int y, int z) {
@ -60,33 +103,172 @@ public class JumpBlock {
this.z = z;
}
public boolean deploy(World targetWorld, int offsetX, int offsetY, int offsetZ) {
public NBTBase getExternal(final String modId) {
if (externals == null) {
return null;
}
NBTBase nbtExternal = externals.get(modId);
if (WarpDriveConfig.LOGGING_JUMPBLOCKS) {
WarpDrive.logger.info("Restoring " + modId + " externals at " + x + " " + y + " " + z + " " + nbtExternal);
}
if (nbtExternal == null) {
return null;
}
return nbtExternal.copy();
}
public void setExternal(final String modId, final NBTBase nbtExternal) {
if (externals == null) {
externals = new HashMap();
}
externals.put(modId, nbtExternal);
if (WarpDriveConfig.LOGGING_JUMPBLOCKS) {
WarpDrive.logger.info("Saved " + modId + " externals at " + x + " " + y + " " + z + " " + nbtExternal);
}
}
// Return updated metadata from rotating a vanilla block
private int getMetadataRotation(NBTTagCompound nbtTileEntity, final byte rotationSteps) {
if (rotationSteps == 0) {
return blockMeta;
}
final byte[] mrotNone = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
final byte[] mrotRail = { 1, 0, 5, 4, 2, 3, 7, 8, 9, 6, 10, 11, 12, 13, 14, 15 };
final byte[] mrotAnvil = { 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 12, 13, 14, 15 };
final byte[] mrotFenceGate = { 1, 0, 2, 3, 5, 6, 7, 4, 8, 9, 10, 11, 12, 13, 14, 15 };
final byte[] mrotPumpkin = { 1, 2, 3, 0, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; // Tripwire hook, Pumpkin, Jack-o-lantern
final byte[] mrotEndPortalFrame = { 1, 2, 3, 0, 5, 6, 7, 4, 8, 9, 10, 11, 12, 13, 14, 15 }; // EndPortal, doors (open/closed, base/top)
final byte[] mrotCocoa = { 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 12, 13, 14, 15 };
final byte[] mrotRepeater = { 1, 2, 3, 0, 5, 6, 7, 4, 9, 10, 11, 8, 13, 14, 15, 12 }; // Repeater (normal/lit), Comparator
final byte[] mrotBed = { 1, 2, 3, 0, 4, 5, 6, 7, 9, 10, 11, 8, 12, 13, 14, 15 };
final byte[] mrotStair = { 2, 3, 1, 0, 6, 7, 5, 4, 8, 9, 10, 11, 12, 13, 14, 15 };
final byte[] mrotSign = { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 1, 2, 3 }; // Sign, Skull
final byte[] mrotTrapDoor = { 3, 2, 0, 1, 7, 6, 4, 5, 11, 10, 8, 9, 15, 14, 12, 13 };
final byte[] mrotLever = { 7, 2, 3, 4, 1, 6, 5, 0, 15, 11, 12, 10, 9, 14, 13, 8 };
final byte[] mrotNetherPortal = { 0, 2, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
final byte[] mrotVine = { 0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15 };
final byte[] mrotButton = { 0, 3, 4, 2, 1, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; // Button, torch (normal, redstone lit/unlit)
final byte[] mrotMushroom = { 0, 3, 6, 9, 2, 5, 8, 1, 4, 7, 10, 11, 12, 13, 14, 15 }; // Red/brown mushroom block
final byte[] mrotForgeDirection = { 0, 1, 5, 4, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; // Furnace (lit/normal), Dispenser/Dropper, Enderchest, Chest (normal/trapped), Hopper, Ladder, Wall sign
final byte[] mrotPiston = { 0, 1, 5, 4, 2, 3, 6, 7, 8, 9, 13, 12, 10, 11, 14, 15 }; // Pistons (sticky/normal, base/head)
final byte[] mrotWoodLog = { 0, 1, 2, 3, 8, 9, 10, 11, 4, 5, 6, 7, 12, 13, 14, 15 };
byte[] mrot = mrotNone;
if (block instanceof BlockRailBase) {
mrot = mrotRail;
} else if (block instanceof BlockRailBase) {
mrot = mrotAnvil;
} else if (block instanceof BlockFenceGate) {
mrot = mrotFenceGate;
} else if (block instanceof BlockPumpkin || block instanceof BlockTripWireHook) {
mrot = mrotPumpkin;
} else if (block instanceof BlockEndPortalFrame || block instanceof BlockDoor) {
mrot = mrotEndPortalFrame;
} else if (block instanceof BlockCocoa) {
mrot = mrotCocoa;
} else if (block instanceof BlockRedstoneDiode) {
mrot = mrotRepeater;
} else if (block instanceof BlockBed) {
mrot = mrotBed;
} else if (block instanceof BlockStairs) {
mrot = mrotStair;
} else if (block instanceof BlockSign) {
if (block == Blocks.wall_sign) {
mrot = mrotForgeDirection;
} else {
mrot = mrotSign;
}
} else if (block instanceof BlockTrapDoor) {
mrot = mrotTrapDoor;
} else if (block instanceof BlockLever) {
mrot = mrotLever;
} else if (block instanceof BlockPortal) {
mrot = mrotNetherPortal;
} else if (block instanceof BlockVine) {
mrot = mrotVine;
} else if (block instanceof BlockButton || block instanceof BlockTorch) {
mrot = mrotButton;
} else if (block instanceof BlockHugeMushroom) {
mrot = mrotMushroom;
} else if (block instanceof BlockFurnace || block instanceof BlockDispenser || block instanceof BlockHopper
|| block instanceof BlockChest || block instanceof BlockEnderChest || block instanceof BlockLadder
|| block instanceof BlockMonitor) {
mrot = mrotForgeDirection;
} else if (block instanceof BlockPistonBase || block instanceof BlockPistonExtension || block instanceof BlockPistonMoving) {
mrot = mrotPiston;
} else if (block instanceof BlockLog) {
mrot = mrotWoodLog;
} else if (block instanceof BlockSkull) {
mrot = mrotNone;
short facing = nbtTileEntity.getShort("Rot");
switch (rotationSteps) {
case 1:
nbtTileEntity.setShort("Rot", mrotSign[facing]);
break;
case 2:
nbtTileEntity.setShort("Rot", mrotSign[mrotSign[facing]]);
break;
case 3:
nbtTileEntity.setShort("Rot", mrotSign[mrotSign[mrotSign[facing]]]);
break;
default:
break;
}
}
switch (rotationSteps) {
case 1:
return mrot[blockMeta];
case 2:
return mrot[mrot[blockMeta]];
case 3:
return mrot[mrot[mrot[blockMeta]]];
default:
return blockMeta;
}
}
public void deploy(World targetWorld, ITransformation transformation) {
try {
int newX = x + offsetX;
int newY = y + offsetY;
int newZ = z + offsetZ;
setBlockNoLight(targetWorld, newX, newY, newZ, block, blockMeta, 2);
NBTTagCompound oldnbt = null;
if (blockTileEntity != null) {
oldnbt = new NBTTagCompound();
blockTileEntity.writeToNBT(oldnbt);
}
int newBlockMeta = blockMeta;
if (externals != null) {
for (Entry<String, NBTBase> external : externals.entrySet()) {
IBlockTransformer blockTransformer = WarpDriveConfig.blockTransformers.get(external.getKey());
if (blockTransformer != null) {
newBlockMeta = blockTransformer.rotate(block, blockMeta, oldnbt, transformation.getRotationSteps(), transformation.getRotationYaw());
}
}
} else {
newBlockMeta = getMetadataRotation(oldnbt, transformation.getRotationSteps());
}
ChunkCoordinates target = transformation.apply(x, y, z);
setBlockNoLight(targetWorld, target.posX, target.posY, target.posZ, block, newBlockMeta, 2);
// Re-schedule air blocks update
if (block == WarpDrive.blockAir) {
targetWorld.markBlockForUpdate(newX, newY, newZ);
targetWorld.scheduleBlockUpdate(newX, newY, newZ, block, 40 + targetWorld.rand.nextInt(20));
targetWorld.markBlockForUpdate(target.posX, target.posY, target.posZ);
targetWorld.scheduleBlockUpdate(target.posX, target.posY, target.posZ, block, 40 + targetWorld.rand.nextInt(20));
}
NBTTagCompound oldnbt = new NBTTagCompound();
if (blockTileEntity != null) {
blockTileEntity.writeToNBT(oldnbt);
oldnbt.setInteger("x", newX);
oldnbt.setInteger("y", newY);
oldnbt.setInteger("z", newZ);
if (oldnbt != null) {
oldnbt.setInteger("x", target.posX);
oldnbt.setInteger("y", target.posY);
oldnbt.setInteger("z", target.posZ);
if (oldnbt.hasKey("mainX") && oldnbt.hasKey("mainY") && oldnbt.hasKey("mainZ")) {// Mekanism 6.0.4.44
if (WarpDriveConfig.LOGGING_JUMPBLOCKS) {
WarpDrive.logger.info(this + " deploy: TileEntity has mainXYZ");
}
oldnbt.setInteger("mainX", oldnbt.getInteger("mainX") + offsetX);
oldnbt.setInteger("mainY", oldnbt.getInteger("mainY") + offsetY);
oldnbt.setInteger("mainZ", oldnbt.getInteger("mainZ") + offsetZ);
ChunkCoordinates mainTarget = transformation.apply(oldnbt.getInteger("mainX"), oldnbt.getInteger("mainY"), oldnbt.getInteger("mainZ"));
oldnbt.setInteger("mainX", mainTarget.posX);
oldnbt.setInteger("mainY", mainTarget.posY);
oldnbt.setInteger("mainZ", mainTarget.posZ);
}
if (oldnbt.hasKey("screenData")) {// IC2NuclearControl 2.2.5a
@ -96,12 +278,14 @@ public class JumpBlock {
if (WarpDriveConfig.LOGGING_JUMPBLOCKS) {
WarpDrive.logger.info(this + " deploy: TileEntity has screenData.min/maxXYZ");
}
nbtScreenData.setInteger("minX", nbtScreenData.getInteger("minX") + offsetX);
nbtScreenData.setInteger("minY", nbtScreenData.getInteger("minY") + offsetY);
nbtScreenData.setInteger("minZ", nbtScreenData.getInteger("minZ") + offsetZ);
nbtScreenData.setInteger("maxX", nbtScreenData.getInteger("maxX") + offsetX);
nbtScreenData.setInteger("maxY", nbtScreenData.getInteger("maxY") + offsetY);
nbtScreenData.setInteger("maxZ", nbtScreenData.getInteger("maxZ") + offsetZ);
ChunkCoordinates minTarget = transformation.apply(nbtScreenData.getInteger("minX"), nbtScreenData.getInteger("minY"), nbtScreenData.getInteger("minZ"));
nbtScreenData.setInteger("minX", minTarget.posX);
nbtScreenData.setInteger("minY", minTarget.posY);
nbtScreenData.setInteger("minZ", minTarget.posZ);
ChunkCoordinates maxTarget = transformation.apply(nbtScreenData.getInteger("maxX"), nbtScreenData.getInteger("maxY"), nbtScreenData.getInteger("maxZ"));
nbtScreenData.setInteger("maxX", maxTarget.posX);
nbtScreenData.setInteger("maxY", maxTarget.posY);
nbtScreenData.setInteger("maxZ", maxTarget.posZ);
oldnbt.setTag("screenData", nbtScreenData);
}
}
@ -141,11 +325,12 @@ public class JumpBlock {
newTileEntity.setWorldObj(targetWorld);
newTileEntity.validate();
targetWorld.setTileEntity(newX, newY, newZ, newTileEntity);
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);
}
return;
} else {
WarpDrive.logger.info(" deploy failed to create new tile entity at " + x + ", " + y + ", " + z + " blockId " + block + ":" + blockMeta);
WarpDrive.logger.info("NBT data was " + oldnbt);
@ -160,10 +345,10 @@ public class JumpBlock {
coordinates = " (unknown coordinates)";
}
WarpDrive.logger.info("moveBlockSimple exception at " + coordinates);
return false;
return;
}
return true;
return;
}
public static void refreshBlockStateOnClient(World world, int x, int y, int z) {

View file

@ -0,0 +1,183 @@
package cr0s.warpdrive.data;
import java.util.ArrayList;
import java.util.List;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.World;
import cr0s.warpdrive.EntityJump;
import cr0s.warpdrive.LocalProfiler;
import cr0s.warpdrive.WarpDrive;
import cr0s.warpdrive.block.movement.TileEntityShipCore;
import cr0s.warpdrive.config.Dictionary;
import cr0s.warpdrive.config.WarpDriveConfig;
public class JumpShip {
public World worldObj;
public int coreX;
public int coreY;
public int coreZ;
public int dx;
public int dz;
public int direction;
public int maxX;
public int maxZ;
public int maxY;
public int minX;
public int minZ;
public int minY;
public JumpBlock[] jumpBlocks;
public TileEntityShipCore shipCore;
public List<MovingEntity> entitiesOnShip;
public JumpShip() {
}
public void messageToAllPlayersOnShip(EntityJump entityJump, String msg) {
if (entitiesOnShip == null) {
shipCore.messageToAllPlayersOnShip(msg);
} else {
WarpDrive.logger.info(entityJump + " messageToAllPlayersOnShip: " + msg);
for (MovingEntity me : entitiesOnShip) {
if (me.entity instanceof EntityPlayer) {
WarpDrive.addChatMessage((EntityPlayer) me.entity, "["
+ ((shipCore != null && shipCore.shipName.length() > 0) ? shipCore.shipName : "WarpCore") + "] " + msg);
}
}
}
}
public String saveEntities(EntityJump entityJump) {
String result = null;
entitiesOnShip = new ArrayList<MovingEntity>();
AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX + 0.99D, maxY + 0.99D, maxZ + 0.99D);
List<Entity> list = entityJump.worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb);
for (Entity entity : list) {
if (entity == null || (entity instanceof EntityJump)) {
continue;
}
String id = EntityList.getEntityString(entity);
if (Dictionary.ENTITIES_ANCHOR.contains(id)) {
result = "Anchor entity " + id + " detected at " + Math.floor(entity.posX) + ", " + Math.floor(entity.posY) + ", " + Math.floor(entity.posZ) + ", aborting jump...";
// we need to continue so players are added so they can see the message...
continue;
}
if (Dictionary.ENTITIES_LEFTBEHIND.contains(id)) {
if (WarpDriveConfig.LOGGING_JUMPBLOCKS) {
WarpDrive.logger.info("Leaving entity " + id + " behind: " + entity);
}
continue;
}
if (WarpDriveConfig.LOGGING_JUMPBLOCKS) {
if (WarpDriveConfig.LOGGING_JUMPBLOCKS) {
WarpDrive.logger.info("Adding entity " + id + ": " + entity);
}
}
MovingEntity movingEntity = new MovingEntity(entity);
entitiesOnShip.add(movingEntity);
}
return result;
}
public void setMinMaxes(EntityJump entityJump, int minXV, int maxXV, int minYV, int maxYV, int minZV, int maxZV) {
minX = minXV;
maxX = maxXV;
minY = minYV;
maxY = maxYV;
minZ = minZV;
maxZ = maxZV;
}
@Override
public String toString() {
return String.format("%s/%d \'%s\' @ \'%s\' (%d %d %d)",
getClass().getSimpleName(), hashCode(),
shipCore == null ? "~NULL~" : (shipCore.uuid + ":" + shipCore.shipName),
"-", // worldObj == null ? "~NULL~" : worldObj.getWorldInfo().getWorldName(),
Double.valueOf(coreX), Double.valueOf(coreY), Double.valueOf(coreZ));
}
public int getRealShipVolume_checkBedrock(EntityJump entityJump, StringBuilder reason) {
LocalProfiler.start("EntityJump.getRealShipVolume_checkBedrock");
int shipVolume = 0;
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
for (int y = minY; y <= maxY; y++) {
Block block = entityJump.worldObj.getBlock(x, y, z);
// Skipping vanilla air & ignored blocks
if (block == Blocks.air || Dictionary.BLOCKS_LEFTBEHIND.contains(block)) {
continue;
}
shipVolume++;
if (WarpDriveConfig.LOGGING_JUMPBLOCKS) {
WarpDrive.logger.info("Block(" + x + ", " + y + ", " + z + ") is " + block.getUnlocalizedName() + "@" + entityJump.worldObj.getBlockMetadata(x, y, z));
}
// Stop on non-movable blocks
if (Dictionary.BLOCKS_ANCHOR.contains(block)) {
reason.append(block.getUnlocalizedName() + " detected onboard at " + x + ", " + y + ", " + z + ". Aborting.");
LocalProfiler.stop();
return -1;
}
}
}
}
// Abort jump if blocks with TE are connecting to the ship (avoid crash when splitting multi-blocks)
for (int x = minX - 1; x <= maxX + 1; x++) {
boolean xBorder = (x == minX - 1) || (x == maxX + 1);
for (int z = minZ - 1; z <= maxZ + 1; z++) {
boolean zBorder = (z == minZ - 1) || (z == maxZ + 1);
for (int y = minY - 1; y <= maxY + 1; y++) {
boolean yBorder = (y == minY - 1) || (y == maxY + 1);
if ((y < 0) || (y > 255)) {
continue;
}
if (!(xBorder || yBorder || zBorder)) {
continue;
}
Block block = worldObj.getBlock(x, y, z);
// Skipping any air block & ignored blocks
if (worldObj.isAirBlock(x, y, z) || Dictionary.BLOCKS_LEFTBEHIND.contains(block)) {
continue;
}
// Skipping non-movable blocks
if (Dictionary.BLOCKS_ANCHOR.contains(block)) {
continue;
}
// Skipping blocks without tile entities
TileEntity tileEntity = worldObj.getTileEntity(x, y, z);
if (tileEntity == null) {
continue;
}
reason.append("Ship snagged by " + block.getLocalizedName() + " at " + x + ", " + y + ", " + z + ". Damage report pending...");
worldObj.createExplosion((Entity) null, x, y, z, Math.min(4F * 30, 4F * (shipVolume / 50)), false);
LocalProfiler.stop();
return -1;
}
}
}
LocalProfiler.stop();
return shipVolume;
}
}

View file

@ -0,0 +1,96 @@
package cr0s.warpdrive.data;
import net.minecraft.entity.Entity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.ChunkCoordinates;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import cr0s.warpdrive.api.ITransformation;
public class Transformation implements ITransformation {
private VectorI sourceCore;
private VectorI targetCore;
private VectorI move;
private byte rotation;
private World targetWorld;
public Transformation(JumpShip ship, World targetWorld, int moveX, int moveY, int moveZ, byte rotation) {
sourceCore = new VectorI(ship.coreX, ship.coreY, ship.coreZ);
this.targetWorld = targetWorld;
move = new VectorI(moveX, moveY, moveZ);
targetCore = sourceCore.add(move);
this.rotation = (byte) ((rotation + 4) % 4);
}
@Override
public World getTargetWorld() {
return targetWorld;
}
@Override
public byte getRotationSteps() {
return rotation;
}
@Override
public float getRotationYaw() {
return 90.0F * rotation;
}
@Override
public Vec3 apply(final double sourceX, final double sourceY, final double sourceZ) {
if (rotation == 0) {
return Vec3.createVectorHelper(sourceX + move.x, sourceY + move.y, sourceZ + move.z);
} else {
double dX = sourceX - sourceCore.x - 0.5D;
double dZ = sourceZ - sourceCore.z - 0.5D;
switch (rotation) {
case 1:
return Vec3.createVectorHelper(targetCore.x + 0.5D - dZ, sourceY + move.y, targetCore.z + 0.5D + dX);
case 2:
return Vec3.createVectorHelper(targetCore.x + 0.5D - dZ, sourceY + move.y, targetCore.z + 0.5D - dX);
case 3:
return Vec3.createVectorHelper(targetCore.x + 0.5D + dZ, sourceY + move.y, targetCore.z + 0.5D - dX);
default:
return null; // dead code
}
}
}
@Override
public ChunkCoordinates apply(final int sourceX, final int sourceY, final int sourceZ) {
if (rotation == 0) {
return new ChunkCoordinates(sourceX + move.x, sourceY + move.y, sourceZ + move.z);
} else {
int dX = sourceX - sourceCore.x;
int dZ = sourceZ - sourceCore.z;
switch (rotation) {
case 1:
return new ChunkCoordinates(targetCore.x - dZ, sourceY + move.y, targetCore.z + dX);
case 2:
return new ChunkCoordinates(targetCore.x - dZ, sourceY + move.y, targetCore.z - dX);
case 3:
return new ChunkCoordinates(targetCore.x + dZ, sourceY + move.y, targetCore.z - dX);
default:
return null; // dead code
}
}
}
@Override
public ChunkCoordinates apply(final TileEntity tileEntity) {
return apply(tileEntity.xCoord, tileEntity.yCoord, tileEntity.zCoord);
}
@Override
public ChunkCoordinates apply(final ChunkCoordinates chunkCoordinates) {
return apply(chunkCoordinates.posX, chunkCoordinates.posY, chunkCoordinates.posZ);
}
public void rotate(Entity entity) {
if (rotation == 0) {
return;
}
entity.rotationYaw = (entity.rotationYaw + 270.0F * rotation) % 360.0F - 180.0F;
}
}