1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-29 21:02:59 +00:00

Started work on upgrading to 1.16.1. Not in a compilable state yet

This commit is contained in:
Alex Evelyn
2020-07-07 13:27:13 -04:00
parent cb66ef7e30
commit 605e1f6b9b
513 changed files with 48117 additions and 534 deletions

View File

@@ -0,0 +1,79 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleUpgradeType;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import javax.annotation.Nonnull;
/**
* A base class for {@link ITurtleUpgrade}s.
*
* One does not have to use this, but it does provide a convenient template.
*/
public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
{
private final Identifier id;
private final TurtleUpgradeType type;
private final String adjective;
private final ItemStack stack;
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack )
{
this.id = id;
this.type = type;
this.adjective = adjective;
this.stack = stack;
}
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item )
{
this( id, type, adjective, new ItemStack( item ) );
}
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack )
{
this( id, type, Util.createTranslationKey( "upgrade", id ) + ".adjective", stack );
}
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemConvertible item )
{
this( id, type, new ItemStack( item ) );
}
@Nonnull
@Override
public final Identifier getUpgradeID()
{
return id;
}
@Nonnull
@Override
public final String getUnlocalisedAdjective()
{
return adjective;
}
@Nonnull
@Override
public final TurtleUpgradeType getType()
{
return type;
}
@Nonnull
@Override
public final ItemStack getCraftingItem()
{
return stack;
}
}

View File

@@ -0,0 +1,303 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.ILuaAPIFactory;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.media.IMediaProvider;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.network.wired.IWiredElement;
import dan200.computercraft.api.network.wired.IWiredNode;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.peripheral.IPeripheralProvider;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* 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 final class ComputerCraftAPI
{
@Nonnull
public static String getInstalledVersion()
{
return getInstance().getInstalledVersion();
}
@Nonnull
public static String getAPIVersion()
{
return "${version}";
}
/**
* Creates a numbered directory in a subfolder of the save directory for a given world, and returns that number.
*
* Use in conjunction with createSaveDirMount() to create a unique place for your peripherals or media items to store files.
*
* @param world The world for which the save dir should be created. This should be the server side world object.
* @param parentSubPath The folder path within the save directory where the new directory should be created. eg: "computercraft/disk"
* @return The numerical value of the name of the new folder, or -1 if the folder could not be created for some reason.
*
* eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now
* available for writing.
* @see #createSaveDirMount(World, String, long)
*/
public static int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath )
{
return getInstance().createUniqueNumberedSaveDir( world, parentSubPath );
}
/**
* Creates a file system mount that maps to a subfolder of the save directory for a given world, and returns it.
*
* Use in conjunction with IComputerAccess.mount() or IComputerAccess.mountWritable() to mount a folder from the
* users save directory onto a computers file system.
*
* @param world The world for which the save dir can be found. This should be the server side world object.
* @param subPath The folder path within the save directory that the mount should map to. eg: "computer/disk/42".
* Use createUniqueNumberedSaveDir() to create a new numbered folder to use.
* @param capacity The amount 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 IWritableMount
*/
@Nullable
public static IWritableMount createSaveDirMount( @Nonnull World world, @Nonnull String subPath, long capacity )
{
return getInstance().createSaveDirMount( world, subPath, capacity );
}
/**
* Creates a file system mount to a resource folder, and returns it.
*
* Use in conjunction with {@link IComputerAccess#mount} or {@link IComputerAccess#mountWritable} to mount a
* resource folder onto a computer's file system.
*
* The files in this mount will be a combination of files in all mod jar, and data packs that contain
* resources with the same domain and path.
*
* @param domain The domain under which to look for resources. eg: "mymod".
* @param subPath The subPath under which to look for resources. eg: "lua/myfiles".
* @return The mount, or {@code null} if it could be created for some reason.
* @see IComputerAccess#mount(String, IMount)
* @see IComputerAccess#mountWritable(String, IWritableMount)
* @see IMount
*/
@Nullable
public static IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
{
return getInstance().createResourceMount( domain, subPath );
}
/**
* Creates a file system mount to a resource folder, and returns it.
*
* Use in conjunction with {@link IComputerAccess#mount} or {@link IComputerAccess#mountWritable} to mount a
* resource folder onto a computer's file system.
*
* The files in this mount will be a combination of files in all mod jar, and data packs that contain
* resources with the same domain and path.
*
* @param klass The mod class to which the files belong.
* @param domain The domain under which to look for resources. eg: "mymod".
* @param subPath The subPath under which to look for resources. eg: "lua/myfiles".
* @return The mount, or {@code null} if it could be created for some reason.
* @see IComputerAccess#mount(String, IMount)
* @see IComputerAccess#mountWritable(String, IWritableMount)
* @see IMount
* @deprecated Use {@link #createResourceMount(String, String)} instead.
*/
@Nullable
@Deprecated
public static IMount createResourceMount( Class<?> klass, @Nonnull String domain, @Nonnull String subPath )
{
return getInstance().createResourceMount( domain, subPath );
}
/**
* Registers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
*
* @param provider The peripheral provider to register.
* @see IPeripheral
* @see IPeripheralProvider
*/
public static void registerPeripheralProvider( @Nonnull IPeripheralProvider provider )
{
getInstance().registerPeripheralProvider( provider );
}
/**
* Registers a new turtle turtle for use in ComputerCraft. After calling this,
* users should be able to craft Turtles with your new turtle. It is recommended to call
* this during the load() method of your mod.
*
* @param upgrade The turtle upgrade to register.
* @see ITurtleUpgrade
*/
public static void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
{
getInstance().registerTurtleUpgrade( upgrade );
}
/**
* Registers a bundled redstone provider to provide bundled redstone output for blocks.
*
* @param provider The bundled redstone provider to register.
* @see IBundledRedstoneProvider
*/
public static void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider )
{
getInstance().registerBundledRedstoneProvider( provider );
}
/**
* If there is a Computer or Turtle at a certain position in the world, get it's bundled redstone output.
*
* @param world The world this block is in.
* @param pos The position this block is at.
* @param side The side to extract the bundled redstone output from.
* @return If there is a block capable of emitting bundled redstone at the location, it's signal (0-65535) will be returned.
* If there is no block capable of emitting bundled redstone at the location, -1 will be returned.
* @see IBundledRedstoneProvider
*/
public static int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )
{
return getInstance().getBundledRedstoneOutput( world, pos, side );
}
/**
* Registers a media provider to provide {@link IMedia} implementations for Items
*
* @param provider The media provider to register.
* @see IMediaProvider
*/
public static void registerMediaProvider( @Nonnull IMediaProvider provider )
{
getInstance().registerMediaProvider( provider );
}
public static void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade )
{
getInstance().registerPocketUpgrade( upgrade );
}
/**
* Attempt to get the game-wide wireless network.
*
* @return The global wireless network, or {@code null} if it could not be fetched.
*/
public static IPacketNetwork getWirelessNetwork()
{
return getInstance().getWirelessNetwork();
}
public static void registerAPIFactory( @Nonnull ILuaAPIFactory factory )
{
getInstance().registerAPIFactory( factory );
}
/**
* Construct a new wired node for a given wired element
*
* @param element The element to construct it for
* @return The element's node
* @see IWiredElement#getNode()
*/
@Nonnull
public static IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element )
{
return getInstance().createWiredNodeForElement( element );
}
/**
* Get the wired network element for a block in world
*
* @param world The world the block exists in
* @param pos The position the block exists in
* @param side The side to extract the network element from
* @return The element's node
* @see IWiredElement#getNode()
*/
@Nullable
public static IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side )
{
return getInstance().getWiredElementAt( world, pos, side );
}
private static IComputerCraftAPI instance;
@Nonnull
private static IComputerCraftAPI getInstance()
{
if( instance != null ) return instance;
try
{
return instance = (IComputerCraftAPI) Class.forName( "dan200.computercraft.ComputerCraftAPIImpl" )
.getField( "INSTANCE" ).get( null );
}
catch( ReflectiveOperationException e )
{
throw new IllegalStateException( "Cannot find ComputerCraft API", e );
}
}
public interface IComputerCraftAPI
{
@Nonnull
String getInstalledVersion();
int createUniqueNumberedSaveDir( @Nonnull World world, @Nonnull String parentSubPath );
@Nullable
IWritableMount createSaveDirMount( @Nonnull World world, @Nonnull String subPath, long capacity );
@Nullable
IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath );
void registerPeripheralProvider( @Nonnull IPeripheralProvider provider );
void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade );
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );
int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side );
void registerMediaProvider( @Nonnull IMediaProvider provider );
void registerPocketUpgrade( @Nonnull IPocketUpgrade upgrade );
@Nonnull
IPacketNetwork getWirelessNetwork();
void registerAPIFactory( @Nonnull ILuaAPIFactory factory );
@Nonnull
IWiredNode createWiredNodeForElement( @Nonnull IWiredElement element );
@Nullable
IWiredElement getWiredElementAt( @Nonnull BlockView world, @Nonnull BlockPos pos, @Nonnull Direction side );
}
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.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,98 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.filesystem;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IComputerAccess;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.List;
/**
* Represents a read only part of a virtual filesystem that can be mounted onto a computer using
* {@link IComputerAccess#mount(String, IMount)}
*
* Ready made implementations of this interface can be created using
* {@link ComputerCraftAPI#createSaveDirMount(World, String, long)} or
* {@link ComputerCraftAPI#createResourceMount(Class, String, String)}, or you're free to implement it yourselves!
*
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @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 If the file exists.
* @throws IOException If an error occurs when checking the existence of the file.
*/
boolean exists( @Nonnull 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 If the file exists and is a directory
* @throws IOException If an error occurs when checking whether the file is a directory.
*/
boolean isDirectory( @Nonnull 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.
* @throws IOException If the file was not a directory, or could not be listed.
*/
void list( @Nonnull String path, @Nonnull 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.
* @throws IOException If the file does not exist, or its size could not be determined.
*/
long getSize( @Nonnull String path ) throws IOException;
/**
* Opens a file with a given path, and returns an {@link InputStream} representing its 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.
* @throws IOException If the file does not exist, or could not be opened.
* @deprecated Use {@link #openChannelForRead(String)} instead
*/
@Nonnull
@Deprecated
InputStream openForRead( @Nonnull String path ) throws IOException;
/**
* Opens a file with a given path, and returns an {@link ReadableByteChannel} representing its contents.
*
* @param path A file path in normalised format, relative to the mount location. ie: "programs/myprogram".
* @return A channel representing the contents of the file. If the channel implements
* {@link java.nio.channels.SeekableByteChannel}, one will be able to seek to arbitrary positions when using binary
* mode.
* @throws IOException If the file does not exist, or could not be opened.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default ReadableByteChannel openChannelForRead( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForRead( path ) );
}
}

View File

@@ -0,0 +1,111 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.filesystem;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IComputerAccess;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.channels.Channels;
import java.nio.channels.WritableByteChannel;
/**
* Represents a part of a virtual filesystem that can be mounted onto a computer using {@link IComputerAccess#mount(String, IMount)}
* or {@link IComputerAccess#mountWritable(String, IWritableMount)}, that can also be written to.
*
* Ready made implementations of this interface can be created using
* {@link ComputerCraftAPI#createSaveDirMount(World, String, long)}, or you're free to implement it yourselves!
*
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see IComputerAccess#mount(String, IMount)
* @see IComputerAccess#mountWritable(String, IWritableMount)
* @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".
* @throws IOException If the directory already exists or could not be created.
*/
void makeDirectory( @Nonnull 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".
* @throws IOException If the file does not exist or could not be deleted.
*/
void delete( @Nonnull String path ) throws IOException;
/**
* Opens a file with a given path, and returns an {@link 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
* @throws IOException If the file could not be opened for writing.
* @deprecated Use {@link #openChannelForWrite(String)} instead.
*/
@Nonnull
@Deprecated
OutputStream openForWrite( @Nonnull String path ) throws IOException;
/**
* Opens a file with a given path, and returns an {@link 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. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one
* will be able to seek to arbitrary positions when using binary mode.
* @throws IOException If the file could not be opened for writing.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default WritableByteChannel openChannelForWrite( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForWrite( path ) );
}
/**
* Opens a file with a given path, and returns an {@link 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.
* @throws IOException If the file could not be opened for writing.
* @deprecated Use {@link #openChannelForAppend(String)} instead.
*/
@Nonnull
@Deprecated
OutputStream openForAppend( @Nonnull String path ) throws IOException;
/**
* Opens a file with a given path, and returns an {@link 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. If the channel implements {@link java.nio.channels.SeekableByteChannel}, one
* will be able to seek to arbitrary positions when using binary mode.
* @throws IOException If the file could not be opened for writing.
*/
@Nonnull
@SuppressWarnings( "deprecation" )
default WritableByteChannel openChannelForAppend( @Nonnull String path ) throws IOException
{
return Channels.newChannel( openForAppend( path ) );
}
/**
* Get the amount 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 amount of free space, in bytes.
* @throws IOException If the remaining space could not be computed.
*/
long getRemainingSpace() throws IOException;
}

View File

@@ -0,0 +1,35 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.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,53 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.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,31 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.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)
*/
@FunctionalInterface
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

@@ -0,0 +1,105 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.lua;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* An interface passed to peripherals and {@link ILuaObject}s 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 {@code 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 LuaException 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 catch this exception. You should use {@link #pullEventRaw(String)}
* should you wish to disable termination.
* @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.
*/
@Nonnull
default Object[] pullEvent( @Nullable String filter ) throws LuaException, InterruptedException
{
Object[] results = pullEventRaw( filter );
if( results.length >= 1 && results[0].equals( "terminate" ) ) throw new LuaException( "Terminated", 0 );
return results;
}
/**
* The same as {@link #pullEvent(String)}, 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
* {@code 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)
*/
@Nonnull
default Object[] pullEventRaw( @Nullable String filter ) throws InterruptedException
{
return yield( new Object[] { filter } );
}
/**
* Yield the current coroutine with some arguments until it is resumed. This method is exactly equivalent to
* {@code coroutine.yield()} in lua. Use {@code 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)
*/
@Nonnull
Object[] yield( @Nullable Object[] arguments ) throws InterruptedException;
/**
* Queue a task to be executed on the main server thread at the beginning of next tick, waiting for it to complete.
* This should be used when you need to interact with the world in a thread-safe manner.
*
* Note that the return values of your task are handled as events, meaning more complex objects such as maps or
* {@link ILuaObject} will not preserve their identities.
*
* @param task The task to execute on the main thread.
* @return The objects returned by {@code task}.
* @throws LuaException If the task could not be queued, or if the task threw an exception.
* @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.
*/
@Nullable
Object[] executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException, InterruptedException;
/**
* Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to
* complete. This should be used when you need to interact with the world in a thread-safe manner but do not care
* about the result or you wish to run asynchronously.
*
* When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success
* value and the return values, or an error message if it failed. If you need to wait on this event, it may be
* better to use {@link #executeMainThreadTask(ILuaTask)}.
*
* @param task The task to execute on the main thread.
* @return The "id" of the task. This will be the first argument to the {@code task_completed} event.
* @throws LuaException If the task could not be queued.
*/
long issueMainThreadTask( @Nonnull ILuaTask task ) throws LuaException;
}

View File

@@ -0,0 +1,56 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.lua;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* An interface for representing custom objects returned by {@link IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}
* 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 {@link IPeripheral#getMethodNames()}.
* See that method for detailed documentation.
*
* @return The method names this object provides.
* @see IPeripheral#getMethodNames()
*/
@Nonnull
String[] getMethodNames();
/**
* Called when a user calls one of the methods that this object implements. This works the same as
* {@link IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}}. See that method for detailed
* documentation.
*
* @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 computercraft
* wishes to call. The integer indicates the index into the getMethodNames() table
* that corresponds to the string passed into peripheral.call()
* @param arguments The arguments for this method. See {@link IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}
* the possible values and conversion rules.
* @return An array of objects, representing the values you wish to return to the Lua program.
* See {@link IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])} for the valid values and
* conversion rules.
* @throws LuaException If the task could not be queued, or if the task threw an exception.
* @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.w
* @see IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])
*/
@Nullable
Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException;
}

View File

@@ -0,0 +1,33 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.lua;
import javax.annotation.Nullable;
/**
* A task which can be executed via {@link ILuaContext#executeMainThreadTask(ILuaTask)} or
* {@link ILuaContext#issueMainThreadTask(ILuaTask)}. This will be run on the main thread, at the beginning of the
* next tick.
*
* @see ILuaContext#executeMainThreadTask(ILuaTask)
* @see ILuaContext#issueMainThreadTask(ILuaTask)
*/
@FunctionalInterface
public interface ILuaTask
{
/**
* Execute this task.
*
* @return The arguments to add to the {@code task_completed} event. These will be returned by
* {@link ILuaContext#executeMainThreadTask(ILuaTask)}.
* @throws LuaException 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.
*/
@Nullable
Object[] execute() throws LuaException;
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.lua;
import javax.annotation.Nullable;
/**
* An exception representing an error in Lua, like that raised by the {@code error()} function.
*/
public class LuaException extends Exception
{
private static final long serialVersionUID = -6136063076818512651L;
private final int level;
public LuaException()
{
this( "error", 1 );
}
public LuaException( @Nullable String message )
{
this( message, 1 );
}
public LuaException( @Nullable String message, int level )
{
super( message );
this.level = level;
}
/**
* The level this error is raised at. Level 1 is the function's caller, level 2 is that function's caller, and so
* on.
*
* @return The level to raise the error at.
*/
public int getLevel()
{
return level;
}
}

View File

@@ -0,0 +1,90 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.media;
import dan200.computercraft.api.filesystem.IMount;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundEvent;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Represents an item that can be placed in a disk drive and used by a Computer.
*
* Implement this interface on your {@link Item} class to allow it to be used in the drive. Alternatively, register
* a {@link IMediaProvider}.
*/
public interface IMedia
{
/**
* Get a string representing the label of this item. Will be called via {@code disk.getLabel()} in lua.
*
* @param stack The {@link ItemStack} to inspect.
* @return The label. ie: "Dan's Programs".
*/
@Nullable
String getLabel( @Nonnull ItemStack stack );
/**
* Set a string representing the label of this item. Will be called vi {@code disk.setLabel()} in lua.
*
* @param stack The {@link 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.
*/
default boolean setLabel( @Nonnull ItemStack stack, @Nullable String label )
{
return false;
}
/**
* If this disk represents an item with audio (like a record), get the readable name of the audio track. ie:
* "Jonathan Coulton - Still Alive"
*
* @param stack The {@link ItemStack} to modify.
* @return The name, or null if this item does not represent an item with audio.
*/
@Nullable
default String getAudioTitle( @Nonnull ItemStack stack )
{
return null;
}
/**
* If this disk represents an item with audio (like a record), get the resource name of the audio track to play.
*
* @param stack The {@link ItemStack} to modify.
* @return The name, or null if this item does not represent an item with audio.
*/
@Nullable
default SoundEvent getAudio( @Nonnull ItemStack stack )
{
return null;
}
/**
* 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 {@link ItemStack} to modify.
* @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 mount returned also
* implements {@link dan200.computercraft.api.filesystem.IWritableMount}, it will mounted using mountWritable()
* @see IMount
* @see dan200.computercraft.api.filesystem.IWritableMount
* @see dan200.computercraft.api.ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see dan200.computercraft.api.ComputerCraftAPI#createResourceMount(Class, String, String)
*/
@Nullable
default IMount createDataMount( @Nonnull ItemStack stack, @Nonnull World world )
{
return null;
}
}

View File

@@ -0,0 +1,31 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.media;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* This interface is used to provide {@link IMedia} implementations for {@link ItemStack}.
*
* @see dan200.computercraft.api.ComputerCraftAPI#registerMediaProvider(IMediaProvider)
*/
@FunctionalInterface
public interface IMediaProvider
{
/**
* Produce an IMedia implementation from an ItemStack.
*
* @param stack The stack from which to extract the media information.
* @return An {@link IMedia} implementation, or {@code null} if the item is not something you wish to handle
* @see dan200.computercraft.api.ComputerCraftAPI#registerMediaProvider(IMediaProvider)
*/
@Nullable
IMedia getMedia( @Nonnull ItemStack stack );
}

View File

@@ -0,0 +1,59 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.network;
import javax.annotation.Nonnull;
/**
* A packet network represents a collection of devices which can send and receive packets.
*
* @see Packet
* @see IPacketReceiver
*/
public interface IPacketNetwork
{
/**
* Add a receiver to the network.
*
* @param receiver The receiver to register to the network.
*/
void addReceiver( @Nonnull IPacketReceiver receiver );
/**
* Remove a receiver from the network.
*
* @param receiver The device to remove from the network.
*/
void removeReceiver( @Nonnull IPacketReceiver receiver );
/**
* Determine whether this network is wireless.
*
* @return Whether this network is wireless.
*/
boolean isWireless();
/**
* Submit a packet for transmitting across the network. This will route the packet through the network, sending it
* to all receivers within range (or any interdimensional ones).
*
* @param packet The packet to send.
* @param range The maximum distance this packet will be sent.
* @see #transmitInterdimensional(Packet)
* @see IPacketReceiver#receiveSameDimension(Packet, double)
*/
void transmitSameDimension( @Nonnull Packet packet, double range );
/**
* Submit a packet for transmitting across the network. This will route the packet through the network, sending it
* to all receivers across all dimensions.
*
* @param packet The packet to send.
* @see #transmitSameDimension(Packet, double)
* @see IPacketReceiver#receiveDifferentDimension(Packet)
*/
void transmitInterdimensional( @Nonnull Packet packet );
}

View File

@@ -0,0 +1,84 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.network;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
/**
* An object on an {@link IPacketNetwork}, capable of receiving packets.
*/
public interface IPacketReceiver
{
/**
* Get the world in which this packet receiver exists.
*
* @return The receivers's world.
*/
@Nonnull
World getWorld();
/**
* Get the position in the world at which this receiver exists.
*
* @return The receiver's position.
*/
@Nonnull
Vec3d getPosition();
/**
* Get the maximum distance this receiver can send and receive messages.
*
* When determining whether a receiver can receive a message, the largest distance of the packet and receiver is
* used - ensuring it is within range. If the packet or receiver is inter-dimensional, then the packet will always
* be received.
*
* @return The maximum distance this device can send and receive messages.
* @see #isInterdimensional()
* @see #receiveSameDimension(Packet packet, double)
* @see IPacketNetwork#transmitInterdimensional(Packet)
*/
double getRange();
/**
* Determine whether this receiver can receive packets from other dimensions.
*
* A device will receive an inter-dimensional packet if either it or the sending device is inter-dimensional.
*
* @return Whether this receiver receives packets from other dimensions.
* @see #getRange()
* @see #receiveDifferentDimension(Packet)
* @see IPacketNetwork#transmitInterdimensional(Packet)
*/
boolean isInterdimensional();
/**
* Receive a network packet from the same dimension.
*
* @param packet The packet to receive. Generally you should check that you are listening on the given channel and,
* if so, queue the appropriate modem event.
* @param distance The distance this packet has travelled from the source.
* @see Packet
* @see #getRange()
* @see IPacketNetwork#transmitSameDimension(Packet, double)
* @see IPacketNetwork#transmitInterdimensional(Packet)
*/
void receiveSameDimension( @Nonnull Packet packet, double distance );
/**
* Receive a network packet from a different dimension.
*
* @param packet The packet to receive. Generally you should check that you are listening on the given channel and,
* if so, queue the appropriate modem event.
* @see Packet
* @see IPacketNetwork#transmitInterdimensional(Packet)
* @see IPacketNetwork#transmitSameDimension(Packet, double)
* @see #isInterdimensional()
*/
void receiveDifferentDimension( @Nonnull Packet packet );
}

View File

@@ -0,0 +1,42 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.network;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
/**
* An object on a {@link IPacketNetwork}, capable of sending packets.
*/
public interface IPacketSender
{
/**
* Get the world in which this packet sender exists.
*
* @return The sender's world.
*/
@Nonnull
World getWorld();
/**
* Get the position in the world at which this sender exists.
*
* @return The sender's position.
*/
@Nonnull
Vec3d getPosition();
/**
* Get some sort of identification string for this sender. This does not strictly need to be unique, but you
* should be able to extract some identifiable information from it.
*
* @return This device's id.
*/
@Nonnull
String getSenderID();
}

View File

@@ -0,0 +1,117 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.network;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
/**
* Represents a packet which may be sent across a {@link IPacketNetwork}.
*
* @see IPacketSender
* @see IPacketNetwork#transmitSameDimension(Packet, double)
* @see IPacketNetwork#transmitInterdimensional(Packet)
* @see IPacketReceiver#receiveDifferentDimension(Packet)
* @see IPacketReceiver#receiveSameDimension(Packet, double)
*/
public class Packet
{
private final int channel;
private final int replyChannel;
private final Object payload;
private final IPacketSender sender;
/**
* Create a new packet, ready for transmitting across the network.
*
* @param channel The channel to send the packet along. Receiving devices should only process packets from on
* channels they are listening to.
* @param replyChannel The channel to reply on.
* @param payload The contents of this packet. This should be a "valid" Lua object, safe for queuing as an
* event or returning from a peripheral call.
* @param sender The object which sent this packet.
*/
public Packet( int channel, int replyChannel, @Nullable Object payload, @Nonnull IPacketSender sender )
{
Objects.requireNonNull( sender, "sender cannot be null" );
this.channel = channel;
this.replyChannel = replyChannel;
this.payload = payload;
this.sender = sender;
}
/**
* Get the channel this packet is sent along. Receivers should generally only process packets from on channels they
* are listening to.
*
* @return This packet's channel.
*/
public int getChannel()
{
return channel;
}
/**
* The channel to reply on. Objects which will reply should send it along this channel.
*
* @return This channel to reply on.
*/
public int getReplyChannel()
{
return replyChannel;
}
/**
* The actual data of this packet. This should be a "valid" Lua object, safe for queuing as an
* event or returning from a peripheral call.
*
* @return The packet's payload
*/
@Nullable
public Object getPayload()
{
return payload;
}
/**
* The object which sent this message.
*
* @return The sending object.
*/
@Nonnull
public IPacketSender getSender()
{
return sender;
}
@Override
public boolean equals( Object o )
{
if( this == o ) return true;
if( o == null || getClass() != o.getClass() ) return false;
Packet packet = (Packet) o;
if( channel != packet.channel ) return false;
if( replyChannel != packet.replyChannel ) return false;
if( !Objects.equals( payload, packet.payload ) ) return false;
return sender.equals( packet.sender );
}
@Override
public int hashCode()
{
int result;
result = channel;
result = 31 * result + replyChannel;
result = 31 * result + (payload != null ? payload.hashCode() : 0);
result = 31 * result + sender.hashCode();
return result;
}
}

View File

@@ -0,0 +1,35 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.network.wired;
import dan200.computercraft.api.ComputerCraftAPI;
import javax.annotation.Nonnull;
/**
* An object which may be part of a wired network.
*
* Elements should construct a node using {@link ComputerCraftAPI#createWiredNodeForElement(IWiredElement)}. This acts
* as a proxy for all network objects. Whilst the node may change networks, an element's node should remain constant
* for its lifespan.
*
* Elements are generally tied to a block or tile entity in world. In such as case, one should provide the
* {@link IWiredElement} capability for the appropriate sides.
*/
public interface IWiredElement extends IWiredSender
{
/**
* Called when objects on the network change. This may occur when network nodes are added or removed, or when
* peripherals change.
*
* @param change The change which occurred.
* @see IWiredNetworkChange
*/
default void networkChanged( @Nonnull IWiredNetworkChange change )
{
}
}

View File

@@ -0,0 +1,86 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.network.wired;
import dan200.computercraft.api.peripheral.IPeripheral;
import javax.annotation.Nonnull;
import java.util.Map;
/**
* A wired network is composed of one of more {@link IWiredNode}s, a set of connections between them, and a series
* of peripherals.
*
* Networks from a connected graph. This means there is some path between all nodes on the network. Further more, if
* there is some path between two nodes then they must be on the same network. {@link IWiredNetwork} will automatically
* handle the merging and splitting of networks (and thus changing of available nodes and peripherals) as connections
* change.
*
* This does mean one can not rely on the network remaining consistent between subsequent operations. Consequently,
* it is generally preferred to use the methods provided by {@link IWiredNode}.
*
* @see IWiredNode#getNetwork()
*/
public interface IWiredNetwork
{
/**
* Create a connection between two nodes.
*
* This should only be used on the server thread.
*
* @param left The first node to connect
* @param right The second node to connect
* @return {@code true} if a connection was created or {@code false} if the connection already exists.
* @throws IllegalStateException If neither node is on the network.
* @throws IllegalArgumentException If {@code left} and {@code right} are equal.
* @see IWiredNode#connectTo(IWiredNode)
* @see IWiredNetwork#connect(IWiredNode, IWiredNode)
*/
boolean connect( @Nonnull IWiredNode left, @Nonnull IWiredNode right );
/**
* Destroy a connection between this node and another.
*
* This should only be used on the server thread.
*
* @param left The first node in the connection.
* @param right The second node in the connection.
* @return {@code true} if a connection was destroyed or {@code false} if no connection exists.
* @throws IllegalArgumentException If either node is not on the network.
* @throws IllegalArgumentException If {@code left} and {@code right} are equal.
* @see IWiredNode#disconnectFrom(IWiredNode)
* @see IWiredNetwork#connect(IWiredNode, IWiredNode)
*/
boolean disconnect( @Nonnull IWiredNode left, @Nonnull IWiredNode right );
/**
* Sever all connections this node has, removing it from this network.
*
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
*
* @param node The node to remove
* @return Whether this node was removed from the network. One cannot remove a node from a network where it is the
* only element.
* @throws IllegalArgumentException If the node is not in the network.
* @see IWiredNode#remove()
*/
boolean remove( @Nonnull IWiredNode node );
/**
* Update the peripherals a node provides.
*
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
*
* @param node The node to attach peripherals for.
* @param peripherals The new peripherals for this node.
* @throws IllegalArgumentException If the node is not in the network.
* @see IWiredNode#updatePeripherals(Map)
*/
void updatePeripherals( @Nonnull IWiredNode node, @Nonnull Map<String, IPeripheral> peripherals );
}

View File

@@ -0,0 +1,38 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.network.wired;
import dan200.computercraft.api.peripheral.IPeripheral;
import javax.annotation.Nonnull;
import java.util.Map;
/**
* Represents a change to the objects on a wired network.
*
* @see IWiredElement#networkChanged(IWiredNetworkChange)
*/
public interface IWiredNetworkChange
{
/**
* A set of peripherals which have been removed. Note that there may be entries with the same name
* in the added and removed set, but with a different peripheral.
*
* @return The set of removed peripherals.
*/
@Nonnull
Map<String, IPeripheral> peripheralsRemoved();
/**
* A set of peripherals which have been added. Note that there may be entries with the same name
* in the added and removed set, but with a different peripheral.
*
* @return The set of added peripherals.
*/
@Nonnull
Map<String, IPeripheral> peripheralsAdded();
}

View File

@@ -0,0 +1,109 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.network.wired;
import dan200.computercraft.api.network.IPacketNetwork;
import dan200.computercraft.api.peripheral.IPeripheral;
import javax.annotation.Nonnull;
import java.util.Map;
/**
* Wired nodes act as a layer between {@link IWiredElement}s and {@link IWiredNetwork}s.
*
* Firstly, a node acts as a packet network, capable of sending and receiving modem messages to connected nodes. These
* methods may be safely used on any thread.
*
* When sending a packet, the system will attempt to find the shortest path between the two nodes based on their
* element's position. Note that packet senders and receivers can have different locations from their associated
* element: the distance between the two will be added to the total packet's distance.
*
* Wired nodes also provide several convenience methods for interacting with a wired network. These should only ever
* be used on the main server thread.
*/
public interface IWiredNode extends IPacketNetwork
{
/**
* The associated element for this network node.
*
* @return This node's element.
*/
@Nonnull
IWiredElement getElement();
/**
* The network this node is currently connected to. Note that this may change
* after any network operation, so it should not be cached.
*
* This should only be used on the server thread.
*
* @return This node's network.
*/
@Nonnull
IWiredNetwork getNetwork();
/**
* Create a connection from this node to another.
*
* This should only be used on the server thread.
*
* @param node The other node to connect to.
* @return {@code true} if a connection was created or {@code false} if the connection already exists.
* @see IWiredNetwork#connect(IWiredNode, IWiredNode)
* @see IWiredNode#disconnectFrom(IWiredNode)
*/
default boolean connectTo( @Nonnull IWiredNode node )
{
return getNetwork().connect( this, node );
}
/**
* Destroy a connection between this node and another.
*
* This should only be used on the server thread.
*
* @param node The other node to disconnect from.
* @return {@code true} if a connection was destroyed or {@code false} if no connection exists.
* @throws IllegalArgumentException If {@code node} is not on the same network.
* @see IWiredNetwork#disconnect(IWiredNode, IWiredNode)
* @see IWiredNode#connectTo(IWiredNode)
*/
default boolean disconnectFrom( @Nonnull IWiredNode node )
{
return getNetwork().disconnect( this, node );
}
/**
* Sever all connections this node has, removing it from this network.
*
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
*
* @return Whether this node was removed from the network. One cannot remove a node from a network where it is the
* only element.
* @throws IllegalArgumentException If the node is not in the network.
* @see IWiredNetwork#remove(IWiredNode)
*/
default boolean remove()
{
return getNetwork().remove( this );
}
/**
* Mark this node's peripherals as having changed.
*
* This should only be used on the server thread. You should only call this on nodes
* that your network element owns.
*
* @param peripherals The new peripherals for this node.
* @see IWiredNetwork#updatePeripherals(IWiredNode, Map)
*/
default void updatePeripherals( @Nonnull Map<String, IPeripheral> peripherals )
{
getNetwork().updatePeripherals( this, peripherals );
}
}

View File

@@ -0,0 +1,31 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.network.wired;
import dan200.computercraft.api.network.IPacketSender;
import javax.annotation.Nonnull;
/**
* An object on a {@link IWiredNetwork} capable of sending packets.
*
* Unlike a regular {@link IPacketSender}, this must be associated with the node you are attempting to
* to send the packet from.
*/
public interface IWiredSender extends IPacketSender
{
/**
* The node in the network representing this object.
*
* This should be used as a proxy for the main network. One should send packets
* and register receivers through this object.
*
* @return The node for this element.
*/
@Nonnull
IWiredNode getNode();
}

View File

@@ -0,0 +1,215 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.peripheral;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaTask;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Map;
/**
* 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 computer's file system in a read only mode.
*
* @param desiredLocation 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.
* @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a
* file in the desired location. Store this value if you wish to unmount the mount later.
* @throws RuntimeException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see #mount(String, IMount, String)
* @see #mountWritable(String, IWritableMount)
* @see #unmount(String)
* @see IMount
*/
@Nullable
default String mount( @Nonnull String desiredLocation, @Nonnull IMount mount )
{
return mount( desiredLocation, mount, getAttachmentName() );
}
/**
* Mount a mount onto the computer's file system in a read only mode.
*
* @param desiredLocation 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.
* @param driveName A custom name to give for this mount location, as returned by {@code fs.getDrive()}.
* @return The location on the computer's file system where you the mount mounted, or {@code null} if there was already a
* file in the desired location. Store this value if you wish to unmount the mount later.
* @throws RuntimeException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see #mount(String, IMount)
* @see #mountWritable(String, IWritableMount)
* @see #unmount(String)
* @see IMount
*/
@Nullable
String mount( @Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName );
/**
* Mount a mount onto the computer's file system in a writable mode.
*
* @param desiredLocation 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.
* @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.
* @throws RuntimeException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see #mount(String, IMount)
* @see #unmount(String)
* @see IMount
*/
@Nullable
default String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount )
{
return mountWritable( desiredLocation, mount, getAttachmentName() );
}
/**
* Mount a mount onto the computer's file system in a writable mode.
*
* @param desiredLocation 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.
* @param driveName A custom name to give for this mount location, as returned by {@code fs.getDrive()}.
* @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.
* @throws RuntimeException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(World, String, long)
* @see ComputerCraftAPI#createResourceMount(Class, String, String)
* @see #mount(String, IMount)
* @see #unmount(String)
* @see IMount
*/
String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount, @Nonnull String driveName );
/**
* Unmounts a directory previously mounted onto the computers file system by {@link #mount(String, IMount)}
* or {@link #mountWritable(String, IWritableMount)}.
*
* 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.
*
* Note that you cannot unmount another peripheral's mounts.
*
* @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 {@link #mount(String, IMount)} or
* {@link #mountWritable(String, IWritableMount)}, as indicated by their return value.
* @throws RuntimeException If the peripheral has been detached.
* @throws RuntimeException If the mount does not exist, or was mounted by another peripheral.
* @see #mount(String, IMount)
* @see #mountWritable(String, IWritableMount)
*/
void unmount( @Nullable String location );
/**
* Returns the numerical ID of this computer.
*
* This is the same number obtained by calling {@code os.getComputerID()} or running the "id" program from lua,
* and is guaranteed unique. This number will be positive.
*
* @return The identifier.
*/
int getID();
/**
* Causes an event to be raised on this computer, which the computer can respond to by calling
* {@code 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 {@code 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().
*
* You may supply {@code null} to indicate that no arguments are to be supplied.
* @throws RuntimeException If the peripheral has been detached.
* @see IPeripheral#callMethod
*/
void queueEvent( @Nonnull String event, @Nullable 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.
* @throws RuntimeException If the peripheral has been detached.
*/
@Nonnull
String getAttachmentName();
/**
* Get a set of peripherals that this computer access can "see", along with their attachment name.
*
* This may include other peripherals on the wired network or peripherals on other sides of the computer.
*
* @return All reachable peripherals
* @see #getAttachmentName()
* @see #getAvailablePeripheral(String)
*/
@Nonnull
default Map<String, IPeripheral> getAvailablePeripherals()
{
return Collections.emptyMap();
}
/**
* Get a reachable peripheral with the given attachment name. This is a equivalent to
* {@link #getAvailablePeripherals()}{@code .get(name)}, though may be more efficient.
*
* @param name The peripheral's attached name
* @return The reachable peripheral, or {@code null} if none can be found.
* @see #getAvailablePeripherals()
*/
@Nullable
default IPeripheral getAvailablePeripheral( @Nonnull String name )
{
return null;
}
/**
* Get a {@link IWorkMonitor} for tasks your peripheral might execute on the main (server) thread.
*
* This should be used to ensure your peripheral integrates with ComputerCraft's monitoring and limiting of how much
* server time each computer consumes. You should not need to use this if you use
* {@link ILuaContext#issueMainThreadTask(ILuaTask)} - this is intended for mods with their own system for running
* work on the main thread.
*
* Please note that the returned implementation is <em>not</em> thread-safe, and should only be used from the main
* thread.
*
* @return The work monitor for the main thread, or {@code null} if this computer does not have one.
*/
@Nullable
default IWorkMonitor getMainThreadMonitor()
{
return null;
}
}

View File

@@ -0,0 +1,142 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.peripheral;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* The interface that defines a peripheral. See {@link IPeripheralProvider} for how to associate blocks with peripherals.
*/
public interface IPeripheral
{
/**
* Should return a string that uniquely identifies this type of peripheral.
* This can be queried from lua by calling {@code peripheral.getType()}
*
* @return A string identifying the type of peripheral.
*/
@Nonnull
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
*/
@Nonnull
String[] getMethodNames();
/**
* This is called when a lua program on an attached computer calls {@code peripheral.call()} with
* one of the methods exposed by {@link #getMethodNames()}.
*
* 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 computercraft
* 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 {@code 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 type "table" will be represented by Object type Map.<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. Integers, Doubles, Floats,
* Strings, Booleans, Maps and ILuaObject and null be converted to their corresponding lua type. All other types
* will be converted to nil.
*
* You may return null to indicate no values should be returned.
* @throws LuaException 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.
* @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 #getMethodNames
*/
@Nullable
Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException;
/**
* Is called when when 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, when a turtle travels into a square next to a peripheral, or when a wired modem adjacent to this
* peripheral is does any of the above.
*
* Between calls to attach and {@link #detach}, the attached computer can make method calls on the peripheral using
* {@code 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.
*
* Be aware that will be called from both the server thread and ComputerCraft Lua thread, and so must be thread-safe
* and reentrant.
*
* @param computer The interface to the computer that is being attached. Remember that multiple computers can be
* attached to a peripheral at once.
* @see #detach
*/
default void attach( @Nonnull IComputerAccess computer )
{
}
/**
* 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, when a
* turtle moves away from a block attached to a peripheral, or when a wired modem adjacent to this peripheral is
* detached.
*
* This method can be used to keep track of which computers are attached to the peripheral, or to take action when
* detachment occurs.
*
* Be aware that this will be called from both the server and ComputerCraft Lua thread, and must be thread-safe
* and reentrant.
*
* @param computer The interface to the computer that is being detached. Remember that multiple computers can be
* attached to a peripheral at once.
* @see #attach
*/
default void detach( @Nonnull IComputerAccess computer )
{
}
/**
* Get the object that this peripheral provides methods for. This will generally be the tile entity
* or block, but may be an inventory, entity, etc...
*
* @return The object this peripheral targets
*/
@Nonnull
default Object getTarget()
{
return this;
}
/**
* Determine whether this peripheral is equivalent to another one.
*
* The minimal example should at least check whether they are the same object. However, you may wish to check if
* they point to the same block or tile entity.
*
* @param other The peripheral to compare against. This may be {@code null}.
* @return Whether these peripherals are equivalent.
*/
boolean equals( @Nullable IPeripheral other );
}

View File

@@ -0,0 +1,39 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.peripheral;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* This interface is used to create peripheral implementations for blocks.
*
* If you have a {@link BlockEntity} which acts as a peripheral, you may alternatively implement
* {@link IPeripheralTile}.
*
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
*/
@FunctionalInterface
public interface IPeripheralProvider
{
/**
* Produce an peripheral implementation from a block location.
*
* @param world The world the block is in.
* @param pos The position the block is at.
* @param side The side to get the peripheral from.
* @return A peripheral, or {@code null} if there is not a peripheral here you'd like to handle.
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
*/
@Nullable
IPeripheral getPeripheral( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side );
}

View File

@@ -0,0 +1,32 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.peripheral;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* A {@link net.minecraft.block.entity.BlockEntity} which may act as a peripheral.
*
* If you need more complex capabilities (such as handling TEs not belonging to your mod), you should use
* {@link IPeripheralProvider}.
*/
public interface IPeripheralTile
{
/**
* Get the peripheral on the given {@code side}.
*
* @param side The side to get the peripheral from.
* @return A peripheral, or {@code null} if there is not a peripheral here.
* @see IPeripheralProvider#getPeripheral(World, BlockPos, Direction)
*/
@Nullable
IPeripheral getPeripheral( @Nonnull Direction side );
}

View File

@@ -0,0 +1,78 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.peripheral;
import javax.annotation.Nonnull;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
/**
* Monitors "work" associated with a computer, keeping track of how much a computer has done, and ensuring every
* computer receives a fair share of any processing time.
*
* This is primarily intended for work done by peripherals on the main thread (such as on a tile entity's tick), but
* could be used for other purposes (such as complex computations done on another thread).
*
* Before running a task, one should call {@link #canWork()} to determine if the computer is currently allowed to
* execute work. If that returns true, you should execute the task and use {@link #trackWork(long, TimeUnit)} to inform
* the monitor how long that task took.
*
* Alternatively, use {@link #runWork(Runnable)} to run and keep track of work.
*
* @see IComputerAccess#getMainThreadMonitor()
*/
public interface IWorkMonitor
{
/**
* If the owning computer is currently allowed to execute work.
*
* @return If we can execute work right now.
*/
boolean canWork();
/**
* If the owning computer is currently allowed to execute work, and has ample time to do so.
*
* This is effectively a more restrictive form of {@link #canWork()}. One should use that in order to determine if
* you may do an initial piece of work, and shouldWork to determine if any additional task may be performed.
*
* @return If we should execute work right now.
*/
boolean shouldWork();
/**
* Inform the monitor how long some piece of work took to execute.
*
* @param time The time some task took to run
* @param unit The unit that {@code time} was measured in.
*/
void trackWork( long time, @Nonnull TimeUnit unit );
/**
* Run a task if possible, and inform the monitor of how long it took.
*
* @param runnable The task to run.
* @return If the task was actually run (namely, {@link #canWork()} returned {@code true}).
*/
default boolean runWork( @Nonnull Runnable runnable )
{
Objects.requireNonNull( runnable, "runnable should not be null" );
if( !canWork() ) return false;
long start = System.nanoTime();
try
{
runnable.run();
}
finally
{
trackWork( System.nanoTime() - start, TimeUnit.NANOSECONDS );
}
return true;
}
}

View File

@@ -0,0 +1,63 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.pocket;
import net.minecraft.item.ItemConvertible;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import javax.annotation.Nonnull;
/**
* A base class for {@link IPocketUpgrade}s.
*
* One does not have to use this, but it does provide a convenient template.
*/
public abstract class AbstractPocketUpgrade implements IPocketUpgrade
{
private final Identifier id;
private final String adjective;
private final ItemStack stack;
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack )
{
this.id = id;
this.adjective = adjective;
this.stack = stack;
}
protected AbstractPocketUpgrade( Identifier identifier, String adjective, ItemConvertible item )
{
this( identifier, adjective, new ItemStack( item ) );
}
protected AbstractPocketUpgrade( Identifier id, ItemConvertible item )
{
this( id, Util.createTranslationKey( "upgrade", id ) + ".adjective", new ItemStack( item ) );
}
@Nonnull
@Override
public final Identifier getUpgradeID()
{
return id;
}
@Nonnull
@Override
public final String getUnlocalisedAdjective()
{
return adjective;
}
@Nonnull
@Override
public final ItemStack getCraftingItem()
{
return stack;
}
}

View File

@@ -0,0 +1,99 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.pocket;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.entity.Entity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Identifier;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Map;
/**
* Wrapper class for pocket computers
*/
public interface IPocketAccess
{
/**
* Gets the entity holding this item.
*
* This must be called on the server thread.
*
* @return The holding entity, or {@code null} if none exists.
*/
@Nullable
Entity getEntity();
/**
* Get the colour of this pocket computer as a RGB number.
*
* @return The colour this pocket computer is. This will be a RGB colour between {@code 0x000000} and
* {@code 0xFFFFFF} or -1 if it has no colour.
* @see #setColour(int)
*/
int getColour();
/**
* Set the colour of the pocket computer to a RGB number.
*
* @param colour The colour this pocket computer should be changed to. This should be a RGB colour between
* {@code 0x000000} and {@code 0xFFFFFF} or -1 to reset to the default colour.
* @see #getColour()
*/
void setColour( int colour );
/**
* Get the colour of this pocket computer's light as a RGB number.
*
* @return The colour this light is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or
* -1 if it has no colour.
* @see #setLight(int)
*/
int getLight();
/**
* Set the colour of the pocket computer's light to a RGB number.
*
* @param colour The colour this modem's light will be changed to. This should be a RGB colour between
* {@code 0x000000} and {@code 0xFFFFFF} or -1 to reset to the default colour.
* @see #getLight()
*/
void setLight( int colour );
/**
* Get the upgrade-specific NBT.
*
* This is persisted between computer reboots and chunk loads.
*
* @return The upgrade's NBT.
* @see #updateUpgradeNBTData()
*/
@Nonnull
CompoundTag getUpgradeNBTData();
/**
* Mark the upgrade-specific NBT as dirty.
*
* @see #getUpgradeNBTData()
*/
void updateUpgradeNBTData();
/**
* Remove the current peripheral and create a new one. You may wish to do this if the methods available change.
*/
void invalidatePeripheral();
/**
* Get a list of all upgrades for the pocket computer.
*
* @return A collection of all upgrade names.
*/
@Nonnull
Map<Identifier, IPeripheral> getUpgrades();
}

View File

@@ -0,0 +1,105 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.pocket;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Additional peripherals for pocket computers.
*
* This is similar to {@link ITurtleUpgrade}.
*/
public interface IPocketUpgrade
{
/**
* Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem" or
* "my_mod:my_upgrade".
*
* You should use a unique resource domain to ensure this upgrade is uniquely identified. The upgrade will fail
* registration if an already used ID is specified.
*
* @return The upgrade's id.
* @see IPocketUpgrade#getUpgradeID()
* @see ComputerCraftAPI#registerPocketUpgrade(IPocketUpgrade)
*/
@Nonnull
Identifier getUpgradeID();
/**
* Return an unlocalised string to describe the type of pocket computer this upgrade provides.
*
* An example of a built-in adjectives is "Wireless" - this is converted to "Wireless Pocket Computer".
*
* @return The unlocalised adjective.
* @see ITurtleUpgrade#getUnlocalisedAdjective()
*/
@Nonnull
String getUnlocalisedAdjective();
/**
* Return an item stack representing the type of item that a pocket computer must be crafted with to create a
* pocket computer which holds this upgrade. This item stack is also used to determine the upgrade given by
* {@code pocket.equip()}/{@code pocket.unequip()}.
*
* Ideally this should be constant over a session. It is recommended that you cache
* the item too, in order to prevent constructing it every time the method is called.
*
* @return The item stack used for crafting. This can be {@link ItemStack#EMPTY} if crafting is disabled.
*/
@Nonnull
ItemStack getCraftingItem();
/**
* Creates a peripheral for the pocket computer.
*
* The peripheral created will be stored for the lifetime of the upgrade, will be passed an argument to
* {@link #update(IPocketAccess, IPeripheral)} and will be attached, detached and have methods called in the same
* manner as an ordinary peripheral.
*
* @param access The access object for the pocket item stack.
* @return The newly created peripheral.
* @see #update(IPocketAccess, IPeripheral)
*/
@Nullable
IPeripheral createPeripheral( @Nonnull IPocketAccess access );
/**
* Called when the pocket computer item stack updates.
*
* @param access The access object for the pocket item stack.
* @param peripheral The peripheral for this upgrade.
* @see #createPeripheral(IPocketAccess)
*/
default void update( @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral )
{
}
/**
* Called when the pocket computer is right clicked.
*
* @param world The world the computer is in.
* @param access The access object for the pocket item stack.
* @param peripheral The peripheral for this upgrade.
* @return {@code true} to stop the GUI from opening, otherwise false. You should always provide some code path
* which returns {@code false}, such as requiring the player to be sneaking - otherwise they will be unable to
* access the GUI.
* @see #createPeripheral(IPocketAccess)
*/
default boolean onRightClick( @Nonnull World world, @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral )
{
return false;
}
}

View File

@@ -0,0 +1,34 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.redstone;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
/**
* This interface is used to provide bundled redstone output for blocks.
*
* @see dan200.computercraft.api.ComputerCraftAPI#registerBundledRedstoneProvider(IBundledRedstoneProvider)
*/
@FunctionalInterface
public interface IBundledRedstoneProvider
{
/**
* Produce an bundled redstone output from a block location.
*
* @param world The world this block is in.
* @param pos The position this block is at.
* @param side The side to extract the bundled redstone output from.
* @return A number in the range 0-65535 to indicate this block is providing output, or -1 if you do not wish to
* handle this block.
* @see dan200.computercraft.api.ComputerCraftAPI#registerBundledRedstoneProvider(IBundledRedstoneProvider)
*/
int getBundledRedstoneOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side );
}

View File

@@ -0,0 +1,290 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle;
import com.mojang.authlib.GameProfile;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IPeripheral;
import net.minecraft.inventory.Inventory;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* The interface passed to turtle 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
* {@link ITurtleUpgrade}.
*/
public interface ITurtleAccess
{
/**
* Returns the world in which the turtle resides.
*
* @return the world in which the turtle resides.
*/
@Nonnull
World getWorld();
/**
* Returns a vector containing the integer co-ordinates at which the turtle resides.
*
* @return a vector containing the integer co-ordinates at which the turtle resides.
*/
@Nonnull
BlockPos getPosition();
/**
* Attempt to move this turtle to a new position.
*
* This will preserve the turtle's internal state, such as it's inventory, computer and upgrades. It should
* be used before playing a movement animation using {@link #playAnimation(TurtleAnimation)}.
*
* @param world The new world to move it to
* @param pos The new position to move it to.
* @return Whether the movement was successful. It may fail if the block was not loaded or the block placement
* was cancelled.
* @throws UnsupportedOperationException When attempting to teleport on the client side.
*/
boolean teleportTo( @Nonnull World world, @Nonnull BlockPos pos );
/**
* Returns a vector containing the floating point 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 floating point co-ordinates at which the turtle resides.
* @see #getVisualYaw(float)
*/
@Nonnull
Vec3d getVisualPosition( float f );
/**
* Returns the yaw the turtle is facing when it is rendered.
*
* @param f The subframe fraction.
* @return The yaw the turtle is facing.
* @see #getVisualPosition(float)
*/
float getVisualYaw( float f );
/**
* Returns the world direction the turtle is currently facing.
*
* @return The world direction the turtle is currently facing.
* @see #setDirection(Direction)
*/
@Nonnull
Direction getDirection();
/**
* Set the direction the turtle is facing. Note that this will not play a rotation animation, you will also need to
* call {@link #playAnimation(TurtleAnimation)} to do so.
*
* @param dir The new direction to set. This should be on either the x or z axis (so north, south, east or west).
* @see #getDirection()
*/
void setDirection( @Nonnull Direction dir );
/**
* Get the currently selected slot in the turtle's inventory.
*
* @return An integer representing the current slot.
* @see #getInventory()
* @see #setSelectedSlot(int)
*/
int getSelectedSlot();
/**
* Set the currently selected slot in the turtle's inventory.
*
* @param slot The slot to set. This must be greater or equal to 0 and less than the inventory size. Otherwise no
* action will be taken.
* @throws UnsupportedOperationException When attempting to change the slot on the client side.
* @see #getInventory()
* @see #getSelectedSlot()
*/
void setSelectedSlot( int slot );
/**
* Set the colour of the turtle to a RGB number.
*
* @param colour The colour this turtle should be changed to. This should be a RGB colour between {@code 0x000000}
* and {@code 0xFFFFFF} or -1 to reset to the default colour.
* @see #getColour()
*/
void setColour( int colour );
/**
* Get the colour of this turtle as a RGB number.
*
* @return The colour this turtle is. This will be a RGB colour between {@code 0x000000} and {@code 0xFFFFFF} or
* -1 if it has no colour.
* @see #setColour(int)
*/
int getColour();
/**
* Get the player who owns this turtle, namely whoever placed it.
*
* @return This turtle's owner.
*/
@Nonnull
GameProfile getOwningPlayer();
/**
* Get the inventory of this turtle
*
* @return This turtle's inventory
*/
@Nonnull
Inventory getInventory();
/**
* Determine whether this turtle will require fuel when performing actions.
*
* @return Whether this turtle needs fuel.
* @see #getFuelLevel()
* @see #setFuelLevel(int)
*/
boolean isFuelNeeded();
/**
* Get the current fuel level of this turtle.
*
* @return The turtle's current fuel level.
* @see #isFuelNeeded()
* @see #setFuelLevel(int)
*/
int getFuelLevel();
/**
* Set the fuel level to a new value. It is generally preferred to use {@link #consumeFuel(int)}} or {@link #addFuel(int)}
* instead.
*
* @param fuel The new amount of fuel. This must be between 0 and the fuel limit.
* @see #getFuelLevel()
* @see #getFuelLimit()
* @see #addFuel(int)
* @see #consumeFuel(int)
*/
void setFuelLevel( int fuel );
/**
* Get the maximum amount of fuel a turtle can hold.
*
* @return The turtle's fuel limit.
*/
int getFuelLimit();
/**
* Removes some fuel from the turtles fuel supply. Negative numbers can be passed in to INCREASE the fuel level of the turtle.
*
* @param fuel The amount of fuel to consume.
* @return Whether the turtle was able to consume the amount of fuel specified. Will return false if you supply a number
* greater than the current fuel level of the turtle. No fuel will be consumed if {@code false} is returned.
* @throws UnsupportedOperationException When attempting to consume fuel on the client side.
*/
boolean consumeFuel( int fuel );
/**
* Increase the turtle's fuel level by the given amount.
*
* @param fuel The amount to refuel with.
* @throws UnsupportedOperationException When attempting to refuel on the client side.
*/
void addFuel( 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 context The Lua context to pull events from.
* @param command An object which will execute the custom command when its point in the queue is reached
* @return The objects the command returned when executed. you should probably return these to the player
* unchanged if called from a peripheral method.
* @throws UnsupportedOperationException When attempting to execute a command on the client side.
* @throws LuaException If the user presses CTRL+T to terminate the current program while {@code executeCommand()} is
* waiting for an event, a "Terminated" exception will be thrown here.
* @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.
* @see ITurtleCommand
* @see ILuaContext#pullEvent(String)
*/
@Nonnull
Object[] executeCommand( @Nonnull ILuaContext context, @Nonnull ITurtleCommand command ) throws LuaException, InterruptedException;
/**
* Start playing a specific animation. This will prevent other turtle commands from executing until
* it is finished.
*
* @param animation The animation to play.
* @throws UnsupportedOperationException When attempting to execute play an animation on the client side.
* @see TurtleAnimation
*/
void playAnimation( @Nonnull TurtleAnimation animation );
/**
* Returns the turtle on the specified side of the turtle, if there is one.
*
* @param side The side to get the upgrade from.
* @return The upgrade on the specified side of the turtle, if there is one.
* @see #setUpgrade(TurtleSide, ITurtleUpgrade)
*/
@Nullable
ITurtleUpgrade getUpgrade( @Nonnull TurtleSide side );
/**
* Set the upgrade for a given side, resetting peripherals and clearing upgrade specific data.
*
* @param side The side to set the upgrade on.
* @param upgrade The upgrade to set, may be {@code null} to clear.
* @see #getUpgrade(TurtleSide)
*/
void setUpgrade( @Nonnull TurtleSide side, @Nullable ITurtleUpgrade upgrade );
/**
* Returns the peripheral created by the upgrade on the specified side of the turtle, if there is one.
*
* @param side The side to get the peripheral from.
* @return The peripheral created by the upgrade on the specified side of the turtle, {@code null} if none exists.
*/
@Nullable
IPeripheral getPeripheral( @Nonnull TurtleSide side );
/**
* Get an upgrade-specific NBT compound, which can be used to store arbitrary data.
*
* This will be persisted across turtle restarts and chunk loads, as well as being synced to the client. You must
* call {@link #updateUpgradeNBTData(TurtleSide)} after modifying it.
*
* @param side The side to get the upgrade data for.
* @return The upgrade-specific data.
* @see #updateUpgradeNBTData(TurtleSide)
*/
@Nonnull
CompoundTag getUpgradeNBTData( @Nullable TurtleSide side );
/**
* Mark the upgrade-specific data as dirty on a specific side. This is required for the data to be synced to the
* client and persisted.
*
* @param side The side to mark dirty.
* @see #updateUpgradeNBTData(TurtleSide)
*/
void updateUpgradeNBTData( @Nonnull TurtleSide side );
}

View File

@@ -0,0 +1,36 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle;
import dan200.computercraft.api.lua.ILuaContext;
import javax.annotation.Nonnull;
/**
* An interface for objects executing custom turtle commands, used with {@link ITurtleAccess#executeCommand(ILuaContext, ITurtleCommand)}.
*
* @see ITurtleAccess#executeCommand(ILuaContext, ITurtleCommand)
*/
@FunctionalInterface
public interface ITurtleCommand
{
/**
* 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 success, or return
* failure with an error message to indicate the command cannot be executed at this time.
*
* @param turtle Access to the turtle for whom the command was issued.
* @return A result, indicating whether this action succeeded or not.
* @see ITurtleAccess#executeCommand(ILuaContext, ITurtleCommand)
* @see TurtleCommandResult#success()
* @see TurtleCommandResult#failure(String)
* @see TurtleCommandResult
*/
@Nonnull
TurtleCommandResult execute( @Nonnull ITurtleAccess turtle );
}

View File

@@ -0,0 +1,144 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.api.turtle.event.TurtleAttackEvent;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.ModelIdentifier;
import net.minecraft.item.ItemStack;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.Direction;
import org.apache.commons.lang3.tuple.Pair;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.vecmath.Matrix4f;
/**
* The primary interface for defining an update for Turtles. A turtle update
* can either be a new tool, or a new peripheral.
*
* @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade)
*/
public interface ITurtleUpgrade
{
/**
* Gets a unique identifier representing this type of turtle upgrade. eg: "computercraft:wireless_modem" or "my_mod:my_upgrade".
* You should use a unique resource domain to ensure this upgrade is uniquely identified.
* The turtle will fail registration if an already used ID is specified.
*
* @return The unique ID for this upgrade.
* @see ComputerCraftAPI#registerTurtleUpgrade(ITurtleUpgrade)
*/
@Nonnull
Identifier getUpgradeID();
/**
* Return an unlocalised string to describe this type of turtle in turtle item names.
*
* Examples of built-in adjectives are "Wireless", "Mining" and "Crafty".
*
* @return The localisation key for this upgrade's adjective.
*/
@Nonnull
String getUnlocalisedAdjective();
/**
* Return whether this turtle adds a tool or a peripheral to the turtle.
*
* @return The type of upgrade this is.
* @see TurtleUpgradeType for the differences between them.
*/
@Nonnull
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. This item stack is also used
* to determine the upgrade given by {@code turtle.equip()}
*
* Ideally this should be constant over a session. It is recommended that you cache
* the item too, in order to prevent constructing it every time the method is called.
*
* @return The item stack to craft with, or {@link ItemStack#EMPTY} if it cannot be crafted.
*/
@Nonnull
ItemStack getCraftingItem();
/**
* 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 upgrade and will be passed as an argument to
* {@link #update(ITurtleAccess, TurtleSide)}. It will be attached, detached 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.
* @return The newly created peripheral. You may return {@code null} if this upgrade is a Tool
* and this method is not expected to be called.
*/
@Nullable
default IPeripheral createPeripheral( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side )
{
return null;
}
/**
* Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called
* by the turtle, and the tool is required to do some work.
*
* Conforming implementations should fire {@code BlockEvent.BreakEvent} and {@link TurtleBlockEvent.Dig}for digging,
* {@code AttackEntityEvent} and {@link TurtleAttackEvent} for attacking.
*
* @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 {@code turtle.dig()}
* or {@code turtle.attack()} lua method should return true. If true is returned, the tool will perform
* a swinging animation. You may return {@code null} if this turtle is a Peripheral and this method is not expected
* to be called.
*/
@Nonnull
default TurtleCommandResult useTool( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side, @Nonnull TurtleVerb verb, @Nonnull Direction direction )
{
return TurtleCommandResult.failure();
}
/**
* Called to obtain the model to be used when rendering a turtle peripheral.
*
* This can be obtained from {@link net.minecraft.client.render.item.ItemModels#getModel(ItemStack)},
* {@link net.minecraft.client.render.model.BakedModelManager#getModel(ModelIdentifier)} or any other
* source.
*
* @param turtle Access to the turtle that the upgrade resides on. This will be null when getting item models!
* @param side Which side of the turtle (left or right) the upgrade resides on.
* @return The model that you wish to be used to render your upgrade, and a transformation to apply to it. Returning
* a transformation of {@code null} has the same effect as the identify matrix.
*/
@Nonnull
@Environment( EnvType.CLIENT )
Pair<BakedModel, Matrix4f> getModel( @Nullable ITurtleAccess turtle, @Nonnull TurtleSide side );
/**
* Called once per tick for each turtle which has the upgrade equipped.
*
* @param turtle Access to the turtle that the upgrade resides on.
* @param side Which side of the turtle (left or right) the upgrade resides on.
*/
default void update( @Nonnull ITurtleAccess turtle, @Nonnull TurtleSide side )
{
}
}

View File

@@ -0,0 +1,87 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle;
/**
* An animation a turtle will play between executing commands.
*
* Each animation takes 8 ticks to complete unless otherwise specified.
*
* @see ITurtleAccess#playAnimation(TurtleAnimation)
*/
public enum TurtleAnimation
{
/**
* An animation which does nothing. This takes no time to complete.
*
* @see #Wait
* @see #ShortWait
*/
None,
/**
* Make the turtle move forward. Note that the animation starts from the block <em>behind</em> it, and
* moves into this one.
*/
MoveForward,
/**
* Make the turtle move backwards. Note that the animation starts from the block <em>in front</em> it, and
* moves into this one.
*/
MoveBack,
/**
* Make the turtle move backwards. Note that the animation starts from the block <em>above</em> it, and
* moves into this one.
*/
MoveUp,
/**
* Make the turtle move backwards. Note that the animation starts from the block <em>below</em> it, and
* moves into this one.
*/
MoveDown,
/**
* Turn the turtle to the left. Note that the animation starts with the turtle facing <em>right</em>, and
* the turtle turns to face in the current direction.
*/
TurnLeft,
/**
* Turn the turtle to the left. Note that the animation starts with the turtle facing <em>right</em>, and
* the turtle turns to face in the current direction.
*/
TurnRight,
/**
* Swing the tool on the left.
*/
SwingLeftTool,
/**
* Swing the tool on the right.
*/
SwingRightTool,
/**
* Wait until the animation has finished, performing no movement.
*
* @see #ShortWait
* @see #None
*/
Wait,
/**
* Wait until the animation has finished, performing no movement. This takes 4 ticks to complete.
*
* @see #Wait
* @see #None
*/
ShortWait,
}

View File

@@ -0,0 +1,115 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle;
import net.minecraft.util.math.Direction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Used to indicate the result of executing a turtle command.
*
* @see ITurtleCommand#execute(ITurtleAccess)
* @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)
*/
public final class TurtleCommandResult
{
private static final TurtleCommandResult EMPTY_SUCCESS = new TurtleCommandResult( true, null, null );
private static final TurtleCommandResult EMPTY_FAILURE = new TurtleCommandResult( false, null, null );
/**
* Create a successful command result with no result.
*
* @return A successful command result with no values.
*/
@Nonnull
public static TurtleCommandResult success()
{
return EMPTY_SUCCESS;
}
/**
* Create a successful command result with the given result values.
*
* @param results The results of executing this command.
* @return A successful command result with the given values.
*/
@Nonnull
public static TurtleCommandResult success( @Nullable Object[] results )
{
if( results == null || results.length == 0 ) return EMPTY_SUCCESS;
return new TurtleCommandResult( true, null, results );
}
/**
* Create a failed command result with no error message.
*
* @return A failed command result with no message.
*/
@Nonnull
public static TurtleCommandResult failure()
{
return EMPTY_FAILURE;
}
/**
* Create a failed command result with an error message.
*
* @param errorMessage The error message to provide.
* @return A failed command result with a message.
*/
@Nonnull
public static TurtleCommandResult failure( @Nullable String errorMessage )
{
if( errorMessage == null ) return EMPTY_FAILURE;
return new TurtleCommandResult( false, errorMessage, null );
}
private final boolean success;
private final String errorMessage;
private final Object[] results;
private TurtleCommandResult( boolean success, String errorMessage, Object[] results )
{
this.success = success;
this.errorMessage = errorMessage;
this.results = results;
}
/**
* Determine whether the command executed successfully.
*
* @return If the command was successful.
*/
public boolean isSuccess()
{
return success;
}
/**
* Get the error message of this command result.
*
* @return The command's error message, or {@code null} if it was a success.
*/
@Nullable
public String getErrorMessage()
{
return errorMessage;
}
/**
* Get the resulting values of this command result.
*
* @return The command's result, or {@code null} if it was a failure.
*/
@Nullable
public Object[] getResults()
{
return results;
}
}

View File

@@ -0,0 +1,23 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle;
/**
* An enum representing the two sides of the turtle that a turtle turtle might reside.
*/
public enum TurtleSide
{
/**
* The turtle's left side (where the pickaxe usually is on a Wireless Mining Turtle)
*/
Left,
/**
* The turtle's right side (where the modem usually is on a Wireless Mining Turtle)
*/
Right,
}

View File

@@ -0,0 +1,44 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle;
/**
* An enum representing the different types of turtle that an {@link ITurtleUpgrade} implementation can add to a turtle.
*
* @see ITurtleUpgrade#getType()
*/
public enum TurtleUpgradeType
{
/**
* A tool is rendered as an item on the side of the turtle, and responds to the {@code turtle.dig()}
* and {@code 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 {@code peripheral} API (Such as the modem on Wireless Turtles).
*/
Peripheral,
/**
* An upgrade which provides both a tool and a peripheral. This can be used when you wish
* your upgrade to also provide methods. For example, a pickaxe could provide methods
* determining whether it can break the given block or not.
*/
Both;
public boolean isTool()
{
return this == Tool || this == Both;
}
public boolean isPeripheral()
{
return this == Peripheral || this == Both;
}
}

View File

@@ -0,0 +1,29 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle;
import net.minecraft.util.math.Direction;
/**
* An enum representing the different actions that an {@link ITurtleUpgrade} of type Tool may be called on to perform by
* a turtle.
*
* @see ITurtleUpgrade#getType()
* @see ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)
*/
public enum TurtleVerb
{
/**
* The turtle called {@code turtle.dig()}, {@code turtle.digUp()} or {@code turtle.digDown()}
*/
Dig,
/**
* The turtle called {@code turtle.attack()}, {@code turtle.attackUp()} or {@code turtle.attackDown()}
*/
Attack,
}

View File

@@ -0,0 +1,286 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2018. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.turtle.event;
import com.mojang.authlib.GameProfile;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.block.entity.CommandBlockBlockEntity;
import net.minecraft.block.entity.SignBlockEntity;
import net.minecraft.command.arguments.EntityAnchorArgumentType;
import net.minecraft.entity.Entity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.passive.HorseBaseEntity;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.network.ClientConnection;
import net.minecraft.network.MessageType;
import net.minecraft.network.NetworkSide;
import net.minecraft.network.NetworkState;
import net.minecraft.network.Packet;
import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket;
import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
import net.minecraft.recipe.Recipe;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.server.network.ServerPlayNetworkHandler;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.network.ServerPlayerInteractionManager;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.text.Text;
import net.minecraft.util.Hand;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.village.TraderOfferList;
import net.minecraft.world.GameMode;
import net.minecraft.world.dimension.DimensionType;
import javax.annotation.Nullable;
import javax.crypto.SecretKey;
import java.util.Collection;
import java.util.OptionalInt;
/**
* A wrapper for {@link ServerPlayerEntity} which denotes a "fake" player.
*
* Please note that this does not implement any of the traditional fake player behaviour. It simply exists to prevent
* me passing in normal players.
*/
public class FakePlayer extends ServerPlayerEntity
{
public FakePlayer( ServerWorld world, GameProfile gameProfile )
{
super( world.getServer(), world, gameProfile, new ServerPlayerInteractionManager( world ) );
networkHandler = new FakeNetHandler( this );
}
// region Direct networkHandler access
@Override
public void enterCombat() { }
@Override
public void endCombat() { }
@Override
public void tick() { }
@Override
public void playerTick() { }
@Override
public void onDeath( DamageSource damage ) { }
@Nullable
@Override
public Entity changeDimension( DimensionType dimension )
{
return this;
}
@Override
public void wakeUp( boolean resetTimer, boolean notify, boolean setSpawn ) { }
@Override
public boolean startRiding( Entity entity, boolean flag )
{
return false;
}
@Override
public void stopRiding() { }
@Override
public void openEditSignScreen( SignBlockEntity tile ) { }
@Override
public OptionalInt openHandledScreen( @Nullable NamedScreenHandlerFactory container )
{
return OptionalInt.empty();
}
@Override
public void sendTradeOffers( int id, TraderOfferList list, int level, int experience, boolean levelled, boolean refreshable ) { }
@Override
public void openHorseInventory( HorseBaseEntity horse, Inventory inventory ) { }
@Override
public void openEditBookScreen( ItemStack stack, Hand hand ) { }
@Override
public void openCommandBlockScreen( CommandBlockBlockEntity block ) { }
@Override
public void onSlotUpdate( ScreenHandler container, int slot, ItemStack stack ) { }
@Override
public void onHandlerRegistered( ScreenHandler container, DefaultedList<ItemStack> defaultedList ) { }
@Override
public void onPropertyUpdate( ScreenHandler container, int key, int value ) { }
@Override
public void closeHandledScreen() { }
@Override
public void updateCursorStack() { }
@Override
public void sendMessage( Text textComponent, boolean status ) { }
@Override
protected void consumeItem() { }
@Override
public void lookAt( EntityAnchorArgumentType.EntityAnchor anchor, Vec3d vec3d ) { }
@Override
public void method_14222( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target ) { }
@Override
protected void onStatusEffectApplied( StatusEffectInstance statusEffectInstance ) { }
@Override
protected void onStatusEffectUpgraded( StatusEffectInstance statusEffectInstance, boolean particles ) { }
@Override
protected void onStatusEffectRemoved( StatusEffectInstance statusEffectInstance ) { }
@Override
public void requestTeleport( double x, double y, double z ) { }
@Override
public void setGameMode( GameMode gameMode ) { }
@Override
public void sendMessage( Text textComponent, MessageType chatMessageType ) { }
@Override
public String getIp()
{
return "[Fake Player]";
}
@Override
public void sendResourcePackUrl( String url, String hash ) { }
@Override
public void onStoppedTracking( Entity entity ) { }
@Override
public void setCameraEntity( Entity entity ) { }
@Override
public void teleport( ServerWorld serverWorld, double x, double y, double z, float pitch, float yaw ) { }
@Override
public void sendInitialChunkPackets( ChunkPos chunkPos, Packet<?> packet, Packet<?> packet2 ) { }
@Override
public void sendUnloadChunkPacket( ChunkPos chunkPos ) { }
@Override
public void playSound( SoundEvent soundEvent, SoundCategory soundCategory, float volume, float pitch ) { }
// endregion
// Indirect
@Override
public int lockRecipes( Collection<Recipe<?>> recipes )
{
return 0;
}
@Override
public int unlockRecipes( Collection<Recipe<?>> recipes )
{
return 0;
}
//
private static class FakeNetHandler extends ServerPlayNetworkHandler
{
FakeNetHandler( ServerPlayerEntity player )
{
super( player.server, new FakeConnection(), player );
}
@Override
public void disconnect( Text message ) { }
@Override
public void onRequestCommandCompletions( RequestCommandCompletionsC2SPacket packet ) { }
@Override
public void sendPacket( Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> listener ) { }
@Override
public void onVehicleMove( VehicleMoveC2SPacket move ) { }
}
private static class FakeConnection extends ClientConnection
{
FakeConnection()
{
super( NetworkSide.CLIENTBOUND );
}
@Override
public void channelActive( ChannelHandlerContext active )
{
}
@Override
public void setState( NetworkState state )
{
}
@Override
public void disconnect( Text message )
{
}
@Override
public void exceptionCaught( ChannelHandlerContext context, Throwable err )
{
}
@Override
protected void channelRead0( ChannelHandlerContext context, Packet<?> packet )
{
}
@Override
public void tick()
{
}
@Override
public void setupEncryption( SecretKey key )
{
}
@Override
public void disableAutoRead()
{
}
@Override
public void setCompressionThreshold( int size )
{
}
@Override
public void send( Packet<?> packet, @Nullable GenericFutureListener<? extends Future<? super Void>> listener )
{
}
}
}

View File

@@ -0,0 +1,84 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle.event;
/**
* A basic action that a turtle may perform, as accessed by the {@code turtle} API.
*
* @see TurtleActionEvent
*/
public enum TurtleAction
{
/**
* A turtle moves to a new position.
*
* @see TurtleBlockEvent.Move
*/
MOVE,
/**
* A turtle turns in a specific direction.
*/
TURN,
/**
* A turtle attempts to dig a block.
*
* @see TurtleBlockEvent.Dig
*/
DIG,
/**
* A turtle attempts to place a block or item in the world.
*
* @see TurtleBlockEvent.Place
*/
PLACE,
/**
* A turtle attempts to attack an entity.
*
* @see TurtleActionEvent
*/
ATTACK,
/**
* Drop an item into an inventory/the world.
*
* @see TurtleInventoryEvent.Drop
*/
DROP,
/**
* Suck an item from an inventory or the world.
*
* @see TurtleInventoryEvent.Suck
*/
SUCK,
/**
* Refuel the turtle's fuel levels.
*/
REFUEL,
/**
* Equip or unequip an item.
*/
EQUIP,
/**
* Inspect a block in world
*
* @see TurtleBlockEvent.Inspect
*/
INSPECT,
/**
* Gather metdata about an item in the turtle's inventory.
*/
INSPECT_ITEM,
}

View File

@@ -0,0 +1,91 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
/**
* An event fired when a turtle is performing a known action.
*/
public class TurtleActionEvent extends TurtleEvent
{
private final TurtleAction action;
private String failureMessage;
private boolean cancelled = false;
public TurtleActionEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action )
{
super( turtle );
Objects.requireNonNull( action, "action cannot be null" );
this.action = action;
}
public TurtleAction getAction()
{
return action;
}
/**
* Sets the cancellation state of this action.
*
* If {@code cancel} is {@code true}, this action will not be carried out.
*
* @param cancel The new canceled value.
* @see TurtleCommandResult#failure()
* @deprecated Use {@link #setCanceled(boolean, String)} instead.
*/
@Deprecated
public void setCanceled( boolean cancel )
{
setCanceled( cancel, null );
}
/**
* Set the cancellation state of this action, setting a failure message if required.
*
* If {@code cancel} is {@code true}, this action will not be carried out.
*
* @param cancel The new canceled value.
* @param failureMessage The message to return to the user explaining the failure.
* @see TurtleCommandResult#failure(String)
*/
public void setCanceled( boolean cancel, @Nullable String failureMessage )
{
this.cancelled = true;
this.failureMessage = cancel ? failureMessage : null;
}
/**
* Get the message with which this will fail.
*
* @return The failure message.
* @see TurtleCommandResult#failure()
* @see #setCanceled(boolean, String)
*/
@Nullable
public String getFailureMessage()
{
return failureMessage;
}
/**
* Determine if this event is cancelled
*
* @return If this event is cancelled
* @see #setCanceled(boolean, String)
*/
public boolean isCancelled()
{
return cancelled;
}
}

View File

@@ -0,0 +1,79 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.turtle.TurtleVerb;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.Direction;
import javax.annotation.Nonnull;
import java.util.Objects;
/**
* Fired when a turtle attempts to attack an entity.
*
* This must be fired by {@link ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)},
* as the base {@code turtle.attack()} command does not fire it.
*
* Note that such commands should also fire {@link net.fabricmc.fabric.api.event.player.AttackEntityCallback}, so you do
* not need to listen to both.
*
* @see TurtleAction#ATTACK
*/
public class TurtleAttackEvent extends TurtlePlayerEvent
{
private final Entity target;
private final ITurtleUpgrade upgrade;
private final TurtleSide side;
public TurtleAttackEvent( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull Entity target, @Nonnull ITurtleUpgrade upgrade, @Nonnull TurtleSide side )
{
super( turtle, TurtleAction.ATTACK, player );
Objects.requireNonNull( target, "target cannot be null" );
Objects.requireNonNull( upgrade, "upgrade cannot be null" );
Objects.requireNonNull( side, "side cannot be null" );
this.target = target;
this.upgrade = upgrade;
this.side = side;
}
/**
* Get the entity being attacked by this turtle.
*
* @return The entity being attacked.
*/
@Nonnull
public Entity getTarget()
{
return target;
}
/**
* Get the upgrade responsible for attacking.
*
* @return The upgrade responsible for attacking.
*/
@Nonnull
public ITurtleUpgrade getUpgrade()
{
return upgrade;
}
/**
* Get the side the attacking upgrade is on.
*
* @return The upgrade's side.
*/
@Nonnull
public TurtleSide getSide()
{
return side;
}
}

View File

@@ -0,0 +1,234 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle.event;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.turtle.TurtleVerb;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.util.Map;
import java.util.Objects;
/**
* A general event for when a turtle interacts with a block or region.
*
* You should generally listen to one of the sub-events instead, cancelling them where
* appropriate.
*
* Note that you are not guaranteed to receive this event, if it has been cancelled by other
* mechanisms, such as block protection systems.
*
* Be aware that some events (such as {@link TurtleInventoryEvent}) do not necessarily interact
* with a block, simply objects within that block space.
*/
public abstract class TurtleBlockEvent extends TurtlePlayerEvent
{
private final World world;
private final BlockPos pos;
protected TurtleBlockEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos )
{
super( turtle, action, player );
Objects.requireNonNull( world, "world cannot be null" );
Objects.requireNonNull( pos, "pos cannot be null" );
this.world = world;
this.pos = pos;
}
/**
* Get the world the turtle is interacting in.
*
* @return The world the turtle is interacting in.
*/
public World getWorld()
{
return world;
}
/**
* Get the position the turtle is interacting with. Note that this is different
* to {@link ITurtleAccess#getPosition()}.
*
* @return The position the turtle is interacting with.
*/
public BlockPos getPos()
{
return pos;
}
/**
* Fired when a turtle attempts to dig a block.
*
* This must be fired by {@link ITurtleUpgrade#useTool(ITurtleAccess, TurtleSide, TurtleVerb, Direction)},
* as the base {@code turtle.dig()} command does not fire it.
*
* Note that such commands should also fire {@link net.fabricmc.fabric.api.event.player.AttackBlockCallback}, so you
* do not need to listen to both.
*
* @see TurtleAction#DIG
*/
public static class Dig extends TurtleBlockEvent
{
private final BlockState block;
private final ITurtleUpgrade upgrade;
private final TurtleSide side;
public Dig( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState block, @Nonnull ITurtleUpgrade upgrade, @Nonnull TurtleSide side )
{
super( turtle, TurtleAction.DIG, player, world, pos );
Objects.requireNonNull( block, "block cannot be null" );
Objects.requireNonNull( upgrade, "upgrade cannot be null" );
Objects.requireNonNull( side, "side cannot be null" );
this.block = block;
this.upgrade = upgrade;
this.side = side;
}
/**
* Get the block which is about to be broken.
*
* @return The block which is going to be broken.
*/
@Nonnull
public BlockState getBlock()
{
return block;
}
/**
* Get the upgrade doing the digging
*
* @return The upgrade doing the digging.
*/
@Nonnull
public ITurtleUpgrade getUpgrade()
{
return upgrade;
}
/**
* Get the side the upgrade doing the digging is on.
*
* @return The upgrade's side.
*/
@Nonnull
public TurtleSide getSide()
{
return side;
}
}
/**
* Fired when a turtle attempts to move into a block.
*
* @see TurtleAction#MOVE
*/
public static class Move extends TurtleBlockEvent
{
public Move( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos )
{
super( turtle, TurtleAction.MOVE, player, world, pos );
}
}
/**
* Fired when a turtle attempts to place a block in the world.
*
* @see TurtleAction#PLACE
*/
public static class Place extends TurtleBlockEvent
{
private final ItemStack stack;
public Place( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull ItemStack stack )
{
super( turtle, TurtleAction.PLACE, player, world, pos );
Objects.requireNonNull( stack, "stack cannot be null" );
this.stack = stack;
}
/**
* Get the item stack that will be placed. This should not be modified.
*
* @return The item stack to be placed.
*/
@Nonnull
public ItemStack getStack()
{
return stack;
}
}
/**
* Fired when a turtle gathers data on a block in world.
*
* You may prevent blocks being inspected, or add additional information to the result.
*
* @see TurtleAction#INSPECT
*/
public static class Inspect extends TurtleBlockEvent
{
private final BlockState state;
private final Map<String, Object> data;
public Inspect( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nonnull BlockState state, @Nonnull Map<String, Object> data )
{
super( turtle, TurtleAction.INSPECT, player, world, pos );
Objects.requireNonNull( state, "state cannot be null" );
Objects.requireNonNull( data, "data cannot be null" );
this.data = data;
this.state = state;
}
/**
* Get the block state which is being inspected.
*
* @return The inspected block state.
*/
@Nonnull
public BlockState getState()
{
return state;
}
/**
* Get the "inspection data" from this block, which will be returned to the user.
*
* @return This block's inspection data.
*/
@Nonnull
public Map<String, Object> getData()
{
return data;
}
/**
* Add new information to the inspection result. Note this will override fields with the same name.
*
* @param newData The data to add. Note all values should be convertible to Lua (see
* {@link dan200.computercraft.api.peripheral.IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}).
*/
public void addData( @Nonnull Map<String, ?> newData )
{
Objects.requireNonNull( newData, "newData cannot be null" );
data.putAll( newData );
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle.event;
import com.google.common.eventbus.EventBus;
import dan200.computercraft.api.turtle.ITurtleAccess;
import javax.annotation.Nonnull;
import java.util.Objects;
/**
* A base class for all events concerning a turtle. This will only ever constructed and fired on the server side,
* so sever specific methods on {@link ITurtleAccess} are safe to use.
*
* You should generally not need to subscribe to this event, preferring one of the more specific classes.
*
* @see TurtleActionEvent
*/
public abstract class TurtleEvent
{
public static final EventBus EVENT_BUS = new EventBus();
private final ITurtleAccess turtle;
protected TurtleEvent( @Nonnull ITurtleAccess turtle )
{
Objects.requireNonNull( turtle, "turtle cannot be null" );
this.turtle = turtle;
}
/**
* Get the turtle which is performing this action.
*
* @return The access for this turtle.
*/
@Nonnull
public ITurtleAccess getTurtle()
{
return turtle;
}
public static boolean post( TurtleActionEvent event )
{
EVENT_BUS.post( event );
return event.isCancelled();
}
}

View File

@@ -0,0 +1,74 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
import java.util.Map;
import java.util.Objects;
/**
* Fired when a turtle gathers data on an item in its inventory.
*
* You may prevent items being inspected, or add additional information to the result. Be aware that this is fired on
* the computer thread, and so any operations on it must be thread safe.
*
* @see TurtleAction#INSPECT_ITEM
*/
public class TurtleInspectItemEvent extends TurtleActionEvent
{
private final ItemStack stack;
private final Map<String, Object> data;
public TurtleInspectItemEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map<String, Object> data )
{
super( turtle, TurtleAction.INSPECT_ITEM );
Objects.requireNonNull( stack, "stack cannot be null" );
Objects.requireNonNull( data, "data cannot be null" );
this.stack = stack;
this.data = data;
}
/**
* The item which is currently being inspected.
*
* @return The item stack which is being inspected. This should <b>not</b> be modified.
*/
@Nonnull
public ItemStack getStack()
{
return stack;
}
/**
* Get the "inspection data" from this item, which will be returned to the user.
*
* @return This items's inspection data.
*/
@Nonnull
public Map<String, Object> getData()
{
return data;
}
/**
* Add new information to the inspection result. Note this will override fields with the same name.
*
* @param newData The data to add. Note all values should be convertible to Lua (see
* {@link dan200.computercraft.api.peripheral.IPeripheral#callMethod(IComputerAccess, ILuaContext, int, Object[])}).
*/
public void addData( @Nonnull Map<String, ?> newData )
{
Objects.requireNonNull( newData, "newData cannot be null" );
data.putAll( newData );
}
}

View File

@@ -0,0 +1,84 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
/**
* Fired when a turtle attempts to interact with an inventory.
*/
public abstract class TurtleInventoryEvent extends TurtleBlockEvent
{
private final Inventory handler;
protected TurtleInventoryEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler )
{
super( turtle, action, player, world, pos );
this.handler = handler;
}
/**
* Get the inventory being interacted with
*
* @return The inventory being interacted with, {@code null} if the item will be dropped to/sucked from the world.
*/
@Nullable
public Inventory getItemHandler()
{
return handler;
}
/**
* Fired when a turtle attempts to suck from an inventory.
*
* @see TurtleAction#SUCK
*/
public static class Suck extends TurtleInventoryEvent
{
public Suck( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler )
{
super( turtle, TurtleAction.SUCK, player, world, pos, handler );
}
}
/**
* Fired when a turtle attempts to drop an item into an inventory.
*
* @see TurtleAction#DROP
*/
public static class Drop extends TurtleInventoryEvent
{
private final ItemStack stack;
public Drop( @Nonnull ITurtleAccess turtle, @Nonnull FakePlayer player, @Nonnull World world, @Nonnull BlockPos pos, @Nullable Inventory handler, @Nonnull ItemStack stack )
{
super( turtle, TurtleAction.DROP, player, world, pos, handler );
Objects.requireNonNull( stack, "stack cannot be null" );
this.stack = stack;
}
/**
* The item which will be inserted into the inventory/dropped on the ground.
*
* @return The item stack which will be dropped. This should <b>not</b> be modified.
*/
@Nonnull
public ItemStack getStack()
{
return stack;
}
}
}

View File

@@ -0,0 +1,43 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. 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.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import javax.annotation.Nonnull;
import java.util.Objects;
/**
* An action done by a turtle which is normally done by a player.
*
* {@link #getPlayer()} may be used to modify the player's attributes or perform permission checks.
*/
public abstract class TurtlePlayerEvent extends TurtleActionEvent
{
private final FakePlayer player;
protected TurtlePlayerEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player )
{
super( turtle, action );
Objects.requireNonNull( player, "player cannot be null" );
this.player = player;
}
/**
* A fake player, representing this turtle.
*
* This may be used for triggering permission checks.
*
* @return A {@link FakePlayer} representing this turtle.
*/
@Nonnull
public FakePlayer getPlayer()
{
return player;
}
}

View File

@@ -0,0 +1,91 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.api.turtle.event;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.item.ItemStack;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Objects;
/**
* Fired when a turtle attempts to refuel from an item.
*
* One may use {@link #setCanceled(boolean, String)} to prevent refueling from this specific item. Additionally, you
* may use {@link #setHandler(Handler)} to register a custom fuel provider.
*/
public class TurtleRefuelEvent extends TurtleActionEvent
{
private final ItemStack stack;
private Handler handler;
public TurtleRefuelEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack )
{
super( turtle, TurtleAction.REFUEL );
Objects.requireNonNull( turtle, "turtle cannot be null" );
this.stack = stack;
}
/**
* Get the stack we are attempting to refuel from.
*
* Do not modify the returned stack - all modifications should be done within the {@link Handler}.
*
* @return The stack to refuel from.
*/
public ItemStack getStack()
{
return stack;
}
/**
* Get the refuel handler for this stack.
*
* @return The refuel handler, or {@code null} if none has currently been set.
* @see #setHandler(Handler)
*/
@Nullable
public Handler getHandler()
{
return handler;
}
/**
* Set the refuel handler for this stack.
*
* You should call this if you can actually refuel from this item, and ideally only if there are no existing
* handlers.
*
* @param handler The new refuel handler.
* @see #getHandler()
*/
public void setHandler( @Nullable Handler handler )
{
this.handler = handler;
}
/**
* Handles refuelling a turtle from a specific item.
*/
@FunctionalInterface
public interface Handler
{
/**
* Refuel a turtle using an item.
*
* @param turtle The turtle to refuel.
* @param stack The stack to refuel with.
* @param slot The slot the stack resides within. This may be used to modify the inventory afterwards.
* @param limit The maximum number of refuel operations to perform. This will often correspond to the number of
* items to consume.
* @return The amount of fuel gained.
*/
int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, int slot, int limit );
}
}