From 696c7d3da5664f057a23625b13d5f06e6fc5849f Mon Sep 17 00:00:00 2001 From: LemADEC Date: Sun, 13 Mar 2016 21:17:09 +0100 Subject: [PATCH] Refactored Jump interfaces Added diagonal and rotation jumps support Added fine movement in hyperspace dimension Updated CC ship default LUA to match its OC counterpart Removed ship size impact on interfaces Improved ship dimension update to be more tolerant --- src/main/java/cr0s/warpdrive/EntityJump.java | 285 ++-- .../movement/TileEntityShipController.java | 204 ++- .../block/movement/TileEntityShipCore.java | 146 +- .../java/cr0s/warpdrive/data/JumpBlock.java | 48 +- .../java/cr0s/warpdrive/data/JumpShip.java | 1 - .../java/cr0s/warpdrive/data/VectorI.java | 7 + .../warpdriveShipController/startup | 1233 +++++++++++------ .../warpdriveShipController/autorun.lua | 361 +++-- 8 files changed, 1419 insertions(+), 866 deletions(-) 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()