From 75a2cc7feb220b64d34621ead3e787fdb9589998 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20N=C3=BCcke?= Date: Fri, 8 Aug 2014 23:17:39 +0200 Subject: [PATCH] Added support for Galacticraft power. --- .../mods/galacticraft/api/package-info.java | 5 + .../galacticraft/api/power/EnergySource.java | 28 + .../api/power/IEnergyHandlerGC.java | 49 ++ .../api/power/IEnergyStorageGC.java | 38 + .../galacticraft/api/power/ILaserNode.java | 26 + .../galacticraft/api/power/package-info.java | 5 + .../galacticraft/api/vector/BlockVec3.java | 598 +++++++++++++ .../mods/galacticraft/api/vector/Vector2.java | 135 +++ .../mods/galacticraft/api/vector/Vector3.java | 820 ++++++++++++++++++ .../galacticraft/api/vector/VectorD3.java | 95 ++ .../galacticraft/api/vector/package-info.java | 5 + src/main/scala/li/cil/oc/Settings.scala | 2 + src/main/scala/li/cil/oc/client/Sound.scala | 4 +- .../cil/oc/common/asm/ClassTransformer.scala | 1 + .../tileentity/traits/PowerAcceptor.scala | 1 + .../traits/power/Galacticraft.scala | 31 + src/main/scala/li/cil/oc/util/mods/Mods.scala | 2 + 17 files changed, 1843 insertions(+), 2 deletions(-) create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/package-info.java create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/power/EnergySource.java create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/power/IEnergyHandlerGC.java create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/power/IEnergyStorageGC.java create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/power/ILaserNode.java create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/power/package-info.java create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/vector/BlockVec3.java create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/vector/Vector2.java create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/vector/Vector3.java create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/vector/VectorD3.java create mode 100644 src/api/java/micdoodle8/mods/galacticraft/api/vector/package-info.java create mode 100644 src/main/scala/li/cil/oc/common/tileentity/traits/power/Galacticraft.scala diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/package-info.java b/src/api/java/micdoodle8/mods/galacticraft/api/package-info.java new file mode 100644 index 000000000..55ce1bae8 --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/package-info.java @@ -0,0 +1,5 @@ +@API(apiVersion = "1.0", owner = "GalacticraftCore", provides = "Galacticraft API") +package micdoodle8.mods.galacticraft.api; + +import cpw.mods.fml.common.API; + diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/power/EnergySource.java b/src/api/java/micdoodle8/mods/galacticraft/api/power/EnergySource.java new file mode 100644 index 000000000..9050ff503 --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/power/EnergySource.java @@ -0,0 +1,28 @@ +package micdoodle8.mods.galacticraft.api.power; + +import net.minecraftforge.common.util.ForgeDirection; + +import java.util.List; + +public abstract class EnergySource +{ + public static class EnergySourceWireless extends EnergySource + { + public final List nodes; + + public EnergySourceWireless(List nodes) + { + this.nodes = nodes; + } + } + + public static class EnergySourceAdjacent extends EnergySource + { + public final ForgeDirection direction; + + public EnergySourceAdjacent(ForgeDirection direction) + { + this.direction = direction; + } + } +} diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/power/IEnergyHandlerGC.java b/src/api/java/micdoodle8/mods/galacticraft/api/power/IEnergyHandlerGC.java new file mode 100644 index 000000000..490760fd8 --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/power/IEnergyHandlerGC.java @@ -0,0 +1,49 @@ +package micdoodle8.mods.galacticraft.api.power; + +public interface IEnergyHandlerGC +{ + /** + * Add energy from an external source + * + * @param from + * Energy Source that is providing power + * @param amount + * Maximum amount of energy to receive + * @param simulate + * If true, the transfer will only be simulated. + * @return The amount of energy that was successfully received (or would + * have been, if simulated). + */ + public float receiveEnergyGC(EnergySource from, float amount, boolean simulate); + + /** + * Remove energy, transferring it to an external source + * + * @param from + * Energy Source that is extracting power + * @param amount + * Maximum amount of energy to extract + * @param simulate + * If true, the transfer will only be simulated. + * @return The amount of energy that was successfully extracted (or would + * have been, if simulated). + */ + public float extractEnergyGC(EnergySource from, float amount, boolean simulate); + + /** + * Returns true if the handler can interface with the provided energy source + */ + public boolean nodeAvailable(EnergySource from); + + /** + * Returns the amount of energy stored in this handler available to the + * provided source + */ + public float getEnergyStoredGC(EnergySource from); + + /** + * Returns the maximum amount of energy stored in this handler available to + * the provided source + */ + public float getMaxEnergyStoredGC(EnergySource from); +} diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/power/IEnergyStorageGC.java b/src/api/java/micdoodle8/mods/galacticraft/api/power/IEnergyStorageGC.java new file mode 100644 index 000000000..4c62c1d52 --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/power/IEnergyStorageGC.java @@ -0,0 +1,38 @@ +package micdoodle8.mods.galacticraft.api.power; + +public interface IEnergyStorageGC +{ + /** + * Add energy to the storage. + * + * @param amount + * Maximum amount of energy to receive + * @param simulate + * If true, the transfer will only be simulated. + * @return The amount of energy that was successfully received (or would + * have been, if simulated). + */ + public float receiveEnergyGC(float amount, boolean simulate); + + /** + * Remove energy from the storage. + * + * @param amount + * Maximum amount of energy to extract + * @param simulate + * If true, the transfer will only be simulated. + * @return The amount of energy that was successfully extracted (or would + * have been, if simulated). + */ + public float extractEnergyGC(float amount, boolean simulate); + + /** + * Returns the amount of energy stored + */ + public float getEnergyStoredGC(); + + /** + * Returns the maximum amount of energy stored + */ + public float getCapacityGC(); +} diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/power/ILaserNode.java b/src/api/java/micdoodle8/mods/galacticraft/api/power/ILaserNode.java new file mode 100644 index 000000000..c6531a947 --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/power/ILaserNode.java @@ -0,0 +1,26 @@ +package micdoodle8.mods.galacticraft.api.power; + +import micdoodle8.mods.galacticraft.api.vector.BlockVec3; +import micdoodle8.mods.galacticraft.api.vector.Vector3; +import net.minecraft.tileentity.TileEntity; + +public interface ILaserNode extends IEnergyHandlerGC +{ + public Vector3 getInputPoint(); + + public Vector3 getOutputPoint(boolean offset); + + public ILaserNode getTarget(); + + public TileEntity getTile(); + + public boolean canConnectTo(ILaserNode node); + + public Vector3 getColor(); + + public void addNode(ILaserNode node); + + public void removeNode(ILaserNode node); + + public int compareTo(ILaserNode otherNode, BlockVec3 origin); +} diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/power/package-info.java b/src/api/java/micdoodle8/mods/galacticraft/api/power/package-info.java new file mode 100644 index 000000000..137eb021f --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/power/package-info.java @@ -0,0 +1,5 @@ +@API(apiVersion = "1.0", owner = "GalacticraftCore", provides = "Galacticraft API") +package micdoodle8.mods.galacticraft.api.power; + +import cpw.mods.fml.common.API; + diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/vector/BlockVec3.java b/src/api/java/micdoodle8/mods/galacticraft/api/vector/BlockVec3.java new file mode 100644 index 000000000..4e2150aa5 --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/vector/BlockVec3.java @@ -0,0 +1,598 @@ +package micdoodle8.mods.galacticraft.api.vector; + +import net.minecraft.block.Block; +import net.minecraft.crash.CrashReport; +import net.minecraft.crash.CrashReportCategory; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ReportedException; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.common.util.ForgeDirection; + +/* BlockVec3 is similar to galacticraft.api.vector.Vector3? + * + * But for speed it uses integer arithmetic not doubles, for block coordinates + * This reduces unnecessary type conversion between integers and doubles and back again. + * (Minecraft block coordinates are always integers, only entity coordinates are doubles.) + * + */ +public class BlockVec3 implements Cloneable +{ + public int x; + public int y; + public int z; + public boolean[] sideDone = { false, false, false, false, false, false }; + private static Chunk chunkCached; + public static int chunkCacheDim = Integer.MAX_VALUE; + private static int chunkCacheX = 1876000; // outside the world edge + private static int chunkCacheZ = 1876000; // outside the world edge + // INVALID_VECTOR is used in cases where a null vector cannot be used + public static final BlockVec3 INVALID_VECTOR = new BlockVec3(-1, -1, -1); + + public BlockVec3() + { + this(0, 0, 0); + } + + public BlockVec3(int x, int y, int z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public BlockVec3(Entity par1) + { + this.x = (int) Math.floor(par1.posX); + this.y = (int) Math.floor(par1.posY); + this.z = (int) Math.floor(par1.posZ); + } + + public BlockVec3(TileEntity par1) + { + this.x = par1.xCoord; + this.y = par1.yCoord; + this.z = par1.zCoord; + } + + /** + * Makes a new copy of this Vector. Prevents variable referencing problems. + */ + @Override + public final BlockVec3 clone() + { + return new BlockVec3(this.x, this.y, this.z); + } + + /** + * Get block ID at the BlockVec3 coordinates, with a forced chunk load if + * the coordinates are unloaded. + * + * @param world + * @return the block ID, or null if the y-coordinate is less than 0 or + * greater than 256 or the x or z is outside the Minecraft worldmap. + * + */ + public Block getBlockID(World world) + { + if (this.y < 0 || this.y >= 256 || this.x < -30000000 || this.z < -30000000 || this.x >= 30000000 || this.z >= 30000000) + { + return null; + } + + int chunkx = this.x >> 4; + int chunkz = this.z >> 4; + try + { + // In a typical inner loop, 80% of the time consecutive calls to + // this will be within the same chunk + if (BlockVec3.chunkCacheX == chunkx && BlockVec3.chunkCacheZ == chunkz && BlockVec3.chunkCacheDim == world.provider.dimensionId && BlockVec3.chunkCached.isChunkLoaded) + { + return BlockVec3.chunkCached.getBlock(this.x & 15, this.y, this.z & 15); + } + else + { + Chunk chunk = null; + chunk = world.getChunkFromChunkCoords(chunkx, chunkz); + BlockVec3.chunkCached = chunk; + BlockVec3.chunkCacheDim = world.provider.dimensionId; + BlockVec3.chunkCacheX = chunkx; + BlockVec3.chunkCacheZ = chunkz; + return chunk.getBlock(this.x & 15, this.y, this.z & 15); + } + } + catch (Throwable throwable) + { + CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Oxygen Sealer thread: Exception getting block type in world"); + CrashReportCategory crashreportcategory = crashreport.makeCategory("Requested block coordinates"); + crashreportcategory.addCrashSection("Location", CrashReportCategory.getLocationInfo(this.x, this.y, this.z)); + throw new ReportedException(crashreport); + } + } + + /** + * Get block ID at the BlockVec3 coordinates without forcing a chunk load. + * + * @param world + * @return the block ID, or null if the y-coordinate is less than 0 or + * greater than 256 or the x or z is outside the Minecraft worldmap. + * Returns Blocks.bedrock if the coordinates being checked are in an + * unloaded chunk + */ + public Block getBlockID_noChunkLoad(World world) + { + if (this.y < 0 || this.y >= 256 || this.x < -30000000 || this.z < -30000000 || this.x >= 30000000 || this.z >= 30000000) + { + return null; + } + + int chunkx = this.x >> 4; + int chunkz = this.z >> 4; + try + { + if (world.getChunkProvider().chunkExists(chunkx, chunkz)) + { + // In a typical inner loop, 80% of the time consecutive calls to + // this will be within the same chunk + if (BlockVec3.chunkCacheX == chunkx && BlockVec3.chunkCacheZ == chunkz && BlockVec3.chunkCacheDim == world.provider.dimensionId && BlockVec3.chunkCached.isChunkLoaded) + { + return BlockVec3.chunkCached.getBlock(this.x & 15, this.y, this.z & 15); + } + else + { + Chunk chunk = null; + chunk = world.getChunkFromChunkCoords(chunkx, chunkz); + BlockVec3.chunkCached = chunk; + BlockVec3.chunkCacheDim = world.provider.dimensionId; + BlockVec3.chunkCacheX = chunkx; + BlockVec3.chunkCacheZ = chunkz; + return chunk.getBlock(this.x & 15, this.y, this.z & 15); + } + } + //Chunk doesn't exist - meaning, it is not loaded + return Blocks.bedrock; + } + catch (Throwable throwable) + { + CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Oxygen Sealer thread: Exception getting block type in world"); + CrashReportCategory crashreportcategory = crashreport.makeCategory("Requested block coordinates"); + crashreportcategory.addCrashSection("Location", CrashReportCategory.getLocationInfo(this.x, this.y, this.z)); + throw new ReportedException(crashreport); + } + } + + public Block getBlock(IBlockAccess par1iBlockAccess) + { + return par1iBlockAccess.getBlock(this.x, this.y, this.z); + } + + /** + * Get block ID at the BlockVec3 coordinates without forcing a chunk load. + * Only call this 'safe' version if x and z coordinates are within the + * Minecraft world map (-30m to +30m) + * + * @param world + * @return the block ID, or null if the y-coordinate is less than 0 or + * greater than 256. Returns Blocks.bedrock if the coordinates being + * checked are in an unloaded chunk + */ + public Block getBlockIDsafe_noChunkLoad(World world) + { + if (this.y < 0 || this.y >= 256) + { + return null; + } + + int chunkx = this.x >> 4; + int chunkz = this.z >> 4; + try + { + if (world.getChunkProvider().chunkExists(chunkx, chunkz)) + { + // In a typical inner loop, 80% of the time consecutive calls to + // this will be within the same chunk + if (BlockVec3.chunkCacheX == chunkx && BlockVec3.chunkCacheZ == chunkz && BlockVec3.chunkCacheDim == world.provider.dimensionId && BlockVec3.chunkCached.isChunkLoaded) + { + return BlockVec3.chunkCached.getBlock(this.x & 15, this.y, this.z & 15); + } + else + { + Chunk chunk = null; + chunk = world.getChunkFromChunkCoords(chunkx, chunkz); + BlockVec3.chunkCached = chunk; + BlockVec3.chunkCacheDim = world.provider.dimensionId; + BlockVec3.chunkCacheX = chunkx; + BlockVec3.chunkCacheZ = chunkz; + return chunk.getBlock(this.x & 15, this.y, this.z & 15); + } + } + //Chunk doesn't exist - meaning, it is not loaded + return Blocks.bedrock; + } + catch (Throwable throwable) + { + CrashReport crashreport = CrashReport.makeCrashReport(throwable, "Oxygen Sealer thread: Exception getting block type in world"); + CrashReportCategory crashreportcategory = crashreport.makeCategory("Requested block coordinates"); + crashreportcategory.addCrashSection("Location", CrashReportCategory.getLocationInfo(this.x, this.y, this.z)); + throw new ReportedException(crashreport); + } + } + + public BlockVec3 add(BlockVec3 par1) + { + this.x += par1.x; + this.y += par1.y; + this.z += par1.z; + return this; + } + + public BlockVec3 translate(BlockVec3 par1) + { + this.x += par1.x; + this.y += par1.y; + this.z += par1.z; + return this; + } + + public BlockVec3 translate(int par1x, int par1y, int par1z) + { + this.x += par1x; + this.y += par1y; + this.z += par1z; + return this; + } + + public static BlockVec3 add(BlockVec3 par1, BlockVec3 a) + { + return new BlockVec3(par1.x + a.x, par1.y + a.y, par1.z + a.z); + } + + public BlockVec3 subtract(BlockVec3 par1) + { + this.x = this.x -= par1.x; + this.y = this.y -= par1.y; + this.z = this.z -= par1.z; + + return this; + } + + public BlockVec3 modifyPositionFromSide(ForgeDirection side, int amount) + { + switch (side.ordinal()) + { + case 0: + this.y -= amount; + break; + case 1: + this.y += amount; + break; + case 2: + this.z -= amount; + break; + case 3: + this.z += amount; + break; + case 4: + this.x -= amount; + break; + case 5: + this.x += amount; + break; + } + return this; + } + + public BlockVec3 newVecSide(int side) + { + BlockVec3 vec = new BlockVec3(this.x, this.y, this.z); + vec.sideDone[side ^ 1] = true; + switch (side) + { + case 0: + vec.y--; + return vec; + case 1: + vec.y++; + return vec; + case 2: + vec.z--; + return vec; + case 3: + vec.z++; + return vec; + case 4: + vec.x--; + return vec; + case 5: + vec.x++; + return vec; + } + return vec; + } + + public BlockVec3 modifyPositionFromSide(ForgeDirection side) + { + return this.modifyPositionFromSide(side, 1); + } + + @Override + public int hashCode() + { + // Upgraded hashCode calculation from the one in VecDirPair to something + // a bit stronger and faster + return ((this.y * 379 + this.x) * 373 + this.z) * 7; + } + + @Override + public boolean equals(Object o) + { + if (o instanceof BlockVec3) + { + BlockVec3 vector = (BlockVec3) o; + return this.x == vector.x && this.y == vector.y && this.z == vector.z; + } + + return false; + } + + @Override + public String toString() + { + return "BlockVec3 [" + this.x + "," + this.y + "," + this.z + "]"; + } + + /** + * This will load the chunk. + */ + public TileEntity getTileEntity(IBlockAccess world) + { + return world.getTileEntity(this.x, this.y, this.z); + } + + /** + * No chunk load: returns null if chunk to side is unloaded + */ + public TileEntity getTileEntityOnSide(World world, ForgeDirection side) + { + int x = this.x; + int y = this.y; + int z = this.z; + switch (side.ordinal()) + { + case 0: + y--; + break; + case 1: + y++; + break; + case 2: + z--; + break; + case 3: + z++; + break; + case 4: + x--; + break; + case 5: + x++; + break; + default: + return null; + } + if (world.blockExists(x, y, z)) + { + return world.getTileEntity(x, y, z); + } + else + { + return null; + } + } + + /** + * No chunk load: returns null if chunk to side is unloaded + */ + public TileEntity getTileEntityOnSide(World world, int side) + { + int x = this.x; + int y = this.y; + int z = this.z; + switch (side) + { + case 0: + y--; + break; + case 1: + y++; + break; + case 2: + z--; + break; + case 3: + z++; + break; + case 4: + x--; + break; + case 5: + x++; + break; + default: + return null; + } + if (world.blockExists(x, y, z)) + { + return world.getTileEntity(x, y, z); + } + else + { + return null; + } + } + + /** + * This will load the chunk to the side. + */ + public boolean blockOnSideHasSolidFace(World world, int side) + { + int x = this.x; + int y = this.y; + int z = this.z; + switch (side) + { + case 0: + y--; + break; + case 1: + y++; + break; + case 2: + z--; + break; + case 3: + z++; + break; + case 4: + x--; + break; + case 5: + x++; + break; + default: + return false; + } + return world.getBlock(x, y, z).isSideSolid(world, x, y, z, ForgeDirection.getOrientation(side ^ 1)); + } + + /** + * No chunk load: returns null if chunk is unloaded + */ + public Block getBlockOnSide(World world, int side) + { + int x = this.x; + int y = this.y; + int z = this.z; + switch (side) + { + case 0: + y--; + break; + case 1: + y++; + break; + case 2: + z--; + break; + case 3: + z++; + break; + case 4: + x--; + break; + case 5: + x++; + break; + default: + return null; + } + if (world.blockExists(x, y, z)) + { + return world.getBlock(x, y, z); + } + else + { + return null; + } + } + + public int getBlockMetadata(IBlockAccess world) + { + return world.getBlockMetadata(this.x, this.y, this.z); + } + + public static BlockVec3 readFromNBT(NBTTagCompound nbtCompound) + { + BlockVec3 tempVector = new BlockVec3(); + tempVector.x = (int) Math.floor(nbtCompound.getInteger("x")); + tempVector.y = (int) Math.floor(nbtCompound.getInteger("y")); + tempVector.z = (int) Math.floor(nbtCompound.getInteger("z")); + return tempVector; + } + + public int distanceTo(BlockVec3 vector) + { + int var2 = vector.x - this.x; + int var4 = vector.y - this.y; + int var6 = vector.z - this.z; + return MathHelper.floor_double(Math.sqrt(var2 * var2 + var4 * var4 + var6 * var6)); + } + + public int distanceSquared(BlockVec3 vector) + { + int var2 = vector.x - this.x; + int var4 = vector.y - this.y; + int var6 = vector.z - this.z; + return var2 * var2 + var4 * var4 + var6 * var6; + } + + public NBTTagCompound writeToNBT(NBTTagCompound par1NBTTagCompound) + { + par1NBTTagCompound.setInteger("x", this.x); + par1NBTTagCompound.setInteger("y", this.y); + par1NBTTagCompound.setInteger("z", this.z); + return par1NBTTagCompound; + } + + public BlockVec3(NBTTagCompound par1NBTTagCompound) + { + this.x = par1NBTTagCompound.getInteger("x"); + this.y = par1NBTTagCompound.getInteger("y"); + this.z = par1NBTTagCompound.getInteger("z"); + } + + public double getMagnitude() + { + return Math.sqrt(this.getMagnitudeSquared()); + } + + public int getMagnitudeSquared() + { + return this.x * this.x + this.y * this.y + this.z * this.z; + } + + public void setBlock(World worldObj, Block block) + { + worldObj.setBlock(this.x, this.y, this.z, block, 0, 3); + } + + public boolean blockExists(World world) + { + return world.blockExists(this.x, this.y, this.z); + } + + public int intX() + { + return this.x; + } + + public int intY() + { + return this.y; + } + + public int intZ() + { + return this.z; + } + + public void setSideDone(int side) + { + this.sideDone[side] = true; + } +} diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/vector/Vector2.java b/src/api/java/micdoodle8/mods/galacticraft/api/vector/Vector2.java new file mode 100644 index 000000000..f3a29e0b4 --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/vector/Vector2.java @@ -0,0 +1,135 @@ +package micdoodle8.mods.galacticraft.api.vector; + +/** + * Vector2 Class is used for defining objects in a 2D space. + * + * @author Calclavia + */ + +public class Vector2 implements Cloneable +{ + public double x; + public double y; + + public Vector2() + { + this(0, 0); + } + + public Vector2(double x, double y) + { + this.x = x; + this.y = y; + } + + /** + * Returns the integer floor value. + * + * @return + */ + public int intX() + { + return (int) Math.floor(this.x); + } + + public int intY() + { + return (int) Math.floor(this.y); + } + + /** + * Makes a new copy of this Vector. Prevents variable referencing problems. + */ + @Override + public final Vector2 clone() + { + return new Vector2(this.x, this.y); + } + + public static double distance(Vector2 point1, Vector2 point2) + { + double xDifference = point1.x - point2.x; + double yDiference = point1.y - point2.y; + return Math.sqrt(xDifference * xDifference + yDiference * yDiference); + } + + public static double slope(Vector2 point1, Vector2 point2) + { + double xDifference = point1.x - point2.x; + double yDiference = point1.y - point2.y; + return yDiference / xDifference; + } + + public double distanceTo(Vector2 target) + { + double xDifference = this.x - target.x; + double yDifference = this.y - target.y; + return Math.sqrt(xDifference * xDifference + yDifference * yDifference); + } + + public Vector2 add(Vector2 par1) + { + this.x += par1.x; + this.y += par1.y; + return this; + } + + public Vector2 add(double par1) + { + this.x += par1; + this.y += par1; + return this; + } + + public Vector2 invert() + { + this.multiply(-1); + return this; + } + + public Vector2 multiply(double amount) + { + this.x *= amount; + this.y *= amount; + return this; + } + + public Vector2 round() + { + return new Vector2(Math.round(this.x), Math.round(this.y)); + } + + public Vector2 ceil() + { + return new Vector2(Math.ceil(this.x), Math.ceil(this.y)); + } + + public Vector2 floor() + { + return new Vector2(Math.floor(this.x), Math.floor(this.y)); + } + + @Override + public int hashCode() + { + return ("X:" + this.x + "Y:" + this.y).hashCode(); + } + + @Override + public boolean equals(Object o) + { + if (o instanceof Vector2) + { + Vector2 vector = (Vector2) o; + return this.x == vector.x && this.y == vector.y; + } + + return false; + } + + @Override + public String toString() + { + return "Vector2 [" + this.x + "," + this.y + "]"; + } +} \ No newline at end of file diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/vector/Vector3.java b/src/api/java/micdoodle8/mods/galacticraft/api/vector/Vector3.java new file mode 100644 index 000000000..f93313b70 --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/vector/Vector3.java @@ -0,0 +1,820 @@ +package micdoodle8.mods.galacticraft.api.vector; + +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.ChunkCoordinates; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; +import org.apache.commons.lang3.builder.EqualsBuilder; +import org.apache.commons.lang3.builder.HashCodeBuilder; + +import java.util.List; + +/** + * Vector3 Class is used for defining objects in a 3D space. + * + * @author Calclavia + */ + +public class Vector3 implements Cloneable +{ + + public double x; + public double y; + public double z; + + public Vector3(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + + public Vector3() + { + this(0, 0, 0); + } + + public Vector3(Vector3 vector) + { + this(vector.x, vector.y, vector.z); + } + + public Vector3(double amount) + { + this(amount, amount, amount); + } + + public Vector3(Entity par1) + { + this(par1.posX, par1.posY, par1.posZ); + } + + public Vector3(TileEntity par1) + { + this(par1.xCoord, par1.yCoord, par1.zCoord); + } + + public Vector3(Vec3 par1) + { + this(par1.xCoord, par1.yCoord, par1.zCoord); + + } + + public Vector3(MovingObjectPosition par1) + { + this(par1.blockX, par1.blockY, par1.blockZ); + } + + public Vector3(ChunkCoordinates par1) + { + this(par1.posX, par1.posY, par1.posZ); + } + + public Vector3(ForgeDirection direction) + { + this(direction.offsetX, direction.offsetY, direction.offsetZ); + } + + /** + * Loads a Vector3 from an NBT compound. + */ + public Vector3(NBTTagCompound nbt) + { + this(nbt.getDouble("x"), nbt.getDouble("y"), nbt.getDouble("z")); + } + + /** + * Get a Vector3 based on the rotationYaw and rotationPitch. + * + * @param rotationYaw + * - Degree + * @param rotationPitch + * - Degree + */ + public Vector3(float rotationYaw, float rotationPitch) + { + this(Math.cos(Math.toRadians(rotationYaw + 90)), Math.sin(Math.toRadians(-rotationPitch)), Math.sin(Math.toRadians(rotationYaw + 90))); + } + + /** + * Returns the coordinates as integers, ideal for block placement. + */ + public int intX() + { + return (int) Math.floor(this.x); + } + + public int intY() + { + return (int) Math.floor(this.y); + } + + public int intZ() + { + return (int) Math.floor(this.z); + } + + public float floatX() + { + return (float) this.x; + } + + public float floatY() + { + return (float) this.y; + } + + public float floatZ() + { + return (float) this.z; + } + + /** + * Makes a new copy of this Vector. Prevents variable referencing problems. + */ + @Override + public final Vector3 clone() + { + return new Vector3(this); + } + + /** + * Easy block access functions. + * + * @param world + * @return + */ + public Block getBlock(IBlockAccess world) + { + return world.getBlock(this.intX(), this.intY(), this.intZ()); + } + + public int getBlockMetadata(IBlockAccess world) + { + return world.getBlockMetadata(this.intX(), this.intY(), this.intZ()); + } + + public TileEntity getTileEntity(IBlockAccess world) + { + return world.getTileEntity(this.intX(), this.intY(), this.intZ()); + } + + public boolean setBlock(World world, Block id, int metadata, int notify) + { + return world.setBlock(this.intX(), this.intY(), this.intZ(), id, metadata, notify); + } + + public boolean setBlock(World world, Block id, int metadata) + { + return this.setBlock(world, id, metadata, 3); + } + + public boolean setBlock(World world, Block id) + { + return this.setBlock(world, id, 0); + } + + /** + * ---------------------- CONVERSION FUNCTIONS ---------------------------- + */ + /** + * Converts this Vector3 into a Vector2 by dropping the Y axis. + */ + public Vector2 toVector2() + { + return new Vector2(this.x, this.z); + } + + /** + * Converts this vector three into a Minecraft Vec3 object + */ + public Vec3 toVec3() + { + return Vec3.createVectorHelper(this.x, this.y, this.z); + } + + /** + * Converts Vector3 into a ForgeDirection. + */ + public ForgeDirection toForgeDirection() + { + for (ForgeDirection direction : ForgeDirection.VALID_DIRECTIONS) + { + if (this.x == direction.offsetX && this.y == direction.offsetY && this.z == direction.offsetZ) + { + return direction; + } + } + + return ForgeDirection.UNKNOWN; + } + + public double getMagnitude() + { + return Math.sqrt(this.getMagnitudeSquared()); + } + + public double getMagnitudeSquared() + { + return this.x * this.x + this.y * this.y + this.z * this.z; + } + + public Vector3 normalize() + { + double d = this.getMagnitude(); + + if (d != 0) + { + this.scale(1 / d); + } + + return this; + } + + /** + * Gets the distance between two vectors + * + * @return The distance + */ + public static double distance(Vector3 vec1, Vector3 vec2) + { + return vec1.distance(vec2); + } + + @Deprecated + public double distanceTo(Vector3 vector3) + { + return this.distance(vector3); + } + + public double distance(Vector3 compare) + { + Vector3 difference = this.clone().difference(compare); + return difference.getMagnitude(); + } + + /** + * Multiplies the vector by negative one. + */ + public Vector3 invert() + { + this.scale(-1); + return this; + } + + public Vector3 translate(Vector3 par1) + { + this.x += par1.x; + this.y += par1.y; + this.z += par1.z; + return this; + } + + public Vector3 translate(double par1) + { + this.x += par1; + this.y += par1; + this.z += par1; + return this; + } + + public static Vector3 translate(Vector3 translate, Vector3 par1) + { + translate.x += par1.x; + translate.y += par1.y; + translate.z += par1.z; + return translate; + } + + public static Vector3 translate(Vector3 translate, double par1) + { + translate.x += par1; + translate.y += par1; + translate.z += par1; + return translate; + } + + @Deprecated + public Vector3 add(Vector3 amount) + { + return this.translate(amount); + } + + @Deprecated + public Vector3 add(double amount) + { + return this.translate(amount); + } + + @Deprecated + public Vector3 subtract(Vector3 amount) + { + return this.translate(amount.clone().invert()); + } + + @Deprecated + public Vector3 subtract(double amount) + { + return this.translate(-amount); + } + + public Vector3 difference(Vector3 amount) + { + return this.translate(amount.clone().invert()); + } + + public Vector3 difference(double amount) + { + return this.translate(-amount); + } + + public Vector3 scale(double amount) + { + this.x *= amount; + this.y *= amount; + this.z *= amount; + return this; + } + + public Vector3 scale(Vector3 amount) + { + this.x *= amount.x; + this.y *= amount.y; + this.z *= amount.z; + return this; + } + + public static Vector3 scale(Vector3 vec, double amount) + { + return vec.scale(amount); + } + + public static Vector3 scale(Vector3 vec, Vector3 amount) + { + return vec.scale(amount); + } + + @Deprecated + public Vector3 multiply(double amount) + { + return this.scale(amount); + } + + @Deprecated + public Vector3 multiply(Vector3 amount) + { + return this.scale(amount); + } + + /** + * Static versions of a lot of functions + */ + public static Vector3 subtract(Vector3 par1, Vector3 par2) + { + return new Vector3(par1.x - par2.x, par1.y - par2.y, par1.z - par2.z); + } + + @Deprecated + public static Vector3 add(Vector3 par1, Vector3 par2) + { + return new Vector3(par1.x + par2.x, par1.y + par2.y, par1.z + par2.z); + } + + @Deprecated + public static Vector3 add(Vector3 par1, double par2) + { + return new Vector3(par1.x + par2, par1.y + par2, par1.z + par2); + } + + @Deprecated + public static Vector3 multiply(Vector3 vec1, Vector3 vec2) + { + return new Vector3(vec1.x * vec2.x, vec1.y * vec2.y, vec1.z * vec2.z); + } + + @Deprecated + public static Vector3 multiply(Vector3 vec1, double vec2) + { + return new Vector3(vec1.x * vec2, vec1.y * vec2, vec1.z * vec2); + } + + public Vector3 round() + { + return new Vector3(Math.round(this.x), Math.round(this.y), Math.round(this.z)); + } + + public Vector3 ceil() + { + return new Vector3(Math.ceil(this.x), Math.ceil(this.y), Math.ceil(this.z)); + } + + public Vector3 floor() + { + return new Vector3(Math.floor(this.x), Math.floor(this.y), Math.floor(this.z)); + } + + public Vector3 toRound() + { + this.x = Math.round(this.x); + this.y = Math.round(this.y); + this.z = Math.round(this.z); + return this; + } + + public Vector3 toCeil() + { + this.x = Math.ceil(this.x); + this.y = Math.ceil(this.y); + this.z = Math.ceil(this.z); + return this; + } + + public Vector3 toFloor() + { + this.x = Math.floor(this.x); + this.y = Math.floor(this.y); + this.z = Math.floor(this.z); + return this; + } + + /** + * Gets all entities inside of this position in block space. + */ + @SuppressWarnings("unchecked") + public List getEntitiesWithin(World worldObj, Class par1Class) + { + return worldObj.getEntitiesWithinAABB(par1Class, AxisAlignedBB.getBoundingBox(this.intX(), this.intY(), this.intZ(), this.intX() + 1, this.intY() + 1, this.intZ() + 1)); + } + + /** + * Gets a position relative to a position's side + * + * @param position + * - The position + * @param side + * - The side. 0-5 + * @return The position relative to the original position's side + */ + public Vector3 modifyPositionFromSide(ForgeDirection side, double amount) + { + return this.translate(new Vector3(side).scale(amount)); + } + + public Vector3 modifyPositionFromSide(ForgeDirection side) + { + this.modifyPositionFromSide(side, 1); + return this; + } + + /** + * Cross product functions + * + * @return The cross product between this vector and another. + */ + public Vector3 toCrossProduct(Vector3 compare) + { + double newX = this.y * compare.z - this.z * compare.y; + double newY = this.z * compare.x - this.x * compare.z; + double newZ = this.x * compare.y - this.y * compare.x; + this.x = newX; + this.y = newY; + this.z = newZ; + return this; + } + + public Vector3 crossProduct(Vector3 compare) + { + return this.clone().toCrossProduct(compare); + } + + public Vector3 xCrossProduct() + { + return new Vector3(0.0D, this.z, -this.y); + } + + public Vector3 zCrossProduct() + { + return new Vector3(-this.y, this.x, 0.0D); + } + + public double dotProduct(Vector3 vec2) + { + return this.x * vec2.x + this.y * vec2.y + this.z * vec2.z; + } + + /** + * @return The perpendicular vector. + */ + public Vector3 getPerpendicular() + { + if (this.z == 0.0F) + { + return this.zCrossProduct(); + } + + return this.xCrossProduct(); + } + + /** + * @return True if this Vector3 is zero. + */ + public boolean isZero() + { + return this.x == 0 && this.y == 0 && this.z == 0; + } + + /** + * Rotate by a this vector around an axis. + * + * @return The new Vector3 rotation. + */ + public Vector3 rotate(float angle, Vector3 axis) + { + return Vector3.translateMatrix(Vector3.getRotationMatrix(angle, axis), this.clone()); + } + + public double[] getRotationMatrix(float angle) + { + double[] matrix = new double[16]; + Vector3 axis = this.clone().normalize(); + double x = axis.x; + double y = axis.y; + double z = axis.z; + angle *= 0.0174532925D; + float cos = (float) Math.cos(angle); + float ocos = 1.0F - cos; + float sin = (float) Math.sin(angle); + matrix[0] = x * x * ocos + cos; + matrix[1] = y * x * ocos + z * sin; + matrix[2] = x * z * ocos - y * sin; + matrix[4] = x * y * ocos - z * sin; + matrix[5] = y * y * ocos + cos; + matrix[6] = y * z * ocos + x * sin; + matrix[8] = x * z * ocos + y * sin; + matrix[9] = y * z * ocos - x * sin; + matrix[10] = z * z * ocos + cos; + matrix[15] = 1.0F; + return matrix; + } + + public static Vector3 translateMatrix(double[] matrix, Vector3 translation) + { + double x = translation.x * matrix[0] + translation.y * matrix[1] + translation.z * matrix[2] + matrix[3]; + double y = translation.x * matrix[4] + translation.y * matrix[5] + translation.z * matrix[6] + matrix[7]; + double z = translation.x * matrix[8] + translation.y * matrix[9] + translation.z * matrix[10] + matrix[11]; + translation.x = x; + translation.y = y; + translation.z = z; + return translation; + } + + public static double[] getRotationMatrix(float angle, Vector3 axis) + { + return axis.getRotationMatrix(angle); + } + + /** + * Rotates this Vector by a yaw, pitch and roll value. + */ + public void rotate(double yaw, double pitch, double roll) + { + double yawRadians = Math.toRadians(yaw); + double pitchRadians = Math.toRadians(pitch); + double rollRadians = Math.toRadians(roll); + + double x = this.x; + double y = this.y; + double z = this.z; + + this.x = x * Math.cos(yawRadians) * Math.cos(pitchRadians) + z * (Math.cos(yawRadians) * Math.sin(pitchRadians) * Math.sin(rollRadians) - Math.sin(yawRadians) * Math.cos(rollRadians)) + y * (Math.cos(yawRadians) * Math.sin(pitchRadians) * Math.cos(rollRadians) + Math.sin(yawRadians) * Math.sin(rollRadians)); + this.z = x * Math.sin(yawRadians) * Math.cos(pitchRadians) + z * (Math.sin(yawRadians) * Math.sin(pitchRadians) * Math.sin(rollRadians) + Math.cos(yawRadians) * Math.cos(rollRadians)) + y * (Math.sin(yawRadians) * Math.sin(pitchRadians) * Math.cos(rollRadians) - Math.cos(yawRadians) * Math.sin(rollRadians)); + this.y = -x * Math.sin(pitchRadians) + z * Math.cos(pitchRadians) * Math.sin(rollRadians) + y * Math.cos(pitchRadians) * Math.cos(rollRadians); + } + + /** + * Rotates a point by a yaw and pitch around the anchor 0,0 by a specific + * angle. + */ + public void rotate(double yaw, double pitch) + { + this.rotate(yaw, pitch, 0); + } + + public void rotate(double yaw) + { + double yawRadians = Math.toRadians(yaw); + + double x = this.x; + double z = this.z; + + if (yaw != 0) + { + this.x = x * Math.cos(yawRadians) - z * Math.sin(yawRadians); + this.z = x * Math.sin(yawRadians) + z * Math.cos(yawRadians); + } + } + + /** + * Gets the delta look position based on the rotation yaw and pitch. + * Minecraft coordinates are messed up. Y and Z are flipped. Yaw is + * displaced by 90 degrees. Pitch is inversed. + * + * @param rotationYaw + * @param rotationPitch + */ + public static Vector3 getDeltaPositionFromRotation(float rotationYaw, float rotationPitch) + { + return new Vector3(rotationYaw, rotationPitch); + } + + /** + * Gets the angle between this vector and another vector. + * + * @return Angle in degrees + */ + public double getAngle(Vector3 vec2) + { + return Vector3.anglePreNorm(this.clone().normalize(), vec2.clone().normalize()); + } + + public static double getAngle(Vector3 vec1, Vector3 vec2) + { + return vec1.getAngle(vec2); + } + + public double anglePreNorm(Vector3 vec2) + { + return Math.acos(this.dotProduct(vec2)); + } + + public static double anglePreNorm(Vector3 vec1, Vector3 vec2) + { + return Math.acos(vec1.clone().dotProduct(vec2)); + } + + /** + * Loads a Vector3 from an NBT compound. + */ + @Deprecated + public static Vector3 readFromNBT(NBTTagCompound nbt) + { + return new Vector3(nbt); + } + + /** + * Saves this Vector3 to disk + * + * @param prefix + * - The prefix of this save. Use some unique string. + * @param nbt + * - The NBT compound object to save the data in + */ + public NBTTagCompound writeToNBT(NBTTagCompound nbt) + { + nbt.setDouble("x", this.x); + nbt.setDouble("y", this.y); + nbt.setDouble("z", this.z); + return nbt; + } + + public static Vector3 UP() + { + return new Vector3(0, 1, 0); + } + + public static Vector3 DOWN() + { + return new Vector3(0, -1, 0); + } + + public static Vector3 NORTH() + { + return new Vector3(0, 0, -1); + } + + public static Vector3 SOUTH() + { + return new Vector3(0, 0, 1); + } + + public static Vector3 WEST() + { + return new Vector3(-1, 0, 0); + } + + public static Vector3 EAST() + { + return new Vector3(1, 0, 0); + } + + @Deprecated + public MovingObjectPosition rayTraceEntities(World world, float rotationYaw, float rotationPitch, boolean collisionFlag, double reachDistance) + { + return this.rayTraceEntities(world, rotationYaw, rotationPitch, reachDistance); + } + + public MovingObjectPosition rayTraceEntities(World world, float rotationYaw, float rotationPitch, double reachDistance) + { + return this.rayTraceEntities(world, Vector3.getDeltaPositionFromRotation(rotationYaw, rotationPitch).scale(reachDistance)); + } + + /** + * Does an entity raytrace. + * + * @param world + * - The world object. + * @param target + * - The rotation in terms of Vector3. Convert using + * getDeltaPositionFromRotation() + * @return The target hit. + */ + public MovingObjectPosition rayTraceEntities(World world, Vector3 target) + { + MovingObjectPosition pickedEntity = null; + Vec3 startingPosition = this.toVec3(); + Vec3 look = target.toVec3(); + double reachDistance = this.distance(target); + Vec3 reachPoint = Vec3.createVectorHelper(startingPosition.xCoord + look.xCoord * reachDistance, startingPosition.yCoord + look.yCoord * reachDistance, startingPosition.zCoord + look.zCoord * reachDistance); + + double checkBorder = 1.1 * reachDistance; + AxisAlignedBB boxToScan = AxisAlignedBB.getBoundingBox(-checkBorder, -checkBorder, -checkBorder, checkBorder, checkBorder, checkBorder).offset(this.x, this.y, this.z); + + @SuppressWarnings("unchecked") + List entitiesHit = world.getEntitiesWithinAABBExcludingEntity(null, boxToScan); + double closestEntity = reachDistance; + + if (entitiesHit == null || entitiesHit.isEmpty()) + { + return null; + } + for (Entity entityHit : entitiesHit) + { + if (entityHit != null && entityHit.canBeCollidedWith() && entityHit.boundingBox != null) + { + float border = entityHit.getCollisionBorderSize(); + AxisAlignedBB aabb = entityHit.boundingBox.expand(border, border, border); + MovingObjectPosition hitMOP = aabb.calculateIntercept(startingPosition, reachPoint); + + if (hitMOP != null) + { + if (aabb.isVecInside(startingPosition)) + { + if (0.0D < closestEntity || closestEntity == 0.0D) + { + pickedEntity = new MovingObjectPosition(entityHit); + if (pickedEntity != null) + { + pickedEntity.hitVec = hitMOP.hitVec; + closestEntity = 0.0D; + } + } + } + else + { + double distance = startingPosition.distanceTo(hitMOP.hitVec); + + if (distance < closestEntity || closestEntity == 0.0D) + { + pickedEntity = new MovingObjectPosition(entityHit); + pickedEntity.hitVec = hitMOP.hitVec; + closestEntity = distance; + } + } + } + } + } + return pickedEntity; + } + + @Override + public int hashCode() + { + return new HashCodeBuilder().append(this.x).append(this.y).append(this.z).hashCode(); + } + + @Override + public boolean equals(Object o) + { + if (o instanceof Vector3) + { + Vector3 vector3 = (Vector3) o; + return new EqualsBuilder().append(this.x, vector3.x).append(this.y, vector3.y).append(this.z, vector3.z).isEquals(); + } + + return false; + } + + @Override + public String toString() + { + return "Vector3 [" + this.x + "," + this.y + "," + this.z + "]"; + } + +} \ No newline at end of file diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/vector/VectorD3.java b/src/api/java/micdoodle8/mods/galacticraft/api/vector/VectorD3.java new file mode 100644 index 000000000..fd0d05ad9 --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/vector/VectorD3.java @@ -0,0 +1,95 @@ +package micdoodle8.mods.galacticraft.api.vector; + +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.ChunkCoordinates; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.Vec3; +import net.minecraftforge.common.util.ForgeDirection; + +public class VectorD3 +{ + public Vector3 position; + public int dimensionID; + + public VectorD3(double x, double y, double z, int dimID) + { + this.position = new Vector3(x, y, z); + this.dimensionID = dimID; + } + + public VectorD3() + { + this(0, 0, 0, 0); + } + + public VectorD3(VectorD3 vector) + { + this(vector.position.x, vector.position.y, vector.position.z, vector.dimensionID); + } + + public VectorD3(Vector3 vector, int dimID) + { + this(vector.x, vector.y, vector.z, dimID); + } + + public VectorD3(double amount) + { + this(amount, amount, amount, 0); + } + + public VectorD3(Entity par1) + { + this(par1.posX, par1.posY, par1.posZ, 0); + } + + public VectorD3(TileEntity par1) + { + this(par1.xCoord, par1.yCoord, par1.zCoord, 0); + } + + public VectorD3(Vec3 par1) + { + this(par1.xCoord, par1.yCoord, par1.zCoord, 0); + + } + + public VectorD3(MovingObjectPosition par1) + { + this(par1.blockX, par1.blockY, par1.blockZ, 0); + } + + public VectorD3(ChunkCoordinates par1) + { + this(par1.posX, par1.posY, par1.posZ, 0); + } + + public VectorD3(ForgeDirection direction) + { + this(direction.offsetX, direction.offsetY, direction.offsetZ, 0); + } + + public VectorD3(NBTTagCompound nbt) + { + this(nbt.getDouble("x"), nbt.getDouble("y"), nbt.getDouble("z"), nbt.getInteger("dimID")); + } + + public VectorD3(float rotationYaw, float rotationPitch) + { + this(Math.cos(Math.toRadians(rotationYaw + 90)), Math.sin(Math.toRadians(-rotationPitch)), Math.sin(Math.toRadians(rotationYaw + 90)), 0); + } + + public NBTTagCompound writeToNBT(NBTTagCompound nbt) + { + this.position.writeToNBT(nbt); + nbt.setInteger("dimID", this.dimensionID); + return nbt; + } + + @Override + public final VectorD3 clone() + { + return new VectorD3(this); + } +} diff --git a/src/api/java/micdoodle8/mods/galacticraft/api/vector/package-info.java b/src/api/java/micdoodle8/mods/galacticraft/api/vector/package-info.java new file mode 100644 index 000000000..0c95c5376 --- /dev/null +++ b/src/api/java/micdoodle8/mods/galacticraft/api/vector/package-info.java @@ -0,0 +1,5 @@ +@API(apiVersion = "1.0", owner = "GalacticraftCore", provides = "Galacticraft API") +package micdoodle8.mods.galacticraft.api.vector; + +import cpw.mods.fml.common.API; + diff --git a/src/main/scala/li/cil/oc/Settings.scala b/src/main/scala/li/cil/oc/Settings.scala index df2179802..9107f9870 100644 --- a/src/main/scala/li/cil/oc/Settings.scala +++ b/src/main/scala/li/cil/oc/Settings.scala @@ -238,6 +238,7 @@ object Settings { // Electricity to provide global power support. val valueBuildCraft = 500.0 val valueFactorization = 6.5 + val valueGalacticraft = 24.0 val valueIndustrialCraft2 = 200.0 val valueMekanism = 5000.0 / 9.0 val valueRedstoneFlux = 35.0 @@ -247,6 +248,7 @@ object Settings { val ratioBuildCraft = valueBuildCraft / valueInternal val ratioFactorization = valueFactorization / valueInternal + val ratioGalacticraft = valueGalacticraft / valueInternal val ratioIndustrialCraft2 = valueIndustrialCraft2 / valueInternal val ratioMekanism = valueMekanism / valueInternal val ratioRedstoneFlux = valueRedstoneFlux / valueInternal diff --git a/src/main/scala/li/cil/oc/client/Sound.scala b/src/main/scala/li/cil/oc/client/Sound.scala index ade548395..3f442c744 100644 --- a/src/main/scala/li/cil/oc/client/Sound.scala +++ b/src/main/scala/li/cil/oc/client/Sound.scala @@ -52,9 +52,9 @@ object Sound { } private def processQueue() { - if (!commandQueue.isEmpty) { + if (commandQueue.nonEmpty) { commandQueue.synchronized { - while (!commandQueue.isEmpty && commandQueue.head.when < System.currentTimeMillis()) { + while (commandQueue.nonEmpty && commandQueue.head.when < System.currentTimeMillis()) { try commandQueue.dequeue()() catch { case t: Throwable => OpenComputers.log.warn("Error processing sound command.", t) } diff --git a/src/main/scala/li/cil/oc/common/asm/ClassTransformer.scala b/src/main/scala/li/cil/oc/common/asm/ClassTransformer.scala index 4844e4325..6a17ab2c2 100644 --- a/src/main/scala/li/cil/oc/common/asm/ClassTransformer.scala +++ b/src/main/scala/li/cil/oc/common/asm/ClassTransformer.scala @@ -20,6 +20,7 @@ class ClassTransformer extends IClassTransformer { private lazy val powerTypes = Map[Mod, Array[String]]( Mods.BuildCraftPower -> Array("buildcraft/api/power/IPowerReceptor"), Mods.Factorization -> Array("factorization/api/IChargeConductor"), + Mods.Galacticraft -> Array("micdoodle8/mods/galacticraft/api/power/IEnergyHandlerGC"), Mods.IndustrialCraft2 -> Array("ic2/api/energy/tile/IEnergySink"), Mods.IndustrialCraft2Classic -> Array("ic2classic/api/energy/tile/IEnergySink"), Mods.Mekanism -> Array("mekanism/api/energy/IStrictEnergyAcceptor"), diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala index c202ae44c..497533a12 100644 --- a/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/PowerAcceptor.scala @@ -4,6 +4,7 @@ trait PowerAcceptor extends power.Common with power.BuildCraft with power.Factorization + with power.Galacticraft with power.IndustrialCraft2Experimental with power.IndustrialCraft2Classic with power.Mekanism diff --git a/src/main/scala/li/cil/oc/common/tileentity/traits/power/Galacticraft.scala b/src/main/scala/li/cil/oc/common/tileentity/traits/power/Galacticraft.scala new file mode 100644 index 000000000..77ad8ed8e --- /dev/null +++ b/src/main/scala/li/cil/oc/common/tileentity/traits/power/Galacticraft.scala @@ -0,0 +1,31 @@ +package li.cil.oc.common.tileentity.traits.power + +import cpw.mods.fml.common.Optional +import li.cil.oc.Settings +import li.cil.oc.util.mods.Mods +import micdoodle8.mods.galacticraft.api.power.EnergySource +import net.minecraftforge.common.util.ForgeDirection + +trait Galacticraft extends Common { + private implicit def toDirection(source: EnergySource) = source match { + case adjacent: EnergySource.EnergySourceAdjacent => adjacent.direction + case _ => ForgeDirection.UNKNOWN + } + + @Optional.Method(modid = Mods.IDs.Galacticraft) + def nodeAvailable(from: EnergySource) = Mods.Galacticraft.isAvailable && canConnectPower(from) + + @Optional.Method(modid = Mods.IDs.Galacticraft) + def receiveEnergyGC(from: EnergySource, amount: Float, simulate: Boolean) = + if (!Mods.Galacticraft.isAvailable) 0 + else (tryChangeBuffer(from, amount * Settings.ratioGalacticraft, !simulate) / Settings.ratioGalacticraft).toFloat + + @Optional.Method(modid = Mods.IDs.Galacticraft) + def getEnergyStoredGC(from: EnergySource) = (globalBuffer(from) / Settings.ratioGalacticraft).toFloat + + @Optional.Method(modid = Mods.IDs.Galacticraft) + def getMaxEnergyStoredGC(from: EnergySource) = (globalBufferSize(from) / Settings.ratioGalacticraft).toFloat + + @Optional.Method(modid = Mods.IDs.Galacticraft) + def extractEnergyGC(from: EnergySource, amount: Float, simulate: Boolean) = 0f +} diff --git a/src/main/scala/li/cil/oc/util/mods/Mods.scala b/src/main/scala/li/cil/oc/util/mods/Mods.scala index 8078cd9dc..bb32bfbca 100644 --- a/src/main/scala/li/cil/oc/util/mods/Mods.scala +++ b/src/main/scala/li/cil/oc/util/mods/Mods.scala @@ -15,6 +15,7 @@ object Mods { final val ElectricalAge = "Eln" final val Factorization = "factorization" final val ForgeMultipart = "ForgeMultipart" + final val Galacticraft = "Galacticraft API" final val GregTech = "gregtech" final val IndustrialCraft2 = "IC2API" final val IndustrialCraft2Classic = "IC2-Classic" @@ -45,6 +46,7 @@ object Mods { val ElectricalAge = new SimpleMod(IDs.ElectricalAge) val Factorization = new SimpleMod(IDs.Factorization, providesPower = true) val ForgeMultipart = new SimpleMod(IDs.ForgeMultipart) + val Galacticraft = new SimpleMod(IDs.Galacticraft, providesPower = true) val GregTech = new SimpleMod(IDs.GregTech) val IndustrialCraft2 = new SimpleMod(IDs.IndustrialCraft2, providesPower = true) val IndustrialCraft2Classic = new SimpleMod(IDs.IndustrialCraft2Classic, providesPower = true)