1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-15 19:55:42 +00:00

Merge pull request #491 from SquidDev-CC/ComputerCraft/feature/api-api

Provide an API for registering custom APIs
This commit is contained in:
SquidDev 2017-12-01 19:18:40 +00:00
commit add86ea100
24 changed files with 659 additions and 238 deletions

View File

@ -9,6 +9,7 @@ package dan200.computercraft;
import com.google.common.base.CaseFormat; import com.google.common.base.CaseFormat;
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.ILuaAPIFactory;
import dan200.computercraft.api.media.IMedia; import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.media.IMediaProvider; import dan200.computercraft.api.media.IMediaProvider;
import dan200.computercraft.api.network.IPacketNetwork; import dan200.computercraft.api.network.IPacketNetwork;
@ -82,10 +83,7 @@ import java.io.*;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
@ -251,6 +249,7 @@ public class ComputerCraft
private static List<IMediaProvider> mediaProviders = new ArrayList<>(); private static List<IMediaProvider> mediaProviders = new ArrayList<>();
private static List<ITurtlePermissionProvider> permissionProviders = new ArrayList<>(); private static List<ITurtlePermissionProvider> permissionProviders = new ArrayList<>();
private static final Map<String, IPocketUpgrade> pocketUpgrades = new HashMap<>(); private static final Map<String, IPocketUpgrade> pocketUpgrades = new HashMap<>();
private static final Set<ILuaAPIFactory> apiFactories = new LinkedHashSet<>();
// Implementation // Implementation
@Mod.Instance( value = ComputerCraft.MOD_ID ) @Mod.Instance( value = ComputerCraft.MOD_ID )
@ -673,6 +672,14 @@ public class ComputerCraft
} }
} }
public static void registerAPIFactory( ILuaAPIFactory provider )
{
if( provider != null )
{
apiFactories.add( provider );
}
}
public static IPeripheral getPeripheralAt( World world, BlockPos pos, EnumFacing side ) public static IPeripheral getPeripheralAt( World world, BlockPos pos, EnumFacing side )
{ {
// Try the handlers in order: // Try the handlers in order:
@ -800,6 +807,11 @@ public class ComputerCraft
return WirelessNetwork.getUniversal(); return WirelessNetwork.getUniversal();
} }
public static Iterable<ILuaAPIFactory> getAPIFactories()
{
return apiFactories;
}
public static int createUniqueNumberedSaveDir( World world, String parentSubPath ) public static int createUniqueNumberedSaveDir( World world, String parentSubPath )
{ {
return IDAssigner.getNextIDFromDirectory(new File(getWorldDir(world), parentSubPath)); return IDAssigner.getNextIDFromDirectory(new File(getWorldDir(world), parentSubPath));

View File

@ -8,6 +8,7 @@ package dan200.computercraft.api;
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.ILuaAPIFactory;
import dan200.computercraft.api.media.IMedia; import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.media.IMediaProvider; import dan200.computercraft.api.media.IMediaProvider;
import dan200.computercraft.api.network.IPacketNetwork; import dan200.computercraft.api.network.IPacketNetwork;
@ -311,6 +312,22 @@ public final class ComputerCraftAPI
return null; return null;
} }
public static void registerAPIFactory( @Nonnull ILuaAPIFactory upgrade )
{
findCC();
if( computerCraft_registerAPIFactory != null )
{
try
{
computerCraft_registerAPIFactory.invoke( null, upgrade );
}
catch( Exception e )
{
// It failed
}
}
}
// The functions below here are private, and are used to interface with the non-API ComputerCraft classes. // The functions below here are private, and are used to interface with the non-API ComputerCraft classes.
// Reflection is used here so you can develop your mod without decompiling ComputerCraft and including // Reflection is used here so you can develop your mod without decompiling ComputerCraft and including
// it in your solution, and so your mod won't crash if ComputerCraft is installed. // it in your solution, and so your mod won't crash if ComputerCraft is installed.
@ -354,6 +371,9 @@ public final class ComputerCraftAPI
} ); } );
computerCraft_getWirelessNetwork = findCCMethod( "getWirelessNetwork", new Class<?>[] { computerCraft_getWirelessNetwork = findCCMethod( "getWirelessNetwork", new Class<?>[] {
} ); } );
computerCraft_registerAPIFactory = findCCMethod( "registerAPIFactory", new Class<?>[] {
ILuaAPIFactory.class
} );
} catch( Exception e ) { } catch( Exception e ) {
System.out.println( "ComputerCraftAPI: ComputerCraft not found." ); System.out.println( "ComputerCraftAPI: ComputerCraft not found." );
} finally { } finally {
@ -390,4 +410,5 @@ public final class ComputerCraftAPI
private static Method computerCraft_registerPermissionProvider = null; private static Method computerCraft_registerPermissionProvider = null;
private static Method computerCraft_registerPocketUpgrade = null; private static Method computerCraft_registerPocketUpgrade = null;
private static Method computerCraft_getWirelessNetwork = null; private static Method computerCraft_getWirelessNetwork = null;
private static Method computerCraft_registerAPIFactory = null;
} }

View File

@ -0,0 +1,38 @@
package dan200.computercraft.api.filesystem;
import java.io.IOException;
/**
* Provides a mount of the entire computer's file system.
*
* This exists for use by various APIs - one should not attempt to mount it.
*/
public interface IFileSystem extends IWritableMount
{
/**
* Combine two paths together, reducing them into a normalised form.
*
* @param path The main path.
* @param child The path to append.
* @return The combined, normalised path.
*/
String combine( String path, String child );
/**
* Copy files from one location to another.
*
* @param from The location to copy from.
* @param to The location to copy to. This should not exist.
* @throws IOException If the copy failed.
*/
void copy( String from, String to ) throws IOException;
/**
* Move files from one location to another.
*
* @param from The location to move from.
* @param to The location to move to. This should not exist.
* @throws IOException If the move failed.
*/
void move( String from, String to ) throws IOException;
}

View File

@ -0,0 +1,29 @@
package dan200.computercraft.api.lua;
import dan200.computercraft.api.filesystem.IFileSystem;
import dan200.computercraft.api.peripheral.IComputerAccess;
import javax.annotation.Nullable;
/**
* An interface passed to {@link ILuaAPIFactory} in order to provide additional information
* about a computer.
*/
public interface IComputerSystem extends IComputerAccess
{
/**
* Get the file system for this computer.
*
* @return The computer's file system, or {@code null} if it is not initialised.
*/
@Nullable
IFileSystem getFileSystem();
/**
* Get the label for this computer
*
* @return This computer's label, or {@code null} if it is not set.
*/
@Nullable
String getLabel();
}

View File

@ -0,0 +1,47 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.lua;
import dan200.computercraft.api.ComputerCraftAPI;
/**
* Represents a {@link ILuaObject} which is stored as a global variable on computer startup.
*
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred
* to use peripherals to provide functionality to users.
*
* @see ILuaAPIFactory
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
*/
public interface ILuaAPI extends ILuaObject
{
/**
* Get the globals this API will be assigned to. This will override any other global, so you should
*
* @return A list of globals this API will be assigned to.
*/
String[] getNames();
/**
* Called when the computer is turned on.
*
* One should only interact with the file system.
*/
default void startup() { }
/**
* Called every time the computer is ticked. This can be used to process various.
*/
default void update() { }
/**
* Called when the computer is turned off or unloaded.
*
* This should reset the state of the object, disposing any remaining file handles, or other resources.
*/
default void shutdown() { }
}

View File

@ -0,0 +1,24 @@
package dan200.computercraft.api.lua;
import dan200.computercraft.api.ComputerCraftAPI;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Construct an {@link ILuaAPI} for a specific computer.
*
* @see ILuaAPI
* @see ComputerCraftAPI#registerAPIFactory(ILuaAPIFactory)
*/
public interface ILuaAPIFactory
{
/**
* Create a new API instance for a given computer.
*
* @param computer The computer this API is for.
* @return The created API, or {@code null} if one should not be injected.
*/
@Nullable
ILuaAPI create( @Nonnull IComputerSystem computer );
}

View File

@ -6,6 +6,7 @@
package dan200.computercraft.core.apis; package dan200.computercraft.core.apis;
import dan200.computercraft.api.lua.ILuaAPI;
import dan200.computercraft.api.lua.ILuaContext; import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaObject; import dan200.computercraft.api.lua.ILuaObject;
import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaException;
@ -100,21 +101,6 @@ public class BufferAPI implements ILuaAPI
}; };
} }
@Override
public void startup()
{
}
@Override
public void advance( double _dt )
{
}
@Override
public void shutdown()
{
}
@Nonnull @Nonnull
@Override @Override
public String[] getMethodNames() public String[] getMethodNames()

View File

@ -0,0 +1,155 @@
package dan200.computercraft.core.apis;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.core.filesystem.FileSystem;
import dan200.computercraft.core.filesystem.FileSystemException;
import javax.annotation.Nonnull;
import java.util.HashSet;
import java.util.Set;
public abstract class ComputerAccess implements IComputerAccess
{
private final IAPIEnvironment m_environment;
private final Set<String> m_mounts = new HashSet<>();
protected ComputerAccess( IAPIEnvironment m_environment )
{
this.m_environment = m_environment;
}
public void unmountAll()
{
FileSystem fileSystem = m_environment.getFileSystem();
for( String m_mount : m_mounts )
{
fileSystem.unmount( m_mount );
}
m_mounts.clear();
}
@Override
public String mount( @Nonnull String desiredLoc, @Nonnull IMount mount )
{
return mount( desiredLoc, mount, getAttachmentName() );
}
@Override
public synchronized String mount( @Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName )
{
// Mount the location
String location;
FileSystem fileSystem = m_environment.getFileSystem();
if( fileSystem == null )
{
throw new IllegalStateException( "File system has not been created" );
}
synchronized( fileSystem )
{
location = findFreeLocation( desiredLoc );
if( location != null )
{
try
{
fileSystem.mount( driveName, location, mount );
}
catch( FileSystemException ignored )
{
}
}
}
if( location != null )
{
m_mounts.add( location );
}
return location;
}
@Override
public String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount )
{
return mountWritable( desiredLoc, mount, getAttachmentName() );
}
@Override
public synchronized String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount, @Nonnull String driveName )
{
// Mount the location
String location;
FileSystem fileSystem = m_environment.getFileSystem();
if( fileSystem == null )
{
throw new IllegalStateException( "File system has not been created" );
}
synchronized( fileSystem )
{
location = findFreeLocation( desiredLoc );
if( location != null )
{
try
{
fileSystem.mountWritable( driveName, location, mount );
}
catch( FileSystemException ignored )
{
}
}
}
if( location != null )
{
m_mounts.add( location );
}
return location;
}
@Override
public void unmount( String location )
{
if( location != null )
{
if( !m_mounts.contains( location ) )
{
throw new RuntimeException( "You didn't mount this location" );
}
m_environment.getFileSystem().unmount( location );
m_mounts.remove( location );
}
}
@Override
public int getID()
{
return m_environment.getComputerID();
}
@Override
public void queueEvent( @Nonnull final String event, final Object[] arguments )
{
m_environment.queueEvent( event, arguments );
}
private String findFreeLocation( String desiredLoc )
{
try
{
FileSystem fileSystem = m_environment.getFileSystem();
if( !fileSystem.exists( desiredLoc ) )
{
return desiredLoc;
}
// We used to check foo2,foo3,foo4,etc here
// but the disk drive does this itself now
return null;
}
catch( FileSystemException e )
{
return null;
}
}
}

View File

@ -6,6 +6,7 @@
package dan200.computercraft.core.apis; package dan200.computercraft.core.apis;
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.apis.handles.BinaryInputHandle; import dan200.computercraft.core.apis.handles.BinaryInputHandle;
@ -48,11 +49,6 @@ public class FSAPI implements ILuaAPI
m_fileSystem = m_env.getFileSystem(); m_fileSystem = m_env.getFileSystem();
} }
@Override
public void advance( double _dt )
{
}
@Override @Override
public void shutdown( ) public void shutdown( )
{ {

View File

@ -7,6 +7,7 @@
package dan200.computercraft.core.apis; package dan200.computercraft.core.apis;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
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.apis.http.*; import dan200.computercraft.core.apis.http.*;
@ -43,12 +44,7 @@ public class HTTPAPI implements ILuaAPI
} }
@Override @Override
public void startup( ) public void update()
{
}
@Override
public void advance( double _dt )
{ {
// Wait for all of our http requests // Wait for all of our http requests
synchronized( m_httpTasks ) synchronized( m_httpTasks )

View File

@ -1,17 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.core.apis;
import dan200.computercraft.api.lua.ILuaObject;
public interface ILuaAPI extends ILuaObject
{
String[] getNames();
void startup(); // LT
void advance( double _dt ); // MT
void shutdown(); // LT
}

View File

@ -6,6 +6,7 @@
package dan200.computercraft.core.apis; package dan200.computercraft.core.apis;
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.shared.util.StringUtil; import dan200.computercraft.shared.util.StringUtil;
@ -102,7 +103,7 @@ public class OSAPI implements ILuaAPI
} }
@Override @Override
public void advance( double dt ) public void update()
{ {
synchronized( m_timers ) synchronized( m_timers )
{ {

View File

@ -8,24 +8,25 @@ package dan200.computercraft.core.apis;
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.ILuaContext; import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.computer.Computer; import dan200.computercraft.core.computer.Computer;
import dan200.computercraft.core.computer.ComputerThread; import dan200.computercraft.core.computer.ComputerThread;
import dan200.computercraft.core.computer.ITask; import dan200.computercraft.core.computer.ITask;
import dan200.computercraft.core.filesystem.FileSystem; import dan200.computercraft.core.filesystem.FileSystem;
import dan200.computercraft.core.filesystem.FileSystemException;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.*; import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import static dan200.computercraft.core.apis.ArgumentHelper.getString; import static dan200.computercraft.core.apis.ArgumentHelper.getString;
public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChangeListener public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChangeListener
{ {
private class PeripheralWrapper implements IComputerAccess private class PeripheralWrapper extends ComputerAccess
{ {
private final String m_side; private final String m_side;
private final IPeripheral m_peripheral; private final IPeripheral m_peripheral;
@ -35,10 +36,9 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
private Map<String, Integer> m_methodMap; private Map<String, Integer> m_methodMap;
private boolean m_attached; private boolean m_attached;
private Set<String> m_mounts;
public PeripheralWrapper( IPeripheral peripheral, String side ) public PeripheralWrapper( IPeripheral peripheral, String side )
{ {
super(m_environment);
m_side = side; m_side = side;
m_peripheral = peripheral; m_peripheral = peripheral;
m_attached = false; m_attached = false;
@ -54,8 +54,6 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
m_methodMap.put( m_methods[i], i ); m_methodMap.put( m_methods[i], i );
} }
} }
m_mounts = new HashSet<>();
} }
public IPeripheral getPeripheral() public IPeripheral getPeripheral()
@ -91,14 +89,11 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
synchronized( this ) synchronized( this )
{ {
m_attached = false;
// Unmount everything the detach function forgot to do // Unmount everything the detach function forgot to do
for( String m_mount : m_mounts ) unmountAll();
{
m_fileSystem.unmount( m_mount );
}
m_mounts.clear();
} }
m_attached = false;
} }
public Object[] call( ILuaContext context, String methodName, Object[] arguments ) throws LuaException, InterruptedException public Object[] call( ILuaContext context, String methodName, Object[] arguments ) throws LuaException, InterruptedException
@ -122,13 +117,6 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
} }
// IComputerAccess implementation // IComputerAccess implementation
@Override
public String mount( @Nonnull String desiredLoc, @Nonnull IMount mount )
{
return mount( desiredLoc, mount, m_side );
}
@Override @Override
public synchronized String mount( @Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName ) public synchronized String mount( @Nonnull String desiredLoc, @Nonnull IMount mount, @Nonnull String driveName )
{ {
@ -137,31 +125,7 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
throw new RuntimeException( "You are not attached to this Computer" ); throw new RuntimeException( "You are not attached to this Computer" );
} }
// Mount the location return super.mount( desiredLoc, mount, driveName );
String location;
synchronized( m_fileSystem )
{
location = findFreeLocation( desiredLoc );
if( location != null )
{
try {
m_fileSystem.mount( driveName, location, mount );
} catch( FileSystemException e ) {
// fail and return null
}
}
}
if( location != null )
{
m_mounts.add( location );
}
return location;
}
@Override
public String mountWritable( @Nonnull String desiredLoc, @Nonnull IWritableMount mount )
{
return mountWritable( desiredLoc, mount, m_side );
} }
@Override @Override
@ -172,68 +136,46 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
throw new RuntimeException( "You are not attached to this Computer" ); throw new RuntimeException( "You are not attached to this Computer" );
} }
// Mount the location return super.mountWritable( desiredLoc, mount, driveName );
String location;
synchronized( m_fileSystem )
{
location = findFreeLocation( desiredLoc );
if( location != null )
{
try {
m_fileSystem.mountWritable( driveName, location, mount );
} catch( FileSystemException e ) {
// fail and return null
}
}
}
if( location != null )
{
m_mounts.add( location );
}
return location;
} }
@Override @Override
public synchronized void unmount( String location ) public synchronized void unmount( String location )
{ {
if( !m_attached ) { if( !m_attached )
{
throw new RuntimeException( "You are not attached to this Computer" ); throw new RuntimeException( "You are not attached to this Computer" );
} }
if( location != null ) super.unmount( location );
{
if( !m_mounts.contains( location ) ) {
throw new RuntimeException( "You didn't mount this location" );
}
m_fileSystem.unmount( location );
m_mounts.remove( location );
}
} }
@Override @Override
public int getID() public int getID()
{ {
if( !m_attached ) { if( !m_attached )
{
throw new RuntimeException( "You are not attached to this Computer" ); throw new RuntimeException( "You are not attached to this Computer" );
} }
return m_environment.getComputerID(); return super.getID();
} }
@Override @Override
public void queueEvent( @Nonnull final String event, final Object[] arguments ) public void queueEvent( @Nonnull final String event, final Object[] arguments )
{ {
if( !m_attached ) { if( !m_attached )
{
throw new RuntimeException( "You are not attached to this Computer" ); throw new RuntimeException( "You are not attached to this Computer" );
} }
m_environment.queueEvent( event, arguments ); super.queueEvent( event, arguments );
} }
@Nonnull @Nonnull
@Override @Override
public String getAttachmentName() public String getAttachmentName()
{ {
if( !m_attached ) { if( !m_attached )
{
throw new RuntimeException( "You are not attached to this Computer" ); throw new RuntimeException( "You are not attached to this Computer" );
} }
return m_side; return m_side;
@ -356,11 +298,6 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
} }
} }
@Override
public void advance( double _dt )
{
}
@Override @Override
public void shutdown( ) public void shutdown( )
{ {
@ -504,25 +441,4 @@ public class PeripheralAPI implements ILuaAPI, IAPIEnvironment.IPeripheralChange
} }
return -1; return -1;
} }
private String findFreeLocation( String desiredLoc )
{
try
{
synchronized( m_fileSystem )
{
if( !m_fileSystem.exists( desiredLoc ) )
{
return desiredLoc;
}
// We used to check foo2,foo3,foo4,etc here
// but the disk drive does this itself now
return null;
}
}
catch( FileSystemException e )
{
return null;
}
}
} }

View File

@ -6,6 +6,7 @@
package dan200.computercraft.core.apis; package dan200.computercraft.core.apis;
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 dan200.computercraft.core.computer.Computer;
@ -33,21 +34,6 @@ public class RedstoneAPI implements ILuaAPI
}; };
} }
@Override
public void startup( )
{
}
@Override
public void advance( double _dt )
{
}
@Override
public void shutdown( )
{
}
@Nonnull @Nonnull
@Override @Override
public String[] getMethodNames() public String[] getMethodNames()

View File

@ -6,6 +6,7 @@
package dan200.computercraft.core.apis; package dan200.computercraft.core.apis;
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.IComputerEnvironment; import dan200.computercraft.core.computer.IComputerEnvironment;
@ -36,21 +37,6 @@ public class TermAPI implements ILuaAPI
}; };
} }
@Override
public void startup( )
{
}
@Override
public void advance( double _dt )
{
}
@Override
public void shutdown( )
{
}
@Nonnull @Nonnull
@Override @Override
public String[] getMethodNames() public String[] getMethodNames()

View File

@ -8,8 +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.*;
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;
@ -18,6 +20,8 @@ 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 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;
@ -174,6 +178,90 @@ public class Computer
} }
} }
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;
@ -371,7 +459,7 @@ public class Computer
{ {
for(ILuaAPI api : m_apis) for(ILuaAPI api : m_apis)
{ {
api.advance( _dt ); api.update();
} }
} }
} }
@ -615,6 +703,16 @@ public class Computer
{ {
m_apis.add( new HTTPAPI( m_apiEnvironment ) ); m_apis.add( new HTTPAPI( m_apiEnvironment ) );
} }
for( ILuaAPIFactory factory : ComputerCraft.getAPIFactories() )
{
ComputerSystem system = new ComputerSystem( m_apiEnvironment );
ILuaAPI api = factory.create( system );
if( api != null )
{
m_apis.add( api );
}
}
} }
private void initLua() private void initLua()
@ -790,7 +888,7 @@ public class Computer
// Shutdown our APIs // Shutdown our APIs
synchronized( m_apis ) synchronized( m_apis )
{ {
for(ILuaAPI api : m_apis) for( ILuaAPI api : m_apis )
{ {
api.shutdown(); api.shutdown();
} }

View File

@ -7,6 +7,7 @@
package dan200.computercraft.core.filesystem; package dan200.computercraft.core.filesystem;
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;
@ -290,6 +291,7 @@ public class FileSystem
} }
} }
private final FileSystemMount m_wrapper = new FileSystemMount( this );
private final Map<String, MountWrapper> m_mounts = new HashMap<>(); private final Map<String, MountWrapper> m_mounts = new HashMap<>();
private final Set<Closeable> m_openFiles = Collections.newSetFromMap( new WeakHashMap<Closeable, Boolean>() ); private final Set<Closeable> m_openFiles = Collections.newSetFromMap( new WeakHashMap<Closeable, Boolean>() );
@ -734,6 +736,11 @@ public class FileSystem
return match; return match;
} }
public IFileSystem getMountWrapper()
{
return m_wrapper;
}
private static String sanitizePath( String path ) private static String sanitizePath( String path )
{ {
return sanitizePath( path, false ); return sanitizePath( path, false );

View File

@ -0,0 +1,185 @@
package dan200.computercraft.core.filesystem;
import dan200.computercraft.api.filesystem.IFileSystem;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.List;
public class FileSystemMount implements IFileSystem
{
private final FileSystem m_filesystem;
public FileSystemMount( FileSystem m_filesystem )
{
this.m_filesystem = m_filesystem;
}
@Override
public void makeDirectory( @Nonnull String path ) throws IOException
{
try
{
m_filesystem.makeDir( path );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Override
public void delete( @Nonnull String path ) throws IOException
{
try
{
m_filesystem.delete( path );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Nonnull
@Override
public OutputStream openForWrite( @Nonnull String path ) throws IOException
{
try
{
return m_filesystem.openForWrite( path, false );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Nonnull
@Override
public OutputStream openForAppend( @Nonnull String path ) throws IOException
{
try
{
return m_filesystem.openForWrite( path, true );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Override
public long getRemainingSpace() throws IOException
{
try
{
return m_filesystem.getFreeSpace( "/" );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Override
public boolean exists( @Nonnull String path ) throws IOException
{
try
{
return m_filesystem.exists( path );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Override
public boolean isDirectory( @Nonnull String path ) throws IOException
{
try
{
return m_filesystem.exists( path );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Override
public void list( @Nonnull String path, @Nonnull List<String> contents ) throws IOException
{
try
{
Collections.addAll( contents, m_filesystem.list( path ) );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Override
public long getSize( @Nonnull String path ) throws IOException
{
try
{
return m_filesystem.getSize( path );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Nonnull
@Override
public InputStream openForRead( @Nonnull String path ) throws IOException
{
try
{
return m_filesystem.openForRead( path );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Override
public String combine( String path, String child )
{
return m_filesystem.combine( path, child );
}
@Override
public void copy( String from, String to ) throws IOException
{
try
{
m_filesystem.copy( from, to );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
@Override
public void move( String from, String to ) throws IOException
{
try
{
m_filesystem.move( from, to );
}
catch( FileSystemException e )
{
throw new IOException( e.getMessage() );
}
}
}

View File

@ -11,7 +11,7 @@ import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaObject; import dan200.computercraft.api.lua.ILuaObject;
import dan200.computercraft.api.lua.ILuaTask; import dan200.computercraft.api.lua.ILuaTask;
import dan200.computercraft.api.lua.LuaException; import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.core.apis.ILuaAPI; import dan200.computercraft.api.lua.ILuaAPI;
import dan200.computercraft.core.computer.Computer; import dan200.computercraft.core.computer.Computer;
import dan200.computercraft.core.computer.ITask; import dan200.computercraft.core.computer.ITask;
import dan200.computercraft.core.computer.MainThread; import dan200.computercraft.core.computer.MainThread;

View File

@ -5,7 +5,7 @@
*/ */
package dan200.computercraft.core.lua; package dan200.computercraft.core.lua;
import dan200.computercraft.core.apis.ILuaAPI; import dan200.computercraft.api.lua.ILuaAPI;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;

View File

@ -8,9 +8,9 @@ package dan200.computercraft.shared.computer.apis;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
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.apis.ILuaAPI;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer; import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.util.WorldUtil; import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -49,21 +49,6 @@ public class CommandAPI implements ILuaAPI
}; };
} }
@Override
public void startup()
{
}
@Override
public void advance( double dt )
{
}
@Override
public void shutdown()
{
}
@Nonnull @Nonnull
@Override @Override
public String[] getMethodNames() public String[] getMethodNames()

View File

@ -12,7 +12,7 @@ import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount; import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.peripheral.IPeripheral; import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.apis.IAPIEnvironment; import dan200.computercraft.core.apis.IAPIEnvironment;
import dan200.computercraft.core.apis.ILuaAPI; import dan200.computercraft.api.lua.ILuaAPI;
import dan200.computercraft.core.computer.Computer; import dan200.computercraft.core.computer.Computer;
import dan200.computercraft.core.computer.IComputerEnvironment; import dan200.computercraft.core.computer.IComputerEnvironment;
import dan200.computercraft.shared.common.ServerTerminal; import dan200.computercraft.shared.common.ServerTerminal;

View File

@ -7,10 +7,10 @@
package dan200.computercraft.shared.pocket.apis; package dan200.computercraft.shared.pocket.apis;
import dan200.computercraft.ComputerCraft; import dan200.computercraft.ComputerCraft;
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.api.pocket.IPocketUpgrade; import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.core.apis.ILuaAPI;
import dan200.computercraft.shared.pocket.core.PocketServerComputer; import dan200.computercraft.shared.pocket.core.PocketServerComputer;
import dan200.computercraft.shared.util.InventoryUtil; import dan200.computercraft.shared.util.InventoryUtil;
import dan200.computercraft.shared.util.WorldUtil; import dan200.computercraft.shared.util.WorldUtil;
@ -39,21 +39,6 @@ public class PocketAPI implements ILuaAPI
}; };
} }
@Override
public void startup()
{
}
@Override
public void advance( double dt )
{
}
@Override
public void shutdown()
{
}
@Nonnull @Nonnull
@Override @Override
public String[] getMethodNames() public String[] getMethodNames()

View File

@ -6,13 +6,13 @@
package dan200.computercraft.shared.turtle.apis; package dan200.computercraft.shared.turtle.apis;
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.api.turtle.ITurtleAccess; import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand; import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleSide; import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.core.apis.IAPIEnvironment; import dan200.computercraft.core.apis.IAPIEnvironment;
import dan200.computercraft.core.apis.ILuaAPI;
import dan200.computercraft.shared.turtle.core.*; import dan200.computercraft.shared.turtle.core.*;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -45,21 +45,6 @@ public class TurtleAPI implements ILuaAPI
}; };
} }
@Override
public void startup( )
{
}
@Override
public void advance( double _dt )
{
}
@Override
public void shutdown( )
{
}
@Nonnull @Nonnull
@Override @Override
public String[] getMethodNames() public String[] getMethodNames()