added cc 1.5 api back and added backwards compatibility so we now support cc 1.5 and 1.6

applying max packet size for packets sent through a switch or access point from cc
access point returns true for isWireless in the cc api now
This commit is contained in:
Florian Nücke 2014-03-30 21:08:46 +02:00
parent 43acfd083b
commit fc0150b9cc
37 changed files with 1527 additions and 138 deletions

View File

@ -0,0 +1,163 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computer.api;
import java.lang.reflect.Method;
import net.minecraft.world.World;
/**
* The static entry point to the ComputerCraft API.
* Members in this class must be called after mod_ComputerCraft has been initialised,
* but may be called before it is fully loaded.
*/
public class ComputerCraftAPI
{
/**
* Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.<br>
* Use in conjuction with createSaveDirMount() to create a unique place for your peripherals or media items to store files.<br>
* @param world The world for which the save dir should be created. This should be the serverside world object.
* @param parentSubPath The folder path within the save directory where the new directory should be created. eg: "computer/disk"
* @return The numerical value of the name of the new folder, or -1 if the folder could not be created for some reason.<br>
* eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now available for writing.
* @see #createSaveDirMount(World, String)
*/
public static int createUniqueNumberedSaveDir( World world, String parentSubPath )
{
findCC();
if( computerCraft_createUniqueNumberedSaveDir != null )
{
try {
return ((Integer)computerCraft_createUniqueNumberedSaveDir.invoke( null, world, parentSubPath )).intValue();
} catch (Exception e){
// It failed
}
}
return -1;
}
/**
* Creates a file system mount that maps to a subfolder of the save directory for a given world, and returns it.<br>
* Use in conjuction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a folder from the
* users save directory onto a computers file system.<br>
* @param world The world for which the save dir can be found. This should be the serverside world object.
* @param subPath The folder path within the save directory that the mount should map to. eg: "computer/disk/42".<br>
* Use createUniqueNumberedSaveDir() to create a new numbered folder to use.
* @param capacity The ammount of data that can be stored in the directory before it fills up, in bytes.
* @return The mount, or null if it could be created for some reason. Use IComputerAccess.mount() or IComputerAccess.mountWritable()
* to mount this on a Computers' file system.
* @see #createUniqueNumberedSaveDir(World, String)
* @see IComputerAccess#mount(String, IMount)
* @see IComputerAccess#mountWritable(String, IWritableMount)
* @see IMount
* @see IMountWritable
*/
public static IWritableMount createSaveDirMount( World world, String subPath, long capacity )
{
findCC();
if( computerCraft_createSaveDirMount != null )
{
try {
return (IWritableMount)computerCraft_createSaveDirMount.invoke( null, world, subPath, capacity );
} catch (Exception e){
// It failed
}
}
return null;
}
/**
* Creates a file system mount to a resource folder, and returns it.<br>
* Use in conjuction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a resource folder onto a computers file system.<br>
* The files in this mount will be a combination of files in the specified mod jar, and resource packs that contain resources with the same domain and path.<br>
* @param class A class in whose jar to look first for the resources to mount. Using your main mod class is recommended. eg: MyMod.class
* @param domain The domain under which to look for resources. eg: "mymod"
* @param subPath The domain under which to look for resources. eg: "mymod/lua/myfiles"
* @return The mount, or null if it could be created for some reason. Use IComputerAccess.mount() or IComputerAccess.mountWritable()
* to mount this on a Computers' file system.
* @see IComputerAccess#mount(String, IMount)
* @see IComputerAccess#mountWritable(String, IMountWritable)
* @see IMount
*/
public static IMount createResourceMount( Class modClass, String domain, String subPath )
{
findCC();
if( computerCraft_createResourceMount != null )
{
try {
return (IMount)computerCraft_createResourceMount.invoke( null, modClass, domain, subPath );
} catch (Exception e){
// It failed
}
}
return null;
}
/**
* Registers a peripheral handler for a TileEntity that you do not have access to. Only
* use this if you want to expose IPeripheral on a TileEntity from another mod. For your own
* mod, just implement IPeripheral on the TileEntity directly.
* @see IPeripheral
* @see IPeripheralHandler
*/
public static void registerExternalPeripheral( Class <? extends net.minecraft.tileentity.TileEntity> clazz, IPeripheralHandler handler )
{
findCC();
if (computerCraft_registerExternalPeripheral != null)
{
try {
computerCraft_registerExternalPeripheral.invoke(null, clazz, handler);
} catch (Exception e){
// It failed
}
}
}
// 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 in MCP without decompiling ComputerCraft and including
// it in your solution.
private static void findCC()
{
if( !ccSearched ) {
try {
computerCraft = Class.forName( "dan200.ComputerCraft" );
computerCraft_createUniqueNumberedSaveDir = findCCMethod( "createUniqueNumberedSaveDir", new Class[] {
World.class, String.class
} );
computerCraft_createSaveDirMount = findCCMethod( "createSaveDirMount", new Class[] {
World.class, String.class, Long.TYPE
} );
computerCraft_createResourceMount = findCCMethod( "createResourceMount", new Class[] {
Class.class, String.class, String.class
} );
computerCraft_registerExternalPeripheral = findCCMethod( "registerExternalPeripheral", new Class[] {
Class.class, IPeripheralHandler.class
} );
} catch( Exception e ) {
net.minecraft.server.MinecraftServer.getServer().logInfo( "ComputerCraftAPI: ComputerCraft not found." );
} finally {
ccSearched = true;
}
}
}
private static Method findCCMethod( String name, Class[] args )
{
try {
return computerCraft.getMethod( name, args );
} catch( NoSuchMethodException e ) {
net.minecraft.server.MinecraftServer.getServer().logInfo( "ComputerCraftAPI: ComputerCraft method " + name + " not found." );
return null;
}
}
private static boolean ccSearched = false;
private static Class computerCraft = null;
private static Method computerCraft_createUniqueNumberedSaveDir = null;
private static Method computerCraft_createSaveDirMount = null;
private static Method computerCraft_createResourceMount = null;
private static Method computerCraft_registerExternalPeripheral = null;
}

View File

@ -0,0 +1,89 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computer.api;
/**
* The interface passed to peripherals by computers or turtles, providing methods
* that they can call. This should not be implemented by your classes. Do not interact
* with computers except via this interface.
*/
public interface IComputerAccess
{
/**
* Mount a mount onto the computers' file system in a read only mode.<br>
* @param desiredLoction The location on the computer's file system where you would like the mount to be mounted.
* @param mount The mount object to mount on the computer. These can be obtained by calling ComputerCraftAPI.createSaveDirMount(), ComputerCraftAPI.createResourceMount() or by creating your own objects that implement the IMount interface.
* @return The location on the computer's file system where you the mount mounted, or null if there was already a file in the desired location. Store this value if you wish to unmount the mount later.
* @see ComputerCraftAPI#createSaveDirMount(World, String)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see #mountWritable(String, IWritableMount)
* @see #unmount(String)
* @see IMount
*/
public String mount( String desiredLocation, IMount mount );
/**
* Mount a mount onto the computers' file system in a writable mode.<br>
* @param desiredLoction The location on the computer's file system where you would like the mount to be mounted.
* @param mount The mount object to mount on the computer. These can be obtained by calling ComputerCraftAPI.createSaveDirMount() or by creating your own objects that implement the IWritableMount interface.
* @return The location on the computer's file system where you the mount mounted, or null if there was already a file in the desired location. Store this value if you wish to unmount the mount later.
* @see ComputerCraftAPI#createSaveDirMount(World, String)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see #mount(String, IMount)
* @see #unmount(String)
* @see IMount
*/
public String mountWritable( String desiredLocation, IWritableMount mount );
/**
* Unmounts a directory previously mounted onto the computers file system by mount() or mountWritable().<br>
* When a directory is unmounted, it will disappear from the computers file system, and the user will no longer be able to
* access it. All directories mounted by a mount or mountWritable are automatically unmounted when the peripheral
* is attached if they have not been explicitly unmounted.
* @param location The desired location in the computers file system of the directory to unmount.
* This must be the location of a directory previously mounted by mount() or mountWritable(), as
* indicated by their return value.
* @see #mount(String, IMount)
* @see #mountWritable(String, IWritableMount)
*/
public void unmount( String location );
/**
* Returns the numerical ID of this computer.<br>
* This is the same number obtained by calling os.getComputerID() or running the "id" program from lua,
* and is guarunteed unique. This number will be positive.
* @return The identifier.
*/
public int getID();
/**
* Causes an event to be raised on this computer, which the computer can respond to by calling
* os.pullEvent(). This can be used to notify the computer when things happen in the world or to
* this peripheral.
* @param event A string identifying the type of event that has occurred, this will be
* returned as the first value from os.pullEvent(). It is recommended that you
* you choose a name that is unique, and recognisable as originating from your
* peripheral. eg: If your peripheral type is "button", a suitable event would be
* "button_pressed".
* @param arguments In addition to a name, you may pass an array of extra arguments to the event, that will
* be supplied as extra return values to os.pullEvent(). Objects in the array will be converted
* to lua data types in the same fashion as the return values of IPeripheral.callMethod().<br>
* You may supply null to indicate that no arguments are to be supplied.
* @see IPeripheral#callMethod
*/
public void queueEvent( String event, Object[] arguments );
/**
* Get a string, unique to the computer, by which the computer refers to this peripheral.
* For directly attached peripherals this will be "left","right","front","back",etc, but
* for peripherals attached remotely it will be different. It is good practice to supply
* this string when raising events to the computer, so that the computer knows from
* which peripheral the event came.
* @return A string unique to the computer, but not globally.
*/
public String getAttachmentName();
}

View File

@ -0,0 +1,44 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computer.api;
import dan200.computer.api.IPeripheral;
/**
* A subclass of IPeripheral specifically for peripherals
* created by ITurtleUpgrade's of type Peripheral. When an
* IHostedPeripheral is created, its IPeripheral methods will be called
* just as if the peripheral was a seperate adjacent block in the world,
* and update() will be called once per tick.
* @see ITurtleUpgrade
*/
public interface IHostedPeripheral extends IPeripheral
{
/**
* A method called on each hosted peripheral once per tick, on the main thread
* over the lifetime of the turtle or block. May be used to update the state
* of the peripheral, and may interact with IComputerAccess or ITurtleAccess
* however it likes at this time.
*/
public void update();
/**
* A method called whenever data is read from the Turtle's NBTTag,
* over the lifetime of the turtle. You should only use this for
* reading data you want to stay with the peripheral.
* @param nbttagcompound The peripheral's NBTTag
*/
public void readFromNBT( net.minecraft.nbt.NBTTagCompound nbttagcompound );
/**
* A method called whenever data is written to the Turtle's NBTTag,
* over the lifetime of the turtle. You should only use this for
* writing data you want to stay with the peripheral.
* @param nbttagcompound The peripheral's NBTTag.
* @param ID The turtle's ID.
*/
public void writeToNBT( net.minecraft.nbt.NBTTagCompound nbttagcompound );
}

View File

@ -0,0 +1,45 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computer.api;
/**
* An interface passed to peripherals and ILuaObjects' by computers or turtles, providing methods
* that allow the peripheral call to wait for events before returning, just like in lua.
* This is very useful if you need to signal work to be performed on the main thread, and don't want to return
* until the work has been completed.
*/
public interface ILuaContext
{
/**
* Wait for an event to occur on the computer, suspending the thread until it arises. This method is exactly equivalent to os.pullEvent() in lua.
* @param filter A specific event to wait for, or null to wait for any event
* @return An object array containing the name of the event that occurred, and any event parameters
* @throws Exception If the user presses CTRL+T to terminate the current program while pullEvent() is waiting for an event, a "Terminated" exception will be thrown here.
* Do not attempt to block this exception, unless you wish to prevent termination, which is not recommended.
* @throws InterruptedException If the user shuts down or reboots the computer while pullEvent() is waiting for an event, InterruptedException will be thrown. This exception must not be caught or intercepted, or the computer will leak memory and end up in a broken state.
*/
public Object[] pullEvent( String filter ) throws Exception, InterruptedException;
/**
* The same as pullEvent(), except "terminated" events are ignored. Only use this if you want to prevent program termination, which is not recommended. This method is exactly equivalent to os.pullEventRaw() in lua.
* @param filter A specific event to wait for, or null to wait for any event
* @return An object array containing the name of the event that occurred, and any event parameters
* @throws InterruptedException If the user shuts down or reboots the computer while pullEventRaw() is waiting for an event, InterruptedException will be thrown. This exception must not be caught or intercepted, or the computer will leak memory and end up in a broken state.
* @see #pullEvent(String)
*/
public Object[] pullEventRaw( String filter ) throws InterruptedException;
/**
* Yield the current coroutine with some arguments until it is resumed. This method is exactly equivalent to coroutine.yield() in lua. Use pullEvent() if you wish to wait for events.
* @param arguments An object array containing the arguments to pass to coroutine.yield()
* @return An object array containing the return values from coroutine.yield()
* @throws InterruptedException If the user shuts down or reboots the computer the coroutine is suspended, InterruptedException will be thrown. This exception must not be caught or intercepted, or the computer will leak memory and end up in a broken state.
* @see #pullEvent(String)
*/
public Object[] yield( Object[] arguments ) throws InterruptedException;
}

View File

@ -0,0 +1,26 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computer.api;
/**
* An interface for representing custom objects returned by IPeripheral.callMethod() calls.
* Return objects implementing this interface to expose objects with methods to lua.
*/
public interface ILuaObject
{
/**
* Get the names of the methods that this object implements. This works the same as IPeripheral.getMethodNames(). See that method for detailed documentation.
* @see IPeripheral#getMethodNames()
*/
public String[] getMethodNames();
/**
* Called when a user calls one of the methods that this object implements. This works the same as IPeripheral.callMethod(). See that method for detailed documentation.
* @see IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])
*/
public Object[] callMethod( ILuaContext context, int method, Object[] arguments ) throws Exception;
}

View File

@ -0,0 +1,57 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computer.api;
import net.minecraft.world.World;
import net.minecraft.item.ItemStack;
/**
* Represents an item that can be placed in a disk drive and used by a Computer.
* Implement this interface on your Item class to allow it to be used in the drive.
*/
public interface IMedia
{
/**
* Get a string representing the label of this item. Will be called vi disk.getLabel() in lua.
* @param stack The itemstack to inspect
* @return The label. ie: "Dan's Programs"
*/
public String getLabel( ItemStack stack );
/**
* Set a string representing the label of this item. Will be called vi disk.setLabel() in lua.
* @param stack The itemstack to modify.
* @param label The string to set the label to.
* @return true if the label was updated, false if the label may not be modified.
*/
public boolean setLabel( ItemStack stack, String label );
/**
* If this disk represents an item with audio (like a record), get the readable name of the audio track. ie: "Jonathon Coulton - Still Alive"
* @param stack The itemstack to inspect.
* @return The name, or null if this item does not represent an item with audio.
*/
public String getAudioTitle( ItemStack stack );
/**
* If this disk represents an item with audio (like a record), get the resource name of the audio track to play.
* @param stack The itemstack to inspect.
* @return The name, or null if this item does not represent an item with audio.
*/
public String getAudioRecordName( ItemStack stack );
/**
* If this disk represents an item with data (like a floppy disk), get a mount representing it's contents. This will be mounted onto the filesystem of the computer while the media is in the disk drive.
* @param stack The itemstack to inspect.
* @param world The world in which the item and disk drive reside.
* @return The mount, or null if this item does not represent an item with data. If the IMount returned also implements IWritableMount, it will mounted using mountWritable()
* @see IMount
* @see IWritableMount
* @see ComputerCraftAPI#createSaveDirMount(World, String)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
*/
public IMount createDataMount( ItemStack stack, World world );
}

View File

@ -0,0 +1,57 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computer.api;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* Represents a read only part of a virtual filesystem that can be mounted onto a computer using IComputerAccess.mount().
* Ready made implementations of this interface can be created using ComputerCraftAPI.createSaveDirMount() or ComputerCraftAPI.createResourceMount(), or you're free to implement it yourselves!
* @see ComputerCraftAPI#createSaveDirMount(World, String)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see IComputerAccess#mount(String, IMount)
* @see IWritableMount
*/
public interface IMount
{
/**
* Returns whether a file with a given path exists or not.
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram"
* @return true if the file exists, false otherwise
*/
public boolean exists( String path ) throws IOException;
/**
* Returns whether a file with a given path is a directory or not.
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms"
* @return true if the file exists and is a directory, false otherwise
*/
public boolean isDirectory( String path ) throws IOException;
/**
* Returns the file names of all the files in a directory.
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprograms"
* @param contents A list of strings. Add all the file names to this list
*/
public void list( String path, List<String> contents ) throws IOException;
/**
* Returns the size of a file with a given path, in bytes
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram"
* @return the size of the file, in bytes
*/
public long getSize( String path ) throws IOException;
/**
* Opens a file with a given path, and returns an inputstream representing it's contents.
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram"
* @return a stream representing the contents of the file
*/
public InputStream openForRead( String path ) throws IOException;
}

View File

@ -0,0 +1,106 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computer.api;
/**
* The interface that defines a peripheral. This should be implemented by the
* TileEntity of any block that you wish to be interacted with by
* computer or turtle.
*/
public interface IPeripheral
{
/**
* Should return a string that uniquely identifies this type of peripheral.
* This can be queried from lua by calling peripheral.getType()
* @return A string identifying the type of peripheral.
*/
public String getType();
/**
* Should return an array of strings that identify the methods that this
* peripheral exposes to Lua. This will be called once before each attachment,
* and should not change when called multiple times.
* @return An array of strings representing method names.
* @see #callMethod
*/
public String[] getMethodNames();
/**
* This is called when a lua program on an attached computer calls peripheral.call() with
* one of the methods exposed by getMethodNames().<br>
* <br>
* Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe
* when interacting with minecraft objects.
* @param computer The interface to the computer that is making the call. Remember that multiple
* computers can be attached to a peripheral at once.
* @param context The context of the currently running lua thread. This can be used to wait for events
* or otherwise yield.
* @param method An integer identifying which of the methods from getMethodNames() the computer
* wishes to call. The integer indicates the index into the getMethodNames() table
* that corresponds to the string passed into peripheral.call()
* @param arguments An array of objects, representing the arguments passed into peripheral.call().<br>
* Lua values of type "string" will be represented by Object type String.<br>
* Lua values of type "number" will be represented by Object type Double.<br>
* Lua values of type "boolean" will be represented by Object type Boolean.<br>
* Lua values of any other type will be represented by a null object.<br>
* This array will be empty if no arguments are passed.
* @return An array of objects, representing values you wish to return to the lua program.<br>
* Integers, Doubles, Floats, Strings, Booleans and null be converted to their corresponding lua type.<br>
* All other types will be converted to nil.<br>
* You may return null to indicate no values should be returned.
* @throws Exception If you throw any exception from this function, a lua error will be raised with the
* same message as your exception. Use this to throw appropriate errors if the wrong
* arguments are supplied to your method.
* @see #getMethodNames
*/
public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, Object[] arguments ) throws Exception;
/**
* Is called before the computer attempts to attach to the peripheral, and should return whether to allow
* the attachment. Use this to restrict the number of computers that can attach, or to limit attachments to
* certain world directions.<br>
* If true is returned, attach() will be called shortly afterwards, and the computer will be able to make method calls.
* If false is returned, attach() will not be called, and the peripheral will be invisible to the computer.
* @param side The world direction (0=bottom, 1=top, etc) that the computer lies relative to the peripheral.
* @return Whether to allow the attachment, as a boolean.
* @see #attach
*/
public boolean canAttachToSide( int side );
/**
* Is called when canAttachToSide has returned true, and a computer is attaching to the peripheral.
* This will occur when a peripheral is placed next to an active computer, when a computer is turned on next to a peripheral,
* or when a turtle travels into a square next to a peripheral.
* Between calls to attach() and detach(), the attached computer can make method calls on the peripheral using peripheral.call().
* This method can be used to keep track of which computers are attached to the peripheral, or to take action when attachment
* occurs.<br>
* <br>
* Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe
* when interacting with minecraft objects.
* @param computer The interface to the computer that is being attached. Remember that multiple
* computers can be attached to a peripheral at once.
* @see #canAttachToSide
* @see #detach
*/
public void attach( IComputerAccess computer );
/**
* Is called when a computer is detaching from the peripheral.
* This will occur when a computer shuts down, when the peripheral is removed while attached to computers,
* or when a turtle moves away from a square attached to a peripheral.
* This method can be used to keep track of which computers are attached to the peripheral, or to take action when detachment
* occurs.<br>
* <br>
* Be aware that this will be called from the ComputerCraft Lua thread, and must be thread-safe
* when interacting with minecraft objects.
* @param computer The interface to the computer that is being detached. Remember that multiple
* computers can be attached to a peripheral at once.
* @see #canAttachToSide
* @see #detach
*/
public void detach( IComputerAccess computer );
}

View File

@ -0,0 +1,17 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computer.api;
import net.minecraft.tileentity.TileEntity;
/**
* TODO: Document me
*/
public interface IPeripheralHandler
{
public IHostedPeripheral getPeripheral( TileEntity tile );
}

View File

@ -0,0 +1,53 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.computer.api;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
/**
* Represents a part of a virtual filesystem that can be mounted onto a computer using IComputerAccess.mount() or IComputerAccess.mountWritable(), that can also be written to.
* Ready made implementations of this interface can be created using ComputerCraftAPI.createSaveDirMount(), or you're free to implement it yourselves!
* @see ComputerCraftAPI#createSaveDirMount(World, String)
* @see IComputerAccess#mountWritable(String, IMount)
* @see IMount
*/
public interface IWritableMount extends IMount
{
/**
* Creates a directory at a given path inside the virtual file system.
* @param path A file path in normalised format, relative to the mount location. ie: "programs/mynewprograms"
*/
public void makeDirectory( String path ) throws IOException;
/**
* Deletes a directory at a given path inside the virtual file system.
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myoldprograms"
*/
public void delete( String path ) throws IOException;
/**
* Opens a file with a given path, and returns an outputstream for writing to it.
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram"
* @return a stream for writing to
*/
public OutputStream openForWrite( String path ) throws IOException;
/**
* Opens a file with a given path, and returns an outputstream for appending to it.
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram"
* @return a stream for writing to
*/
public OutputStream openForAppend( String path ) throws IOException;
/**
* Get the ammount of free space on the mount, in bytes. You should decrease this value as the user writes to the mount, and write operations should fail once it reaches zero.
* @return The ammount of free space, in bytes.
*/
public long getRemainingSpace() throws IOException;
}

View File

@ -0,0 +1,158 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.turtle.api;
import dan200.computer.api.*;
/**
* The interface passed to upgrades by turtles, providing methods that they can call.
* This should not be implemented by your classes. Do not interact with turtles except via this interface and ITurtleUpgrade.
*/
public interface ITurtleAccess
{
/**
* Returns the world in which the turtle resides.
* @return the world in which the turtle resides.
*/
public net.minecraft.world.World getWorld();
/**
* Returns a vector containing the integer block co-ordinates at which the turtle resides.
* @return a vector containing the integer block co-ordinates at which the turtle resides.
*/
public net.minecraft.util.Vec3 getPosition();
/**
* Returns a vector containing the co-ordinates at which the turtle is rendered.
* This will shift when the turtle is moving.
* @param f The subframe fraction
* @return a vector containing the integer block co-ordinates at which the turtle resides.
*/
public net.minecraft.util.Vec3 getVisualPosition( float f );
/**
* Returns the world direction the turtle is currently facing.
* @return the world direction the turtle is currently facing.
*/
public int getFacingDir();
/**
* Returns the size of the turtles inventory, in number of slots. This will currently always be 16.
* @return the size of the turtles inventory, in number of slots. This will currently always be 16.
*/
public int getInventorySize();
/**
* Returns which slot the turtle currently has selected in its inventory using turtle.select().
* Unlike the 1-based lua representation, this will be between 0 and getInventorySize() - 1.
* @return which slot the turtle currently has selected in its inventory
*/
public int getSelectedSlot();
/**
* Returns the item stack that the turtle has in one of its inventory slots.
* @param index which inventory slot to retreive, should be between 0 and getInventorySize() - 1
* @return the item stack that the turtle has in one of its inventory slots. May be null.
*/
public net.minecraft.item.ItemStack getSlotContents( int index );
/**
* Changes the item stack that the turtle has in one of its inventory slots.
* @param index which inventory slot to change, should be between 0 and getInventorySize() - 1
* @param stack an item stack to put in the slot. May be null.
*/
public void setSlotContents( int index, net.minecraft.item.ItemStack stack );
/**
* Tries to store an item stack into the turtles current inventory, starting from the turtles
* currently selected inventory slot.
* @param stack The item stack to try and store.
* @return true if the stack was completely stored in the inventory, false if
* it was only partially stored, or could not fit at all. If false is returned
* and the stack was partially stored, the ItemStack passed into "stack" will now
* represent the stack of items that is left over.
*/
public boolean storeItemStack( net.minecraft.item.ItemStack stack );
/**
* Drops an item stack from the turtle onto the floor, or into an inventory is there is one
* adjacent to the turtle in the direction specified.
* @param stack The item stack to drop.
* @param dir The world direction to drop the item
* @return true if the stack was dropped, or completely stored in the adjacent inventory, false if
* it was only partially stored in the adjacent inventory, or could not fit at all. If false is returned
* and the stack was partially stored, the ItemStack passed into "stack" will now
* represent the stack of items that is left over.
*/
public boolean dropItemStack( net.minecraft.item.ItemStack stack, int dir );
/**
* "Deploys" an item stack in the direction specified. This simulates a player right clicking, and calls onItemUse() on the Item class.
* Will return true if some kind of deployment happened, and may modify the item stack. For block item types, this can be
* used to place blocks. Some kinds of items (such as shears when facing a sheep) may modify the turtles inventory during this call.
* @param stack The item stack to deploy
* @param dir The world direction to deploy the item
* @return true if the stack was deployed, false if it was not.
*/
public boolean deployWithItemStack( net.minecraft.item.ItemStack stack, int dir );
/**
* Tries to "attack" entities with an item stack in the direction specified. This simulates a player left clicking, but will
* not affect blocks. If an entity is attacked and killed during this call, its dropped items will end up in the turtles
* inventory.
* @param stack The item stack to attack with
* @param dir The world direction to attack with the item
* @return true if something was attacked, false if it was not
*/
public boolean attackWithItemStack( net.minecraft.item.ItemStack stack, int dir, float damageMultiplier );
/**
* Returns the current fuel level of the turtle, this is the same integer returned by turtle.getFuelLevel(),
* that decreases by 1 every time the turtle moves. Can be used to have your tool or peripheral require or supply
* fuel to the turtle.
* @return the fuel level
*/
public int getFuelLevel();
/**
* Tries to increase the fuel level of a turtle by burning an item stack. If the item passed in is a fuel source, fuel
* will increase and true will be returned. Otherwise, nothing will happen and false will be returned.
* @param stack The stack to try to refuel with
* @return Whether the turtle was refueled
*/
public boolean refuelWithItemStack( net.minecraft.item.ItemStack stack );
/**
* Removes some fuel from the turtles fuel supply. Negative numbers can be passed in to INCREASE the fuel level of the turtle.
* @return Whether the turtle was able to consume the ammount of fuel specified. Will return false if you supply a number
* greater than the current fuel level of the turtle.
*/
public boolean consumeFuel( int fuel );
/**
* Adds a custom command to the turtles command queue. Unlike peripheral methods, these custom commands will be executed
* on the main thread, so are guaranteed to be able to access Minecraft objects safely, and will be queued up
* with the turtles standard movement and tool commands. An issued command will return an unique integer, which will
* be supplied as a parameter to a "turtle_response" event issued to the turtle after the command has completed. Look at the
* lua source code for "rom/apis/turtle" for how to build a lua wrapper around this functionality.
* @param handler an object which will execute the custom command when its point in the queue is reached
* @return the unique command identifier described above
* @see ITurtleCommandHandler
*/
public int issueCommand( ITurtleCommandHandler handler );
/**
* Returns the upgrade on the specified side of the turtle, if there is one.
* @return the upgrade on the specified side of the turtle, if there is one.
*/
public ITurtleUpgrade getUpgrade( TurtleSide side );
/**
* Returns the peripheral created by the upgrade on the specified side of the turtle, if there is one.
* @return the peripheral created by the upgrade on the specified side of the turtle, if there is one.
*/
public IHostedPeripheral getPeripheral( TurtleSide side );
}

View File

@ -0,0 +1,25 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.turtle.api;
/**
* An interface for objects executing custom turtle commands, used with ITurtleAccess.issueCommand
* @see ITurtleAccess#issueCommand( ITurtleCommandHandler )
*/
public interface ITurtleCommandHandler
{
/**
* Will be called by the turtle on the main thread when it is time to execute the custom command.
* The handler should either perform the work of the command, and return true for success, or return
* false to indicate failure if the command cannot be executed at this time.
* @param turtle access to the turtle for whom the command was issued
* @return true for success, false for failure. If true is returned, the turtle will wait 0.4 seconds
* before executing the next command in its queue, as it does for the standard turtle commands.
* @see ITurtleAccess#issueCommand( ITurtleCommandHandler )
*/
public boolean handleCommand( ITurtleAccess turtle );
}

View File

@ -0,0 +1,92 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.turtle.api;
import net.minecraft.util.Icon;
import dan200.computer.api.*;
/**
* The primary interface for defining an upgrade for Turtles. A turtle upgrade
* can either be a new tool, or a new peripheral.
* @see TurtleAPI#registerUpgrade( ITurtleUpgrade )
*/
public interface ITurtleUpgrade
{
/**
* Gets a unique numerical identifier representing this type of turtle upgrade.
* Like Minecraft block and item IDs, you should strive to make this number unique
* among all turtle upgrades that have been released for ComputerCraft.
* The ID must be in the range 64 to 255, as the ID is stored as an 8-bit value,
* and 0-64 is reserved for future use by ComputerCraft. The upgrade will
* fail registration if an already used ID is specified.
* @see TurtleAPI#registerUpgrade( ITurtleUpgrade )
*/
public int getUpgradeID();
/**
* Return a String to describe this type of upgrade in turtle item names.
* Examples of built-in adjectives are "Wireless", "Mining" and "Crafty".
*/
public String getAdjective();
/**
* Return whether this upgrade adds a tool or a peripheral to the turtle.
* Currently, turtle crafting is restricted to one tool & one peripheral per turtle.
* @see TurtleUpgradeType for the differences between the two.
*/
public TurtleUpgradeType getType();
/**
* Return an item stack representing the type of item that a turtle must be crafted
* with to create a turtle which holds this upgrade.
* Currently, turtle crafting is restricted to one tool & one peripheral per turtle.
*/
public net.minecraft.item.ItemStack getCraftingItem();
/**
* Return whether this turtle upgrade is an easter egg, and should be attempted to be hidden
* from the creative mode inventory and recipe book plugins.
*/
public boolean isSecret();
/**
* Will only be called for Peripheral upgrades. Creates a peripheral for a turtle
* being placed using this upgrade. The peripheral created will be stored
* for the lifetime of the turtle, will have update() called once-per-tick, and will be
* attach'd detach'd and have methods called in the same manner as a Computer peripheral.
* @param turtle Access to the turtle that the peripheral is being created for.
* @param side Which side of the turtle (left or right) that the upgrade resides on.
* @returns The newly created peripheral. You may return null if this upgrade is a Tool
* and this method is not expected to be called.
*/
public IHostedPeripheral createPeripheral( ITurtleAccess turtle, TurtleSide side );
/**
* Will only be called for Tool upgrades. Called when turtle.dig() or turtle.attack() is called
* by the turtle, and the tool is required to do some work.
* @param turtle Access to the turtle that the tool resides on.
* @param side Which side of the turtle (left or right) the tool resides on.
* @param verb Which action (dig or attack) the turtle is being called on to perform.
* @param direction Which world direction the action should be performed in, relative to the turtles
* position. This will either be up, down, or the direction the turtle is facing, depending on
* whether dig, digUp or digDown was called.
* @return Whether the turtle was able to perform the action, and hence whether the turtle.dig()
* or turtle.attack() lua method should return true. If true is returned, the tool will perform
* a swinging animation. You may return false if this upgrade is a Peripheral
* and this method is not expected to be called.
*/
public boolean useTool( ITurtleAccess turtle, TurtleSide side, TurtleVerb verb, int direction );
/**
* Called to obtain the Icon to be used when rendering a turtle peripheral. Needs to be a "block"
* type Icon for now, as there is no way to determine which texture sheet an Icon is from by the
* Icon itself.
* @param turtle Access to the turtle that the peripheral resides on.
* @param side Which side of the turtle (left or right) the peripheral resides on.
* @return The Icon that you wish to be used to render your turtle peripheral.
*/
public Icon getIcon( ITurtleAccess turtle, TurtleSide side );
}

View File

@ -0,0 +1,78 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.turtle.api;
import java.lang.reflect.Method;
/**
* The static entry point to the ComputerCraft Turtle Upgrade API.
* Members in this class must be called after mod_CCTurtle has been initialised,
* but may be called before it is fully loaded.
*/
public class TurtleAPI
{
/**
* Registers a new turtle upgrade for use in ComputerCraft. After calling this,
* users should be able to craft Turtles with your new upgrade. It is recommended to call
* this during the load() method of your mod.
* @throws Exception if you try to register an upgrade with an already used or reserved upgradeID
* @see ITurtleUpgrade
*/
public static void registerUpgrade( ITurtleUpgrade upgrade )
{
if( upgrade != null )
{
findCCTurtle();
if( ccTurtle_registerTurtleUpgrade != null )
{
try {
ccTurtle_registerTurtleUpgrade.invoke( null, new Object[]{ upgrade } );
} catch( Exception e ) {
// It failed
}
}
}
}
// 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 in MCP without decompiling ComputerCraft and including
// it in your solution.
private static void findCCTurtle()
{
if( !ccTurtleSearched ) {
// Search for CCTurtle
try {
ccTurtle = Class.forName( "dan200.CCTurtle" );
ccTurtle_registerTurtleUpgrade = findCCTurtleMethod( "registerTurtleUpgrade", new Class[] {
ITurtleUpgrade.class
} );
} catch( ClassNotFoundException e ) {
System.out.println("ComputerCraftAPI: CCTurtle not found.");
} finally {
ccTurtleSearched = true;
}
}
}
private static Method findCCTurtleMethod( String name, Class[] args )
{
try {
return ccTurtle.getMethod( name, args );
} catch( NoSuchMethodException e ) {
System.out.println("ComputerCraftAPI: CCTurtle method " + name + " not found.");
return null;
}
}
private static boolean ccTurtleSearched = false;
private static Class ccTurtle = null;
private static Method ccTurtle_registerTurtleUpgrade = null;
}

View File

@ -0,0 +1,23 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.turtle.api;
/**
* An enum representing the two sides of the turtle that a turtle upgrade might reside.
*/
public enum TurtleSide
{
/**
* The turtles left side (where the pickaxe usually is on a Wireless Mining Turtle)
*/
Left,
/**
* The turtles right side (where the modem usually is on a Wireless Mining Turtle)
*/
Right,
}

View File

@ -0,0 +1,27 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.turtle.api;
/**
* An enum representing the two different types of upgrades that an ITurtleUpgrade
* implementation can add to a turtle.
* @see ITurtleUpgrade
*/
public enum TurtleUpgradeType
{
/**
* A tool is rendered as an item on the side of the turtle, and responds to the turtle.dig()
* and turtle.attack() methods (Such as pickaxe or sword on Mining and Melee turtles).
*/
Tool,
/**
* A peripheral adds a special peripheral which is attached to the side of the turtle,
* and can be interacted with the peripheral API (Such as the modem on Wireless Turtles).
*/
Peripheral,
}

View File

@ -0,0 +1,26 @@
/**
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2013. This API may be redistributed unmodified and in full only.
* For help using the API, and posting your mods, visit the forums at computercraft.info.
*/
package dan200.turtle.api;
/**
* An enum representing the two different actions that an ITurtleUpgrade of type
* Tool may be called on to perform by a turtle.
* @see ITurtleUpgrade
* @see ITurtleUpgrade#useTool
*/
public enum TurtleVerb
{
/**
* The turtle called turtle.dig(), turtle.digUp() or turtle.digDown()
*/
Dig,
/**
* The turtle called turtle.attack(), turtle.attackUp() or turtle.attackDown()
*/
Attack,
}

View File

@ -1,8 +1,6 @@
package li.cil.oc.api;
import cpw.mods.fml.common.Optional;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import li.cil.oc.api.detail.FileSystemAPI;
import li.cil.oc.api.fs.Label;
import li.cil.oc.api.network.ManagedEnvironment;
@ -118,7 +116,7 @@ public final class FileSystem {
* @return a file system wrapping the specified mount.
*/
@Optional.Method(modid = "ComputerCraft")
public static li.cil.oc.api.fs.FileSystem fromComputerCraft(final IMount mount) {
public static li.cil.oc.api.fs.FileSystem fromComputerCraft(final dan200.computer.api.IMount mount) {
if (instance != null)
return instance.fromComputerCraft(mount);
return null;
@ -131,7 +129,33 @@ public final class FileSystem {
* @return a file system wrapping the specified mount.
*/
@Optional.Method(modid = "ComputerCraft")
public static li.cil.oc.api.fs.FileSystem fromComputerCraft(final IWritableMount mount) {
public static li.cil.oc.api.fs.FileSystem fromComputerCraft(final dan200.computer.api.IWritableMount mount) {
if (instance != null)
return instance.fromComputerCraft(mount);
return null;
}
/**
* Creates a new file system based on a read-only ComputerCraft mount.
*
* @param mount the mount to wrap with a file system.
* @return a file system wrapping the specified mount.
*/
@Optional.Method(modid = "ComputerCraft")
public static li.cil.oc.api.fs.FileSystem fromComputerCraft(final dan200.computercraft.api.filesystem.IMount mount) {
if (instance != null)
return instance.fromComputerCraft(mount);
return null;
}
/**
* Creates a new file system based on a read-write ComputerCraft mount.
*
* @param mount the mount to wrap with a file system.
* @return a file system wrapping the specified mount.
*/
@Optional.Method(modid = "ComputerCraft")
public static li.cil.oc.api.fs.FileSystem fromComputerCraft(final dan200.computercraft.api.filesystem.IWritableMount mount) {
if (instance != null)
return instance.fromComputerCraft(mount);
return null;

View File

@ -1,8 +1,6 @@
package li.cil.oc.api.detail;
import cpw.mods.fml.common.Optional;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import li.cil.oc.api.fs.FileSystem;
import li.cil.oc.api.fs.Label;
import li.cil.oc.api.network.ManagedEnvironment;
@ -77,7 +75,7 @@ public interface FileSystemAPI {
* @return a file system wrapping the specified mount.
*/
@Optional.Method(modid = "ComputerCraft")
FileSystem fromComputerCraft(IMount mount);
FileSystem fromComputerCraft(dan200.computer.api.IMount mount);
/**
* Creates a new file system based on a read-write ComputerCraft mount.
@ -86,7 +84,25 @@ public interface FileSystemAPI {
* @return a file system wrapping the specified mount.
*/
@Optional.Method(modid = "ComputerCraft")
FileSystem fromComputerCraft(IWritableMount mount);
FileSystem fromComputerCraft(dan200.computer.api.IWritableMount mount);
/**
* Creates a new file system based on a read-only ComputerCraft mount.
*
* @param mount the mount to wrap with a file system.
* @return a file system wrapping the specified mount.
*/
@Optional.Method(modid = "ComputerCraft")
FileSystem fromComputerCraft(dan200.computercraft.api.filesystem.IMount mount);
/**
* Creates a new file system based on a read-write ComputerCraft mount.
*
* @param mount the mount to wrap with a file system.
* @return a file system wrapping the specified mount.
*/
@Optional.Method(modid = "ComputerCraft")
FileSystem fromComputerCraft(dan200.computercraft.api.filesystem.IWritableMount mount);
/**
* Creates a network node that makes the specified file system available via

View File

@ -37,5 +37,5 @@
@cpw.mods.fml.common.API(
owner = "OpenComputers|Core",
provides = "OpenComputersAPI",
apiVersion = "1.4.10")
apiVersion = "1.4.11")
package li.cil.oc.api;

View File

@ -15,7 +15,7 @@ import li.cil.oc.server.component.machine.{LuaJLuaArchitecture, NativeLuaArchite
import li.cil.oc.server.network.WirelessNetwork
import li.cil.oc.server.{TickHandler, driver, fs, network}
import li.cil.oc.util.LuaStateFactory
import li.cil.oc.util.mods.{Mods, ComputerCraft}
import li.cil.oc.util.mods.{Mods, ComputerCraft16}
import net.minecraftforge.common.MinecraftForge
class Proxy {
@ -28,8 +28,8 @@ class Proxy {
if (Mods.ForgeMultipart.isAvailable) {
MultiPart.init()
}
if (Mods.ComputerCraft.isAvailable) {
ComputerCraft.init()
if (Mods.ComputerCraft16.isAvailable) {
ComputerCraft16.init()
}
api.CreativeTab.Instance = CreativeTab
@ -65,6 +65,13 @@ class Proxy {
api.Driver.add(driver.item.UpgradeSolarGenerator)
api.Driver.add(driver.item.WirelessNetworkCard)
if (Mods.ComputerCraft15.isAvailable) {
api.Driver.add(driver.item.CC15Media)
}
if (Mods.ComputerCraft16.isAvailable) {
api.Driver.add(driver.item.CC16Media)
}
api.Driver.add(driver.converter.FluidTankInfo)
api.Driver.add(driver.converter.ItemStack)

View File

@ -1,31 +1,52 @@
package li.cil.oc.common.tileentity
import cpw.mods.fml.common.Optional
import dan200.computercraft.api.lua.ILuaContext
import dan200.computercraft.api.peripheral.{IComputerAccess, IPeripheral}
import li.cil.oc.api
import dan200.computer.api.{ILuaContext, IComputerAccess, IPeripheral}
import li.cil.oc.api.network.{Packet, Message}
import li.cil.oc.server.PacketSender
import li.cil.oc.util.mods.Mods
import li.cil.oc.{Settings, api}
import net.minecraftforge.common.ForgeDirection
import scala.collection.mutable
@Optional.Interface(iface = "dan200.computercraft.api.peripheral.IPeripheral", modid = "ComputerCraft")
// Note on the CC1.5+1.6 compatibility
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// We simply implement both APIs. Since 1.6 moved all logic out of the actual
// tile entities (this is essentially exactly like OC's block drivers, except
// that in CC computers are adapters, too) we can keep the CC 1.6 stuff in the
// peripheral provider.
// The @Optional annotations are probably superfluous, they're just there
// because I'm paranoid. If either one of the two APIs is missing, our class
// transformer will take care of stripping out methods and interfaces that are
// not present.
// Aside from that, at least for now CC 1.6 is shipping both the new and the
// old API, so there should be no ClassNotFoundExceptions anyway.
@Optional.Interface(iface = "dan200.computer.api.IPeripheral", modid = "ComputerCraft")
class Router extends traits.Hub with traits.NotAnalyzable with IPeripheral {
var lastMessage = 0L
private val computers = mutable.ArrayBuffer.empty[AnyRef]
val computers = mutable.Map.empty[AnyRef, ComputerWrapper]
private val openPorts = mutable.Map.empty[AnyRef, mutable.Set[Int]]
val openPorts = mutable.Map.empty[AnyRef, mutable.Set[Int]]
// ----------------------------------------------------------------------- //
@Optional.Method(modid = "ComputerCraft")
override def getType = "oc_adapter"
@Optional.Method(modid = "ComputerCraft")
override def canAttachToSide(side: Int) = true
@Optional.Method(modid = "ComputerCraft")
override def attach(computer: IComputerAccess) {
computers += computer
computers += computer -> new ComputerWrapper {
override def id = computer.getID
override def attachmentName = computer.getAttachmentName
override def queueEvent(name: String, args: Array[AnyRef]) = computer.queueEvent(name, args)
}
openPorts += computer -> mutable.Set.empty
}
@ -36,38 +57,40 @@ class Router extends traits.Hub with traits.NotAnalyzable with IPeripheral {
}
@Optional.Method(modid = "ComputerCraft")
override def getMethodNames = Array("open", "isOpen", "close", "closeAll", "transmit", "isWireless")
override def getMethodNames = Array("open", "isOpen", "close", "closeAll", "maxPacketSize", "transmit", "isWireless")
@Optional.Method(modid = "ComputerCraft")
override def callMethod(computer: IComputerAccess, context: ILuaContext, method: Int, arguments: Array[AnyRef]) = getMethodNames()(method) match {
override def callMethod(computer: IComputerAccess, context: ILuaContext, method: Int, arguments: Array[AnyRef]) =
callMethod(computer, computer.getID, computer.getAttachmentName, method, arguments)
@Optional.Method(modid = "ComputerCraft")
def callMethod(computer: AnyRef, computerId: Int, attachmentName: String, method: Int, arguments: Array[AnyRef]): Array[AnyRef] = getMethodNames()(method) match {
case "open" =>
val port = checkPort(arguments, 0)
if (openPorts(computer).size >= 128)
throw new IllegalArgumentException("too many open channels")
Array(Boolean.box(openPorts(computer).add(port)))
result(openPorts(computer).add(port))
case "isOpen" =>
val port = checkPort(arguments, 0)
Array(Boolean.box(openPorts(computer).contains(port)))
result(openPorts(computer).contains(port))
case "close" =>
val port = checkPort(arguments, 0)
Array(Boolean.box(openPorts(computer).remove(port)))
result(openPorts(computer).remove(port))
case "closeAll" =>
openPorts(computer).clear()
null
case "maxPacketSize" =>
result(Settings.get.maxNetworkPacketSize)
case "transmit" =>
val sendPort = checkPort(arguments, 0)
val answerPort = checkPort(arguments, 1)
val data = Seq(Int.box(answerPort)) ++ arguments.drop(2)
val packet = api.Network.newPacket(s"cc${computer.getID}_${computer.getAttachmentName}", null, sendPort, data.toArray)
relayPacket(null, packet)
null
case "isWireless" => Array(java.lang.Boolean.FALSE)
val packet = api.Network.newPacket(s"cc${computerId}_$attachmentName", null, sendPort, data.toArray)
result(tryEnqueuePacket(null, packet))
case "isWireless" => result(this.isInstanceOf[WirelessRouter])
case _ => null
}
@Optional.Method(modid = "ComputerCraft")
override def equals(other: IPeripheral) = other == this
// ----------------------------------------------------------------------- //
protected def checkPort(args: Array[AnyRef], index: Int) = {
@ -80,10 +103,10 @@ class Router extends traits.Hub with traits.NotAnalyzable with IPeripheral {
}
protected def queueMessage(source: String, destination: String, port: Int, answerPort: Int, args: Array[AnyRef]) {
for (computer <- computers.map(_.asInstanceOf[IComputerAccess])) {
val address = s"cc${computer.getID}_${computer.getAttachmentName}"
for ((computer, wrapper) <- computers) {
val address = s"cc${wrapper.id}_${wrapper.attachmentName}"
if (source != address && Option(destination).forall(_ == address) && openPorts(computer).contains(port))
computer.queueEvent("modem_message", Array(Seq(computer.getAttachmentName, Int.box(port), Int.box(answerPort)) ++ args.map {
wrapper.queueEvent("modem_message", Array(Seq(wrapper.attachmentName, Int.box(port), Int.box(answerPort)) ++ args.map {
case x: Array[Byte] => new String(x, "UTF-8")
case x => x
}: _*))
@ -117,3 +140,12 @@ class Router extends traits.Hub with traits.NotAnalyzable with IPeripheral {
}
}
}
// Abstraction layer for CC computers to support 1.5 and 1.6 API.
trait ComputerWrapper {
def id: Int
def attachmentName: String
def queueEvent(name: String, args: Array[AnyRef])
}

View File

@ -36,20 +36,22 @@ trait Hub extends traits.Environment with SidedEnvironment {
if (relayCooldown > 0) {
relayCooldown -= 1
}
else if (queue.nonEmpty) {
else if (queue.nonEmpty) queue.synchronized {
val (sourceSide, packet) = queue.dequeue()
relayPacket(sourceSide, packet)
relayCooldown = relayDelay
}
}
protected def tryEnqueuePacket(sourceSide: ForgeDirection, packet: Packet) {
protected def tryEnqueuePacket(sourceSide: ForgeDirection, packet: Packet) = queue.synchronized {
if (packet.ttl > 0 && queue.size < maxQueueSize) {
queue += sourceSide -> packet.hop()
if (relayCooldown <= 0) {
relayCooldown = relayDelay
}
true
}
else false
}
protected def relayPacket(sourceSide: ForgeDirection, packet: Packet) {
@ -73,7 +75,7 @@ trait Hub extends traits.Environment with SidedEnvironment {
}
}
override def writeToNBT(nbt: NBTTagCompound) {
override def writeToNBT(nbt: NBTTagCompound) = queue.synchronized {
super.writeToNBT(nbt)
// Side check for Waila (and other mods that may call this client side).
if (isServer) {

View File

@ -50,7 +50,6 @@ class NetworkCard extends ManagedComponent {
def send(context: Context, args: Arguments): Array[AnyRef] = {
val address = args.checkString(0)
val port = checkPort(args.checkInteger(1))
checkPacketSize(args.drop(2))
val packet = api.Network.newPacket(node.address, address, port, args.drop(2).toArray)
doSend(packet)
result(true)
@ -59,7 +58,6 @@ class NetworkCard extends ManagedComponent {
@Callback(doc = """function(port:number, data...) -- Broadcasts the specified data on the specified port.""")
def broadcast(context: Context, args: Arguments): Array[AnyRef] = {
val port = checkPort(args.checkInteger(0))
checkPacketSize(args.drop(1))
val packet = api.Network.newPacket(node.address, null, port, args.drop(1).toArray)
doBroadcast(packet)
result(true)
@ -121,19 +119,4 @@ class NetworkCard extends ManagedComponent {
protected def checkPort(port: Int) =
if (port < 1 || port > 0xFFFF) throw new IllegalArgumentException("invalid port number")
else port
protected def checkPacketSize(data: Iterable[AnyRef]) {
val size = data.foldLeft(0)((acc, arg) => {
acc + (arg match {
case null | Unit | None => 4
case _: java.lang.Boolean => 4
case _: java.lang.Double => 8
case value: java.lang.String => value.length
case value: Array[Byte] => value.length
})
})
if (size > Settings.get.maxNetworkPacketSize) {
throw new IllegalArgumentException("packet too big (max " + Settings.get.maxNetworkPacketSize + ")")
}
}
}

View File

@ -0,0 +1,50 @@
package li.cil.oc.server.driver.item
import dan200.computer.api.IMedia
import li.cil.oc
import li.cil.oc.api.driver.Slot
import li.cil.oc.api.fs.Label
import li.cil.oc.util.mods.{ComputerCraft15, Mods}
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
import net.minecraft.tileentity.TileEntity
object CC15Media extends Item {
override def slot(stack: ItemStack) = Slot.Disk
override def createEnvironment(stack: ItemStack, container: TileEntity) =
if (Mods.ComputerCraft15.isAvailable && ComputerCraft15.isDisk(stack) && container != null) {
val address = addressFromTag(dataTag(stack))
val mount = ComputerCraft15.createDiskMount(stack, container.getWorldObj)
Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack), container)) match {
case Some(environment) =>
environment.node.asInstanceOf[oc.server.network.Node].address = address
environment
case _ => null
}
}
else null
override def worksWith(stack: ItemStack) = Mods.ComputerCraft15.isAvailable && ComputerCraft15.isDisk(stack)
private def addressFromTag(tag: NBTTagCompound) =
if (tag.hasKey("node") && tag.getCompoundTag("node").hasKey("address")) {
tag.getCompoundTag("node").getString("address")
}
else java.util.UUID.randomUUID().toString
private class ComputerCraftLabel(val stack: ItemStack) extends Label {
val media = stack.getItem.asInstanceOf[IMedia]
override def getLabel = media.getLabel(stack)
override def setLabel(value: String) {
media.setLabel(stack, value)
}
override def load(nbt: NBTTagCompound) {}
override def save(nbt: NBTTagCompound) {}
}
}

View File

@ -0,0 +1,50 @@
package li.cil.oc.server.driver.item
import net.minecraft.item.ItemStack
import net.minecraft.tileentity.TileEntity
import li.cil.oc.util.mods.{ComputerCraft16, Mods}
import li.cil.oc
import li.cil.oc.api.fs.Label
import dan200.computercraft.api.media.IMedia
import net.minecraft.nbt.NBTTagCompound
import li.cil.oc.api.driver.Slot
object CC16Media extends Item {
override def slot(stack: ItemStack) = Slot.Disk
override def createEnvironment(stack: ItemStack, container: TileEntity) =
if (Mods.ComputerCraft16.isAvailable && ComputerCraft16.isDisk(stack) && container != null) {
val address = addressFromTag(dataTag(stack))
val mount = ComputerCraft16.createDiskMount(stack, container.getWorldObj)
Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack), container)) match {
case Some(environment) =>
environment.node.asInstanceOf[oc.server.network.Node].address = address
environment
case _ => null
}
}
else null
override def worksWith(stack: ItemStack) = Mods.ComputerCraft16.isAvailable && ComputerCraft16.isDisk(stack)
private def addressFromTag(tag: NBTTagCompound) =
if (tag.hasKey("node") && tag.getCompoundTag("node").hasKey("address")) {
tag.getCompoundTag("node").getString("address")
}
else java.util.UUID.randomUUID().toString
private class ComputerCraftLabel(val stack: ItemStack) extends Label {
val media = stack.getItem.asInstanceOf[IMedia]
override def getLabel = media.getLabel(stack)
override def setLabel(value: String) {
media.setLabel(stack, value)
}
override def load(nbt: NBTTagCompound) {}
override def save(nbt: NBTTagCompound) {}
}
}

View File

@ -1,11 +1,9 @@
package li.cil.oc.server.driver.item
import dan200.computercraft.api.media.IMedia
import li.cil.oc
import li.cil.oc.api.driver.Slot
import li.cil.oc.api.fs.Label
import li.cil.oc.common.item.{FloppyDisk, HardDiskDrive}
import li.cil.oc.util.mods.{Mods, ComputerCraft}
import li.cil.oc.{Settings, Items}
import net.minecraft.item.ItemStack
import net.minecraft.nbt.NBTTagCompound
@ -13,29 +11,17 @@ import net.minecraft.tileentity.TileEntity
object FileSystem extends Item {
override def worksWith(stack: ItemStack) =
isOneOf(stack, Items.hdd1, Items.hdd2, Items.hdd3, Items.floppyDisk) ||
(Mods.ComputerCraft.isAvailable && ComputerCraft.isDisk(stack))
isOneOf(stack, Items.hdd1, Items.hdd2, Items.hdd3, Items.floppyDisk)
override def createEnvironment(stack: ItemStack, container: TileEntity) =
if (Mods.ComputerCraft.isAvailable && ComputerCraft.isDisk(stack) && container != null) {
val address = addressFromTag(dataTag(stack))
val mount = ComputerCraft.createDiskMount(stack, container.getWorldObj)
Option(oc.api.FileSystem.asManagedEnvironment(mount, new ComputerCraftLabel(stack), container)) match {
case Some(environment) =>
environment.node.asInstanceOf[oc.server.network.Node].address = address
environment
case _ => null
}
}
else Items.multi.subItem(stack) match {
Items.multi.subItem(stack) match {
case Some(hdd: HardDiskDrive) => createEnvironment(stack, hdd.kiloBytes * 1024, container)
case Some(disk: FloppyDisk) => createEnvironment(stack, Settings.get.floppySize * 1024, container)
case _ => null
}
override def slot(stack: ItemStack) =
if (Mods.ComputerCraft.isAvailable && ComputerCraft.isDisk(stack)) Slot.Disk
else Items.multi.subItem(stack) match {
Items.multi.subItem(stack) match {
case Some(hdd: HardDiskDrive) => Slot.HardDiskDrive
case Some(disk: FloppyDisk) => Slot.Disk
case _ => throw new IllegalArgumentException()
@ -66,20 +52,6 @@ object FileSystem extends Item {
}
else java.util.UUID.randomUUID().toString
private class ComputerCraftLabel(val stack: ItemStack) extends Label {
val media = stack.getItem.asInstanceOf[IMedia]
override def getLabel = media.getLabel(stack)
override def setLabel(value: String) {
media.setLabel(stack, value)
}
override def load(nbt: NBTTagCompound) {}
override def save(nbt: NBTTagCompound) {}
}
private class ItemLabel(val stack: ItemStack) extends Label {
var label: Option[String] = None

View File

@ -0,0 +1,33 @@
package li.cil.oc.server.fs
import dan200.computer.api.IMount
class CC15FileSystem(val mount: IMount) extends InputStreamFileSystem {
override def spaceTotal = 0
override def spaceUsed = 0
// ----------------------------------------------------------------------- //
override def exists(path: String) = mount.exists(path)
override def isDirectory(path: String) = mount.isDirectory(path)
override def lastModified(path: String) = 0L
override def list(path: String) = {
val result = new java.util.ArrayList[String]
mount.list(path, result)
result.toArray.map(_.asInstanceOf[String])
}
override def size(path: String) = mount.getSize(path)
// ----------------------------------------------------------------------- //
protected def openInputStream(path: String) = try {
Some(mount.openForRead(path))
} catch {
case _: Throwable => None
}
}

View File

@ -0,0 +1,43 @@
package li.cil.oc.server.fs
import dan200.computer.api.IWritableMount
import java.io.{OutputStream, IOException}
import li.cil.oc.api.fs.Mode
class CC15WritableFileSystem(override val mount: IWritableMount)
extends CC15FileSystem(mount)
with OutputStreamFileSystem {
override def delete(path: String) = try {
mount.delete(path)
true
} catch {
case _: Throwable => false
}
override def makeDirectory(path: String) = try {
mount.makeDirectory(path)
true
} catch {
case _: Throwable => false
}
override protected def openOutputHandle(id: Int, path: String, mode: Mode): Option[OutputHandle] = try {
Some(new ComputerCraftOutputHandle(mount, mode match {
case Mode.Append => mount.openForAppend(path)
case Mode.Write => mount.openForWrite(path)
case _ => throw new IllegalArgumentException()
}, this, id, path))
} catch {
case _: Throwable => None
}
protected class ComputerCraftOutputHandle(val mount: IWritableMount, val stream: OutputStream, owner: OutputStreamFileSystem, handle: Int, path: String) extends OutputHandle(owner, handle, path) {
override def length() = mount.getSize(path)
override def position() = throw new IOException("bad file descriptor")
override def write(value: Array[Byte]) = stream.write(value)
}
}

View File

@ -2,7 +2,7 @@ package li.cil.oc.server.fs
import dan200.computercraft.api.filesystem.IMount
class ComputerCraftFileSystem(val mount: IMount) extends InputStreamFileSystem {
class CC16FileSystem(val mount: IMount) extends InputStreamFileSystem {
override def spaceTotal = 0
override def spaceUsed = 0

View File

@ -4,8 +4,8 @@ import dan200.computercraft.api.filesystem.IWritableMount
import java.io.{IOException, OutputStream}
import li.cil.oc.api.fs.Mode
class ComputerCraftWritableFileSystem(override val mount: IWritableMount)
extends ComputerCraftFileSystem(mount)
class CC16WritableFileSystem(override val mount: IWritableMount)
extends CC16FileSystem(mount)
with OutputStreamFileSystem {
override def delete(path: String) = try {

View File

@ -1,7 +1,6 @@
package li.cil.oc.server.fs
import cpw.mods.fml.common.Optional
import dan200.computercraft.api.filesystem.{IWritableMount, IMount}
import java.io
import java.net.URL
import li.cil.oc.api.fs.Label
@ -67,10 +66,16 @@ object FileSystem extends api.detail.FileSystemAPI {
def fromMemory(capacity: Long): api.fs.FileSystem = new RamFileSystem(capacity)
@Optional.Method(modid = "ComputerCraft")
def fromComputerCraft(mount: IMount) = new ComputerCraftFileSystem(mount)
def fromComputerCraft(mount: dan200.computer.api.IMount) = new CC15FileSystem(mount)
@Optional.Method(modid = "ComputerCraft")
def fromComputerCraft(mount: IWritableMount) = new ComputerCraftWritableFileSystem(mount)
def fromComputerCraft(mount: dan200.computer.api.IWritableMount) = new CC15WritableFileSystem(mount)
@Optional.Method(modid = "ComputerCraft")
def fromComputerCraft(mount: dan200.computercraft.api.filesystem.IMount) = new CC16FileSystem(mount)
@Optional.Method(modid = "ComputerCraft")
def fromComputerCraft(mount: dan200.computercraft.api.filesystem.IWritableMount) = new CC16WritableFileSystem(mount)
def asManagedEnvironment(fileSystem: api.fs.FileSystem, label: Label, container: net.minecraft.tileentity.TileEntity) =
Option(fileSystem).flatMap(fs => Some(new component.FileSystem(fs, label, Option(container)))).orNull

View File

@ -460,8 +460,10 @@ object Network extends api.detail.NetworkAPI {
def newNode(host: Environment, reachability: Visibility) = new NodeBuilder(host, reachability)
override def newPacket(source: String, destination: String, port: Int, data: Array[AnyRef]) =
override def newPacket(source: String, destination: String, port: Int, data: Array[AnyRef]) = {
checkPacketSize(data)
new Packet(source, destination, port, data)
}
override def newPacket(nbt: NBTTagCompound) = {
val source = nbt.getString("source")
@ -484,6 +486,23 @@ object Network extends api.detail.NetworkAPI {
new Packet(source, destination, port, data, ttl)
}
private def checkPacketSize(data: Iterable[AnyRef]) {
val size = data.foldLeft(0)((acc, arg) => {
acc + (arg match {
case null | Unit | None => 4
case _: java.lang.Boolean => 4
case _: java.lang.Integer => 4
case _: java.lang.Double => 8
case value: java.lang.String => value.length
case value: Array[Byte] => value.length
case _ => 0
})
})
if (size > Settings.get.maxNetworkPacketSize) {
throw new IllegalArgumentException("packet too big (max " + Settings.get.maxNetworkPacketSize + ")")
}
}
class NodeBuilder(val _host: Environment, val _reachability: Visibility) extends api.detail.Builder.NodeBuilder {
def withComponent(name: String, visibility: Visibility) = new Network.ComponentBuilder(_host, _reachability, name, visibility)

View File

@ -1,31 +0,0 @@
package li.cil.oc.util.mods
import dan200.computercraft.api.ComputerCraftAPI
import dan200.computercraft.api.filesystem.{IMount, IWritableMount}
import dan200.computercraft.api.media.IMedia
import dan200.computercraft.api.peripheral.IPeripheralProvider
import li.cil.oc
import li.cil.oc.common.tileentity.Router
import net.minecraft.item.ItemStack
import net.minecraft.world.World
object ComputerCraft {
def init() {
ComputerCraftAPI.registerPeripheralProvider(new IPeripheralProvider {
override def getPeripheral(world: World, x: Int, y: Int, z: Int, side: Int) = world.getBlockTileEntity(x, y, z) match {
case router: Router => router
case _ => null
}
})
}
def isDisk(stack: ItemStack) = stack.getItem.isInstanceOf[IMedia]
def createDiskMount(stack: ItemStack, world: World) = if (isDisk(stack)) {
stack.getItem.asInstanceOf[IMedia].createDataMount(stack, world) match {
case mount: IWritableMount => oc.api.FileSystem.fromComputerCraft(mount)
case mount: IMount => oc.api.FileSystem.fromComputerCraft(mount)
case _ => null
}
} else null
}

View File

@ -0,0 +1,18 @@
package li.cil.oc.util.mods
import dan200.computer.api.{IMount, IWritableMount, IMedia}
import li.cil.oc
import net.minecraft.item.ItemStack
import net.minecraft.world.World
object ComputerCraft15 {
def isDisk(stack: ItemStack) = stack.getItem.isInstanceOf[IMedia]
def createDiskMount(stack: ItemStack, world: World) = if (isDisk(stack)) {
stack.getItem.asInstanceOf[IMedia].createDataMount(stack, world) match {
case mount: IWritableMount => oc.api.FileSystem.fromComputerCraft(mount)
case mount: IMount => oc.api.FileSystem.fromComputerCraft(mount)
case _ => null
}
} else null
}

View File

@ -0,0 +1,64 @@
package li.cil.oc.util.mods
import dan200.computercraft.api.ComputerCraftAPI
import dan200.computercraft.api.filesystem.{IMount, IWritableMount}
import dan200.computercraft.api.media.IMedia
import dan200.computercraft.api.peripheral.{IComputerAccess, IPeripheral, IPeripheralProvider}
import li.cil.oc
import li.cil.oc.common.tileentity.{ComputerWrapper, Router}
import net.minecraft.item.ItemStack
import net.minecraft.world.World
import dan200.computercraft.api.lua.ILuaContext
import scala.collection.mutable
object ComputerCraft16 {
def init() {
ComputerCraftAPI.registerPeripheralProvider(new IPeripheralProvider {
override def getPeripheral(world: World, x: Int, y: Int, z: Int, side: Int) = world.getBlockTileEntity(x, y, z) match {
case router: Router => new RouterPeripheral(router)
case _ => null
}
})
}
def isDisk(stack: ItemStack) = stack.getItem.isInstanceOf[IMedia]
def createDiskMount(stack: ItemStack, world: World) = if (isDisk(stack)) {
stack.getItem.asInstanceOf[IMedia].createDataMount(stack, world) match {
case mount: IWritableMount => oc.api.FileSystem.fromComputerCraft(mount)
case mount: IMount => oc.api.FileSystem.fromComputerCraft(mount)
case _ => null
}
} else null
class RouterPeripheral(val router: Router) extends IPeripheral {
override def getType = router.getType
override def attach(computer: IComputerAccess) {
router.computers += computer -> new ComputerWrapper {
override def id = computer.getID
override def attachmentName = computer.getAttachmentName
override def queueEvent(name: String, args: Array[AnyRef]) = computer.queueEvent(name, args)
}
router.openPorts += computer -> mutable.Set.empty
}
override def detach(computer: IComputerAccess) {
router.computers -= computer
router.openPorts -= computer
}
override def getMethodNames = router.getMethodNames
override def callMethod(computer: IComputerAccess, context: ILuaContext, method: Int, arguments: Array[AnyRef]) =
router.callMethod(computer, computer.getID, computer.getAttachmentName, method, arguments)
override def equals(other: IPeripheral) = other match {
case rp: RouterPeripheral => rp.router == router
case _ => false
}
}
}

View File

@ -4,22 +4,38 @@ import cpw.mods.fml.common.versioning.VersionParser
import cpw.mods.fml.common.{ModAPIManager, Loader}
object Mods {
val BattleGear2 = new Mod("battlegear2")
val BuildCraftPower = new Mod("BuildCraftAPI|power")
val ComputerCraft = new Mod("ComputerCraft@[1.6,1.50)")
val ForgeMultipart = new Mod("ForgeMultipart")
val GregTech = new Mod("gregtech_addon")
val IndustrialCraft2 = new Mod("IC2")
val MineFactoryReloaded = new Mod("MineFactoryReloaded")
val NotEnoughItems = new Mod("NotEnoughItems")
val PortalGun = new Mod("PortalGun")
val ProjectRed = new Mod("ProjRed|Transmission")
val RedLogic = new Mod("RedLogic")
val StargateTech2 = new Mod("StargateTech2@[0.6.0,)")
val ThermalExpansion = new Mod("ThermalExpansion")
val UniversalElectricity = new Mod("UniversalElectricity@[3.1,)")
val BattleGear2 = new SimpleMod("battlegear2")
val BuildCraftPower = new SimpleMod("BuildCraftAPI|power")
val ComputerCraft15 = new Mod {
val isAvailable = try Class.forName("dan200.computer.api.ComputerCraftAPI") != null catch {
case _: Throwable => false
}
}
val ComputerCraft16 = new Mod {
val isAvailable = try Class.forName("dan200.computercraft.api.ComputerCraftAPI") != null catch {
case _: Throwable => false
}
}
val ComputerCraft = new Mod {
override def isAvailable = ComputerCraft15.isAvailable || ComputerCraft16.isAvailable
}
val ForgeMultipart = new SimpleMod("ForgeMultipart")
val GregTech = new SimpleMod("gregtech_addon")
val IndustrialCraft2 = new SimpleMod("IC2")
val MineFactoryReloaded = new SimpleMod("MineFactoryReloaded")
val NotEnoughItems = new SimpleMod("NotEnoughItems")
val PortalGun = new SimpleMod("PortalGun")
val ProjectRed = new SimpleMod("ProjRed|Transmission")
val RedLogic = new SimpleMod("RedLogic")
val StargateTech2 = new SimpleMod("StargateTech2@[0.6.0,)")
val ThermalExpansion = new SimpleMod("ThermalExpansion")
val UniversalElectricity = new SimpleMod("UniversalElectricity@[3.1,)")
class Mod(val id: String) {
trait Mod {
def isAvailable: Boolean
}
class SimpleMod(val id: String) {
val isAvailable = {
val version = VersionParser.parseVersionReference(id)
if (Loader.isModLoaded(version.getLabel))