diff --git a/src/main/java/cr0s/warpdrive/EntityJump.java b/src/main/java/cr0s/warpdrive/EntityJump.java index fd67aff9..3d678ed2 100644 --- a/src/main/java/cr0s/warpdrive/EntityJump.java +++ b/src/main/java/cr0s/warpdrive/EntityJump.java @@ -16,6 +16,7 @@ import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.server.MinecraftServer; import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.ChunkCoordinates; import net.minecraft.util.MathHelper; import net.minecraft.util.Vec3; @@ -26,6 +27,7 @@ import net.minecraftforge.common.ForgeChunkManager; import net.minecraftforge.common.ForgeChunkManager.Ticket; import net.minecraftforge.common.ForgeChunkManager.Type; import cr0s.warpdrive.api.IBlockTransformer; +import cr0s.warpdrive.api.ITransformation; import cr0s.warpdrive.block.movement.TileEntityShipCore; import cr0s.warpdrive.config.Dictionary; import cr0s.warpdrive.config.WarpDriveConfig; @@ -42,8 +44,8 @@ public class EntityJump extends Entity { // Jump vector private Transformation transformation; - private int distance; - public int shipLength; + private int moveX, moveY, moveZ; + private byte rotationSteps; private boolean isHyperspaceJump; private World targetWorld; @@ -64,7 +66,7 @@ public class EntityJump extends Entity { private int state = STATE_IDLE; private int currentIndexInShip = 0; - public JumpShip ship = new JumpShip(); + public JumpShip ship; private boolean betweenWorlds; private int destX, destY, destZ; @@ -76,35 +78,38 @@ public class EntityJump extends Entity { public EntityJump(World world) { super(world); targetWorld = worldObj; - if (WarpDriveConfig.LOGGING_JUMP) { - WarpDrive.logger.info(this + " Entity created (empty) in dimension " + worldObj.getProviderName() + " - " + worldObj.getWorldInfo().getWorldName()); + if (!world.isRemote) { + WarpDrive.logger.error(this + " Entity created (empty) in dimension " + worldObj.getProviderName() + " - " + worldObj.getWorldInfo().getWorldName()); } } - public EntityJump(World world, int x, int y, int z, int _dx, int _dz, TileEntityShipCore _shipCore, boolean _isHyperspaceJump, int _distance, int _direction, - boolean _isCoordJump, int _destX, int _destY, int _destZ) { + public EntityJump(World world, int x, int y, int z, int _dx, int _dz, TileEntityShipCore shipCore, boolean isHyperspaceJump, + final int moveX, final int moveY, final int moveZ, final byte rotationSteps, + boolean isCoordJump, int destX, int destY, int destZ) { super(world); this.posX = x + 0.5D; this.posY = y + 0.5D; this.posZ = z + 0.5D; + this.ship = new JumpShip(); this.ship.worldObj = worldObj; this.ship.coreX = x; this.ship.coreY = y; this.ship.coreZ = z; this.ship.dx = _dx; this.ship.dz = _dz; - this.ship.shipCore = _shipCore; - this.isHyperspaceJump = _isHyperspaceJump; - this.distance = _distance; - this.ship.direction = _direction; - this.isCoordJump = _isCoordJump; - this.destX = _destX; - this.destY = _destY; - this.destZ = _destZ; + this.ship.shipCore = shipCore; + this.isHyperspaceJump = isHyperspaceJump; + this.moveX = moveX; + this.moveY = moveY; + this.moveZ = moveZ; + this.rotationSteps = rotationSteps; + this.isCoordJump = isCoordJump; + this.destX = destX; + this.destY = destY; + this.destZ = destZ; // set by reactor ship.maxX = ship.maxZ = ship.maxY = ship.minX = ship.minZ = ship.minY = 0; - shipLength = 0; // set when preparing jump targetWorld = null; @@ -292,25 +297,6 @@ public class EntityJump extends Entity { LocalProfiler.stop(); } - public static String getDirectionLabel(int direction) { - switch (direction) { - case -1: - return "UP"; - case -2: - return "DOWN"; - case 0: - return "FRONT"; - case 180: - return "BACK"; - case 90: - return "LEFT"; - case 255: - return "RIGHT"; - default: - return direction + " degrees"; - } - } - private void prepareToJump() { if (WarpDriveConfig.LOGGING_JUMP) { WarpDrive.logger.info(this + " Preparing to jump..."); @@ -322,14 +308,37 @@ public class EntityJump extends Entity { boolean isInSpace = (worldObj.provider.dimensionId == WarpDriveConfig.G_SPACE_DIMENSION_ID); boolean isInHyperSpace = (worldObj.provider.dimensionId == WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID); - boolean toSpace = (ship.direction == -1) && (ship.maxY + distance > 255) && (!isInSpace) && (!isInHyperSpace); - boolean fromSpace = (ship.direction == -2) && (ship.minY - distance < 0) && isInSpace; + boolean toSpace = (moveY > 0) && (ship.maxY + moveY > 255) && (!isInSpace) && (!isInHyperSpace); + boolean fromSpace = (moveY < 0) && (ship.minY + moveY < 0) && isInSpace; betweenWorlds = fromSpace || toSpace || isHyperspaceJump; - int moveX = 0; - int moveY = 0; - int moveZ = 0; - if (!isHyperspaceJump && toSpace) { + if (isHyperspaceJump) { + if (isInHyperSpace) { + targetWorld = MinecraftServer.getServer().worldServerForDimension(WarpDriveConfig.G_SPACE_DIMENSION_ID); + if (targetWorld == null) { + LocalProfiler.stop(); + String msg = "Unable to load Space dimension " + WarpDriveConfig.G_SPACE_DIMENSION_ID + ", aborting jump."; + ship.messageToAllPlayersOnShip(this, msg); + killEntity(msg); + return; + } + } else if (isInSpace) { + targetWorld = MinecraftServer.getServer().worldServerForDimension(WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID); + if (targetWorld == null) { + LocalProfiler.stop(); + String msg = "Unable to load Hyperspace dimension " + WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID + ", aborting jump."; + ship.messageToAllPlayersOnShip(this, msg); + killEntity(msg); + return; + } + } else { + String msg = "Unable to reach hyperspace from a planet"; + killEntity(msg); + ship.messageToAllPlayersOnShip(this, msg); + LocalProfiler.stop(); + return; + } + } else if (toSpace) { Boolean planetFound = false; Boolean planetValid = false; int closestPlanetDistance = Integer.MAX_VALUE; @@ -359,7 +368,7 @@ public class EntityJump extends Entity { } if (!planetFound) { LocalProfiler.stop(); - String msg = "Unable to reach space!\nThere's no valid transition plane for current dimension " + worldObj.provider.getDimensionName() + " (" + String msg = "Unable to reach space!\nThere's not planet defined for current dimension " + worldObj.provider.getDimensionName() + " (" + worldObj.provider.dimensionId + ")"; ship.messageToAllPlayersOnShip(this, msg); killEntity(msg); @@ -378,7 +387,7 @@ public class EntityJump extends Entity { killEntity(msg); return; } - } else if (!isHyperspaceJump && fromSpace) { + } else if (fromSpace) { Boolean planetFound = false; int closestPlaneDistance = Integer.MAX_VALUE; Planet closestTransitionPlane = null; @@ -408,7 +417,7 @@ public class EntityJump extends Entity { if (closestTransitionPlane == null) { msg = "No planet defined, unable to enter atmosphere!"; } else { - msg = "No planet in range, unable to enter atmosphere!\nClosest transition plane is " + closestPlaneDistance + " m away (" + msg = "No planet in range, unable to enter atmosphere!\nClosest planet is " + closestPlaneDistance + " m away (" + (closestTransitionPlane.spaceCenterX - closestTransitionPlane.borderSizeX) + ", 250," + (closestTransitionPlane.spaceCenterZ - closestTransitionPlane.borderSizeZ) + ") to (" + (closestTransitionPlane.spaceCenterX + closestTransitionPlane.borderSizeX) + ", 255," @@ -418,24 +427,6 @@ public class EntityJump extends Entity { killEntity(msg); return; } - } else if (isHyperspaceJump && isInHyperSpace) { - targetWorld = MinecraftServer.getServer().worldServerForDimension(WarpDriveConfig.G_SPACE_DIMENSION_ID); - if (targetWorld == null) { - LocalProfiler.stop(); - String msg = "Unable to load Space dimension " + WarpDriveConfig.G_SPACE_DIMENSION_ID + ", aborting jump."; - ship.messageToAllPlayersOnShip(this, msg); - killEntity(msg); - return; - } - } else if (isHyperspaceJump && isInSpace) { - targetWorld = MinecraftServer.getServer().worldServerForDimension(WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID); - if (targetWorld == null) { - LocalProfiler.stop(); - String msg = "Unable to load Hyperspace dimension " + WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID + ", aborting jump."; - ship.messageToAllPlayersOnShip(this, msg); - killEntity(msg); - return; - } } else { targetWorld = worldObj; } @@ -443,19 +434,9 @@ public class EntityJump extends Entity { // Calculate jump vector if (isCoordJump) { moveX = destX - ship.coreX; - moveZ = destZ - ship.coreZ; moveY = destY - ship.coreY; - distance = 0; // FIXME: check collision in straight path, starting with getPossibleJumpDistance() ? - } else if (isHyperspaceJump) { - distance = 0; - if (!isInSpace && !isInHyperSpace) { - String msg = "Unable to reach hyperspace from a planet"; - killEntity(msg); - ship.messageToAllPlayersOnShip(this, msg); - LocalProfiler.stop(); - return; - } - } else { + moveZ = destZ - ship.coreZ; + } else if (!isHyperspaceJump) { if (toSpace) { // enter space at current altitude moveY = 0; @@ -464,15 +445,10 @@ public class EntityJump extends Entity { moveY = 245 - ship.maxY; } else { // Do not check in long jumps - if (distance < 256) { - distance = getPossibleJumpDistance(); + if (Math.max(moveX, moveZ) < 256) { + getPossibleJumpDistance(); } - int movementVector[] = getVector(ship.direction); - moveX = movementVector[0] * distance; - moveY = movementVector[1] * distance; - moveZ = movementVector[2] * distance; - if ((ship.maxY + moveY) > 255) { moveY = 255 - ship.maxY; } @@ -482,7 +458,7 @@ public class EntityJump extends Entity { } } } - transformation = new Transformation(ship, targetWorld, moveX, moveY, moveZ, (byte) 0); + transformation = new Transformation(ship, targetWorld, moveX, moveY, moveZ, rotationSteps); if (betweenWorlds && WarpDriveConfig.LOGGING_JUMP) { WarpDrive.logger.info(this + " From world " + worldObj.provider.getDimensionName() + " to " + targetWorld.provider.getDimensionName()); @@ -490,7 +466,14 @@ public class EntityJump extends Entity { // Validate positions aren't overlapping if (!betweenWorlds) { - if (Math.abs(moveX) <= (ship.maxX - ship.minX + 1) && Math.abs(moveY) <= (ship.maxY - ship.minY + 1) && Math.abs(moveZ) <= (ship.maxZ - ship.minZ + 1)) { + ChunkCoordinates target1 = transformation.apply(ship.minX, ship.minY, ship.minZ); + ChunkCoordinates target2 = transformation.apply(ship.maxX, ship.maxY, ship.maxZ); + AxisAlignedBB aabbSource = AxisAlignedBB.getBoundingBox(ship.minX, ship.minY, ship.minZ, ship.maxX, ship.maxY, ship.maxZ); + aabbSource.expand(1.0D, 1.0D, 1.0D); + AxisAlignedBB aabbTarget = AxisAlignedBB.getBoundingBox( + Math.min(target1.posX, target2.posX), Math.min(target1.posY, target2.posY), Math.min(target1.posZ, target2.posZ), + Math.max(target1.posX, target2.posX), Math.max(target1.posY, target2.posY), Math.max(target1.posZ, target2.posZ)); + if (aabbSource.intersectsWith(aabbTarget)) { // render fake explosions doCollisionDamage(false); @@ -529,9 +512,22 @@ public class EntityJump extends Entity { } else if (isHyperspaceJump && isInHyperSpace) { ship.messageToAllPlayersOnShip(this, "Leaving HYPERSPACE.."); } else if (isCoordJump) { - ship.messageToAllPlayersOnShip(this, "Jumping to coordinates (" + destX + "; " + ship.coreY + "; " + destZ + ")!"); + ship.messageToAllPlayersOnShip(this, "Jumping to coordinates (" + destX + " " + destY + " " + destZ + ")!"); } else { - ship.messageToAllPlayersOnShip(this, "Jumping " + getDirectionLabel(ship.direction) + " by " + distance + " blocks"); + ship.messageToAllPlayersOnShip(this, "Jumping of " + Math.round(Math.sqrt(moveX * moveX + moveY * moveY + moveZ * moveZ)) + " blocks (" + moveX + " " + moveY + " " + moveZ + ")"); + } + switch (rotationSteps) { + case 1: + ship.messageToAllPlayersOnShip(this, "Turning to the right"); + break; + case 2: + ship.messageToAllPlayersOnShip(this, "Turning back"); + break; + case 3: + ship.messageToAllPlayersOnShip(this, "Turning to the left"); + break; + default: + break; } // validate ship content @@ -791,14 +787,15 @@ public class EntityJump extends Entity { if (WarpDriveConfig.LOGGING_JUMP) { WarpDrive.logger.info(this + " Calculating possible jump distance..."); } - int testDistance = this.distance; + int originalRange = Math.max(Math.abs(moveX), Math.max(Math.abs(moveY), Math.abs(moveZ))); + int testRange = originalRange; int blowPoints = 0; collisionDetected = false; CheckMovementResult result = null; - while (testDistance >= 0) { + while (testRange >= 0) { // Is there enough space in destination point? - result = checkMovement(testDistance, false); + result = checkMovement(testRange / (double)originalRange, false); if (result == null) { break; @@ -807,16 +804,20 @@ public class EntityJump extends Entity { if (result.isCollision) { blowPoints++; } - testDistance--; + testRange--; } + VectorI finalMovement = getMovementVector(testRange / (double)originalRange); + moveX = finalMovement.x; + moveY = finalMovement.y; + moveZ = finalMovement.z; - if (distance != testDistance && WarpDriveConfig.LOGGING_JUMP) { - WarpDrive.logger.info(this + " Jump distance adjusted to " + testDistance + " after " + blowPoints + " collisions"); + if (originalRange != testRange && WarpDriveConfig.LOGGING_JUMP) { + WarpDrive.logger.info(this + " Jump range adjusted from " + originalRange + " to " + testRange + " after " + blowPoints + " collisions"); } // Register explosion(s) at collision point if (blowPoints > WarpDriveConfig.SHIP_COLLISION_TOLERANCE_BLOCKS) { - result = checkMovement(Math.max(1, testDistance + 1), true); + result = checkMovement(Math.max(1, testRange + 1), true); if (result != null) { /* * Strength scaling: @@ -834,15 +835,15 @@ public class EntityJump extends Entity { collisionStrength = (4.0F + blowPoints - WarpDriveConfig.SHIP_COLLISION_TOLERANCE_BLOCKS) * massCorrection; collisionAtSource = result.atSource; collisionAtTarget = result.atTarget; - WarpDrive.logger.info(this + " Reporting " + collisionAtTarget.size() + " collisions coordinates " + blowPoints - + " blowPoints with massCorrection of " + String.format("%.2f", massCorrection) + " => strength " - + String.format("%.2f", collisionStrength)); + WarpDrive.logger.info(this + " Reporting " + collisionAtTarget.size() + " collisions points after " + blowPoints + + " blowPoints with " + String.format("%.2f", massCorrection) + " ship mass correction => " + + String.format("%.2f", collisionStrength) + " explosion strength"); } else { WarpDrive.logger.error("WarpDrive error: unable to compute collision points, ignoring..."); } } - return testDistance; + return testRange; } private void doCollisionDamage(boolean atTarget) { @@ -1007,46 +1008,6 @@ public class EntityJump extends Entity { return true; } - public int[] getVector(int i) { - int v[] = { 0, 0, 0 }; - - switch (i) { - case -1: - v[1] = 1; - break; - - case -2: - v[1] = -1; - break; - - case 0: - v[0] = ship.dx; - v[2] = ship.dz; - break; - - case 180: - v[0] = -ship.dx; - v[2] = -ship.dz; - break; - - case 90: - v[0] = ship.dz; - v[2] = -ship.dx; - break; - - case 270: - v[0] = -ship.dz; - v[2] = ship.dx; - break; - - default: - WarpDrive.logger.error(this + " Invalid direction " + i); - break; - } - - return v; - } - class CheckMovementResult { public ArrayList atSource; public ArrayList atTarget; @@ -1071,42 +1032,40 @@ public class EntityJump extends Entity { } }; - private CheckMovementResult checkMovement(int testDistance, boolean fullCollisionDetails) { + private CheckMovementResult checkMovement(final double ratio, final boolean fullCollisionDetails) { CheckMovementResult result = new CheckMovementResult(); - if ((ship.direction == -1 && ship.maxY + testDistance > 255) && !betweenWorlds) { - result.add(ship.coreX, ship.maxY + testDistance, ship.coreZ, ship.coreX + 0.5D, ship.maxY + testDistance + 1.0D, ship.coreZ + 0.5D, false, - "Reactor will blow due +high limit"); + VectorI testMovement = getMovementVector(ratio); + VectorI offset = new VectorI((int)Math.signum(moveX), (int)Math.signum(moveY), (int)Math.signum(moveZ)); + + if ((moveY > 0 && ship.maxY + testMovement.y > 255) && !betweenWorlds) { + result.add(ship.coreX, ship.maxY + testMovement.y, ship.coreZ, ship.coreX + 0.5D, ship.maxY + testMovement.y + 1.0D, ship.coreZ + 0.5D, false, + "Ship core is moving too high"); return result; } - if ((ship.direction == -2 && ship.minY - testDistance <= 8) && !betweenWorlds) { - result.add(ship.coreX, ship.minY - testDistance, ship.coreZ, ship.coreX + 0.5D, ship.maxY - testDistance, ship.coreZ + 0.5D, false, "Reactor will blow due -low limit"); + if ((moveY < 0 && ship.minY + testMovement.y <= 8) && !betweenWorlds) { + result.add(ship.coreX, ship.minY + testMovement.y, ship.coreZ, ship.coreX + 0.5D, ship.maxY + testMovement.y, ship.coreZ + 0.5D, false, + "Ship core is moving too low"); return result; } - int movementVector[] = getVector(ship.direction); - int lmoveX = movementVector[0] * testDistance; - int lmoveY = movementVector[1] * testDistance; - int lmoveZ = movementVector[2] * testDistance; - - int x, y, z, newX, newY, newZ; + int x, y, z; + ITransformation testTransformation = new Transformation(ship, targetWorld, testMovement.x, testMovement.y, testMovement.z, rotationSteps); + ChunkCoordinates coordTarget; Block blockSource; Block blockTarget; for (y = ship.minY; y <= ship.maxY; y++) { - newY = y + lmoveY; for (x = ship.minX; x <= ship.maxX; x++) { - newX = x + lmoveX; for (z = ship.minZ; z <= ship.maxZ; z++) { - newZ = z + lmoveZ; - + coordTarget = testTransformation.apply(x, y, z); blockSource = worldObj.getBlock(x, y, z); - blockTarget = worldObj.getBlock(newX, newY, newZ); + blockTarget = worldObj.getBlock(coordTarget.posX, coordTarget.posY, coordTarget.posZ); if (Dictionary.BLOCKS_ANCHOR.contains(blockTarget)) { result.add(x, y, z, - newX + 0.5D - movementVector[0] * 1.0D, - newY + 0.5D - movementVector[1] * 1.0D, - newZ + 0.5D - movementVector[2] * 1.0D, - true, "Unpassable block " + blockTarget + " detected at destination (" + newX + ";" + newY + ";" + newZ + ")"); + coordTarget.posX + 0.5D - offset.x, + coordTarget.posY + 0.5D - offset.y, + coordTarget.posZ + 0.5D - offset.z, + true, "Unpassable block " + blockTarget + " detected at destination (" + coordTarget.posX + " " + coordTarget.posY + " " + coordTarget.posZ + ")"); if (!fullCollisionDetails) { return result; } @@ -1117,10 +1076,10 @@ public class EntityJump extends Entity { && blockTarget != Blocks.air && !Dictionary.BLOCKS_EXPANDABLE.contains(blockTarget)) { result.add(x, y, z, - newX + 0.5D + movementVector[0] * 0.1D, - newY + 0.5D + movementVector[1] * 0.1D, - newZ + 0.5D + movementVector[2] * 0.1D, - true, "Obstacle block #" + blockTarget + " detected at (" + newX + ", " + newY + ", " + newZ + ")"); + coordTarget.posX + 0.5D + offset.x * 0.1D, + coordTarget.posY + 0.5D + offset.y * 0.1D, + coordTarget.posZ + 0.5D + offset.z * 0.1D, + true, "Obstacle block " + blockTarget + " detected at (" + coordTarget.posX + " " + coordTarget.posY + " " + coordTarget.posZ + ")"); if (!fullCollisionDetails) { return result; } @@ -1136,6 +1095,10 @@ public class EntityJump extends Entity { } } + private VectorI getMovementVector(final double ratio) { + return new VectorI((int)Math.round(moveX * ratio), (int)Math.round(moveY * ratio), (int)Math.round(moveZ * ratio)); + } + private static ArrayList removeDuplicates(List l) { Set s = new TreeSet(new Comparator() { @Override diff --git a/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipController.java b/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipController.java index 889ebc8f..16ad816f 100644 --- a/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipController.java +++ b/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipController.java @@ -16,6 +16,7 @@ import cr0s.warpdrive.WarpDrive; import cr0s.warpdrive.block.TileEntityAbstractInterfaced; import cr0s.warpdrive.block.movement.TileEntityShipCore.ShipCoreMode; import cr0s.warpdrive.config.WarpDriveConfig; +import cr0s.warpdrive.data.VectorI; import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.peripheral.IComputerAccess; @@ -27,6 +28,10 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { // Variables private int distance = 0; private int direction = 0; + private int moveFront = 0; + private int moveUp = 0; + private int moveRight = 0; + private byte rotationSteps = 0; private ShipCoreMode mode = ShipCoreMode.IDLE; private boolean jumpFlag = false; @@ -76,7 +81,9 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { "isInHyperspace", "targetJumpgate", "isAttached", - "getEnergyRequired" + "getEnergyRequired", + "movement", + "rotationSteps" }); CC_scripts = Arrays.asList("startup"); } @@ -111,7 +118,7 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { } } - private void setMode(int mode) { + private void setMode(final int mode) { ShipCoreMode[] modes = ShipCoreMode.values(); if (mode >= 0 && mode <= modes.length) { this.mode = modes[mode]; @@ -121,21 +128,37 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { } } - private void setDirection(int dir) { - if (dir == 1) { + private void setDirection(final int parDirection) { + if (parDirection == 1) { this.direction = -1; - } else if (dir == 2) { + } else if (parDirection == 2) { this.direction = -2; - } else if (dir == 255) { + } else if (parDirection == 255) { this.direction = 270; } else { - this.direction = dir; + this.direction = parDirection; } if (WarpDriveConfig.LOGGING_JUMP) { WarpDrive.logger.info(this + " Direction set to " + direction); } } + private void setMovement(final int parMoveFront, final int parMoveUp, final int parMoveRight) { + moveFront = parMoveFront; + moveUp = parMoveUp; + moveRight = parMoveRight; + if (WarpDriveConfig.LOGGING_JUMP) { + WarpDrive.logger.info(this + " Movement set to " + moveFront + " front, " + moveUp + " up, " + moveRight + " right"); + } + } + + private void setRotationSteps(final byte parRotationSteps) { + rotationSteps = (byte) ((parRotationSteps + 4) % 4); + if (WarpDriveConfig.LOGGING_JUMP) { + WarpDrive.logger.info(this + " RotationSteps set to " + rotationSteps); + } + } + private void doJump() { if (core != null) { // Adding random ticks to warmup @@ -159,6 +182,8 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { setDown(tag.getInteger("down")); setDistance(tag.getInteger("distance")); setDirection(tag.getInteger("direction")); + setMovement(tag.getInteger("moveFront"), tag.getInteger("moveUp"), tag.getInteger("moveRight")); + setRotationSteps(tag.getByte("rotationSteps")); playersString = tag.getString("players"); updatePlayersList(); setBeaconFrequency(tag.getString("bfreq")); @@ -169,15 +194,19 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { super.writeToNBT(tag); updatePlayersString(); tag.setString("players", playersString); - tag.setInteger("mode", this.mode.getCode()); - tag.setInteger("front", this.front); - tag.setInteger("right", this.right); - tag.setInteger("up", this.up); - tag.setInteger("back", this.back); - tag.setInteger("left", this.left); - tag.setInteger("down", this.down); - tag.setInteger("distance", this.distance); - tag.setInteger("direction", this.direction); + tag.setInteger("mode", mode.getCode()); + tag.setInteger("front", front); + tag.setInteger("right", right); + tag.setInteger("up", up); + tag.setInteger("back", back); + tag.setInteger("left", left); + tag.setInteger("down", down); + tag.setInteger("distance", distance); + tag.setInteger("direction", direction); + tag.setInteger("moveFront", moveFront); + tag.setInteger("moveUp", moveUp); + tag.setInteger("moveRight", moveRight); + tag.setByte("rotationSteps", rotationSteps); tag.setString("bfreq", getBeaconFrequency()); // FIXME: shouldn't we save boolean jumpFlag, boolean summonFlag, String toSummon, String targetJumpgateName? } @@ -375,13 +404,6 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { return this.distance; } - /** - * @return current reactor mode - */ - public ShipCoreMode getMode() { - return mode; - } - /** * @return the direction */ @@ -389,6 +411,20 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { return direction; } + /** + * @return the rotation steps + */ + public byte getRotationSteps() { + return rotationSteps; + } + + /** + * @return current reactor mode + */ + public ShipCoreMode getMode() { + return mode; + } + /** * @return the summonFlag */ @@ -397,8 +433,7 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { } /** - * @param summonFlag - * to set + * @param summonFlag to set */ public void setSummonAllFlag(boolean summonFlag) { this.summonFlag = summonFlag; @@ -412,8 +447,7 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { } /** - * @param toSummon - * the toSummon to set + * @param toSummon the toSummon to set */ public void setToSummon(String toSummon) { this.toSummon = toSummon; @@ -427,11 +461,12 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { } /** - * @param beaconFrequency - * the beaconFrequency to set + * @param beaconFrequency the beaconFrequency to set */ public void setBeaconFrequency(String beaconFrequency) { - //WarpDrive.debugPrint("Setting beacon frequency: " + beaconFrequency); + if (WarpDriveConfig.LOGGING_LUA) { + WarpDrive.logger.info(this + " Beacon frequency set to " + beaconFrequency); + } this.beaconFrequency = beaconFrequency; } @@ -492,6 +527,18 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { return direction(argumentsOCtoCC(arguments)); } + @Callback + @Optional.Method(modid = "OpenComputers") + public Object[] movement(Context context, Arguments arguments) { + return movement(argumentsOCtoCC(arguments)); + } + + @Callback + @Optional.Method(modid = "OpenComputers") + public Object[] rotationSteps(Context context, Arguments arguments) { + return rotationSteps(argumentsOCtoCC(arguments)); + } + @Callback @Optional.Method(modid = "OpenComputers") public Object[] getAttachedPlayers(Context context, Arguments arguments) { @@ -607,20 +654,17 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { try { if (arguments.length == 3) { int argInt0, argInt1, argInt2; - argInt0 = toInt(arguments[0]); - argInt1 = toInt(arguments[1]); - argInt2 = toInt(arguments[2]); - if (argInt0 < 0 || argInt1 < 0 || argInt2 < 0) { - return new Integer[] { getFront(), getRight(), getUp() }; - } - if (WarpDriveConfig.LOGGING_JUMP) { + argInt0 = clamp(0, WarpDriveConfig.SHIP_MAX_SIDE_SIZE, Math.abs(toInt(arguments[0]))); + argInt1 = clamp(0, WarpDriveConfig.SHIP_MAX_SIDE_SIZE, Math.abs(toInt(arguments[1]))); + argInt2 = clamp(0, WarpDriveConfig.SHIP_MAX_SIDE_SIZE, Math.abs(toInt(arguments[2]))); + if (WarpDriveConfig.LOGGING_LUA) { WarpDrive.logger.info(this + " Positive dimensions set to front " + argInt0 + ", right " + argInt1 + ", up " + argInt2); } setFront(argInt0); setRight(argInt1); - setUp(argInt2); + setUp(Math.min(255 - yCoord, argInt2)); } - } catch (Exception e) { + } catch (Exception exception) { return new Integer[] { getFront(), getRight(), getUp() }; } @@ -631,20 +675,17 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { try { if (arguments.length == 3) { int argInt0, argInt1, argInt2; - argInt0 = toInt(arguments[0]); - argInt1 = toInt(arguments[1]); - argInt2 = toInt(arguments[2]); - if (argInt0 < 0 || argInt1 < 0 || argInt2 < 0) { - return new Integer[] { getBack(), getLeft(), getDown() }; - } - if (WarpDriveConfig.LOGGING_JUMP) { + argInt0 = clamp(0, WarpDriveConfig.SHIP_MAX_SIDE_SIZE, Math.abs(toInt(arguments[0]))); + argInt1 = clamp(0, WarpDriveConfig.SHIP_MAX_SIDE_SIZE, Math.abs(toInt(arguments[1]))); + argInt2 = clamp(0, WarpDriveConfig.SHIP_MAX_SIDE_SIZE, Math.abs(toInt(arguments[2]))); + if (WarpDriveConfig.LOGGING_LUA) { WarpDrive.logger.info(this + " Negative dimensions set to back " + argInt0 + ", left " + argInt1 + ", down " + argInt2); } setBack(argInt0); setLeft(argInt1); - setDown(argInt2); + setDown(Math.min(yCoord, argInt2)); } - } catch (Exception e) { + } catch (Exception exception) { return new Integer[] { getBack(), getLeft(), getDown() }; } @@ -656,7 +697,7 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { if (arguments.length == 1) { setMode(toInt(arguments[0])); } - } catch (Exception e) { + } catch (Exception exception) { return new Integer[] { mode.getCode() }; } @@ -668,7 +709,7 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { if (arguments.length == 1) { setDistance(toInt(arguments[0])); } - } catch (Exception e) { + } catch (Exception exception) { return new Integer[] { getDistance() }; } @@ -680,13 +721,37 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { if (arguments.length == 1) { setDirection(toInt(arguments[0])); } - } catch (Exception e) { + } catch (Exception exception) { return new Integer[] { getDirection() }; } return new Integer[] { getDirection() }; } + private Object[] movement(Object[] arguments) { + try { + if (arguments.length == 3) { + setMovement(toInt(arguments[0]), toInt(arguments[1]), toInt(arguments[2])); + } + } catch (Exception exception) { + return new Integer[] { moveFront, moveUp, moveRight }; + } + + return new Integer[] { moveFront, moveUp, moveRight }; + } + + private Object[] rotationSteps(Object[] arguments) { + try { + if (arguments.length == 1) { + setRotationSteps((byte)toInt(arguments[0])); + } + } catch (Exception exception) { + return new Integer[] { (int) rotationSteps }; + } + + return new Integer[] { (int) rotationSteps }; + } + private Object[] getAttachedPlayers(Object[] arguments) { String list = ""; @@ -707,7 +772,7 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { } try { playerIndex = toInt(arguments[0]); - } catch (Exception e) { + } catch (Exception exception) { return new Object[] { false }; } @@ -856,6 +921,12 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { if (core != null) { return new Object[] { (boolean) (core.controller != null) }; } + } else if (methodName.equals("movement")) { + return movement(arguments); + + } else if (methodName.equals("rotationSteps")) { + return rotationSteps(arguments); + } return super.callMethod(computer, context, method, arguments); @@ -876,6 +947,35 @@ public class TileEntityShipController extends TileEntityAbstractInterfaced { targetJumpgateName = parTargetJumpgateName; } + public VectorI getMovement() { + if (moveFront != 0 || moveUp != 0 || moveRight != 0) { + return new VectorI(moveFront, moveUp, moveRight); + } + switch (direction) { + case -1: + return new VectorI(0, distance, 0); + + case -2: + return new VectorI(0, -distance, 0); + + case 0: + return new VectorI(distance, 0, 0); + + case 180: + return new VectorI(-distance, 0, 0); + + case 90: + return new VectorI(0, 0, -distance); + + case 270: + return new VectorI(0, 0, distance); + + default: + WarpDrive.logger.error(this + " Invalid direction " + direction); + return new VectorI(0, 0, 0); + } + } + @Override public String toString() { return String.format("%s \'%s\' @ \'%s\' (%d %d %d)", new Object[] { diff --git a/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipCore.java b/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipCore.java index d2c2a979..0dee5b31 100644 --- a/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipCore.java +++ b/src/main/java/cr0s/warpdrive/block/movement/TileEntityShipCore.java @@ -29,6 +29,7 @@ import cr0s.warpdrive.config.Dictionary; import cr0s.warpdrive.config.WarpDriveConfig; import cr0s.warpdrive.data.Jumpgate; import cr0s.warpdrive.data.StarMapEntry; +import cr0s.warpdrive.data.VectorI; import cr0s.warpdrive.world.SpaceTeleporter; /** @@ -39,17 +40,12 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { public Boolean launchState = false; - public final int JUMP_UP = -1; - public final int JUMP_DOWN = -2; public int dx, dz; private int direction; public int maxX, maxY, maxZ; public int minX, minY, minZ; - public int shipFront, shipBack; - public int shipLeft, shipRight; - public int shipUp, shipDown; public int shipLength; public int shipMass; public int shipVolume; @@ -74,27 +70,27 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { return code; } } - + private int warmupTime = 0; private int cooldownTime = 0; public int randomWarmupAddition = 0; - + private int chestTeleportUpdateTicks = 0; - private final int registryUpdateInterval_ticks = 20 * WarpDriveConfig.SHIP_CORE_REGISTRY_UPDATE_INTERVAL_SECONDS; + private final int registryUpdateInterval_ticks = 20 * WarpDriveConfig.SHIP_CORE_REGISTRY_UPDATE_INTERVAL_SECONDS; private int registryUpdateTicks = 0; - private int bootTicks = 20; - + private int bootTicks = 20; + public UUID uuid = null; public String shipName = "default"; public int isolationBlocksCount = 0; public double isolationRate = 0.0D; public int isolationUpdateTicks = 0; - + public TileEntityShipController controller; - + private boolean soundPlayed = false; - + public TileEntityShipCore() { super(); peripheralName = "warpdriveShipCore"; @@ -356,17 +352,17 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { int xmin, ymin, zmin; xmin = xCoord - WarpDriveConfig.RADAR_MAX_ISOLATION_RANGE; xmax = xCoord + WarpDriveConfig.RADAR_MAX_ISOLATION_RANGE; - + zmin = zCoord - WarpDriveConfig.RADAR_MAX_ISOLATION_RANGE; zmax = zCoord + WarpDriveConfig.RADAR_MAX_ISOLATION_RANGE; - + // scan 1 block higher to encourage putting isolation block on both // ground and ceiling ymin = Math.max(0, yCoord - WarpDriveConfig.RADAR_MAX_ISOLATION_RANGE + 1); ymax = Math.min(255, yCoord + WarpDriveConfig.RADAR_MAX_ISOLATION_RANGE + 1); - + int newCount = 0; - + // Search for warp isolation blocks for (int y = ymin; y <= ymax; y++) { for (int x = xmin; x <= xmax; x++) { @@ -407,25 +403,25 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { private void summonPlayers() { AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ); - + for (int i = 0; i < controller.players.size(); i++) { String nick = controller.players.get(i); EntityPlayerMP player = MinecraftServer.getServer().getConfigurationManager().func_152612_a(nick); - + if (player != null && !testBB(aabb, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ))) { summonPlayer(player, xCoord + dx, yCoord, zCoord + dz); } } } - + private void summonSinglePlayer(String nickname) { AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(this.minX, this.minY, this.minZ, this.maxX, this.maxY, this.maxZ); - + for (int i = 0; i < controller.players.size(); i++) { String nick = controller.players.get(i); EntityPlayerMP player = MinecraftServer.getServer().getConfigurationManager().func_152612_a(nick); - + if (player != null && nick.equals(nickname) && !testBB(aabb, MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ))) { summonPlayer(player, xCoord + dx, yCoord, zCoord + dz); @@ -433,7 +429,7 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { } } } - + private void summonPlayer(EntityPlayerMP player, int x, int y, int z) { if (consumeEnergy(WarpDriveConfig.SHIP_TELEPORT_ENERGY_PER_ENTITY, false)) { if (player.dimension != worldObj.provider.dimensionId) { @@ -451,13 +447,16 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { } } } - + public boolean validateShipSpatialParameters(StringBuilder reason) { if (controller == null) { reason.append("TileEntityReactor.validateShipSpatialParameters: no controller detected!"); return false; } direction = controller.getDirection(); + int shipFront, shipBack; + int shipLeft, shipRight; + int shipUp, shipDown; shipFront = controller.getFront(); shipRight = controller.getRight(); shipUp = controller.getUp(); @@ -492,7 +491,7 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { x2 = xCoord + shipRight; } } - + if (x1 < x2) { minX = x1; maxX = x2; @@ -500,7 +499,7 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { minX = x2; maxX = x1; } - + if (z1 < z2) { minZ = z1; maxZ = z2; @@ -508,32 +507,10 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { minZ = z2; maxZ = z1; } - + minY = yCoord - shipDown; maxY = yCoord + shipUp; - shipLength = 0; - - switch (direction) { - case 0: - case 180: - shipLength = shipBack + shipFront; - break; - - case 90: - case 270: - shipLength = shipLeft + shipRight; - break; - - case -1: - case -2: - shipLength = shipDown + shipUp; - break; - - default: - reason.append("Invalid jump direction " + direction); - return false; - } - + // Ship side is too big if ( (shipBack + shipFront) > WarpDriveConfig.SHIP_MAX_SIDE_SIZE || (shipLeft + shipRight) > WarpDriveConfig.SHIP_MAX_SIDE_SIZE @@ -541,50 +518,50 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { reason.append("Ship is too big (max is " + WarpDriveConfig.SHIP_MAX_SIDE_SIZE + " per side)"); return false; } - + boolean isUnlimited = false; AxisAlignedBB axisalignedbb = AxisAlignedBB.getBoundingBox(minX, minY, minZ, maxX + 0.99D, maxY + 0.99D, maxZ + 0.99D); List list = worldObj.getEntitiesWithinAABBExcludingEntity(null, axisalignedbb); - for (Object o : list) { - if (o == null || !(o instanceof EntityPlayer)) { + for (Object object : list) { + if (object == null || !(object instanceof EntityPlayer)) { continue; } - - String playerName = ((EntityPlayer) o).getDisplayName(); + + String playerName = ((EntityPlayer) object).getDisplayName(); for (String unlimiteName : WarpDriveConfig.SHIP_VOLUME_UNLIMITED_PLAYERNAMES) { isUnlimited = isUnlimited || unlimiteName.equals(playerName); } } - + updateShipMassAndVolume(); - if (!isUnlimited && shipMass > WarpDriveConfig.SHIP_VOLUME_MAX_ON_PLANET_SURFACE && worldObj.provider.dimensionId == 0) { + if (!isUnlimited && shipMass > WarpDriveConfig.SHIP_VOLUME_MAX_ON_PLANET_SURFACE && worldObj.provider.dimensionId == 0) {// FIXME: need to support any planets and landing movement reason.append("Ship is too big for the overworld (max is " + WarpDriveConfig.SHIP_VOLUME_MAX_ON_PLANET_SURFACE + " blocks)"); return false; } - + return true; } - + private void doBeaconJump() { // Search beacon coordinates String freq = controller.getBeaconFrequency(); int beaconX = 0, beaconZ = 0; boolean isBeaconFound = false; EntityPlayerMP player; - + for (int i = 0; i < MinecraftServer.getServer().getConfigurationManager().playerEntityList.size(); i++) { player = (EntityPlayerMP) MinecraftServer.getServer().getConfigurationManager().playerEntityList.get(i); - + // Skip players from other dimensions if (player.dimension != worldObj.provider.dimensionId) { continue; } - + TileEntity tileEntity = worldObj.getTileEntity( MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY) - 1, MathHelper.floor_double(player.posZ)); - + if (tileEntity != null && (tileEntity instanceof TileEntityShipController)) { if (((TileEntityShipController) tileEntity).getBeaconFrequency().equals(freq)) { beaconX = tileEntity.xCoord; @@ -600,14 +577,13 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { // Consume energy 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); + EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, dx, dz, this, false, 0, 0, 0, (byte)0, true, beaconX, yCoord, beaconZ); 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); } else { @@ -680,7 +656,7 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { private boolean isFreePlaceForShip(int destX, int destY, int destZ) { int newX, newZ; - if (destY + shipUp > 255 || destY - shipDown < 5) { + if (controller == null || destY + controller.getUp() > 255 || destY - controller.getDown() < 5) { return false; } @@ -770,14 +746,13 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { // Consume energy 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); + EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, dx, dz, this, false, 0, 0, 0, (byte)0, true, destX, destY, destZ); 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); } else { @@ -792,7 +767,7 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { if (!consumeEnergy(requiredEnergy, true)) { messageToAllPlayersOnShip("Insufficient energy to jump! Core is currently charged with " + getEnergyStored() + " EU while jump requires " + requiredEnergy + " EU"); - this.controller.setJumpFlag(false); + controller.setJumpFlag(false); return; } @@ -819,9 +794,9 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { StringBuilder reason = new StringBuilder(); if (nearestGate == null || !isShipInJumpgate(nearestGate, reason)) { - this.messageToAllPlayersOnShip("Ship is too small (" + shipMass + "/" + WarpDriveConfig.SHIP_VOLUME_MIN_FOR_HYPERSPACE + messageToAllPlayersOnShip("Ship is too small (" + shipMass + "/" + WarpDriveConfig.SHIP_VOLUME_MIN_FOR_HYPERSPACE + ").\nInsufficient ship mass to open hyperspace portal.\nUse a jumpgate to reach or exit hyperspace."); - this.controller.setJumpFlag(false); + controller.setJumpFlag(false); return; } } @@ -838,21 +813,31 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { messageToAllPlayersOnShip("Insufficient energy level"); return; } + int moveX = 0; + int moveY = 0; + int moveZ = 0; - if (this.currentMode == ShipCoreMode.BASIC_JUMP) { - distance += shipLength; - } - - if (currentMode == ShipCoreMode.LONG_JUMP && (direction != -1) && (direction != -2)) { - if (worldObj.provider.dimensionId == WarpDriveConfig.G_HYPERSPACE_DIMENSION_ID) { - distance *= 100; + if (currentMode != ShipCoreMode.HYPERSPACE) { + VectorI movement = controller.getMovement(); + moveX = dx * movement.x - dz * movement.z; + moveY = movement.y; + moveZ = dz * movement.x + dx * movement.z; + if (currentMode == ShipCoreMode.BASIC_JUMP) { + // VectorI sizes = new VectorI(controller.getBack() + controller.getFront(), controller.getDown() + controller.getUp(), controller.getLeft() + controller.getRight()); + // moveX += Math.signum((double)moveX) * Math.abs(dx * sizes.x - dz * sizes.z); + // moveY += Math.signum((double)moveY) * (sizes.y); + // moveZ += Math.signum((double)moveZ) * Math.abs(dz * sizes.x + dx * sizes.z); + } else if (currentMode == ShipCoreMode.LONG_JUMP) { + moveX *= 100; + moveZ *= 100; } } if (WarpDriveConfig.LOGGING_JUMP) { - WarpDrive.logger.info(this + " Distance adjusted to " + distance + " blocks."); + WarpDrive.logger.info(this + " Movement adjusted to (" + moveX + " " + moveY + " " + moveZ + ") blocks."); } - EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, dx, dz, this, (currentMode == ShipCoreMode.HYPERSPACE), distance, direction, + EntityJump jump = new EntityJump(worldObj, xCoord, yCoord, zCoord, dx, dz, this, (currentMode == ShipCoreMode.HYPERSPACE), + moveX, moveY, moveZ, controller.getRotationSteps(), false, 0, 0, 0); jump.ship.maxX = maxX; jump.ship.minX = minX; @@ -860,7 +845,6 @@ public class TileEntityShipCore extends TileEntityAbstractEnergy { jump.ship.minZ = minZ; jump.ship.maxY = maxY; jump.ship.minY = minY; - jump.shipLength = shipLength; jump.on = true; worldObj.spawnEntityInWorld(jump); } diff --git a/src/main/java/cr0s/warpdrive/data/JumpBlock.java b/src/main/java/cr0s/warpdrive/data/JumpBlock.java index 574b3cdc..7484528b 100644 --- a/src/main/java/cr0s/warpdrive/data/JumpBlock.java +++ b/src/main/java/cr0s/warpdrive/data/JumpBlock.java @@ -231,21 +231,21 @@ public class JumpBlock { public void deploy(World targetWorld, ITransformation transformation) { try { - NBTTagCompound oldnbt = null; + NBTTagCompound nbtToDeploy = null; if (blockTileEntity != null) { - oldnbt = new NBTTagCompound(); - blockTileEntity.writeToNBT(oldnbt); + nbtToDeploy = new NBTTagCompound(); + blockTileEntity.writeToNBT(nbtToDeploy); } int newBlockMeta = blockMeta; if (externals != null) { for (Entry external : externals.entrySet()) { IBlockTransformer blockTransformer = WarpDriveConfig.blockTransformers.get(external.getKey()); if (blockTransformer != null) { - newBlockMeta = blockTransformer.rotate(block, blockMeta, oldnbt, transformation.getRotationSteps(), transformation.getRotationYaw()); + newBlockMeta = blockTransformer.rotate(block, blockMeta, nbtToDeploy, transformation.getRotationSteps(), transformation.getRotationYaw()); } } } else { - newBlockMeta = getMetadataRotation(oldnbt, transformation.getRotationSteps()); + newBlockMeta = getMetadataRotation(nbtToDeploy, transformation.getRotationSteps()); } ChunkCoordinates target = transformation.apply(x, y, z); setBlockNoLight(targetWorld, target.posX, target.posY, target.posZ, block, newBlockMeta, 2); @@ -256,23 +256,23 @@ public class JumpBlock { targetWorld.scheduleBlockUpdate(target.posX, target.posY, target.posZ, block, 40 + targetWorld.rand.nextInt(20)); } - if (oldnbt != null) { - oldnbt.setInteger("x", target.posX); - oldnbt.setInteger("y", target.posY); - oldnbt.setInteger("z", target.posZ); + if (nbtToDeploy != null) { + nbtToDeploy.setInteger("x", target.posX); + nbtToDeploy.setInteger("y", target.posY); + nbtToDeploy.setInteger("z", target.posZ); - if (oldnbt.hasKey("mainX") && oldnbt.hasKey("mainY") && oldnbt.hasKey("mainZ")) {// Mekanism 6.0.4.44 + if (nbtToDeploy.hasKey("mainX") && nbtToDeploy.hasKey("mainY") && nbtToDeploy.hasKey("mainZ")) {// Mekanism 6.0.4.44 if (WarpDriveConfig.LOGGING_JUMPBLOCKS) { WarpDrive.logger.info(this + " deploy: TileEntity has mainXYZ"); } - 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); + ChunkCoordinates mainTarget = transformation.apply(nbtToDeploy.getInteger("mainX"), nbtToDeploy.getInteger("mainY"), nbtToDeploy.getInteger("mainZ")); + nbtToDeploy.setInteger("mainX", mainTarget.posX); + nbtToDeploy.setInteger("mainY", mainTarget.posY); + nbtToDeploy.setInteger("mainZ", mainTarget.posZ); } - if (oldnbt.hasKey("screenData")) {// IC2NuclearControl 2.2.5a - NBTTagCompound nbtScreenData = oldnbt.getCompoundTag("screenData"); + if (nbtToDeploy.hasKey("screenData")) {// IC2NuclearControl 2.2.5a + NBTTagCompound nbtScreenData = nbtToDeploy.getCompoundTag("screenData"); if ( nbtScreenData.hasKey("minX") && nbtScreenData.hasKey("minY") && nbtScreenData.hasKey("minZ") && nbtScreenData.hasKey("maxX") && nbtScreenData.hasKey("maxY") && nbtScreenData.hasKey("maxZ")) { if (WarpDriveConfig.LOGGING_JUMPBLOCKS) { @@ -286,24 +286,24 @@ public class JumpBlock { nbtScreenData.setInteger("maxX", maxTarget.posX); nbtScreenData.setInteger("maxY", maxTarget.posY); nbtScreenData.setInteger("maxZ", maxTarget.posZ); - oldnbt.setTag("screenData", nbtScreenData); + nbtToDeploy.setTag("screenData", nbtScreenData); } } - if (oldnbt.hasKey("hasValidBubble")) {// Galacticraft 3.0.11.333 - oldnbt.setBoolean("hasValidBubble", false); + if (nbtToDeploy.hasKey("hasValidBubble")) {// Galacticraft 3.0.11.333 + nbtToDeploy.setBoolean("hasValidBubble", false); // old bubble will die naturally due to missing tile entity, new one will be spawned } TileEntity newTileEntity = null; boolean isForgeMultipart = false; - if (WarpDriveConfig.isForgeMultipartLoaded && oldnbt.hasKey("id") && oldnbt.getString("id") == "savedMultipart") { + if (WarpDriveConfig.isForgeMultipartLoaded && nbtToDeploy.hasKey("id") && nbtToDeploy.getString("id") == "savedMultipart") { isForgeMultipart = true; - newTileEntity = (TileEntity) WarpDriveConfig.forgeMultipart_helper_createTileFromNBT.invoke(null, targetWorld, oldnbt); + newTileEntity = (TileEntity) WarpDriveConfig.forgeMultipart_helper_createTileFromNBT.invoke(null, targetWorld, nbtToDeploy); } else if (block == WarpDriveConfig.CC_Computer || block == WarpDriveConfig.CC_peripheral || block == WarpDriveConfig.CCT_Turtle || block == WarpDriveConfig.CCT_Expanded || block == WarpDriveConfig.CCT_Advanced) { - newTileEntity = TileEntity.createAndLoadEntity(oldnbt); + newTileEntity = TileEntity.createAndLoadEntity(nbtToDeploy); newTileEntity.invalidate(); } /* else if (block == WarpDriveConfig.AS_Turbine) { @@ -318,7 +318,7 @@ public class JumpBlock { } /* No 1.7.10 version */ if (newTileEntity == null) { - newTileEntity = TileEntity.createAndLoadEntity(oldnbt); + newTileEntity = TileEntity.createAndLoadEntity(nbtToDeploy); } if (newTileEntity != null) { @@ -333,7 +333,7 @@ public class JumpBlock { 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); + WarpDrive.logger.info("NBT data was " + nbtToDeploy); } } } catch (Exception exception) { diff --git a/src/main/java/cr0s/warpdrive/data/JumpShip.java b/src/main/java/cr0s/warpdrive/data/JumpShip.java index 356ec3fb..28fd0f16 100644 --- a/src/main/java/cr0s/warpdrive/data/JumpShip.java +++ b/src/main/java/cr0s/warpdrive/data/JumpShip.java @@ -25,7 +25,6 @@ public class JumpShip { public int coreZ; public int dx; public int dz; - public int direction; public int maxX; public int maxZ; public int maxY; diff --git a/src/main/java/cr0s/warpdrive/data/VectorI.java b/src/main/java/cr0s/warpdrive/data/VectorI.java index 1e16618d..e0ea23ee 100644 --- a/src/main/java/cr0s/warpdrive/data/VectorI.java +++ b/src/main/java/cr0s/warpdrive/data/VectorI.java @@ -318,4 +318,11 @@ public class VectorI implements Cloneable { public int getMagnitudeSquared() { return x * x + y * y + z * z; } + + public VectorI scale(final int amount) { + x *= amount; + y *= amount; + z *= amount; + return this; + } } \ No newline at end of file diff --git a/src/main/resources/assets/warpdrive/lua.ComputerCraft/warpdriveShipController/startup b/src/main/resources/assets/warpdrive/lua.ComputerCraft/warpdriveShipController/startup index 32aa6dcd..faba2497 100644 --- a/src/main/resources/assets/warpdrive/lua.ComputerCraft/warpdriveShipController/startup +++ b/src/main/resources/assets/warpdrive/lua.ComputerCraft/warpdriveShipController/startup @@ -4,491 +4,936 @@ if not term.isColor() then end print("loading...") --- set alarm side if you need this -Alarm = "top" - Style = { - CDeflt = colors.white, - BGDeflt = colors.blue, + CDefault = colors.white, + BGDefault = colors.blue, + CTitle = colors.black, BGTitle = colors.cyan, - CWarn = colors.white, - BGWarn = colors.red + + CWarning = colors.white, + BGWarning = colors.red, + + CSuccess = colors.white, + BGSuccess = colors.lime, + + CDisabled = colors.gray, + BGDisabled = colors.blue } -function SetColorDeflt() - term.setBackgroundColor(Style.BGDeflt) - term.setTextColor(Style.CDeflt) +----------- Monitor support + +function SetMonitorColorFrontBack(frontColor, backgroundColor) + term.setBackgroundColor(backgroundColor) + term.setTextColor(frontColor) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + monitor.setTextColor(frontColor) + monitor.setBackgroundColor(backgroundColor) + end + end +end + +function Write(text) + term.write(text) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + if key ~= data.radar_monitorIndex then + monitor.write(text) + end + end + end +end + +function SetCursorPos(x, y) + term.setCursorPos(x, y) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + if key ~= data.radar_monitorIndex then + monitor.setCursorPos(x, y) + end + end + end +end + +function SetColorDefault() + SetMonitorColorFrontBack(Style.CDefault, Style.BGDefault) end function SetColorTitle() - term.setBackgroundColor(Style.BGTitle) - term.setTextColor(Style.CTitle) + SetMonitorColorFrontBack(Style.CTitle, Style.BGTitle) end -function SetColorWarn() - term.setBackgroundColor(Style.BGWarn) - term.setTextColor(Style.CWarn) +function SetColorWarning() + SetMonitorColorFrontBack(Style.CWarning, Style.BGWarning) +end + +function SetColorSuccess() + SetMonitorColorFrontBack(Style.CSuccess, Style.BGSuccess) +end + +function SetColorDisabled() + SetMonitorColorFrontBack(Style.CDisabled, Style.BGDisabled) end function Clear() + clearWarningTick = -1 + SetColorDefault() term.clear() - term.setCursorPos(1,1) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + if key ~= data.radar_monitorIndex then + monitor.clear() + end + end + end + SetCursorPos(1, 1) end -function Show(Text) - term.write(Text) - local xt,yt = term.getCursorPos() - term.setCursorPos(1, yt+1) +function ClearLine() + SetColorDefault() + term.clearLine() + if monitors ~= nil then + for key,monitor in pairs(monitors) do + if key ~= data.radar_monitorIndex then + monitor.clearLine() + end + end + end + SetCursorPos(1, 1) end -function ShowTitle(Text) - SetColorTitle() - term.setCursorPos(12, 1) - Show(Text) - SetColorDeflt() +function WriteLn(text) + Write(text) + local x, y = term.getCursorPos() + local width, height = term.getSize() + if y > height - 1 then + y = 1 + end + SetCursorPos(1, y + 1) end -function ShowMenu(Text) - term.write(Text) +function WriteCentered(y, text) + SetCursorPos((51 - text:len()) / 2, y) + term.write(text) + if monitors ~= nil then + for key,monitor in pairs(monitors) do + if key ~= data.radar_monitorIndex then + local sizeX, sizeY = monitor.getSize() + monitor.setCursorPos((sizeX - text:len()) / 2, y) + monitor.write(text) + end + end + end local xt, yt = term.getCursorPos() - for i = xt, 51 do - term.write(" ") + SetCursorPos(1, yt + 1) +end + +function ShowTitle(text) + Clear() + SetColorTitle() + WriteCentered(1, text) + SetColorDefault() +end + +function ShowMenu(text) + Write(text) + local sizeX, sizeY = term.getSize() + local xt, yt = term.getCursorPos() + for i = xt, sizeX do + Write(" ") end - term.setCursorPos(1, yt+1) + SetCursorPos(1, yt + 1) end -function ShowWarning(Text) - SetColorWarn() - term.setCursorPos(10, 19) - term.write(" "..Text.." ") - SetColorDeflt() +local clearWarningTick = -1 +function ShowWarning(text) + local sizeX, sizeY = term.getSize() + SetColorWarning() + SetCursorPos((sizeX - text:len() - 2) / 2, sizeY) + Write(" " .. text .. " ") + SetColorDefault() + clearWarningTick = 5 end - -function SaveData() - local file = fs.open("shipdata.txt", "w") - file.writeLine(textutils.serialize(SData)) - file.close() -end - -function ReadData() - local file = fs.open("shipdata.txt", "r") - SData = textutils.unserialize(file.readAll()) - file.close() -end - -function Explode(d, p) - local t, ll - t = {} - ll = 0 - if(#p == 1) then return {p} end - while true do - l = string.find(p ,d, ll, true) - if l ~= nil then - table.insert(t, string.sub(p, ll, l-1)) - ll = l+1 - else - table.insert(t, string.sub(p, ll)) - break - end - end - return t -end - -function ShowDirection() - if SData.Direction == 1 then - Show(" Direction = Up") - elseif SData.Direction == 2 then - Show(" Direction = Down") - elseif SData.Direction == 0 then - Show(" Direction = Front") - elseif SData.Direction == 180 then - Show(" Direction = Back") - elseif SData.Direction == 90 then - Show(" Direction = Left") - elseif SData.Direction == 270 then - Show(" Direction = Right") +function ClearWarning() + if clearWarningTick > 0 then + clearWarningTick = clearWarningTick - 1 + elseif clearWarningTick == 0 then + SetColorDefault() + local sizeX, sizeY = term.getSize() + SetCursorPos(1, sizeY) + ClearLine() end end -function CalcRealDistance() - if IsInHyper then - RealDistance = SData.Distance * 100 - MinimumDistance = 1 - JumpCost = (1000 * weight) + (1000 * SData.Distance) +----------- Formatting & popups + +function FormatFloat(value, nbchar) + local str = "?" + if value ~= nil then + str = string.format("%g", value) + end + if nbchar ~= nil then + str = string.sub(" " .. str, -nbchar) + end + return str +end +function FormatInteger(value, nbchar) + local str = "?" + if value ~= nil then + str = string.format("%d", value) + end + if nbchar ~= nil then + str = string.sub(" " .. str, -nbchar) + end + return str +end + +function boolToYesNo(bool) + if bool then + return "YES" else - if SData.Direction == 1 or SData.Direction == 2 then - MinimumDistance = GUp + GDown - RealDistance = SData.Distance + MinimumDistance - elseif SData.Direction == 0 or SData.Direction == 180 then - MinimumDistance = GFront + GBack - RealDistance = SData.Distance + MinimumDistance - elseif SData.Direction == 90 or SData.Direction == 270 then - MinimumDistance = GLeft + GRight - RealDistance = SData.Distance + MinimumDistance - end - MinimumDistance = MinimumDistance + 2 - JumpCost = (10 * weight) + (100 * SData.Distance) + return "no" end end -function CalcNewCoords(cx, cy, cz) - local res = {x=cx, y=cy, z=cz} - if SData.Direction == 1 then - res.y = res.y + RealDistance - elseif SData.Direction == 2 then - res.y = res.y - RealDistance +function readInputNumber(currentValue) + local inputAbort = false + local input = string.format(currentValue) + if input == "0" then + input = "" end - local dx, dy, dz = ship.getOrientation() - if dx ~= 0 then - if SData.Direction == 0 then - res.x = res.x + (RealDistance * dx) - elseif SData.Direction == 180 then - res.x = res.x - (RealDistance * dx) - elseif SData.Direction == 90 then - res.z = res.z + (RealDistance * dx) - elseif SData.Direction == 270 then - res.z = res.z - (RealDistance * dx) + local x, y = term.getCursorPos() + repeat + ClearWarning() + SetColorDefault() + SetCursorPos(x, y) + Write(input .. " ") + input = string.sub(input, -9) + + local params = { os.pullEventRaw() } + local eventName = params[1] + local address = params[2] + if address == nil then address = "none" end + if eventName == "key" then + local keycode = params[2] + if keycode >= 2 and keycode <= 10 then -- 1 to 9 + input = input .. string.format(keycode - 1) + elseif keycode == 11 or keycode == 82 then -- 0 & keypad 0 + input = input .. "0" + elseif keycode >= 79 and keycode <= 81 then -- keypad 1 to 3 + input = input .. string.format(keycode - 78) + elseif keycode >= 75 and keycode <= 77 then -- keypad 4 to 6 + input = input .. string.format(keycode - 71) + elseif keycode >= 71 and keycode <= 73 then -- keypad 7 to 9 + input = input .. string.format(keycode - 64) + elseif keycode == 14 then -- Backspace + input = string.sub(input, 1, string.len(input) - 1) + elseif keycode == 211 then -- Delete + input = "" + elseif keycode == 28 then -- Enter + inputAbort = true + elseif keycode == 74 then -- - + if string.sub(input, 1, 1) == "-" then + input = string.sub(input, 2) + else + input = "-" .. input + end + elseif keycode == 78 then -- + + if string.sub(input, 1, 1) == "-" then + input = string.sub(input, 2) + end + else + ShowWarning("Key " .. keycode .. " is invalid") + end + elseif eventName == "char" then + -- drop it + elseif eventName == "key_up" then + -- drop it + elseif eventName == "mouse_click" then + -- drop it + elseif eventName == "mouse_up" then + -- drop it + elseif eventName == "mouse_drag" then + -- drop it + elseif eventName == "terminate" then + inputAbort = true + elseif not common_event(eventName, params[3]) then + ShowWarning("Event '" .. eventName .. "', " .. address .. " is unsupported") end + until inputAbort + SetCursorPos(1, y + 1) + if input == "" or input == "-" then + return currentValue else - if SData.Direction == 0 then - res.z = res.z + (RealDistance * dz) - elseif SData.Direction == 180 then - res.z = res.z - (RealDistance * dz) - elseif SData.Direction == 90 then - res.x = res.x + (RealDistance * dz) - elseif SData.Direction == 270 then - res.x = res.x - (RealDistance * dz) + return tonumber(input) + end +end + +function readInputText(currentValue) + local inputAbort = false + local input = string.format(currentValue) + local x, y = term.getCursorPos() + os.pullEventRaw() -- skip first char event + repeat + ClearWarning() + SetColorDefault() + SetCursorPos(x, y) + Write(input .. " ") + input = string.sub(input, -30) + + local params = { os.pullEventRaw() } + local eventName = params[1] + local address = params[2] + if address == nil then address = "none" end + if eventName == "key" then + local keycode = params[2] + if keycode == 14 then -- Backspace + input = string.sub(input, 1, string.len(input) - 1) + elseif keycode == 211 then -- Delete + input = "" + elseif keycode == 28 then -- Enter + inputAbort = true + else + -- ShowWarning("Key " .. keycode .. " is invalid") + end + elseif eventName == "char" then + local char = params[2] + if char >= ' ' and char <= '~' then -- 1 to 9 + input = input .. char + else + ShowWarning("Char #" .. string.byte(char) .. " is invalid") + end + elseif eventName == "key_up" then + -- drop it + elseif eventName == "mouse_click" then + -- drop it + elseif eventName == "mouse_up" then + -- drop it + elseif eventName == "mouse_drag" then + -- drop it + elseif eventName == "terminate" then + inputAbort = true + elseif not common_event(eventName, params[3]) then + ShowWarning("Event '" .. eventName .. "', " .. address .. " is unsupported") end - end - return res -end - -function ShowInfo() - ShowTitle(Title) - X, Y, Z = ship.position() - Show("Core:") - Show(" x, y, z = "..X..", "..Y..", "..Z) - local energy, energyMax = ship.energy() - Show(" Energy = " .. math.floor(100 * energy / energyMax) .. " % (" .. energy .. "EU)") - local playersString, playersArray = ship.getAttachedPlayers() - Show(" Attached players = " .. playersString) - Show("Dimensions:") - Show(" Front, Right, Up = "..GFront..", "..GRight..", "..GUp) - Show(" Back, Left, Down = "..GBack..", "..GLeft..", "..GDown) - Show(" Size = "..weight.." blocks") - Show("Warp data:") - ShowDirection() - local dest = CalcNewCoords(X, Y, Z) - Show(" Distance = "..RealDistance.." ("..JumpCost.."EU, "..math.floor(energy/JumpCost).." jumps)") - Show(" Dest.coordinates = "..dest.x..", "..dest.y..", "..dest.z) - if SData.Summon then - Show(" Summon after = Yes") + until inputAbort + SetCursorPos(1, y + 1) + if input == "" then + return currentValue else - Show(" Summon after = No") + return input end end -function Confirm() +function readConfirmation() ShowWarning("Are you sure? (y/n)") - local event, keycode = os.pullEvent("key") - if keycode == 21 then - return true + repeat + local params = { os.pullEventRaw() } + local eventName = params[1] + local address = params[2] + if address == nil then address = "none" end + if eventName == "key" then + local keycode = params[2] + if keycode == 21 then -- Y + return true + else + return false + end + elseif eventName == "char" then + -- drop it + elseif eventName == "key_up" then + -- drop it + elseif eventName == "mouse_click" then + -- drop it + elseif eventName == "mouse_up" then + -- drop it + elseif eventName == "mouse_drag" then + -- drop it + elseif eventName == "terminate" then + return false + elseif not common_event(eventName, params[3]) then + ShowWarning("Event '" .. eventName .. "', " .. address .. " is unsupported") + end + until false +end + +----------- commons: menu, event handlers, etc. + +function common_event(eventName, param) + if eventName == "redstone" then + -- redstone_event(param) + elseif eventName == "timer" then else return false end + return true end -function Warp() - rs.setOutput(Alarm, false) - sleep(1) - ship.direction(SData.Direction) - if IsInHyper then - ship.mode(2) - else - ship.mode(1) - end - ship.jump() +function menu_common() + SetCursorPos(1, 18) + SetColorTitle() + ShowMenu("0 Connections, 1 Ship core, X Exit") end -function SetDistance() - Clear() - ShowTitle("<==== Set distance ====>") - SData.Distance = 0 - CalcRealDistance() - MaximumDistance = MinimumDistance + 127 - if IsInHyper then - term.write("Distance * 100 (min "..MinimumDistance..", max "..MaximumDistance.."): ") +----------- Configuration + +function data_save() + local file = fs.open("shipdata.txt", "w") + if file ~= nil then + file:writeLine(textutils.serialize(data)) + file:close() else - term.write("Distance (min "..MinimumDistance..", max "..MaximumDistance.."): ") - end - sleep(0.3) - SData.Distance = tonumber(read()) - if SData.Distance == nil then SData.Distance = 1 end - if SData.Distance < MinimumDistance or SData.Distance > MaximumDistance then - SData.Distance = 1 - ShowWarning("Wrong distance. Try again.") - os.pullEvent("key") - CalcRealDistance() - else - if not IsInHyper then - SData.Distance = SData.Distance - RealDistance - end - ship.distance(SData.Distance) - CalcRealDistance() + ShowWarning("No file system") end end -function SetDirection() - local drun = true - while(drun) do - Clear() - ShowTitle("<==== Set direction ====>") - ShowDirection() - term.setCursorPos(1, 16) - SetColorTitle() - ShowMenu("Use directional keys") - ShowMenu("W/S keys for Up/Down") - ShowMenu("Enter - confirm") - SetColorDeflt() - local event, keycode = os.pullEvent("key") - if keycode == 200 then - SData.Direction = 0 - elseif keycode == 17 then - SData.Direction = 1 - elseif keycode == 203 then - SData.Direction = 90 - elseif keycode == 205 then - SData.Direction = 270 - elseif keycode == 208 then - SData.Direction = 180 - elseif keycode == 31 then - SData.Direction = 2 - elseif keycode == 28 then - drun = false - end - end +function data_read() + data = { } + if fs.exists("shipdata.txt") then + local file = fs.open("shipdata.txt", "r") + data = textutils.unserialize(file:readAll()) + file:close() + end + if data.core_summon == nil then data.core_summon = false; end end -function SetDimensions() - Clear() - ShowTitle("<==== Set dimensions ====>") - sleep(0.3) - term.write(" Front ("..GFront..") : ") - GFront = tonumber(read()) - term.write(" Right ("..GRight..") : ") - GRight = tonumber(read()) - term.write(" Up ("..GUp..") : ") - GUp = tonumber(read()) - term.write(" Back ("..GBack..") : ") - GBack = tonumber(read()) - term.write(" Left ("..GLeft..") : ") - GLeft = tonumber(read()) - term.write(" Down ("..GDown..") : ") - GDown = tonumber(read()) - term.write("Setting dimensions...") - ship.dim_positive(GFront, GRight, GUp) - ship.dim_negative(GBack, GLeft, GDown) - weight = ship.getShipSize() +function data_setName() + ShowTitle("<==== Set name ====>") + + SetCursorPos(1, 2) + Write("Enter ship name: ") + label = readInputText(label) + os.setComputerLabel(label) + if ship ~= nil then + ship.coreFrequency(label) + end + os.reboot() end -function Summon() - Clear() - ShowTitle("<==== Summon players ====>") - local playersString, playersArray = ship.getAttachedPlayers() - if playersArray == nil then - Show("- no players attached -") - sleep(1.0) +----------- Ship support + +core_front = 0 +core_right = 0 +core_up = 0 +core_back = 0 +core_left = 0 +core_down = 0 +core_isInHyper = false +core_jumpCost = 0 +core_shipSize = 0 +core_movement = { 0, 0, 0 } +core_rotationSteps = 0 + +function core_boot() + if ship == nil then return end - for i = 1, #playersArray do - Show(i..". "..playersArray[i]) + + Write("Booting Ship Core") + + if data.core_summon then + ship.summon_all() end + + WriteLn("...") + core_front, core_right, core_up = ship.dim_positive() + core_back, core_left, core_down = ship.dim_negative() + core_isInHyper = ship.isInHyperspace() + core_rotationSteps = ship.rotationSteps() + core_movement = { ship.movement() } + if ship.direction ~= nil then + ship.direction(666) + ship.distance(0) + end + WriteLn("Ship core detected...") + + repeat + pos = ship.position() + os.sleep(0.3) + until pos ~= nil + X, Y, Z = ship.position() + WriteLn("Ship position triangulated...") + + repeat + isAttached = ship.isAttached() + os.sleep(0.3) + until isAttached ~= false + WriteLn("Ship core linked...") + + repeat + core_shipSize = ship.getShipSize() + os.sleep(0.3) + until core_shipSize ~= nil + WriteLn("Ship size updated...") + + ship.mode(1) +end +function core_writeMovement() + local message = " Movement = " + local count = 0 + if core_movement[1] > 0 then + message = message .. core_movement[1] .. " front" + count = count + 1 + elseif core_movement[1] < 0 then + message = message .. (- core_movement[1]) .. " back" + count = count + 1 + end + if core_movement[2] > 0 then + if count > 0 then message = message .. ", "; end + message = message .. core_movement[2] .. " up" + count = count + 1 + elseif core_movement[2] < 0 then + if count > 0 then message = message .. ", "; end + message = message .. (- core_movement[2]) .. " down" + count = count + 1 + end + if core_movement[3] > 0 then + if count > 0 then message = message .. ", "; end + message = message .. core_movement[3] .. " right" + count = count + 1 + elseif core_movement[3] < 0 then + if count > 0 then message = message .. ", "; end + message = message .. (- core_movement[3]) .. " left" + count = count + 1 + end + + if core_rotationSteps == 1 then + if count > 0 then message = message .. ", "; end + message = message .. "Turn right" + count = count + 1 + elseif core_rotationSteps == 2 then + if count > 0 then message = message .. ", "; end + message = message .. "Turn back" + count = count + 1 + elseif core_rotationSteps == 3 then + if count > 0 then message = message .. ", "; end + message = message .. "Turn left" + count = count + 1 + end + + if count == 0 then + message = message .. "(none)" + end + WriteLn(message) +end + +function core_writeRotation() + if core_rotationSteps == 0 then + WriteLn(" Rotation = Front") + elseif core_rotationSteps == 1 then + WriteLn(" Rotation = Right +90") + elseif core_rotationSteps == 2 then + WriteLn(" Rotation = Back 180") + elseif core_rotationSteps == 3 then + WriteLn(" Rotation = Left -90") + end +end + +function core_computeNewCoordinates(cx, cy, cz) + local res = { x = cx, y = cy, z = cz } + local dx, dy, dz = ship.getOrientation() + local worldMovement = { x = 0, y = 0, z = 0 } + worldMovement.x = dx * core_movement[1] - dz * core_movement[3] + worldMovement.y = core_movement[2] + worldMovement.z = dz * core_movement[1] + dx * core_movement[3] + core_actualDistance = math.ceil(math.sqrt(worldMovement.x * worldMovement.x + worldMovement.y * worldMovement.y + worldMovement.z * worldMovement.z)) + core_jumpCost = ship.getEnergyRequired(core_actualDistance) + res.x = res.x + worldMovement.x + res.y = res.y + worldMovement.y + res.z = res.z + worldMovement.z + return res +end + +function core_warp() + -- rs.setOutput(alarm_side, true) + if readConfirmation() then + -- rs.setOutput(alarm_side, false) + ship.movement(core_movement[1], core_movement[2], core_movement[3]) + ship.rotationSteps(core_rotationSteps) + ship.mode(1) + ship.jump() + -- ship = nil + end + -- rs.setOutput(alarm_side, false) +end + +function core_page_setMovement() + ShowTitle("<==== Set movement ====>") + + core_movement[1] = core_page_setDistanceAxis(2, "Front", core_movement[1], math.abs(core_front + core_back + 1)) + core_movement[2] = core_page_setDistanceAxis(3, "Up" , core_movement[2], math.abs(core_up + core_down + 1)) + core_movement[3] = core_page_setDistanceAxis(4, "Right", core_movement[3], math.abs(core_left + core_right + 1)) + core_movement = { ship.movement(core_movement[1], core_movement[2], core_movement[3]) } +end + +function core_page_setDistanceAxis(line, axis, userEntry, shipLength) + local maximumDistance = shipLength + 127 + if core_isInHyper and line ~= 3 then + maximumDistance = shipLength + 127 * 100 + end + repeat + SetCursorPos(1, line) + Write(axis .. " (min " .. (shipLength + 1) .. ", max " .. maximumDistance .. "): ") + userEntry = readInputNumber(userEntry) + if userEntry == 0 then + return userEntry + end + if math.abs(userEntry) <= shipLength or math.abs(userEntry) > maximumDistance then + ShowWarning("Wrong distance. Try again.") + end + until math.abs(userEntry) > shipLength and math.abs(userEntry) <= maximumDistance + + return userEntry +end + +function core_page_setRotation() + local inputAbort = false + local drun = true + repeat + ShowTitle("<==== Set rotation ====>") + core_writeRotation() + SetCursorPos(1, 19) + SetColorTitle() + ShowMenu("Use directional keys") + ShowMenu("Enter - confirm") + SetColorDefault() + local params = { os.pullEventRaw() } + local eventName = params[1] + local address = params[2] + if address == nil then address = "none" end + if eventName == "key" then + local keycode = params[2] + if keycode == 200 then + core_rotationSteps = 0 + elseif keycode == 203 then + core_rotationSteps = 3 + elseif keycode == 205 then + core_rotationSteps = 1 + elseif keycode == 208 then + core_rotationSteps = 2 + elseif keycode == 28 then + inputAbort = true + else + ShowWarning("Key " .. keycode .. " is invalid") + end + elseif eventName == "char" then + -- drop it + elseif eventName == "key_up" then + -- drop it + elseif eventName == "mouse_click" then + -- drop it + elseif eventName == "mouse_up" then + -- drop it + elseif eventName == "mouse_drag" then + -- drop it + elseif eventName == "terminate" then + inputAbort = true + elseif not common_event(eventName, params[3]) then + ShowWarning("Event '" .. eventName .. "', " .. address .. " is unsupported") + end + until inputAbort + core_rotationSteps = ship.rotationSteps(core_rotationSteps) +end + +function core_page_setDimensions() + ShowTitle("<==== Set dimensions ====>") + Write(" Front (".. core_front ..") : ") + core_front = readInputNumber(core_front) + Write(" Right (".. core_right ..") : ") + core_right = readInputNumber(core_right) + Write(" Up (".. core_up ..") : ") + core_up = readInputNumber(core_up) + Write(" Back (".. core_back ..") : ") + core_back = readInputNumber(core_back) + Write(" Left (".. core_left ..") : ") + core_left = readInputNumber(core_left) + Write(" Down (".. core_down ..") : ") + core_down = readInputNumber(core_down) + Write("Setting dimensions...") + core_front, core_right, core_up = ship.dim_positive(core_front, core_right, core_up) + core_back, core_left, core_down = ship.dim_negative(core_back, core_left, core_down) + core_shipSize = ship.getShipSize() + if core_shipSize == nil then core_shipSize = 0 end +end + +function core_page_summon() + ShowTitle("<==== Summon players ====>") + local playersString, playersArray = ship.getAttachedPlayers() + for i = 1, #playersArray do + WriteLn(i..". "..playersArray[i]) + end SetColorTitle() ShowMenu("Enter player number") ShowMenu("or press enter to summon everyone") - SetColorDeflt() - sleep(0.3) - term.write(":") - local input = read() + SetColorDefault() + + Write(":") + local input = readInputNumber("") if input == "" then - ship.summonAll() + ship.summon_all() else input = tonumber(input) ship.summon(input - 1) end end -function JumpToBeacon() - Clear() +function core_page_jumpToBeacon() ShowTitle("<==== Jump to beacon ====>") - sleep(0.3) - term.write("Enter beacon frequency: ") - local freq = tostring(read()) - rs.setOutput(Alarm, true) - if Confirm() then - rs.setOutput(Alarm, false) + + Write("Enter beacon frequency: ") + local freq = readInputText("") + -- rs.setOutput(alarm_side, true) + if readConfirmation() then + -- rs.setOutput(alarm_side, false) ship.mode(4) ship.beaconFrequency(freq) ship.jump() + -- ship = nil end - rs.setOutput(Alarm, false) + -- rs.setOutput(alarm_side, false) end -function JumpToGate() - Clear() - ShowTitle("<==== Jump to JumpGate ====>") - sleep(0.3) - term.write("Enter jumpgate name: ") - local name = tostring(read()) - rs.setOutput(Alarm, true) - if Confirm() then - rs.setOutput(Alarm, false) +function core_page_jumpToGate() + ShowTitle("<==== Jump to Jumpgate ====>") + + Write("Enter jumpgate name: ") + local name = readInputText("") + -- rs.setOutput(alarm_side, true) + if readConfirmation() then + -- rs.setOutput(alarm_side, false) ship.mode(6) ship.targetJumpgate(name) ship.jump() + -- ship = nil end - rs.setOutput(Alarm, false) + -- rs.setOutput(alarm_side, false) end -function SetShipName() - Clear() - ShowTitle("<==== Set ship name ====>") - sleep(0.3) - term.write("Enter ship name: ") - SData.Shipname = tostring(read()) - os.setComputerLabel(SData.Shipname) - ship.coreFrequency(SData.Shipname) - SaveData() - os.reboot() -end - -if fs.exists("shipdata.txt") then - ReadData() -else - SData = { - Summon = false, - Distance = 1, - Direction = 0, - Shipname = "" - } -end - -Side = { "bottom", "top", "back", "left", "right" } -for i = 1,5 do - if peripheral.getType(Side[i]) == "warpdriveShipController" then - ship = peripheral.wrap(Side[i]) - break - else - ship = nil - end -end - -if ship == nil then - ShowWarning("No ship controller detected") - os.pullEvent("key") - os.reboot() -end -print("Ship controller detected...") - -SetColorDeflt() - -if SData.Shipname == "" then - SetShipName() -end - -Title = "" - -if SData.Summon then - ship.summonAll() -end - -GFront, GRight, GUp = ship.dim_positive() -GBack, GLeft, GDown = ship.dim_negative() -IsInHyper = ship.isInHyperspace() -repeat - sleep(0.3) - pos = ship.position() -until pos ~= nil -print("Ship core detected...") -X, Y, Z = ship.position() - -repeat - sleep(0.3) - isAttached = ship.isAttached() -until isAttached -print("Ship core linked...") - -repeat - sleep(0.3) - weight = ship.getShipSize() -until weight ~= nil -print("Ship weight updated...") - -CalcRealDistance() - -ship.mode(1) - -mainloop = true -while(mainloop) do - Clear() - ShowInfo() - term.setCursorPos(1, 15) - SetColorTitle() - ShowMenu("D - Dimensions, M - Toggle summon, N - Ship name") - ShowMenu("S - Set Warp Data, J - Jump, G - Jump to JumpGate") - ShowMenu("B - Jump to Beacon, H - Jump to Hyperspace") - ShowMenu("C - Summon crew, X - Shutdown Controller and Exit") - SetColorDeflt() - local event, keycode = os.pullEvent("key") - if keycode == 31 then - SetDirection() - SetDistance() - SaveData() - elseif keycode == 50 then - if SData.Summon then - SData.Summon = false +function core_page() + ShowTitle(label .. " - Ship status") + if ship ~= nil then + -- WriteLn("") + X, Y, Z = ship.position() + WriteLn("Core:") + WriteLn(" x, y, z = " .. X .. ", " .. Y .. ", " .. Z) + local energy, energyMax = ship.energy() + if energy == nil then energy = 0 end + if energyMax == nil then energyMax = 1 end + WriteLn(" Energy = " .. math.floor(energy / energyMax * 100) .. " % (" .. energy .. "EU)") + local playersString, playersArray = ship.getAttachedPlayers() + if playersString == "" then players = "-" end + WriteLn(" Attached players = " .. playersString) + -- WriteLn("") + WriteLn("Dimensions:") + WriteLn(" Front, Right, Up = " .. FormatInteger(core_front) .. ", " .. FormatInteger(core_right) .. ", " .. FormatInteger(core_up)) + WriteLn(" Back, Left, Down = " .. FormatInteger(core_back) .. ", " .. FormatInteger(core_left) .. ", " .. FormatInteger(core_down)) + WriteLn(" Size = " .. core_shipSize .. " blocks") + -- WriteLn("") + WriteLn("Warp data:") + core_writeMovement() + local dest = core_computeNewCoordinates(X, Y, Z) + WriteLn(" Distance = " .. core_actualDistance .. " (" .. core_jumpCost .. "EU, " .. math.floor(energy / core_jumpCost) .. " jumps)") + WriteLn(" Dest.coordinates = " .. FormatInteger(dest.x) .. ", " .. FormatInteger(dest.y) .. ", " .. FormatInteger(dest.z)) + if data.core_summon then + WriteLn(" Summon after = Yes") else - SData.Summon = true + WriteLn(" Summon after = No") end - SaveData() - elseif keycode == 32 then - SetDimensions() - SaveData() - elseif keycode == 36 then - rs.setOutput(Alarm, true) - if Confirm() then - Warp() + else + ShowWarning("No ship controller detected") + end + + SetCursorPos(1, 15) + SetColorTitle() + ShowMenu("D - set Dimensions, N - set ship Name") + ShowMenu("M - set Movement, J - Jump, G - jump through Gate") + ShowMenu("B - jump to Beacon, H - jump to Hyperspace") + ShowMenu("C - summon Crew, M - Toggle summon") +end + +function core_key(char, keycode) + if keycode == 50 then -- M + core_page_setMovement() + core_page_setRotation() + data_save() + return true + elseif keycode == 20 then -- T + if data.core_summon then + data.core_summon = false + else + data.core_summon = true end - rs.setOutput(Alarm, false) - elseif keycode == 46 then - Summon() - elseif keycode == 48 then - JumpToBeacon() - elseif keycode == 34 then - JumpToGate() - elseif keycode == 35 then - rs.setOutput(Alarm, true) - if Confirm() then - rs.setOutput(Alarm, false) + data_save() + return true + elseif keycode == 32 then -- D + core_page_setDimensions() + data_save() + return true + elseif keycode == 36 then -- J + core_warp() + return true + elseif keycode == 46 then -- C + core_page_summon() + return true + elseif keycode == 48 then -- B + core_page_jumpToBeacon() + return true + elseif keycode == 34 then -- G + core_page_jumpToGate() + return true + elseif keycode == 35 then -- H + -- rs.setOutput(alarm_side, true) + if readConfirmation() then + -- rs.setOutput(alarm_side, false) ship.mode(5) ship.jump() - end - rs.setOutput(Alarm, false) - elseif keycode == 45 then - mainloop = false + -- ship = nil + end + -- rs.setOutput(alarm_side, false) + return true elseif keycode == 49 then - SetShipName() + data_setName() + return true + end + return false +end + +----------- Boot sequence + +label = os.computerLabel() +if not label then + label = "" .. os.computerLabel() +end + +-- read configuration +data_read() +Clear() +print("data_read...") + +-- initial scanning +monitors = {} +ShowTitle(label .. " - Connecting...") +WriteLn("") + +sides = peripheral.getNames() +ship = nil +for key,side in pairs(sides) do + sleep(0) + if peripheral.getType(side) == "monitor" then + WriteLn("Wrapping " .. side) + lmonitor = peripheral.wrap(side) + table.insert(monitors, lmonitor) + lmonitor.setTextScale(monitor_textScale) + elseif peripheral.getType(side) == "warpdriveShipController" then + WriteLn("Wrapping " .. side) + ship = peripheral.wrap(side) end end -if SData.Summon then - SData.Summon = false - SaveData() +if not os.computerLabel() and ship ~= nil then + data_setName() end + +-- peripherals status +function connections_page() + ShowTitle(label .. " - Connections") + + WriteLn("") + if ship == nil then + SetColorDisabled() + WriteLn("No ship controller detected") + else + SetColorSuccess() + WriteLn("Ship controller detected") + end +end + +-- peripheral boot up Clear() -print("wish you good") -ship.mode(0) -sleep(0.5) -os.shutdown() \ No newline at end of file +connections_page() +SetColorDefault() +WriteLn("") +os.sleep(0) +core_boot() +os.sleep(0) + +-- main loop +abort = false +refresh = true +page = connections_page +keyHandler = nil +repeat + ClearWarning() + if refresh then + Clear() + page() + menu_common() + refresh = false + end + params = { os.pullEventRaw() } + eventName = params[1] + address = params[2] + if address == nil then address = "none" end + -- WriteLn("...") + -- WriteLn("Event '" .. eventName .. "', " .. address .. ", " .. params[3] .. ", " .. params[4] .. " received") + -- os.sleep(0.2) + if eventName == "key" then + keycode = params[2] + if char == 88 or char == 120 or keycode == 45 then -- x for eXit + abort = true + elseif char == 48 or keycode == 11 or keycode == 82 then -- 0 + page = connections_page + keyHandler = nil + refresh = true + elseif char == 49 or keycode == 2 or keycode == 79 then -- 1 + page = core_page + keyHandler = core_key + refresh = true + elseif keyHandler ~= nil and keyHandler(char, keycode) then + refresh = true + os.sleep(0) + elseif char == 0 then -- control chars + refresh = false + os.sleep(0) + else + ShowWarning("Key " .. keycode .. " is invalid") + os.sleep(0.2) + end + -- func(unpack(params)) + -- abort, refresh = false, false + elseif eventName == "char" then + -- drop it + elseif eventName == "key_up" then + -- drop it + elseif eventName == "mouse_click" then + -- drop it + elseif eventName == "mouse_up" then + -- drop it + elseif eventName == "mouse_drag" then + -- drop it + elseif eventName == "terminate" then + abort = true + elseif not common_event(eventName, params[3]) then + ShowWarning("Event '" .. eventName .. "', " .. address .. " is unsupported") + refresh = true + os.sleep(0.2) + end +until abort + +-- exiting +if data.core_summon then + data.core_summon = false + data_save() +end + +if ship ~= nil then + ship.mode(0) +end + +-- clear screens on exit +SetMonitorColorFrontBack(colors.white, colors.black) +term.clear() +SetCursorPos(1, 1) +Write("") diff --git a/src/main/resources/assets/warpdrive/lua.OpenComputers/warpdriveShipController/autorun.lua b/src/main/resources/assets/warpdrive/lua.OpenComputers/warpdriveShipController/autorun.lua index 44737e91..2626b131 100644 --- a/src/main/resources/assets/warpdrive/lua.OpenComputers/warpdriveShipController/autorun.lua +++ b/src/main/resources/assets/warpdrive/lua.OpenComputers/warpdriveShipController/autorun.lua @@ -5,6 +5,11 @@ local event = require("event") local fs = require("filesystem") local serialization = require("serialization") +if not term.isAvailable() then + computer.beep() + return +end + Style = { CDefault = 0xFFFFFF, BGDefault = 0x0000FF, @@ -22,11 +27,6 @@ Style = { BGDisabled = 0x0000FF } -if not term.isAvailable() then - computer.beep() - return -end - ----------- Monitor support -- need to memorize colors so we can see debug stack dump @@ -196,7 +196,7 @@ function readInputNumber(currentValue) SetCursorPos(x, y) Write(input .. " ") input = string.sub(input, -9) - + local params = { event.pull() } local eventName = params[1] local address = params[2] @@ -210,6 +210,16 @@ function readInputNumber(currentValue) input = input .. string.format(keycode - 1) elseif char == 48 or keycode == 11 then -- 0 input = input .. "0" + elseif char == 45 or keycode == 74 then -- - + if string.sub(input, 1, 1) == "-" then + input = string.sub(input, 2) + else + input = "-" .. input + end + elseif char == 43 or keycode == 78 then -- + + if string.sub(input, 1, 1) == "-" then + input = string.sub(input, 2) + end elseif char == 8 then -- Backspace input = string.sub(input, 1, string.len(input) - 1) elseif char == 0 and keycode == 211 then -- Delete @@ -220,7 +230,13 @@ function readInputNumber(currentValue) ShowWarning("Key " .. char .. " " .. keycode .. " is invalid") end elseif eventName == "key_up" then - -- drop it + -- drop it + elseif eventName == "touch" then + -- drop it + elseif eventName == "drop" then + -- drop it + elseif eventName == "drag" then + -- drop it elseif eventName == "interrupted" then inputAbort = true elseif not common_event(eventName, params[3]) then @@ -228,7 +244,7 @@ function readInputNumber(currentValue) end until inputAbort SetCursorPos(1, y + 1) - if input == "" then + if input == "" or input == "-" then return currentValue else return tonumber(input) @@ -266,6 +282,12 @@ function readInputText(currentValue) end elseif eventName == "key_up" then -- drop it + elseif eventName == "touch" then + -- drop it + elseif eventName == "drop" then + -- drop it + elseif eventName == "drag" then + -- drop it elseif eventName == "interrupted" then inputAbort = true elseif not common_event(eventName, params[3]) then @@ -289,13 +311,19 @@ function readConfirmation() if address == nil then address = "none" end if eventName == "key_down" then local char = params[3] - if char == 89 or char == 121 then -- Y + if char == 89 or char == 121 or keycode == 21 then -- Y return true else return false end elseif eventName == "key_up" then -- drop it + elseif eventName == "touch" then + -- drop it + elseif eventName == "drop" then + -- drop it + elseif eventName == "drag" then + -- drop it elseif eventName == "interrupted" then return false elseif not common_event(eventName, params[3]) then @@ -346,8 +374,6 @@ function data_read() file:close() end if data.core_summon == nil then data.core_summon = false; end - if data.core_distance == nil then data.core_distance = 0; end - if data.core_direction == nil then data.core_direction = 0; end end function data_setName() @@ -372,117 +398,129 @@ core_back = 0 core_left = 0 core_down = 0 core_isInHyper = false -core_shipLength = 0 -core_realDistance = 0 core_jumpCost = 0 core_shipSize = 0 +core_movement = { 0, 0, 0 } +core_rotationSteps = 0 function core_boot() if ship == nil then return end - + Write("Booting Ship Core") - + if data.core_summon then ship.summon_all() end - - Write(".") + + WriteLn("...") core_front, core_right, core_up = ship.dim_positive() core_back, core_left, core_down = ship.dim_negative() core_isInHyper = ship.isInHyperspace() - - Write(".") + core_rotationSteps = ship.rotationSteps() + core_movement = { ship.movement() } + if ship.direction ~= nil then + ship.direction(666) + ship.distance(0) + end + WriteLn("Ship core detected...") + repeat pos = ship.position() os.sleep(0.3) until pos ~= nil X, Y, Z = ship.position() - Write(".") + WriteLn("Ship position triangulated...") + repeat isAttached = ship.isAttached() os.sleep(0.3) until isAttached ~= false - - Write(".") + WriteLn("Ship core linked...") + repeat core_shipSize = ship.getShipSize() os.sleep(0.3) until core_shipSize ~= nil - - Write(".") - core_computeRealDistance() - - Write(".") + WriteLn("Ship size updated...") + ship.mode(1) - WriteLn("") end -function core_writeDirection() - if data.core_direction == 1 then - WriteLn(" Direction = Up") - elseif data.core_direction == 2 then - WriteLn(" Direction = Down") - elseif data.core_direction == 0 then - WriteLn(" Direction = Front") - elseif data.core_direction == 180 then - WriteLn(" Direction = Back") - elseif data.core_direction == 90 then - WriteLn(" Direction = Left") - elseif data.core_direction == 270 then - WriteLn(" Direction = Right") +function core_writeMovement() + local message = " Movement = " + local count = 0 + if core_movement[1] > 0 then + message = message .. core_movement[1] .. " front" + count = count + 1 + elseif core_movement[1] < 0 then + message = message .. (- core_movement[1]) .. " back" + count = count + 1 end + if core_movement[2] > 0 then + if count > 0 then message = message .. ", "; end + message = message .. core_movement[2] .. " up" + count = count + 1 + elseif core_movement[2] < 0 then + if count > 0 then message = message .. ", "; end + message = message .. (- core_movement[2]) .. " down" + count = count + 1 + end + if core_movement[3] > 0 then + if count > 0 then message = message .. ", "; end + message = message .. core_movement[3] .. " right" + count = count + 1 + elseif core_movement[3] < 0 then + if count > 0 then message = message .. ", "; end + message = message .. (- core_movement[3]) .. " left" + count = count + 1 + end + + if core_rotationSteps == 1 then + if count > 0 then message = message .. ", "; end + message = message .. "Turn right" + count = count + 1 + elseif core_rotationSteps == 2 then + if count > 0 then message = message .. ", "; end + message = message .. "Turn back" + count = count + 1 + elseif core_rotationSteps == 3 then + if count > 0 then message = message .. ", "; end + message = message .. "Turn left" + count = count + 1 + end + + if count == 0 then + message = message .. "(none)" + end + WriteLn(message) end -function core_computeRealDistance() - if core_isInHyper then - core_shipLength = 0 - core_realDistance = data.core_distance * 100 + core_shipLength - ship.mode(2) - else - if data.core_direction == 1 or data.core_direction == 2 then - core_shipLength = core_up + core_down + 1 - elseif data.core_direction == 0 or data.core_direction == 180 then - core_shipLength = core_front + core_back + 1 - elseif data.core_direction == 90 or data.core_direction == 270 then - core_shipLength = core_left + core_right + 1 - end - core_realDistance = data.core_distance + core_shipLength - 1 - ship.mode(1) +function core_writeRotation() + if core_rotationSteps == 0 then + WriteLn(" Rotation = Front") + elseif core_rotationSteps == 1 then + WriteLn(" Rotation = Right +90") + elseif core_rotationSteps == 2 then + WriteLn(" Rotation = Back 180") + elseif core_rotationSteps == 3 then + WriteLn(" Rotation = Left -90") end - core_jumpCost = ship.getEnergyRequired(core_realDistance) end function core_computeNewCoordinates(cx, cy, cz) local res = { x = cx, y = cy, z = cz } - if data.core_direction == 1 then - res.y = res.y + core_realDistance - elseif data.core_direction == 2 then - res.y = res.y - core_realDistance - end local dx, dy, dz = ship.getOrientation() - if dx ~= 0 then - if data.core_direction == 0 then - res.x = res.x + (core_realDistance * dx) - elseif data.core_direction == 180 then - res.x = res.x - (core_realDistance * dx) - elseif data.core_direction == 90 then - res.z = res.z + (core_realDistance * dx) - elseif data.core_direction == 270 then - res.z = res.z - (core_realDistance * dx) - end - else - if data.core_direction == 0 then - res.z = res.z + (core_realDistance * dz) - elseif data.core_direction == 180 then - res.z = res.z - (core_realDistance * dz) - elseif data.core_direction == 90 then - res.x = res.x + (core_realDistance * dz) - elseif data.core_direction == 270 then - res.x = res.x - (core_realDistance * dz) - end - end + local worldMovement = { x = 0, y = 0, z = 0 } + worldMovement.x = dx * core_movement[1] - dz * core_movement[3] + worldMovement.y = core_movement[2] + worldMovement.z = dz * core_movement[1] + dx * core_movement[3] + core_actualDistance = math.ceil(math.sqrt(worldMovement.x * worldMovement.x + worldMovement.y * worldMovement.y + worldMovement.z * worldMovement.z)) + core_jumpCost = ship.getEnergyRequired(core_actualDistance) + res.x = res.x + worldMovement.x + res.y = res.y + worldMovement.y + res.z = res.z + worldMovement.z return res end @@ -490,55 +528,53 @@ function core_warp() -- rs.setOutput(alarm_side, true) if readConfirmation() then -- rs.setOutput(alarm_side, false) - ship.direction(data.core_direction) - ship.distance(data.core_distance) - if core_isInHyper then - ship.mode(2) - else - ship.mode(1) - end + ship.movement(core_movement[1], core_movement[2], core_movement[3]) + ship.rotationSteps(core_rotationSteps) + ship.mode(1) ship.jump() -- ship = nil end -- rs.setOutput(alarm_side, false) end -function core_page_setDistance() - ShowTitle("<==== Set distance ====>") +function core_page_setMovement() + ShowTitle("<==== Set movement ====>") - core_computeRealDistance() - local maximumDistance = core_shipLength + 127 - local userEntry = core_realDistance - if userEntry <= 1 then - userEntry = 0 - end - repeat - SetCursorPos(1, 2) - if core_isInHyper then - Write("Distance * 100 (min " .. core_shipLength .. ", max " .. maximumDistance .. "): ") - else - Write("Distance (min " .. (core_shipLength + 1) .. ", max " .. maximumDistance .. "): ") - end - userEntry = readInputNumber(userEntry) - if userEntry <= core_shipLength or userEntry > maximumDistance then - ShowWarning("Wrong distance. Try again.") - end - until userEntry > core_shipLength and userEntry <= maximumDistance - - data.core_distance = userEntry - core_shipLength + 1 - core_computeRealDistance() + core_movement[1] = core_page_setDistanceAxis(2, "Front", core_movement[1], math.abs(core_front + core_back + 1)) + core_movement[2] = core_page_setDistanceAxis(3, "Up" , core_movement[2], math.abs(core_up + core_down + 1)) + core_movement[3] = core_page_setDistanceAxis(4, "Right", core_movement[3], math.abs(core_left + core_right + 1)) + core_movement = { ship.movement(core_movement[1], core_movement[2], core_movement[3]) } end -function core_page_setDirection() +function core_page_setDistanceAxis(line, axis, userEntry, shipLength) + local maximumDistance = shipLength + 127 + if core_isInHyper and line ~= 3 then + maximumDistance = shipLength + 127 * 100 + end + repeat + SetCursorPos(1, line) + Write(axis .. " (min " .. (shipLength + 1) .. ", max " .. maximumDistance .. "): ") + userEntry = readInputNumber(userEntry) + if userEntry == 0 then + return userEntry + end + if math.abs(userEntry) <= shipLength or math.abs(userEntry) > maximumDistance then + ShowWarning("Wrong distance. Try again.") + end + until math.abs(userEntry) > shipLength and math.abs(userEntry) <= maximumDistance + + return userEntry +end + +function core_page_setRotation() local inputAbort = false local drun = true repeat - ShowTitle("<==== Set direction ====>") - core_writeDirection() + ShowTitle("<==== Set rotation ====>") + core_writeRotation() SetCursorPos(1, 19) SetColorTitle() ShowMenu("Use directional keys") - ShowMenu("W/S keys for Up/Down") ShowMenu("Enter - confirm") SetColorDefault() local params = { event.pull() } @@ -549,17 +585,13 @@ function core_page_setDirection() local char = params[3] local keycode = params[4] if keycode == 200 then - data.core_direction = 0 - elseif keycode == 17 or keycode == 201 then - data.core_direction = 1 + core_rotationSteps = 0 elseif keycode == 203 then - data.core_direction = 90 + core_rotationSteps = 3 elseif keycode == 205 then - data.core_direction = 270 + core_rotationSteps = 1 elseif keycode == 208 then - data.core_direction = 180 - elseif keycode == 31 or keycode == 209 then - data.core_direction = 2 + core_rotationSteps = 2 elseif keycode == 28 then inputAbort = true else @@ -567,12 +599,19 @@ function core_page_setDirection() end elseif eventName == "key_up" then -- drop it + elseif eventName == "touch" then + -- drop it + elseif eventName == "drop" then + -- drop it + elseif eventName == "drag" then + -- drop it elseif eventName == "interrupted" then inputAbort = true elseif not common_event(eventName, params[3]) then ShowWarning("Event '" .. eventName .. "', " .. address .. " is unsupported") end until inputAbort + core_rotationSteps = ship.rotationSteps(core_rotationSteps) end function core_page_setDimensions() @@ -590,8 +629,8 @@ function core_page_setDimensions() Write(" Down (".. core_down ..") : ") core_down = readInputNumber(core_down) Write("Setting dimensions...") - ship.dim_positive(core_front, core_right, core_up) - ship.dim_negative(core_back, core_left, core_down) + core_front, core_right, core_up = ship.dim_positive(core_front, core_right, core_up) + core_back, core_left, core_down = ship.dim_negative(core_back, core_left, core_down) core_shipSize = ship.getShipSize() if core_shipSize == nil then core_shipSize = 0 end end @@ -606,7 +645,7 @@ function core_page_summon() ShowMenu("Enter player number") ShowMenu("or press enter to summon everyone") SetColorDefault() - + Write(":") local input = readInputNumber("") if input == "" then @@ -619,7 +658,7 @@ end function core_page_jumpToBeacon() ShowTitle("<==== Jump to beacon ====>") - + Write("Enter beacon frequency: ") local freq = readInputText("") -- rs.setOutput(alarm_side, true) @@ -635,7 +674,7 @@ end function core_page_jumpToGate() ShowTitle("<==== Jump to Jumpgate ====>") - + Write("Enter jumpgate name: ") local name = readInputText("") -- rs.setOutput(alarm_side, true) @@ -670,9 +709,9 @@ function core_page() WriteLn(" Size = " .. core_shipSize .. " blocks") WriteLn("") WriteLn("Warp data:") - core_writeDirection() + core_writeMovement() local dest = core_computeNewCoordinates(X, Y, Z) - WriteLn(" Distance = " .. core_realDistance .. " (" .. core_jumpCost .. "EU, " .. math.floor(energy / core_jumpCost) .. " jumps)") + WriteLn(" Distance = " .. core_actualDistance .. " (" .. core_jumpCost .. "EU, " .. math.floor(energy / core_jumpCost) .. " jumps)") WriteLn(" Dest.coordinates = " .. FormatInteger(dest.x) .. ", " .. FormatInteger(dest.y) .. ", " .. FormatInteger(dest.z)) if data.core_summon then WriteLn(" Summon after = Yes") @@ -682,29 +721,29 @@ function core_page() else ShowWarning("No ship controller detected") end - + SetCursorPos(1, 19) SetColorTitle() - ShowMenu("D - Dimensions, M - Toggle summon, N - Ship name") - ShowMenu("S - Set Warp Data, J - Jump, G - Jump to JumpGate") - ShowMenu("B - Jump to Beacon, H - Jump to Hyperspace") - ShowMenu("C - summon Crew") + ShowMenu("D - set Dimensions, N - set ship Name") + ShowMenu("M - set Movement, J - Jump, G - jump through Gate") + ShowMenu("B - jump to Beacon, H - jump to Hyperspace") + ShowMenu("C - summon Crew, M - Toggle summon") end function core_key(char, keycode) - if char == 83 or char == 115 then -- S - core_page_setDirection() - core_page_setDistance() + if char == 77 or char == 109 then -- M + core_page_setMovement() + core_page_setRotation() data_save() return true - elseif char == 77 or char == 109 then -- M + elseif char == 84 or char == 116 then -- T if data.core_summon then data.core_summon = false - else - data.core_summon = true - end - data_save() - return true + else + data.core_summon = true + end + data_save() + return true elseif char == 68 or char == 100 then -- D core_page_setDimensions() data_save() @@ -739,6 +778,7 @@ function core_key(char, keycode) end ----------- Boot sequence + label = computer.address() if not label then label = "" .. computer.address() @@ -759,7 +799,6 @@ for address, componentType in component.list() do ship = component.proxy(address) end end --- os.sleep(1) if not computer.address() and ship ~= nil then data_setName() @@ -768,7 +807,7 @@ end -- peripherals status function connections_page() ShowTitle(label .. " - Connections") - + WriteLn("") if ship == nil then SetColorDisabled() @@ -811,13 +850,13 @@ repeat if eventName == "key_down" then char = params[3] keycode = params[4] - if char == 88 or char == 120 then -- x for eXit + if char == 88 or char == 120 or keycode == 45 then -- x for eXit abort = true - elseif char == 48 or keycode == 11 then -- 0 + elseif char == 48 or keycode == 11 or keycode == 82 then -- 0 page = connections_page keyHandler = nil refresh = true - elseif char == 49 or keycode == 2 then -- 1 + elseif char == 49 or keycode == 2 or keycode == 79 then -- 1 page = core_page keyHandler = core_key refresh = true @@ -834,9 +873,15 @@ repeat -- func(unpack(params)) -- abort, refresh = false, false elseif eventName == "char" then - -- drop it + -- drop it elseif eventName == "key_up" then - -- drop it + -- drop it + elseif eventName == "touch" then + -- drop it + elseif eventName == "drop" then + -- drop it + elseif eventName == "drag" then + -- drop it elseif eventName == "interrupted" then abort = true elseif not common_event(eventName, params[3]) then @@ -846,6 +891,16 @@ repeat end until abort +-- exiting +if data.core_summon then + data.core_summon = false + data_save() +end + +if ship ~= nil then + ship.mode(0) +end + -- clear screens on exit SetMonitorColorFrontBack(0xFFFFFF, 0x000000) term.clear()