public synchronized void callMethod(int MethodIndex, Object[] Arguments) throws Exception { switch (ComputerMethod.values()[MethodIndex]) { case move: if (Arguments.length != 3) { throw (new Exception("usage: move('direction', true/false, true/false)")); } System.out.println(Arguments[0]); SetupMotion( ParseDirectionArgument(Arguments[0]), ParseBooleanArgument(Arguments[1], "simulation"), ParseBooleanArgument(Arguments[2], "anchoring")); break; case anchored_move: if (Arguments.length != 1) { throw (new Exception("usage: anchored_move('direction')")); } SetupMotion(ParseDirectionArgument(Arguments[0]), false, true); break; case check_anchored_move: if (Arguments.length != 1) { throw (new Exception("usage: check_anchored_move('direction')")); } SetupMotion(ParseDirectionArgument(Arguments[0]), true, true); break; case unanchored_move: if (Arguments.length != 1) { throw (new Exception("usage: unanchored_move('direction')")); } SetupMotion(ParseDirectionArgument(Arguments[0]), false, false); break; case check_unanchored_move: if (Arguments.length != 1) { throw (new Exception("usage: check_unanchored_move('direction')")); } SetupMotion(ParseDirectionArgument(Arguments[0]), true, false); break; default: throw (new Exception("no such command")); } Error = null; Obstructed = false; }
static { for (int Index = 0; Index < numMethods; Index++) { methodNames[Index] = ComputerMethod.values()[Index].name(); } }
@Optional.InterfaceList({ @Optional.Interface(iface = "li.cil.oc.api.network.SimpleComponent", modid = "OpenComputers"), @Optional.Interface(iface = "li.cil.oc.api.network.ManagedPeripheral", modid = "OpenComputers"), @Optional.Interface(iface = "dan200.computer.api.IPeripheral", modid = "ComputerCraft") }) public class CarriageControllerEntity extends CarriageDriveEntity implements IPeripheral, SimpleComponent, ManagedPeripheral { public enum ComputerMethod { move, anchored_move, check_anchored_move, unanchored_move, check_unanchored_move } public static final int numMethods = ComputerMethod.values().length; public static final String[] methodNames = new String[numMethods]; static { for (int Index = 0; Index < numMethods; Index++) { methodNames[Index] = ComputerMethod.values()[Index].name(); } } public static final Map<String, Integer> methodIds = new HashMap<String, Integer>(); static { for (int i = 0; i < numMethods; ++i) { methodIds.put(methodNames[i], i); } } public Object ThreadLockObject = new Object(); public boolean Simulating; public Directions MotionDirection; public CarriageMotionException Error; public boolean Obstructed; public int ObstructionX; public int ObstructionY; public int ObstructionZ; public Runnable delayedCall; @Override public void HandleToolUsage(int Side, boolean Sneaking) {} @Override public synchronized void updateEntity() { if (worldObj.isRemote) { return; } if (Stale) { HandleNeighbourBlockChange(); } if (MotionDirection == null) { return; } try { Move(); } catch (CarriageMotionException Error) { this.Error = Error; if (Error instanceof CarriageObstructionException) { Obstructed = true; ObstructionX = ((CarriageObstructionException) Error).X; ObstructionY = ((CarriageObstructionException) Error).Y; ObstructionZ = ((CarriageObstructionException) Error).Z; } } MotionDirection = null; if (delayedCall != null) { delayedCall.run(); delayedCall = null; } notify(); } public boolean Anchored; @Override public boolean Anchored() { return (Anchored); } public boolean ParseBooleanArgument(Object Argument, String Label) throws Exception { try { return ((Boolean) Argument); } catch (Throwable Throwable) { throw (new Exception("invalid " + Label + " flag")); } } public Directions ParseDirectionArgument(Object Argument) throws Exception { if (Argument instanceof Double) { try { return (Directions.values()[(int) Math.round((Double) Argument)]); } catch (Throwable Throwable) { throw (new Exception("direction index out of range")); } } try { String Direction = (String) Argument; if (Direction.equalsIgnoreCase("down") || Direction.equalsIgnoreCase("negy")) { return (Directions.NegY); } if (Direction.equalsIgnoreCase("up") || Direction.equalsIgnoreCase("posy")) { return (Directions.PosY); } if (Direction.equalsIgnoreCase("north") || Direction.equalsIgnoreCase("negz")) { return (Directions.NegZ); } if (Direction.equalsIgnoreCase("south") || Direction.equalsIgnoreCase("posz")) { return (Directions.PosZ); } if (Direction.equalsIgnoreCase("west") || Direction.equalsIgnoreCase("negx")) { return (Directions.NegX); } if (Direction.equalsIgnoreCase("east") || Direction.equalsIgnoreCase("posx")) { return (Directions.PosX); } } catch (Throwable Throwable) { throw (new Exception("Test")); } throw (new Exception("invalid direction")); } public void SetupMotion(Directions MotionDirection, boolean Simulating, boolean Anchored) { this.MotionDirection = MotionDirection; this.Simulating = Simulating; this.Anchored = Anchored; } public synchronized void callMethod(int MethodIndex, Object[] Arguments) throws Exception { switch (ComputerMethod.values()[MethodIndex]) { case move: if (Arguments.length != 3) { throw (new Exception("usage: move('direction', true/false, true/false)")); } System.out.println(Arguments[0]); SetupMotion( ParseDirectionArgument(Arguments[0]), ParseBooleanArgument(Arguments[1], "simulation"), ParseBooleanArgument(Arguments[2], "anchoring")); break; case anchored_move: if (Arguments.length != 1) { throw (new Exception("usage: anchored_move('direction')")); } SetupMotion(ParseDirectionArgument(Arguments[0]), false, true); break; case check_anchored_move: if (Arguments.length != 1) { throw (new Exception("usage: check_anchored_move('direction')")); } SetupMotion(ParseDirectionArgument(Arguments[0]), true, true); break; case unanchored_move: if (Arguments.length != 1) { throw (new Exception("usage: unanchored_move('direction')")); } SetupMotion(ParseDirectionArgument(Arguments[0]), false, false); break; case check_unanchored_move: if (Arguments.length != 1) { throw (new Exception("usage: check_unanchored_move('direction')")); } SetupMotion(ParseDirectionArgument(Arguments[0]), true, false); break; default: throw (new Exception("no such command")); } Error = null; Obstructed = false; } public void Move() throws CarriageMotionException { if (Active) { throw (new CarriageMotionException("controller already active")); } if (CarriageDirection == null) { throw (new CarriageMotionException( "no carriage or too many carriages attached to controller")); } CarriagePackage Package = PreparePackage(MotionDirection); if (Simulating) { return; } InitiateMotion(Package); } @Override public CarriagePackage GeneratePackage( CarriageEntity Carriage, Directions CarriageDirection, Directions MotionDirection) throws CarriageMotionException { CarriagePackage Package; if (Anchored) { if (MotionDirection == CarriageDirection) { throw (new CarriageMotionException( "cannot push carriage away from controller in anchored mode")); } if (MotionDirection == CarriageDirection.Opposite()) { throw (new CarriageMotionException( "cannot pull carriage into controller in anchored mode")); } Package = new CarriagePackage(this, Carriage, MotionDirection); Carriage.FillPackage(Package); if (Package.Body.contains(Package.DriveRecord)) { throw (new CarriageMotionException( "carriage is attempting to move controller while in anchored mode")); } if (Package.Body.contains(Package.DriveRecord.NextInDirection(MotionDirection.Opposite()))) { throw (new CarriageMotionException( "carriage is obstructed by controller while in anchored mode")); } } else { Package = new CarriagePackage(this, Carriage, MotionDirection); Package.AddBlock(Package.DriveRecord); if (MotionDirection != CarriageDirection) { Package.AddPotentialObstruction(Package.DriveRecord.NextInDirection(MotionDirection)); } Carriage.FillPackage(Package); } Package.Finalize(); return (Package); } // ComputerCraft @Optional.Method(modid = "ComputerCraft") @Override public String getType() { return ("RIM_CarriageController"); } @Optional.Method(modid = "ComputerCraft") @Override public boolean canAttachToSide(int Side) { return (true); } @Optional.Method(modid = "ComputerCraft") @Override public void attach(IComputerAccess Computer) {} @Optional.Method(modid = "ComputerCraft") @Override public void detach(IComputerAccess Computer) {} @Optional.Method(modid = "ComputerCraft") @Override public String[] getMethodNames() { return methodNames; } @Optional.Method(modid = "ComputerCraft") @Override public Object[] callMethod( IComputerAccess Computer, ILuaContext LuaContext, int MethodIndex, Object[] Arguments) throws Exception { callMethod(MethodIndex, Arguments); try { do { wait(); } while (MotionDirection != null); } catch (Throwable Throwable) { throw (new Exception(Throwable)); } if (Error == null) { return (new Object[] {true}); } if (!Obstructed) { return (new Object[] {false, Error.getMessage()}); } return (new Object[] {false, Error.getMessage(), ObstructionX, ObstructionY, ObstructionZ}); } // OpenComputers @Override @Optional.Method(modid = "OpenComputers") public String getComponentName() { // Convention for OC names is a) lower case, b) valid variable names, // so this can be used as `component.br_reactor.setActive(true)` e.g. return "carriage"; } @Override @Optional.Method(modid = "OpenComputers") public String[] methods() { return methodNames; } @Override @Optional.Method(modid = "OpenComputers") public Object[] invoke(final String method, final Context context, final Arguments args) throws Exception { final Object[] arguments = new Object[args.count()]; for (int i = 0; i < args.count(); ++i) { if (args.isString(i)) { arguments[i] = args.checkString(i); } else { arguments[i] = args.checkAny(i); } } final Integer methodId = methodIds.get(method); if (methodId == null) { throw new NoSuchMethodError(); } delayedCall = new Runnable() { @Override public void run() { if (Error == null) { // TODO The computer has already been saved when we get here // so we have to come up with some other way to tell the // computer that the command was a success *after* the move. // Possibly by saving a flag in this tile entity's nbt tag, // but I don't know how RiM saves the command block itself. // context.signal("carriage_moved", true); } else if (!Obstructed) { context.signal("carriage_moved", false, Error.getMessage()); } else { context.signal( "carriage_moved", false, Error.getMessage(), ObstructionX, ObstructionY, ObstructionZ); } } }; callMethod(methodId, arguments); return new Object[] {true}; } }