mirror of
				https://github.com/SquidDev-CC/CC-Tweaked
				synced 2025-10-31 05:33:00 +00:00 
			
		
		
		
	Handle managing computer inputs/outputs separatly
The Computer class currently has several resposiblities such as storing id/label, managing redstone/peirpherals, handling management of the computer (on/off/events) and updating the output. In order to simplify this a little bit, we move our IAPIEnvironment implementation into a separate file, and store all "world state" (redstone + peripherals) in there. While we still need to have some level of updating them within the main Computer instance, it's substantially simpler.
This commit is contained in:
		| @@ -14,20 +14,32 @@ import dan200.computercraft.core.filesystem.FileSystem; | |||||||
| import dan200.computercraft.core.terminal.Terminal; | import dan200.computercraft.core.terminal.Terminal; | ||||||
| import dan200.computercraft.core.tracking.TrackingField; | import dan200.computercraft.core.tracking.TrackingField; | ||||||
|  |  | ||||||
|  | import javax.annotation.Nonnull; | ||||||
|  | import javax.annotation.Nullable; | ||||||
|  |  | ||||||
| public interface IAPIEnvironment extends IComputerOwned | public interface IAPIEnvironment extends IComputerOwned | ||||||
| { | { | ||||||
|  |     String[] SIDE_NAMES = new String[] { | ||||||
|  |         "bottom", "top", "back", "front", "right", "left", | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     int SIDE_COUNT = 6; | ||||||
|  |  | ||||||
|     interface IPeripheralChangeListener |     interface IPeripheralChangeListener | ||||||
|     { |     { | ||||||
|         void onPeripheralChanged( int side, IPeripheral newPeripheral ); |         void onPeripheralChanged( int side, @Nullable IPeripheral newPeripheral ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Nonnull | ||||||
|     @Override |     @Override | ||||||
|     Computer getComputer(); |     Computer getComputer(); | ||||||
|  |  | ||||||
|     int getComputerID(); |     int getComputerID(); | ||||||
|  |  | ||||||
|  |     @Nonnull | ||||||
|     IComputerEnvironment getComputerEnvironment(); |     IComputerEnvironment getComputerEnvironment(); | ||||||
|  |  | ||||||
|  |     @Nonnull | ||||||
|     Terminal getTerminal(); |     Terminal getTerminal(); | ||||||
|  |  | ||||||
|     FileSystem getFileSystem(); |     FileSystem getFileSystem(); | ||||||
| @@ -50,17 +62,18 @@ public interface IAPIEnvironment extends IComputerOwned | |||||||
|  |  | ||||||
|     int getBundledInput( int side ); |     int getBundledInput( int side ); | ||||||
|  |  | ||||||
|     void setPeripheralChangeListener( IPeripheralChangeListener listener ); |     void setPeripheralChangeListener( @Nullable IPeripheralChangeListener listener ); | ||||||
|  |  | ||||||
|  |     @Nullable | ||||||
|     IPeripheral getPeripheral( int side ); |     IPeripheral getPeripheral( int side ); | ||||||
|  |  | ||||||
|     String getLabel(); |     String getLabel(); | ||||||
|  |  | ||||||
|     void setLabel( String label ); |     void setLabel( @Nullable String label ); | ||||||
|  |  | ||||||
|     void addTrackingChange( TrackingField field, long change ); |     void addTrackingChange( @Nonnull TrackingField field, long change ); | ||||||
|  |  | ||||||
|     default void addTrackingChange( TrackingField field ) |     default void addTrackingChange( @Nonnull TrackingField field ) | ||||||
|     { |     { | ||||||
|         addTrackingChange( field, 1 ); |         addTrackingChange( field, 1 ); | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -278,13 +278,13 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange | |||||||
|                 }, null ); |                 }, null ); | ||||||
|  |  | ||||||
|                 // Queue a detachment event |                 // Queue a detachment event | ||||||
|                 m_environment.queueEvent( "peripheral_detach", new Object[] { Computer.s_sideNames[side] } ); |                 m_environment.queueEvent( "peripheral_detach", new Object[] { IAPIEnvironment.SIDE_NAMES[side] } ); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             // Assign the new peripheral |             // Assign the new peripheral | ||||||
|             if( newPeripheral != null ) |             if( newPeripheral != null ) | ||||||
|             { |             { | ||||||
|                 m_peripherals[side] = new PeripheralWrapper( newPeripheral, Computer.s_sideNames[side] ); |                 m_peripherals[side] = new PeripheralWrapper( newPeripheral, IAPIEnvironment.SIDE_NAMES[side] ); | ||||||
|             } |             } | ||||||
|             else |             else | ||||||
|             { |             { | ||||||
| @@ -317,7 +317,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange | |||||||
|                 }, null ); |                 }, null ); | ||||||
|  |  | ||||||
|                 // Queue an attachment event |                 // Queue an attachment event | ||||||
|                 m_environment.queueEvent( "peripheral", new Object[] { Computer.s_sideNames[side] } ); |                 m_environment.queueEvent( "peripheral", new Object[] { IAPIEnvironment.SIDE_NAMES[side] } ); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @@ -483,9 +483,9 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange | |||||||
|     private int parseSide( Object[] args ) throws LuaException |     private int parseSide( Object[] args ) throws LuaException | ||||||
|     { |     { | ||||||
|         String side = getString( args, 0 ); |         String side = getString( args, 0 ); | ||||||
|         for( int n = 0; n < Computer.s_sideNames.length; n++ ) |         for( int n = 0; n < IAPIEnvironment.SIDE_NAMES.length; n++ ) | ||||||
|         { |         { | ||||||
|             if( side.equals( Computer.s_sideNames[n] ) ) |             if( side.equals( IAPIEnvironment.SIDE_NAMES[n] ) ) | ||||||
|             { |             { | ||||||
|                 return n; |                 return n; | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ package dan200.computercraft.core.apis; | |||||||
| import dan200.computercraft.api.lua.ILuaAPI; | import dan200.computercraft.api.lua.ILuaAPI; | ||||||
| import dan200.computercraft.api.lua.ILuaContext; | import dan200.computercraft.api.lua.ILuaContext; | ||||||
| import dan200.computercraft.api.lua.LuaException; | import dan200.computercraft.api.lua.LuaException; | ||||||
| import dan200.computercraft.core.computer.Computer; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; | import javax.annotation.Nonnull; | ||||||
| import java.util.HashMap; | import java.util.HashMap; | ||||||
| @@ -65,9 +64,9 @@ public class RedstoneAPI implements ILuaAPI | |||||||
|             { |             { | ||||||
|                 // getSides |                 // getSides | ||||||
|                 Map<Object, Object> table = new HashMap<>(); |                 Map<Object, Object> table = new HashMap<>(); | ||||||
|                 for( int i = 0; i < Computer.s_sideNames.length; i++ ) |                 for( int i = 0; i < IAPIEnvironment.SIDE_NAMES.length; i++ ) | ||||||
|                 { |                 { | ||||||
|                     table.put( i + 1, Computer.s_sideNames[i] ); |                     table.put( i + 1, IAPIEnvironment.SIDE_NAMES[i] ); | ||||||
|                 } |                 } | ||||||
|                 return new Object[] { table }; |                 return new Object[] { table }; | ||||||
|             } |             } | ||||||
| @@ -156,9 +155,9 @@ public class RedstoneAPI implements ILuaAPI | |||||||
|     private int parseSide( Object[] args ) throws LuaException |     private int parseSide( Object[] args ) throws LuaException | ||||||
|     { |     { | ||||||
|         String side = getString( args, 0 ); |         String side = getString( args, 0 ); | ||||||
|         for( int n = 0; n < Computer.s_sideNames.length; n++ ) |         for( int n = 0; n < IAPIEnvironment.SIDE_NAMES.length; n++ ) | ||||||
|         { |         { | ||||||
|             if( side.equals( Computer.s_sideNames[n] ) ) |             if( side.equals( IAPIEnvironment.SIDE_NAMES[n] ) ) | ||||||
|             { |             { | ||||||
|                 return n; |                 return n; | ||||||
|             } |             } | ||||||
|   | |||||||
| @@ -0,0 +1,68 @@ | |||||||
|  | /* | ||||||
|  |  * This file is part of ComputerCraft - http://www.computercraft.info | ||||||
|  |  * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. | ||||||
|  |  * Send enquiries to dratcliffe@gmail.com | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package dan200.computercraft.core.computer; | ||||||
|  |  | ||||||
|  | import dan200.computercraft.api.lua.ILuaAPI; | ||||||
|  | import dan200.computercraft.api.lua.ILuaContext; | ||||||
|  | import dan200.computercraft.api.lua.LuaException; | ||||||
|  |  | ||||||
|  | import javax.annotation.Nonnull; | ||||||
|  | import javax.annotation.Nullable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * A wrapper for {@link ILuaAPI}s which cleans up after a {@link ComputerSystem} when the computer is shutdown. | ||||||
|  |  */ | ||||||
|  | public class ApiWrapper implements ILuaAPI | ||||||
|  | { | ||||||
|  |     private final ILuaAPI delegate; | ||||||
|  |     private final ComputerSystem system; | ||||||
|  |  | ||||||
|  |     ApiWrapper( ILuaAPI delegate, ComputerSystem system ) | ||||||
|  |     { | ||||||
|  |         this.delegate = delegate; | ||||||
|  |         this.system = system; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String[] getNames() | ||||||
|  |     { | ||||||
|  |         return delegate.getNames(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void startup() | ||||||
|  |     { | ||||||
|  |         delegate.startup(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void update() | ||||||
|  |     { | ||||||
|  |         delegate.update(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void shutdown() | ||||||
|  |     { | ||||||
|  |         delegate.shutdown(); | ||||||
|  |         system.unmountAll(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Nonnull | ||||||
|  |     @Override | ||||||
|  |     public String[] getMethodNames() | ||||||
|  |     { | ||||||
|  |         return delegate.getMethodNames(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Nullable | ||||||
|  |     @Override | ||||||
|  |     public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException | ||||||
|  |     { | ||||||
|  |         return delegate.callMethod( context, method, arguments ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -8,11 +8,10 @@ package dan200.computercraft.core.computer; | |||||||
|  |  | ||||||
| import com.google.common.base.Objects; | import com.google.common.base.Objects; | ||||||
| import dan200.computercraft.ComputerCraft; | import dan200.computercraft.ComputerCraft; | ||||||
| import dan200.computercraft.api.filesystem.IFileSystem; |  | ||||||
| import dan200.computercraft.api.filesystem.IMount; | import dan200.computercraft.api.filesystem.IMount; | ||||||
| import dan200.computercraft.api.filesystem.IWritableMount; | import dan200.computercraft.api.filesystem.IWritableMount; | ||||||
| import dan200.computercraft.api.lua.ILuaAPI; | import dan200.computercraft.api.lua.ILuaAPI; | ||||||
| import dan200.computercraft.api.lua.*; | import dan200.computercraft.api.lua.ILuaAPIFactory; | ||||||
| import dan200.computercraft.api.peripheral.IPeripheral; | import dan200.computercraft.api.peripheral.IPeripheral; | ||||||
| import dan200.computercraft.core.apis.*; | import dan200.computercraft.core.apis.*; | ||||||
| import dan200.computercraft.core.filesystem.FileSystem; | import dan200.computercraft.core.filesystem.FileSystem; | ||||||
| @@ -20,11 +19,7 @@ import dan200.computercraft.core.filesystem.FileSystemException; | |||||||
| import dan200.computercraft.core.lua.CobaltLuaMachine; | import dan200.computercraft.core.lua.CobaltLuaMachine; | ||||||
| import dan200.computercraft.core.lua.ILuaMachine; | import dan200.computercraft.core.lua.ILuaMachine; | ||||||
| import dan200.computercraft.core.terminal.Terminal; | import dan200.computercraft.core.terminal.Terminal; | ||||||
| import dan200.computercraft.core.tracking.Tracking; |  | ||||||
| import dan200.computercraft.core.tracking.TrackingField; |  | ||||||
|  |  | ||||||
| import javax.annotation.Nonnull; |  | ||||||
| import javax.annotation.Nullable; |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.io.InputStream; | import java.io.InputStream; | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| @@ -32,10 +27,6 @@ import java.util.List; | |||||||
|  |  | ||||||
| public class Computer | public class Computer | ||||||
| { | { | ||||||
|     public static final String[] s_sideNames = new String[] { |  | ||||||
|         "bottom", "top", "back", "front", "right", "left", |  | ||||||
|     }; |  | ||||||
|  |  | ||||||
|     private enum State |     private enum State | ||||||
|     { |     { | ||||||
|         Off, |         Off, | ||||||
| @@ -44,319 +35,81 @@ public class Computer | |||||||
|         Stopping, |         Stopping, | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     private static class APIEnvironment implements IAPIEnvironment |  | ||||||
|     { |  | ||||||
|         private Computer m_computer; |  | ||||||
|         private IAPIEnvironment.IPeripheralChangeListener m_peripheralListener; |  | ||||||
|  |  | ||||||
|         public APIEnvironment( Computer computer ) |  | ||||||
|         { |  | ||||||
|             m_computer = computer; |  | ||||||
|             m_peripheralListener = null; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public Computer getComputer() |  | ||||||
|         { |  | ||||||
|             return m_computer; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public int getComputerID() |  | ||||||
|         { |  | ||||||
|             return m_computer.assignID(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public IComputerEnvironment getComputerEnvironment() |  | ||||||
|         { |  | ||||||
|             return m_computer.m_environment; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public Terminal getTerminal() |  | ||||||
|         { |  | ||||||
|             return m_computer.m_terminal; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public FileSystem getFileSystem() |  | ||||||
|         { |  | ||||||
|             return m_computer.m_fileSystem; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void shutdown() |  | ||||||
|         { |  | ||||||
|             m_computer.shutdown(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void reboot() |  | ||||||
|         { |  | ||||||
|             m_computer.reboot(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void queueEvent( String event, Object[] args ) |  | ||||||
|         { |  | ||||||
|             m_computer.queueEvent( event, args ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void setOutput( int side, int output ) |  | ||||||
|         { |  | ||||||
|             m_computer.setRedstoneOutput( side, output ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public int getOutput( int side ) |  | ||||||
|         { |  | ||||||
|             return m_computer.getInternalRedstoneOutput( side ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public int getInput( int side ) |  | ||||||
|         { |  | ||||||
|             return m_computer.getRedstoneInput( side ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void setBundledOutput( int side, int output ) |  | ||||||
|         { |  | ||||||
|             m_computer.setBundledRedstoneOutput( side, output ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public int getBundledOutput( int side ) |  | ||||||
|         { |  | ||||||
|             return m_computer.getInternalBundledRedstoneOutput( side ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public int getBundledInput( int side ) |  | ||||||
|         { |  | ||||||
|             return m_computer.getBundledRedstoneInput( side ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public IPeripheral getPeripheral( int side ) |  | ||||||
|         { |  | ||||||
|             synchronized( m_computer.m_peripherals ) |  | ||||||
|             { |  | ||||||
|                 return m_computer.m_peripherals[side]; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void setPeripheralChangeListener( IPeripheralChangeListener listener ) |  | ||||||
|         { |  | ||||||
|             synchronized( m_computer.m_peripherals ) |  | ||||||
|             { |  | ||||||
|                 m_peripheralListener = listener; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public String getLabel() |  | ||||||
|         { |  | ||||||
|             return m_computer.getLabel(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void setLabel( String label ) |  | ||||||
|         { |  | ||||||
|             m_computer.setLabel( label ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void addTrackingChange( TrackingField field, long change ) |  | ||||||
|         { |  | ||||||
|             Tracking.addValue( m_computer, field, change ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         public void onPeripheralChanged( int side, IPeripheral peripheral ) |  | ||||||
|         { |  | ||||||
|             synchronized( m_computer.m_peripherals ) |  | ||||||
|             { |  | ||||||
|                 if( m_peripheralListener != null ) |  | ||||||
|                 { |  | ||||||
|                     m_peripheralListener.onPeripheralChanged( side, peripheral ); |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static class ComputerSystem extends ComputerAccess implements IComputerSystem |  | ||||||
|     { |  | ||||||
|         private final IAPIEnvironment m_environment; |  | ||||||
|  |  | ||||||
|         private ComputerSystem( IAPIEnvironment m_environment ) |  | ||||||
|         { |  | ||||||
|             super( m_environment ); |  | ||||||
|             this.m_environment = m_environment; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Nonnull |  | ||||||
|         @Override |  | ||||||
|         public String getAttachmentName() |  | ||||||
|         { |  | ||||||
|             return "computer"; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Nullable |  | ||||||
|         @Override |  | ||||||
|         public IFileSystem getFileSystem() |  | ||||||
|         { |  | ||||||
|             FileSystem fs = m_environment.getFileSystem(); |  | ||||||
|             return fs == null ? null : fs.getMountWrapper(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Nullable |  | ||||||
|         @Override |  | ||||||
|         public String getLabel() |  | ||||||
|         { |  | ||||||
|             return m_environment.getLabel(); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static class APIWrapper implements ILuaAPI |  | ||||||
|     { |  | ||||||
|         private final ILuaAPI delegate; |  | ||||||
|         private final ComputerSystem system; |  | ||||||
|  |  | ||||||
|         private APIWrapper( ILuaAPI delegate, ComputerSystem system ) |  | ||||||
|         { |  | ||||||
|             this.delegate = delegate; |  | ||||||
|             this.system = system; |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public String[] getNames() |  | ||||||
|         { |  | ||||||
|             return delegate.getNames(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void startup() |  | ||||||
|         { |  | ||||||
|             delegate.startup(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void update() |  | ||||||
|         { |  | ||||||
|             delegate.update(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Override |  | ||||||
|         public void shutdown() |  | ||||||
|         { |  | ||||||
|             delegate.shutdown(); |  | ||||||
|             system.unmountAll(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Nonnull |  | ||||||
|         @Override |  | ||||||
|         public String[] getMethodNames() |  | ||||||
|         { |  | ||||||
|             return delegate.getMethodNames(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         @Nullable |  | ||||||
|         @Override |  | ||||||
|         public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException |  | ||||||
|         { |  | ||||||
|             return delegate.callMethod( context, method, arguments ); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static IMount s_romMount = null; |     private static IMount s_romMount = null; | ||||||
|  |  | ||||||
|     private int m_id; |     private int m_id; | ||||||
|     private String m_label; |     private String m_label = null; | ||||||
|     private final IComputerEnvironment m_environment; |     private final IComputerEnvironment m_environment; | ||||||
|  |  | ||||||
|     private int m_ticksSinceStart; |     private int m_ticksSinceStart = -1; | ||||||
|     private boolean m_startRequested; |     private boolean m_startRequested = false; | ||||||
|     private State m_state; |     private State m_state = State.Off; | ||||||
|     private boolean m_blinking; |     private boolean m_blinking = false; | ||||||
|  |  | ||||||
|     private ILuaMachine m_machine; |     private ILuaMachine m_machine = null; | ||||||
|     private final List<ILuaAPI> m_apis; |     private final List<ILuaAPI> m_apis = new ArrayList<>(); | ||||||
|     private final APIEnvironment m_apiEnvironment; |     private final Environment m_internalEnvironment = new Environment( this ); | ||||||
|  |  | ||||||
|     private final Terminal m_terminal; |     private final Terminal m_terminal; | ||||||
|     private FileSystem m_fileSystem; |     private FileSystem m_fileSystem = null; | ||||||
|     private IWritableMount m_rootMount; |     private IWritableMount m_rootMount = null; | ||||||
|  |  | ||||||
|     private final int[] m_internalOutput; |  | ||||||
|     private final int[] m_internalBundledOutput; |  | ||||||
|     private boolean m_internalOutputChanged; |  | ||||||
|  |  | ||||||
|     private final int[] m_externalOutput; |  | ||||||
|     private final int[] m_externalBundledOutput; |  | ||||||
|     private boolean m_externalOutputChanged; |     private boolean m_externalOutputChanged; | ||||||
|  |  | ||||||
|     private final int[] m_input; |  | ||||||
|     private final int[] m_bundledInput; |  | ||||||
|     private boolean m_inputChanged; |  | ||||||
|  |  | ||||||
|     private final IPeripheral[] m_peripherals; |  | ||||||
|  |  | ||||||
|     public Computer( IComputerEnvironment environment, Terminal terminal, int id ) |     public Computer( IComputerEnvironment environment, Terminal terminal, int id ) | ||||||
|     { |     { | ||||||
|  |         m_id = id; | ||||||
|  |         m_environment = environment; | ||||||
|  |         m_terminal = terminal; | ||||||
|  |  | ||||||
|  |         // Ensure the computer thread is running as required. | ||||||
|         ComputerThread.start(); |         ComputerThread.start(); | ||||||
|  |  | ||||||
|         m_id = id; |         // Add all default APIs to the loaded list. | ||||||
|         m_label = null; |         m_apis.add( new TermAPI( m_internalEnvironment ) ); | ||||||
|         m_environment = environment; |         m_apis.add( new RedstoneAPI( m_internalEnvironment ) ); | ||||||
|  |         m_apis.add( new FSAPI( m_internalEnvironment ) ); | ||||||
|  |         m_apis.add( new PeripheralAPI( m_internalEnvironment ) ); | ||||||
|  |         m_apis.add( new OSAPI( m_internalEnvironment ) ); | ||||||
|  |         if( ComputerCraft.http_enable ) m_apis.add( new HTTPAPI( m_internalEnvironment ) ); | ||||||
|  |  | ||||||
|         m_ticksSinceStart = -1; |         // Load in the API registered APIs. | ||||||
|         m_startRequested = false; |         for( ILuaAPIFactory factory : ApiFactories.getAll() ) | ||||||
|         m_state = State.Off; |  | ||||||
|         m_blinking = false; |  | ||||||
|  |  | ||||||
|         m_terminal = terminal; |  | ||||||
|         m_fileSystem = null; |  | ||||||
|  |  | ||||||
|         m_machine = null; |  | ||||||
|         m_apis = new ArrayList<>(); |  | ||||||
|         m_apiEnvironment = new APIEnvironment( this ); |  | ||||||
|  |  | ||||||
|         m_internalOutput = new int[6]; |  | ||||||
|         m_internalBundledOutput = new int[6]; |  | ||||||
|         m_internalOutputChanged = true; |  | ||||||
|  |  | ||||||
|         m_externalOutput = new int[6]; |  | ||||||
|         m_externalBundledOutput = new int[6]; |  | ||||||
|         m_externalOutputChanged = true; |  | ||||||
|  |  | ||||||
|         m_input = new int[6]; |  | ||||||
|         m_bundledInput = new int[6]; |  | ||||||
|         m_inputChanged = false; |  | ||||||
|  |  | ||||||
|         m_peripherals = new IPeripheral[6]; |  | ||||||
|         for( int i = 0; i < 6; i++ ) |  | ||||||
|         { |         { | ||||||
|             m_peripherals[i] = null; |             ComputerSystem system = new ComputerSystem( m_internalEnvironment ); | ||||||
|  |             ILuaAPI api = factory.create( system ); | ||||||
|  |             if( api != null ) m_apis.add( new ApiWrapper( api, system ) ); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|         m_rootMount = null; |     IComputerEnvironment getComputerEnvironment() | ||||||
|         createAPIs(); |     { | ||||||
|  |         return m_environment; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     FileSystem getFileSystem() | ||||||
|  |     { | ||||||
|  |         return m_fileSystem; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Terminal getTerminal() | ||||||
|  |     { | ||||||
|  |         return m_terminal; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public Environment getEnvironment() | ||||||
|  |     { | ||||||
|  |         return m_internalEnvironment; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public IAPIEnvironment getAPIEnvironment() |     public IAPIEnvironment getAPIEnvironment() | ||||||
|     { |     { | ||||||
|         return m_apiEnvironment; |         return m_internalEnvironment; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void turnOn() |     public void turnOn() | ||||||
|     { |     { | ||||||
|         if( m_state == State.Off ) |         if( m_state == State.Off ) m_startRequested = true; | ||||||
|         { |  | ||||||
|             m_startRequested = true; |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void shutdown() |     public void shutdown() | ||||||
| @@ -396,12 +149,9 @@ public class Computer | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void unload() |     public void unload() | ||||||
|     { |  | ||||||
|         synchronized( this ) |  | ||||||
|     { |     { | ||||||
|         stopComputer( false ); |         stopComputer( false ); | ||||||
|     } |     } | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public int getID() |     public int getID() | ||||||
|     { |     { | ||||||
| @@ -436,7 +186,7 @@ public class Computer | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void advance( double _dt ) |     public void advance() | ||||||
|     { |     { | ||||||
|         synchronized( this ) |         synchronized( this ) | ||||||
|         { |         { | ||||||
| @@ -453,57 +203,18 @@ public class Computer | |||||||
|  |  | ||||||
|             if( m_state == State.Running ) |             if( m_state == State.Running ) | ||||||
|             { |             { | ||||||
|                 // Fire the redstone event if our redstone input has changed |                 // Update the environment's internal state. | ||||||
|                 synchronized( m_input ) |                 m_internalEnvironment.update(); | ||||||
|                 { |  | ||||||
|                     if( m_inputChanged ) |  | ||||||
|                     { |  | ||||||
|                         queueEvent( "redstone", null ); |  | ||||||
|                         m_inputChanged = false; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 // Advance our APIs |                 // Advance our APIs | ||||||
|                 synchronized( m_apis ) |                 for( ILuaAPI api : m_apis ) api.update(); | ||||||
|                 { |  | ||||||
|                     for( ILuaAPI api : m_apis ) |  | ||||||
|                     { |  | ||||||
|                         api.update(); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         // Set outputchanged if the internal redstone has changed |         // Prepare to propagate the environment's output to the world. | ||||||
|         synchronized( m_internalOutput ) |         if( m_internalEnvironment.updateOutput() ) m_externalOutputChanged = true; | ||||||
|         { |  | ||||||
|             if( m_internalOutputChanged ) |  | ||||||
|             { |  | ||||||
|                 boolean changed = false; |  | ||||||
|                 for( int i = 0; i < 6; i++ ) |  | ||||||
|                 { |  | ||||||
|                     if( m_externalOutput[i] != m_internalOutput[i] ) |  | ||||||
|                     { |  | ||||||
|                         m_externalOutput[i] = m_internalOutput[i]; |  | ||||||
|                         changed = true; |  | ||||||
|                     } |  | ||||||
|                     if( m_externalBundledOutput[i] != m_internalBundledOutput[i] ) |  | ||||||
|                     { |  | ||||||
|                         m_externalBundledOutput[i] = m_internalBundledOutput[i]; |  | ||||||
|                         changed = true; |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|                 m_internalOutputChanged = false; |  | ||||||
|                 if( changed ) |  | ||||||
|                 { |  | ||||||
|                     m_externalOutputChanged = true; |  | ||||||
|                 } |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         // Set outputchanged if the terminal has changed from blinking to not |         // Set output changed if the terminal has changed from blinking to not | ||||||
|         synchronized( m_terminal ) |  | ||||||
|         { |  | ||||||
|         boolean blinking = |         boolean blinking = | ||||||
|             m_terminal.getCursorBlink() && |             m_terminal.getCursorBlink() && | ||||||
|                 m_terminal.getCursorX() >= 0 && m_terminal.getCursorX() < m_terminal.getWidth() && |                 m_terminal.getCursorX() >= 0 && m_terminal.getCursorX() < m_terminal.getWidth() && | ||||||
| @@ -515,7 +226,6 @@ public class Computer | |||||||
|             m_externalOutputChanged = true; |             m_externalOutputChanged = true; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public boolean pollAndResetChanged() |     public boolean pollAndResetChanged() | ||||||
|     { |     { | ||||||
| @@ -528,12 +238,9 @@ public class Computer | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     public boolean isBlinking() |     public boolean isBlinking() | ||||||
|     { |  | ||||||
|         synchronized( m_terminal ) |  | ||||||
|     { |     { | ||||||
|         return isOn() && m_blinking; |         return isOn() && m_blinking; | ||||||
|     } |     } | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public IWritableMount getRootMount() |     public IWritableMount getRootMount() | ||||||
|     { |     { | ||||||
| @@ -553,10 +260,7 @@ public class Computer | |||||||
|         try |         try | ||||||
|         { |         { | ||||||
|             m_fileSystem = new FileSystem( "hdd", getRootMount() ); |             m_fileSystem = new FileSystem( "hdd", getRootMount() ); | ||||||
|             if( s_romMount == null ) |             if( s_romMount == null ) s_romMount = m_environment.createResourceMount( "computercraft", "lua/rom" ); | ||||||
|             { |  | ||||||
|                 s_romMount = m_environment.createResourceMount( "computercraft", "lua/rom" ); |  | ||||||
|             } |  | ||||||
|             if( s_romMount != null ) |             if( s_romMount != null ) | ||||||
|             { |             { | ||||||
|                 m_fileSystem.mount( "rom", "rom", s_romMount ); |                 m_fileSystem.mount( "rom", "rom", s_romMount ); | ||||||
| @@ -571,104 +275,6 @@ public class Computer | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     // Redstone |  | ||||||
|  |  | ||||||
|     public int getRedstoneOutput( int side ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_internalOutput ) |  | ||||||
|         { |  | ||||||
|             return isOn() ? m_externalOutput[side] : 0; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private int getInternalRedstoneOutput( int side ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_internalOutput ) |  | ||||||
|         { |  | ||||||
|             return isOn() ? m_internalOutput[side] : 0; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void setRedstoneOutput( int side, int level ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_internalOutput ) |  | ||||||
|         { |  | ||||||
|             if( m_internalOutput[side] != level ) |  | ||||||
|             { |  | ||||||
|                 m_internalOutput[side] = level; |  | ||||||
|                 m_internalOutputChanged = true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void setRedstoneInput( int side, int level ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_input ) |  | ||||||
|         { |  | ||||||
|             if( m_input[side] != level ) |  | ||||||
|             { |  | ||||||
|                 m_input[side] = level; |  | ||||||
|                 m_inputChanged = true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private int getRedstoneInput( int side ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_input ) |  | ||||||
|         { |  | ||||||
|             return m_input[side]; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public int getBundledRedstoneOutput( int side ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_internalOutput ) |  | ||||||
|         { |  | ||||||
|             return isOn() ? m_externalBundledOutput[side] : 0; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private int getInternalBundledRedstoneOutput( int side ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_internalOutput ) |  | ||||||
|         { |  | ||||||
|             return isOn() ? m_internalBundledOutput[side] : 0; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void setBundledRedstoneOutput( int side, int combination ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_internalOutput ) |  | ||||||
|         { |  | ||||||
|             if( m_internalBundledOutput[side] != combination ) |  | ||||||
|             { |  | ||||||
|                 m_internalBundledOutput[side] = combination; |  | ||||||
|                 m_internalOutputChanged = true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void setBundledRedstoneInput( int side, int combination ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_input ) |  | ||||||
|         { |  | ||||||
|             if( m_bundledInput[side] != combination ) |  | ||||||
|             { |  | ||||||
|                 m_bundledInput[side] = combination; |  | ||||||
|                 m_inputChanged = true; |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private int getBundledRedstoneInput( int side ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_input ) |  | ||||||
|         { |  | ||||||
|             return m_bundledInput[side]; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Peripherals |     // Peripherals | ||||||
|  |  | ||||||
|     public void addAPI( ILuaAPI api ) |     public void addAPI( ILuaAPI api ) | ||||||
| @@ -676,57 +282,8 @@ public class Computer | |||||||
|         m_apis.add( api ); |         m_apis.add( api ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @SuppressWarnings( "deprecation" ) |  | ||||||
|     public void addAPI( dan200.computercraft.core.apis.ILuaAPI api ) |  | ||||||
|     { |  | ||||||
|         addAPI( (ILuaAPI) api ); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public void setPeripheral( int side, IPeripheral peripheral ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_peripherals ) |  | ||||||
|         { |  | ||||||
|             IPeripheral existing = m_peripherals[side]; |  | ||||||
|             if( (existing == null && peripheral != null) || |  | ||||||
|                 (existing != null && peripheral == null) || |  | ||||||
|                 (existing != null && !existing.equals( peripheral )) ) |  | ||||||
|             { |  | ||||||
|                 m_peripherals[side] = peripheral; |  | ||||||
|                 m_apiEnvironment.onPeripheralChanged( side, peripheral ); |  | ||||||
|             } |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     public IPeripheral getPeripheral( int side ) |  | ||||||
|     { |  | ||||||
|         synchronized( m_peripherals ) |  | ||||||
|         { |  | ||||||
|             return m_peripherals[side]; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     // Lua |     // Lua | ||||||
|  |  | ||||||
|     private void createAPIs() |  | ||||||
|     { |  | ||||||
|         m_apis.add( new TermAPI( m_apiEnvironment ) ); |  | ||||||
|         m_apis.add( new RedstoneAPI( m_apiEnvironment ) ); |  | ||||||
|         m_apis.add( new FSAPI( m_apiEnvironment ) ); |  | ||||||
|         m_apis.add( new PeripheralAPI( m_apiEnvironment ) ); |  | ||||||
|         m_apis.add( new OSAPI( m_apiEnvironment ) ); |  | ||||||
|         if( ComputerCraft.http_enable ) |  | ||||||
|         { |  | ||||||
|             m_apis.add( new HTTPAPI( m_apiEnvironment ) ); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         for( ILuaAPIFactory factory : ApiFactories.getAll() ) |  | ||||||
|         { |  | ||||||
|             ComputerSystem system = new ComputerSystem( m_apiEnvironment ); |  | ||||||
|             ILuaAPI api = factory.create( system ); |  | ||||||
|             if( api != null ) m_apis.add( api ); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private void initLua() |     private void initLua() | ||||||
|     { |     { | ||||||
|         // Create the lua machine |         // Create the lua machine | ||||||
| @@ -824,10 +381,7 @@ public class Computer | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     // Init terminal |                     // Init terminal | ||||||
|                     synchronized( m_terminal ) |  | ||||||
|                     { |  | ||||||
|                     m_terminal.reset(); |                     m_terminal.reset(); | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     // Init filesystem |                     // Init filesystem | ||||||
|                     if( !initFileSystem() ) |                     if( !initFileSystem() ) | ||||||
| @@ -919,11 +473,8 @@ public class Computer | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     if( m_machine != null ) |                     if( m_machine != null ) | ||||||
|                     { |  | ||||||
|                         synchronized( m_terminal ) |  | ||||||
|                     { |                     { | ||||||
|                         m_terminal.reset(); |                         m_terminal.reset(); | ||||||
|                         } |  | ||||||
|  |  | ||||||
|                         synchronized( m_machine ) |                         synchronized( m_machine ) | ||||||
|                         { |                         { | ||||||
| @@ -933,15 +484,7 @@ public class Computer | |||||||
|                     } |                     } | ||||||
|  |  | ||||||
|                     // Reset redstone output |                     // Reset redstone output | ||||||
|                     synchronized( m_internalOutput ) |                     m_internalEnvironment.resetOutput(); | ||||||
|                     { |  | ||||||
|                         for( int i = 0; i < 6; i++ ) |  | ||||||
|                         { |  | ||||||
|                             m_internalOutput[i] = 0; |  | ||||||
|                             m_internalBundledOutput[i] = 0; |  | ||||||
|                         } |  | ||||||
|                         m_internalOutputChanged = true; |  | ||||||
|                     } |  | ||||||
|  |  | ||||||
|                     m_state = State.Off; |                     m_state = State.Off; | ||||||
|                     m_externalOutputChanged = true; |                     m_externalOutputChanged = true; | ||||||
| @@ -1002,4 +545,23 @@ public class Computer | |||||||
|  |  | ||||||
|         ComputerThread.queueTask( task, computer ); |         ComputerThread.queueTask( task, computer ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     @Deprecated | ||||||
|  |     public void setPeripheral( int side, IPeripheral peripheral ) | ||||||
|  |     { | ||||||
|  |         m_internalEnvironment.setPeripheral( side, peripheral ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Deprecated | ||||||
|  |     public void addAPI( dan200.computercraft.core.apis.ILuaAPI api ) | ||||||
|  |     { | ||||||
|  |         addAPI( (ILuaAPI) api ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Deprecated | ||||||
|  |     @SuppressWarnings( "unused" ) | ||||||
|  |     public void advance( double dt ) | ||||||
|  |     { | ||||||
|  |         advance(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -0,0 +1,58 @@ | |||||||
|  | /* | ||||||
|  |  * This file is part of ComputerCraft - http://www.computercraft.info | ||||||
|  |  * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. | ||||||
|  |  * Send enquiries to dratcliffe@gmail.com | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package dan200.computercraft.core.computer; | ||||||
|  |  | ||||||
|  | import dan200.computercraft.api.filesystem.IFileSystem; | ||||||
|  | import dan200.computercraft.api.lua.IComputerSystem; | ||||||
|  | import dan200.computercraft.api.lua.ILuaAPIFactory; | ||||||
|  | import dan200.computercraft.api.peripheral.IComputerAccess; | ||||||
|  | import dan200.computercraft.core.apis.ComputerAccess; | ||||||
|  | import dan200.computercraft.core.apis.IAPIEnvironment; | ||||||
|  | import dan200.computercraft.core.filesystem.FileSystem; | ||||||
|  |  | ||||||
|  | import javax.annotation.Nonnull; | ||||||
|  | import javax.annotation.Nullable; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Implementation of {@link IComputerAccess}/{@link IComputerSystem} for external APIs. | ||||||
|  |  * | ||||||
|  |  * @see dan200.computercraft.api.ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory) | ||||||
|  |  * @see ILuaAPIFactory | ||||||
|  |  * @see ApiWrapper | ||||||
|  |  */ | ||||||
|  | public class ComputerSystem extends ComputerAccess implements IComputerSystem | ||||||
|  | { | ||||||
|  |     private final IAPIEnvironment m_environment; | ||||||
|  |  | ||||||
|  |     ComputerSystem( IAPIEnvironment m_environment ) | ||||||
|  |     { | ||||||
|  |         super( m_environment ); | ||||||
|  |         this.m_environment = m_environment; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Nonnull | ||||||
|  |     @Override | ||||||
|  |     public String getAttachmentName() | ||||||
|  |     { | ||||||
|  |         return "computer"; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Nullable | ||||||
|  |     @Override | ||||||
|  |     public IFileSystem getFileSystem() | ||||||
|  |     { | ||||||
|  |         FileSystem fs = m_environment.getFileSystem(); | ||||||
|  |         return fs == null ? null : fs.getMountWrapper(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Nullable | ||||||
|  |     @Override | ||||||
|  |     public String getLabel() | ||||||
|  |     { | ||||||
|  |         return m_environment.getLabel(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -0,0 +1,306 @@ | |||||||
|  | /* | ||||||
|  |  * This file is part of ComputerCraft - http://www.computercraft.info | ||||||
|  |  * Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission. | ||||||
|  |  * Send enquiries to dratcliffe@gmail.com | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | package dan200.computercraft.core.computer; | ||||||
|  |  | ||||||
|  | import dan200.computercraft.api.peripheral.IPeripheral; | ||||||
|  | import dan200.computercraft.core.apis.IAPIEnvironment; | ||||||
|  | import dan200.computercraft.core.filesystem.FileSystem; | ||||||
|  | import dan200.computercraft.core.terminal.Terminal; | ||||||
|  | import dan200.computercraft.core.tracking.Tracking; | ||||||
|  | import dan200.computercraft.core.tracking.TrackingField; | ||||||
|  |  | ||||||
|  | import javax.annotation.Nonnull; | ||||||
|  | import java.util.Arrays; | ||||||
|  |  | ||||||
|  | /** | ||||||
|  |  * Represents the "environment" that a {@link Computer} exists in. | ||||||
|  |  * | ||||||
|  |  * This handles storing and updating of peripherals and redstone. | ||||||
|  |  * | ||||||
|  |  * <h2>Redstone</h2> | ||||||
|  |  * We holds three kinds of arrays for redstone, in normal and bundled versions: | ||||||
|  |  * <ul> | ||||||
|  |  * <li>{@link #internalOutput} is the redstone output which the computer has currently set. This is read on both | ||||||
|  |  * threads, and written on the computer thread.</li> | ||||||
|  |  * <li>{@link #externalOutput} is the redstone output currently propagated to the world. This is only read and written | ||||||
|  |  * on the main thread.</li> | ||||||
|  |  * <li>{@link #input} is the redstone input from external sources. This is read on both threads, and written on the main | ||||||
|  |  * thread.</li> | ||||||
|  |  * </ul> | ||||||
|  |  * | ||||||
|  |  * <h2>Peripheral</h2> | ||||||
|  |  * We also keep track of peripherals. These are read on both threads, and only written on the main thread. | ||||||
|  |  */ | ||||||
|  | public final class Environment implements IAPIEnvironment | ||||||
|  | { | ||||||
|  |     private final Computer computer; | ||||||
|  |  | ||||||
|  |     private boolean internalOutputChanged = false; | ||||||
|  |     private final int[] internalOutput = new int[SIDE_COUNT]; | ||||||
|  |     private final int[] internalBundledOutput = new int[SIDE_COUNT]; | ||||||
|  |  | ||||||
|  |     private final int[] externalOutput = new int[SIDE_COUNT]; | ||||||
|  |     private final int[] externalBundledOutput = new int[SIDE_COUNT]; | ||||||
|  |  | ||||||
|  |     private boolean inputChanged = false; | ||||||
|  |     private final int[] input = new int[SIDE_COUNT]; | ||||||
|  |     private final int[] bundledInput = new int[SIDE_COUNT]; | ||||||
|  |  | ||||||
|  |     private final IPeripheral[] peripherals = new IPeripheral[SIDE_COUNT]; | ||||||
|  |     private IPeripheralChangeListener peripheralListener = null; | ||||||
|  |  | ||||||
|  |     Environment( Computer computer ) | ||||||
|  |     { | ||||||
|  |         this.computer = computer; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Nonnull | ||||||
|  |     @Override | ||||||
|  |     public Computer getComputer() | ||||||
|  |     { | ||||||
|  |         return computer; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public int getComputerID() | ||||||
|  |     { | ||||||
|  |         return computer.assignID(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Nonnull | ||||||
|  |     @Override | ||||||
|  |     public IComputerEnvironment getComputerEnvironment() | ||||||
|  |     { | ||||||
|  |         return computer.getComputerEnvironment(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Nonnull | ||||||
|  |     @Override | ||||||
|  |     public Terminal getTerminal() | ||||||
|  |     { | ||||||
|  |         return computer.getTerminal(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public FileSystem getFileSystem() | ||||||
|  |     { | ||||||
|  |         return computer.getFileSystem(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void shutdown() | ||||||
|  |     { | ||||||
|  |         computer.shutdown(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void reboot() | ||||||
|  |     { | ||||||
|  |         computer.reboot(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void queueEvent( String event, Object[] args ) | ||||||
|  |     { | ||||||
|  |         computer.queueEvent( event, args ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public int getInput( int side ) | ||||||
|  |     { | ||||||
|  |         return input[side]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public int getBundledInput( int side ) | ||||||
|  |     { | ||||||
|  |         return bundledInput[side]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void setOutput( int side, int output ) | ||||||
|  |     { | ||||||
|  |         synchronized( internalOutput ) | ||||||
|  |         { | ||||||
|  |             if( internalOutput[side] != output ) | ||||||
|  |             { | ||||||
|  |                 internalOutput[side] = output; | ||||||
|  |                 internalOutputChanged = true; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public int getOutput( int side ) | ||||||
|  |     { | ||||||
|  |         synchronized( internalOutput ) | ||||||
|  |         { | ||||||
|  |             return computer.isOn() ? internalOutput[side] : 0; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void setBundledOutput( int side, int output ) | ||||||
|  |     { | ||||||
|  |         synchronized( internalOutput ) | ||||||
|  |         { | ||||||
|  |             if( internalBundledOutput[side] != output ) | ||||||
|  |             { | ||||||
|  |                 internalBundledOutput[side] = output; | ||||||
|  |                 internalOutputChanged = true; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public int getBundledOutput( int side ) | ||||||
|  |     { | ||||||
|  |         synchronized( internalOutput ) | ||||||
|  |         { | ||||||
|  |             return computer.isOn() ? internalBundledOutput[side] : 0; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public int getExternalRedstoneOutput( int side ) | ||||||
|  |     { | ||||||
|  |         return computer.isOn() ? externalOutput[side] : 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public int getExternalBundledRedstoneOutput( int side ) | ||||||
|  |     { | ||||||
|  |         return computer.isOn() ? externalBundledOutput[side] : 0; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setRedstoneInput( int side, int level ) | ||||||
|  |     { | ||||||
|  |         if( input[side] != level ) | ||||||
|  |         { | ||||||
|  |             input[side] = level; | ||||||
|  |             inputChanged = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setBundledRedstoneInput( int side, int combination ) | ||||||
|  |     { | ||||||
|  |         if( bundledInput[side] != combination ) | ||||||
|  |         { | ||||||
|  |             bundledInput[side] = combination; | ||||||
|  |             inputChanged = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Called on the main thread to update the internal state of the computer. | ||||||
|  |      * | ||||||
|  |      * This just queues a {@code redstone} event if the input has changed. | ||||||
|  |      */ | ||||||
|  |     void update() | ||||||
|  |     { | ||||||
|  |         if( inputChanged ) | ||||||
|  |         { | ||||||
|  |             inputChanged = false; | ||||||
|  |             queueEvent( "redstone", null ); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     /** | ||||||
|  |      * Called on the main thread to propagate the internal outputs to the external ones. | ||||||
|  |      * | ||||||
|  |      * @return If the outputs have changed. | ||||||
|  |      */ | ||||||
|  |     boolean updateOutput() | ||||||
|  |     { | ||||||
|  |         // Set outputchanged if the internal redstone has changed | ||||||
|  |         synchronized( internalOutput ) | ||||||
|  |         { | ||||||
|  |             if( !internalOutputChanged ) return false; | ||||||
|  |  | ||||||
|  |             boolean changed = false; | ||||||
|  |  | ||||||
|  |             for( int i = 0; i < SIDE_COUNT; i++ ) | ||||||
|  |             { | ||||||
|  |                 if( externalOutput[i] != internalOutput[i] ) | ||||||
|  |                 { | ||||||
|  |                     externalOutput[i] = internalOutput[i]; | ||||||
|  |                     changed = true; | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 if( externalBundledOutput[i] != internalBundledOutput[i] ) | ||||||
|  |                 { | ||||||
|  |                     externalBundledOutput[i] = internalBundledOutput[i]; | ||||||
|  |                     changed = true; | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             internalOutputChanged = false; | ||||||
|  |  | ||||||
|  |             return changed; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void resetOutput() | ||||||
|  |     { | ||||||
|  |         // Reset redstone output | ||||||
|  |         synchronized( internalOutput ) | ||||||
|  |         { | ||||||
|  |             Arrays.fill( internalOutput, 0 ); | ||||||
|  |             Arrays.fill( internalBundledOutput, 0 ); | ||||||
|  |             internalOutputChanged = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public IPeripheral getPeripheral( int side ) | ||||||
|  |     { | ||||||
|  |         synchronized( peripherals ) | ||||||
|  |         { | ||||||
|  |             return peripherals[side]; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public void setPeripheral( int side, IPeripheral peripheral ) | ||||||
|  |     { | ||||||
|  |         synchronized( peripherals ) | ||||||
|  |         { | ||||||
|  |             IPeripheral existing = peripherals[side]; | ||||||
|  |             if( (existing == null && peripheral != null) || | ||||||
|  |                 (existing != null && peripheral == null) || | ||||||
|  |                 (existing != null && !existing.equals( peripheral )) ) | ||||||
|  |             { | ||||||
|  |                 peripherals[side] = peripheral; | ||||||
|  |                 if( peripheralListener != null ) peripheralListener.onPeripheralChanged( side, peripheral ); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void setPeripheralChangeListener( IPeripheralChangeListener listener ) | ||||||
|  |     { | ||||||
|  |         synchronized( peripherals ) | ||||||
|  |         { | ||||||
|  |             peripheralListener = listener; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public String getLabel() | ||||||
|  |     { | ||||||
|  |         return computer.getLabel(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void setLabel( String label ) | ||||||
|  |     { | ||||||
|  |         computer.setLabel( label ); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     @Override | ||||||
|  |     public void addTrackingChange( @Nonnull TrackingField field, long change ) | ||||||
|  |     { | ||||||
|  |         Tracking.addValue( computer, field, change ); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -9,6 +9,7 @@ package dan200.computercraft.shared.command; | |||||||
| import com.google.common.collect.Sets; | import com.google.common.collect.Sets; | ||||||
| import dan200.computercraft.ComputerCraft; | import dan200.computercraft.ComputerCraft; | ||||||
| import dan200.computercraft.api.peripheral.IPeripheral; | import dan200.computercraft.api.peripheral.IPeripheral; | ||||||
|  | import dan200.computercraft.core.apis.IAPIEnvironment; | ||||||
| import dan200.computercraft.core.computer.Computer; | import dan200.computercraft.core.computer.Computer; | ||||||
| import dan200.computercraft.core.tracking.ComputerTracker; | import dan200.computercraft.core.tracking.ComputerTracker; | ||||||
| import dan200.computercraft.core.tracking.Tracking; | import dan200.computercraft.core.tracking.Tracking; | ||||||
| @@ -126,7 +127,7 @@ public final class CommandComputerCraft extends CommandDelegate | |||||||
|                         IPeripheral peripheral = computer.getPeripheral( i ); |                         IPeripheral peripheral = computer.getPeripheral( i ); | ||||||
|                         if( peripheral != null ) |                         if( peripheral != null ) | ||||||
|                         { |                         { | ||||||
|                             table.row( header( "Peripheral " + Computer.s_sideNames[i] ), text( peripheral.getType() ) ); |                             table.row( header( "Peripheral " + IAPIEnvironment.SIDE_NAMES[i] ), text( peripheral.getType() ) ); | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -51,6 +51,7 @@ public abstract class BlockGeneric extends Block implements ITileEntityProvider | |||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     @Deprecated |     @Deprecated | ||||||
|  |     @SuppressWarnings( "deprecation" ) | ||||||
|     public final void neighborChanged( IBlockState state, World world, BlockPos pos, Block block, BlockPos neighbour ) |     public final void neighborChanged( IBlockState state, World world, BlockPos pos, Block block, BlockPos neighbour ) | ||||||
|     { |     { | ||||||
|         TileEntity tile = world.getTileEntity( pos ); |         TileEntity tile = world.getTileEntity( pos ); | ||||||
|   | |||||||
| @@ -105,7 +105,7 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput | |||||||
|     public void update() |     public void update() | ||||||
|     { |     { | ||||||
|         super.update(); |         super.update(); | ||||||
|         m_computer.advance( 0.05 ); |         m_computer.advance(); | ||||||
|  |  | ||||||
|         m_changedLastFrame = m_computer.pollAndResetChanged() || m_changed; |         m_changedLastFrame = m_computer.pollAndResetChanged() || m_changed; | ||||||
|         m_changed = false; |         m_changed = false; | ||||||
| @@ -283,22 +283,22 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput | |||||||
|  |  | ||||||
|     public int getRedstoneOutput( int side ) |     public int getRedstoneOutput( int side ) | ||||||
|     { |     { | ||||||
|         return m_computer.getRedstoneOutput( side ); |         return m_computer.getEnvironment().getExternalRedstoneOutput( side ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void setRedstoneInput( int side, int level ) |     public void setRedstoneInput( int side, int level ) | ||||||
|     { |     { | ||||||
|         m_computer.setRedstoneInput( side, level ); |         m_computer.getEnvironment().setRedstoneInput( side, level ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public int getBundledRedstoneOutput( int side ) |     public int getBundledRedstoneOutput( int side ) | ||||||
|     { |     { | ||||||
|         return m_computer.getBundledRedstoneOutput( side ); |         return m_computer.getEnvironment().getExternalBundledRedstoneOutput( side ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void setBundledRedstoneInput( int side, int combination ) |     public void setBundledRedstoneInput( int side, int combination ) | ||||||
|     { |     { | ||||||
|         m_computer.setBundledRedstoneInput( side, combination ); |         m_computer.getEnvironment().setBundledRedstoneInput( side, combination ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void addAPI( ILuaAPI api ) |     public void addAPI( ILuaAPI api ) | ||||||
| @@ -306,7 +306,7 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput | |||||||
|         m_computer.addAPI( api ); |         m_computer.addAPI( api ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @SuppressWarnings( "deprecation" ) |     @Deprecated | ||||||
|     public void addAPI( dan200.computercraft.core.apis.ILuaAPI api ) |     public void addAPI( dan200.computercraft.core.apis.ILuaAPI api ) | ||||||
|     { |     { | ||||||
|         m_computer.addAPI( api ); |         m_computer.addAPI( api ); | ||||||
| @@ -314,12 +314,12 @@ public class ServerComputer extends ServerTerminal implements IComputer, IComput | |||||||
|  |  | ||||||
|     public void setPeripheral( int side, IPeripheral peripheral ) |     public void setPeripheral( int side, IPeripheral peripheral ) | ||||||
|     { |     { | ||||||
|         m_computer.setPeripheral( side, peripheral ); |         m_computer.getEnvironment().setPeripheral( side, peripheral ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public IPeripheral getPeripheral( int side ) |     public IPeripheral getPeripheral( int side ) | ||||||
|     { |     { | ||||||
|         return m_computer.getPeripheral( side ); |         return m_computer.getEnvironment().getPeripheral( side ); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public void setLabel( String label ) |     public void setLabel( String label ) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 SquidDev
					SquidDev