1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-08-27 16:02:17 +00:00

Update core, api and ROM to match latest CC:T

Mostly fine, but breaking change in that getWorld -> getLevel. Possibly
worth deferring to 1.18
This commit is contained in:
Jonathan Coates 2021-11-27 10:12:27 +00:00
parent 70a24d371d
commit 58e747506e
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
127 changed files with 1923 additions and 2622 deletions

View File

@ -6,7 +6,6 @@
package dan200.computercraft;
import dan200.computercraft.api.turtle.event.TurtleAction;
import dan200.computercraft.core.apis.http.options.Action;
import dan200.computercraft.core.apis.http.options.AddressRule;
import dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks;
@ -40,7 +39,6 @@ import org.apache.logging.log4j.Logger;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.TimeUnit;
@ -91,7 +89,6 @@ public final class ComputerCraft implements ModInitializer
public static int advancedTurtleFuelLimit = 100000;
public static boolean turtlesObeyBlockProtection = true;
public static boolean turtlesCanPush = true;
public static EnumSet<TurtleAction> turtleDisabledActions = EnumSet.noneOf( TurtleAction.class );
public static int computerTermWidth = 51;
public static int computerTermHeight = 19;

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -32,19 +31,11 @@ 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.
* 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
{
private static IComputerCraftAPI instance;
@Nonnull
@Deprecated
public static String getAPIVersion()
{
return getInstalledVersion();
}
@Nonnull
public static String getInstalledVersion()
{
@ -52,23 +43,10 @@ public final class ComputerCraftAPI
}
@Nonnull
private static IComputerCraftAPI getInstance()
@Deprecated
public static String getAPIVersion()
{
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 );
}
return getInstalledVersion();
}
/**
@ -80,7 +58,8 @@ public final class ComputerCraftAPI
* @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.
* eg: if createUniqueNumberedSaveDir( world, "computer/disk" ) was called returns 42, then "computer/disk/42" is now
* available for writing.
* @see #createSaveDirMount(Level, String, long)
*/
public static int createUniqueNumberedSaveDir( @Nonnull Level world, @Nonnull String parentSubPath )
@ -91,15 +70,15 @@ public final class ComputerCraftAPI
/**
* 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.
* 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 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.
* @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(Level, String)
* @see IComputerAccess#mount(String, IMount)
* @see IComputerAccess#mountWritable(String, IWritableMount)
@ -115,8 +94,8 @@ public final class ComputerCraftAPI
/**
* 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.
* 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. For instance, ComputerCraft's resources are stored in
@ -137,7 +116,7 @@ public final class ComputerCraftAPI
}
/**
* Registers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
* rers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
*
* @param provider The peripheral provider to register.
* @see IPeripheral
@ -160,8 +139,9 @@ public final class ComputerCraftAPI
}
/**
* 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.
* 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
@ -188,8 +168,8 @@ public final class ComputerCraftAPI
* @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.
* @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 Level world, @Nonnull BlockPos pos, @Nonnull Direction side )
@ -256,6 +236,24 @@ public final class ComputerCraftAPI
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

View File

@ -43,17 +43,13 @@ public final class TransformedModel
public static TransformedModel of( @Nonnull ModelResourceLocation location )
{
ModelManager modelManager = Minecraft.getInstance()
.getModelManager();
ModelManager modelManager = Minecraft.getInstance().getModelManager();
return new TransformedModel( modelManager.getModel( location ) );
}
public static TransformedModel of( @Nonnull ItemStack item, @Nonnull Transformation transform )
{
BakedModel model = Minecraft.getInstance()
.getItemRenderer()
.getItemModelShaper()
.getItemModel( item );
BakedModel model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel( item );
return new TransformedModel( model, transform );
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.nio.file.attribute.BasicFileAttributes;

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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 javax.annotation.Nonnull;

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -17,10 +16,12 @@ import java.nio.file.attribute.BasicFileAttributes;
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)}.
* 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(Level, String, long)} or {@link
* ComputerCraftAPI#createResourceMount(String, String)}, or you're free to implement it yourselves!
* Ready made implementations of this interface can be created using
* {@link ComputerCraftAPI#createSaveDirMount(Level, String, long)} or
* {@link ComputerCraftAPI#createResourceMount(String, String)}, or you're free to implement it yourselves!
*
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see ComputerCraftAPI#createResourceMount(String, String)
@ -29,43 +30,6 @@ import java.util.List;
*/
public interface IMount
{
/**
* 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;
/**
* 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
ReadableByteChannel openForRead( @Nonnull String path ) throws IOException;
/**
* Get attributes about the given file.
*
* @param path The path to query.
* @return File attributes for the given file.
* @throws IOException If the file does not exist, or attributes could not be fetched.
*/
@Nonnull
default BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException
{
if( !exists( path ) )
{
throw new FileOperationException( path, "No such file" );
}
return new FileAttributes( isDirectory( path ), getSize( path ) );
}
/**
* Returns whether a file with a given path exists or not.
*
@ -84,6 +48,15 @@ public interface IMount
*/
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.
*
@ -92,4 +65,30 @@ public interface IMount
* @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 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
ReadableByteChannel openForRead( @Nonnull String path ) throws IOException;
/**
* Get attributes about the given file.
*
* @param path The path to query.
* @return File attributes for the given file.
* @throws IOException If the file does not exist, or attributes could not be fetched.
*/
@Nonnull
default BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException
{
if( !exists( path ) ) throw new FileOperationException( path, "No such file" );
return new FileAttributes( isDirectory( path ), getSize( path ) );
}
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -17,11 +16,11 @@ import java.nio.channels.WritableByteChannel;
import java.util.OptionalLong;
/**
* 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.
* 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(Level, String, long)}, or you're free to
* implement it yourselves!
* Ready made implementations of this interface can be created using
* {@link ComputerCraftAPI#createSaveDirMount(Level, String, long)}, or you're free to implement it yourselves!
*
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see IComputerAccess#mount(String, IMount)
@ -50,8 +49,8 @@ public interface IWritableMount extends IMount
* 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.
* @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
@ -61,16 +60,16 @@ public interface IWritableMount extends IMount
* 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.
* @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
WritableByteChannel openForAppend( @Nonnull String path ) throws IOException;
/**
* 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.
* 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.
@ -78,7 +77,8 @@ public interface IWritableMount extends IMount
long getRemainingSpace() throws IOException;
/**
* Get the capacity of this mount. This should be equal to the size of all files/directories on this mount, minus the {@link #getRemainingSpace()}.
* Get the capacity of this mount. This should be equal to the size of all files/directories on this mount, minus
* the {@link #getRemainingSpace()}.
*
* @return The capacity of this mount, in bytes.
*/

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -19,25 +18,6 @@ import static dan200.computercraft.api.lua.LuaValues.checkFinite;
*/
public interface IArguments
{
/**
* Drop a number of arguments. The returned arguments instance will access arguments at position {@code i + count}, rather than {@code i}. However,
* errors will still use the given argument index.
*
* @param count The number of arguments to drop.
* @return The new {@link IArguments} instance.
*/
IArguments drop( int count );
default Object[] getAll()
{
Object[] result = new Object[count()];
for( int i = 0; i < result.length; i++ )
{
result[i] = get( i );
}
return result;
}
/**
* Get the number of arguments passed to this function.
*
@ -62,6 +42,37 @@ public interface IArguments
@Nullable
Object get( int index );
/**
* Drop a number of arguments. The returned arguments instance will access arguments at position {@code i + count},
* rather than {@code i}. However, errors will still use the given argument index.
*
* @param count The number of arguments to drop.
* @return The new {@link IArguments} instance.
*/
IArguments drop( int count );
default Object[] getAll()
{
Object[] result = new Object[count()];
for( int i = 0; i < result.length; i++ ) result[i] = get( i );
return result;
}
/**
* Get an argument as a double.
*
* @param index The argument number.
* @return The argument's value.
* @throws LuaException If the value is not a number.
* @see #getFiniteDouble(int) if you require this to be finite (i.e. not infinite or NaN).
*/
default double getDouble( int index ) throws LuaException
{
Object value = get( index );
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
return ((Number) value).doubleValue();
}
/**
* Get an argument as an integer.
*
@ -84,12 +95,8 @@ public interface IArguments
default long getLong( int index ) throws LuaException
{
Object value = get( index );
if( !(value instanceof Number) )
{
throw LuaValues.badArgumentOf( index, "number", value );
}
return LuaValues.checkFiniteNum( index, (Number) value )
.longValue();
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
return LuaValues.checkFiniteNum( index, (Number) value ).longValue();
}
/**
@ -104,24 +111,6 @@ public interface IArguments
return checkFinite( index, getDouble( index ) );
}
/**
* Get an argument as a double.
*
* @param index The argument number.
* @return The argument's value.
* @throws LuaException If the value is not a number.
* @see #getFiniteDouble(int) if you require this to be finite (i.e. not infinite or NaN).
*/
default double getDouble( int index ) throws LuaException
{
Object value = get( index );
if( !(value instanceof Number) )
{
throw LuaValues.badArgumentOf( index, "number", value );
}
return ((Number) value).doubleValue();
}
/**
* Get an argument as a boolean.
*
@ -132,26 +121,10 @@ public interface IArguments
default boolean getBoolean( int index ) throws LuaException
{
Object value = get( index );
if( !(value instanceof Boolean) )
{
throw LuaValues.badArgumentOf( index, "boolean", value );
}
if( !(value instanceof Boolean) ) throw LuaValues.badArgumentOf( index, "boolean", value );
return (Boolean) value;
}
/**
* Get a string argument as a byte array.
*
* @param index The argument number.
* @return The argument's value. This is a <em>read only</em> buffer.
* @throws LuaException If the value is not a string.
*/
@Nonnull
default ByteBuffer getBytes( int index ) throws LuaException
{
return LuaValues.encode( getString( index ) );
}
/**
* Get an argument as a string.
*
@ -163,13 +136,23 @@ public interface IArguments
default String getString( int index ) throws LuaException
{
Object value = get( index );
if( !(value instanceof String) )
{
throw LuaValues.badArgumentOf( index, "string", value );
}
if( !(value instanceof String) ) throw LuaValues.badArgumentOf( index, "string", value );
return (String) value;
}
/**
* Get a string argument as a byte array.
*
* @param index The argument number.
* @return The argument's value. This is a <em>read only</em> buffer.
* @throws LuaException If the value is not a string.
*/
@Nonnull
default ByteBuffer getBytes( int index ) throws LuaException
{
return LuaValues.encode( getString( index ) );
}
/**
* Get a string argument as an enum value.
*
@ -196,75 +179,10 @@ public interface IArguments
default Map<?, ?> getTable( int index ) throws LuaException
{
Object value = get( index );
if( !(value instanceof Map) )
{
throw LuaValues.badArgumentOf( index, "table", value );
}
if( !(value instanceof Map) ) throw LuaValues.badArgumentOf( index, "table", value );
return (Map<?, ?>) value;
}
/**
* Get a string argument as a byte array.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present. This is a <em>read only</em> buffer.
* @throws LuaException If the value is not a string.
*/
default Optional<ByteBuffer> optBytes( int index ) throws LuaException
{
return optString( index ).map( LuaValues::encode );
}
/**
* Get an argument as a string.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a string.
*/
default Optional<String> optString( int index ) throws LuaException
{
Object value = get( index );
if( value == null )
{
return Optional.empty();
}
if( !(value instanceof String) )
{
throw LuaValues.badArgumentOf( index, "string", value );
}
return Optional.of( (String) value );
}
/**
* Get a string argument as an enum value.
*
* @param index The argument number.
* @param klass The type of enum to parse.
* @param <T> The type of enum to parse.
* @return The argument's value.
* @throws LuaException If the value is not a string or not a valid option for this enum.
*/
@Nonnull
default <T extends Enum<T>> Optional<T> optEnum( int index, Class<T> klass ) throws LuaException
{
Optional<String> str = optString( index );
return str.isPresent() ? Optional.of( LuaValues.checkEnum( index, klass, str.get() ) ) : Optional.empty();
}
/**
* Get an argument as a double.
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a number.
*/
default double optDouble( int index, double def ) throws LuaException
{
return optDouble( index ).orElse( def );
}
/**
* Get an argument as a double.
*
@ -276,30 +194,11 @@ public interface IArguments
default Optional<Double> optDouble( int index ) throws LuaException
{
Object value = get( index );
if( value == null )
{
return Optional.empty();
}
if( !(value instanceof Number) )
{
throw LuaValues.badArgumentOf( index, "number", value );
}
if( value == null ) return Optional.empty();
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
return Optional.of( ((Number) value).doubleValue() );
}
/**
* Get an argument as an int.
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a number.
*/
default int optInt( int index, int def ) throws LuaException
{
return optInt( index ).orElse( def );
}
/**
* Get an argument as an int.
*
@ -323,16 +222,122 @@ public interface IArguments
default Optional<Long> optLong( int index ) throws LuaException
{
Object value = get( index );
if( value == null )
{
return Optional.empty();
}
if( !(value instanceof Number) )
{
throw LuaValues.badArgumentOf( index, "number", value );
}
return Optional.of( LuaValues.checkFiniteNum( index, (Number) value )
.longValue() );
if( value == null ) return Optional.empty();
if( !(value instanceof Number) ) throw LuaValues.badArgumentOf( index, "number", value );
return Optional.of( LuaValues.checkFiniteNum( index, (Number) value ).longValue() );
}
/**
* Get an argument as a finite number (not infinite or NaN).
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not finite.
*/
default Optional<Double> optFiniteDouble( int index ) throws LuaException
{
Optional<Double> value = optDouble( index );
if( value.isPresent() ) LuaValues.checkFiniteNum( index, value.get() );
return value;
}
/**
* Get an argument as a boolean.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a boolean.
*/
default Optional<Boolean> optBoolean( int index ) throws LuaException
{
Object value = get( index );
if( value == null ) return Optional.empty();
if( !(value instanceof Boolean) ) throw LuaValues.badArgumentOf( index, "boolean", value );
return Optional.of( (Boolean) value );
}
/**
* Get an argument as a string.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a string.
*/
default Optional<String> optString( int index ) throws LuaException
{
Object value = get( index );
if( value == null ) return Optional.empty();
if( !(value instanceof String) ) throw LuaValues.badArgumentOf( index, "string", value );
return Optional.of( (String) value );
}
/**
* Get a string argument as a byte array.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present. This is a <em>read only</em> buffer.
* @throws LuaException If the value is not a string.
*/
default Optional<ByteBuffer> optBytes( int index ) throws LuaException
{
return optString( index ).map( LuaValues::encode );
}
/**
* Get a string argument as an enum value.
*
* @param index The argument number.
* @param klass The type of enum to parse.
* @param <T> The type of enum to parse.
* @return The argument's value.
* @throws LuaException If the value is not a string or not a valid option for this enum.
*/
@Nonnull
default <T extends Enum<T>> Optional<T> optEnum( int index, Class<T> klass ) throws LuaException
{
Optional<String> str = optString( index );
return str.isPresent() ? Optional.of( LuaValues.checkEnum( index, klass, str.get() ) ) : Optional.empty();
}
/**
* Get an argument as a table.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a table.
*/
default Optional<Map<?, ?>> optTable( int index ) throws LuaException
{
Object value = get( index );
if( value == null ) return Optional.empty();
if( !(value instanceof Map) ) throw LuaValues.badArgumentOf( index, "map", value );
return Optional.of( (Map<?, ?>) value );
}
/**
* Get an argument as a double.
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a number.
*/
default double optDouble( int index, double def ) throws LuaException
{
return optDouble( index ).orElse( def );
}
/**
* Get an argument as an int.
*
* @param index The argument number.
* @param def The default value, if this argument is not given.
* @return The argument's value, or {@code def} if none was provided.
* @throws LuaException If the value is not a number.
*/
default int optInt( int index, int def ) throws LuaException
{
return optInt( index ).orElse( def );
}
/**
@ -361,23 +366,6 @@ public interface IArguments
return optFiniteDouble( index ).orElse( def );
}
/**
* Get an argument as a finite number (not infinite or NaN).
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not finite.
*/
default Optional<Double> optFiniteDouble( int index ) throws LuaException
{
Optional<Double> value = optDouble( index );
if( value.isPresent() )
{
LuaValues.checkFiniteNum( index, value.get() );
}
return value;
}
/**
* Get an argument as a boolean.
*
@ -391,27 +379,6 @@ public interface IArguments
return optBoolean( index ).orElse( def );
}
/**
* Get an argument as a boolean.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a boolean.
*/
default Optional<Boolean> optBoolean( int index ) throws LuaException
{
Object value = get( index );
if( value == null )
{
return Optional.empty();
}
if( !(value instanceof Boolean) )
{
throw LuaValues.badArgumentOf( index, "boolean", value );
}
return Optional.of( (Boolean) value );
}
/**
* Get an argument as a string.
*
@ -437,25 +404,4 @@ public interface IArguments
{
return optTable( index ).orElse( def );
}
/**
* Get an argument as a table.
*
* @param index The argument number.
* @return The argument's value, or {@link Optional#empty()} if not present.
* @throws LuaException If the value is not a table.
*/
default Optional<Map<?, ?>> optTable( int index ) throws LuaException
{
Object value = get( index );
if( value == null )
{
return Optional.empty();
}
if( !(value instanceof Map) )
{
throw LuaValues.badArgumentOf( index, "map", value );
}
return Optional.of( (Map<?, ?>) value );
}
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -12,7 +11,8 @@ 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.
* An interface passed to {@link ILuaAPIFactory} in order to provide additional information
* about a computer.
*/
public interface IComputerSystem extends IComputerAccess
{

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.IDynamicPeripheral;
@ -13,13 +12,15 @@ import javax.annotation.Nonnull;
/**
* An interface for representing custom objects returned by peripherals or other Lua objects.
*
* Generally, one does not need to implement this type - it is sufficient to return an object with some methods annotated with {@link LuaFunction}. {@link
* IDynamicLuaObject} is useful when you wish your available methods to change at runtime.
* Generally, one does not need to implement this type - it is sufficient to return an object with some methods
* annotated with {@link LuaFunction}. {@link IDynamicLuaObject} is useful when you wish your available methods to
* change at runtime.
*/
public interface IDynamicLuaObject
{
/**
* Get the names of the methods that this object implements. This should not change over the course of the object's lifetime.
* Get the names of the methods that this object implements. This should not change over the course of the object's
* lifetime.
*
* @return The method names this object provides.
* @see IDynamicPeripheral#getMethodNames()
@ -30,10 +31,13 @@ public interface IDynamicLuaObject
/**
* Called when a user calls one of the methods that this object implements.
*
* @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 method index from {@link #getMethodNames()} the computer wishes to call.
* @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 method index from {@link #getMethodNames()} the computer wishes
* to call.
* @param arguments The arguments for this method.
* @return The result of this function. Either an immediate value ({@link MethodResult#of(Object...)} or an instruction to yield.
* @return The result of this function. Either an immediate value ({@link MethodResult#of(Object...)} or an
* instruction to yield.
* @throws LuaException If the function threw an exception.
*/
@Nonnull

View File

@ -3,17 +3,16 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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 Lua object which is stored as a global variable on computer startup. This must either provide {@link LuaFunction} annotated functions or
* implement {@link IDynamicLuaObject}.
* Represents a Lua object which is stored as a global variable on computer startup. This must either provide
* {@link LuaFunction} annotated functions or implement {@link IDynamicLuaObject}.
*
* Before implementing this interface, consider alternative methods of providing methods. It is generally preferred to use peripherals to provide
* functionality to users.
* 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)

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -18,7 +17,8 @@ public interface ILuaCallback
/**
* Resume this coroutine.
*
* @param args The result of resuming this coroutine. These will have the same form as described in {@link LuaFunction}.
* @param args The result of resuming this coroutine. These will have the same form as described in
* {@link LuaFunction}.
* @return The result of this continuation. Either the result to return to the callee, or another yield.
* @throws LuaException On an error.
*/

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -41,5 +40,8 @@ public interface ILuaContext
* @throws LuaException If the task could not be queued, or if the task threw an exception.
*/
@Nonnull
MethodResult executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException;
default MethodResult executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException
{
return TaskCallback.make( this, task );
}
}

View File

@ -3,14 +3,13 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
/**
* A function, which can be called from Lua. If you need to return a table of functions, it is recommended to use an object with {@link LuaFunction}
* methods, or implement {@link IDynamicLuaObject}.
* A function, which can be called from Lua. If you need to return a table of functions, it is recommended to use
* an object with {@link LuaFunction} methods, or implement {@link IDynamicLuaObject}.
*
* @see MethodResult#of(Object)
*/
@ -18,8 +17,8 @@ import javax.annotation.Nonnull;
public interface ILuaFunction
{
/**
* Call this function with a series of arguments. Note, this will <em>always</em> be called on the computer thread, and so its implementation must be
* thread-safe.
* Call this function with a series of arguments. Note, this will <em>always</em> be called on the computer thread,
* and so its implementation must be thread-safe.
*
* @param arguments The arguments for this function
* @return The result of calling this function.

View File

@ -3,14 +3,14 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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#issueMainThreadTask(ILuaTask)} This will be run on the main thread, at the beginning of the next
* tick.
* A task which can be executed via {@link ILuaContext#issueMainThreadTask(ILuaTask)} This will be run on the main
* thread, at the beginning of the
* next tick.
*
* @see ILuaContext#issueMainThreadTask(ILuaTask)
*/
@ -21,8 +21,9 @@ public interface ILuaTask
* Execute this task.
*
* @return The arguments to add to the {@code task_completed} event.
* @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 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

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -42,7 +41,8 @@ public class LuaException extends Exception
}
/**
* The level this error is raised at. Level 1 is the function's caller, level 2 is that function's caller, and so on.
* 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.
*/

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -16,8 +15,8 @@ import java.util.Optional;
/**
* Used to mark a Java function which is callable from Lua.
*
* Methods annotated with {@link LuaFunction} must be public final instance methods. They can have any number of parameters, but they must be of the
* following types:
* Methods annotated with {@link LuaFunction} must be public final instance methods. They can have any number of
* parameters, but they must be of the following types:
*
* <ul>
* <li>{@link ILuaContext} (and {@link IComputerAccess} if on a {@link IPeripheral})</li>
@ -49,7 +48,8 @@ public @interface LuaFunction
String[] value() default {};
/**
* Run this function on the main server thread. This should be specified for any method which interacts with Minecraft in a thread-unsafe manner.
* Run this function on the main server thread. This should be specified for any method which interacts with
* Minecraft in a thread-unsafe manner.
*
* @return Whether this functi
* @see ILuaContext#issueMainThreadTask(ILuaTask)

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -38,8 +37,41 @@ public final class LuaValues
chars[i] = c < 256 ? (byte) c : 63;
}
return ByteBuffer.wrap( chars )
.asReadOnlyBuffer();
return ByteBuffer.wrap( chars ).asReadOnlyBuffer();
}
/**
* Returns a more detailed representation of this number's type. If this is finite, it will just return "number",
* otherwise it returns whether it is infinite or NaN.
*
* @param value The value to extract the type for.
* @return This value's numeric type.
*/
@Nonnull
public static String getNumericType( double value )
{
if( Double.isNaN( value ) ) return "nan";
if( value == Double.POSITIVE_INFINITY ) return "inf";
if( value == Double.NEGATIVE_INFINITY ) return "-inf";
return "number";
}
/**
* Get a string representation of the given value's type.
*
* @param value The value whose type we are trying to compute.
* @return A string representation of the given value's type, in a similar format to that provided by Lua's
* {@code type} function.
*/
@Nonnull
public static String getType( @Nullable Object value )
{
if( value == null ) return "nil";
if( value instanceof String ) return "string";
if( value instanceof Boolean ) return "boolean";
if( value instanceof Number ) return "number";
if( value instanceof Map ) return "table";
return "userdata";
}
/**
@ -70,38 +102,6 @@ public final class LuaValues
return new LuaException( "bad argument #" + (index + 1) + " (" + expected + " expected, got " + actual + ")" );
}
/**
* Get a string representation of the given value's type.
*
* @param value The value whose type we are trying to compute.
* @return A string representation of the given value's type, in a similar format to that provided by Lua's {@code type} function.
*/
@Nonnull
public static String getType( @Nullable Object value )
{
if( value == null )
{
return "nil";
}
if( value instanceof String )
{
return "string";
}
if( value instanceof Boolean )
{
return "boolean";
}
if( value instanceof Number )
{
return "number";
}
if( value instanceof Map )
{
return "table";
}
return "userdata";
}
/**
* Ensure a numeric argument is finite (i.e. not infinite or {@link Double#NaN}.
*
@ -126,38 +126,10 @@ public final class LuaValues
*/
public static double checkFinite( int index, double value ) throws LuaException
{
if( !Double.isFinite( value ) )
{
throw badArgument( index, "number", getNumericType( value ) );
}
if( !Double.isFinite( value ) ) throw badArgument( index, "number", getNumericType( value ) );
return value;
}
/**
* Returns a more detailed representation of this number's type. If this is finite, it will just return "number", otherwise it returns whether it is
* infinite or NaN.
*
* @param value The value to extract the type for.
* @return This value's numeric type.
*/
@Nonnull
public static String getNumericType( double value )
{
if( Double.isNaN( value ) )
{
return "nan";
}
if( value == Double.POSITIVE_INFINITY )
{
return "inf";
}
if( value == Double.NEGATIVE_INFINITY )
{
return "-inf";
}
return "number";
}
/**
* Ensure a string is a valid enum value.
*
@ -172,11 +144,7 @@ public final class LuaValues
{
for( T possibility : klass.getEnumConstants() )
{
if( possibility.name()
.equalsIgnoreCase( value ) )
{
return possibility;
}
if( possibility.name().equalsIgnoreCase( value ) ) return possibility;
}
throw new LuaException( "bad argument #" + (index + 1) + " (unknown option " + value + ")" );

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -18,8 +17,8 @@ import java.util.Objects;
/**
* The result of invoking a Lua method.
*
* Method results either return a value immediately ({@link #of(Object...)} or yield control to the parent coroutine. When the current coroutine is resumed,
* we invoke the provided {@link ILuaCallback#resume(Object[])} callback.
* Method results either return a value immediately ({@link #of(Object...)} or yield control to the parent coroutine.
* When the current coroutine is resumed, we invoke the provided {@link ILuaCallback#resume(Object[])} callback.
*/
public final class MethodResult
{
@ -57,11 +56,12 @@ public final class MethodResult
/**
* Return a single value immediately.
*
* Integers, doubles, floats, strings, booleans, {@link Map}, {@link Collection}s, arrays and {@code null} will be converted to their corresponding Lua
* type. {@code byte[]} and {@link ByteBuffer} will be treated as binary strings. {@link ILuaFunction} will be treated as a function.
* Integers, doubles, floats, strings, booleans, {@link Map}, {@link Collection}s, arrays and {@code null} will be
* converted to their corresponding Lua type. {@code byte[]} and {@link ByteBuffer} will be treated as binary
* strings. {@link ILuaFunction} will be treated as a function.
*
* In order to provide a custom object with methods, one may return a {@link IDynamicLuaObject}, or an arbitrary class with {@link LuaFunction}
* annotations. Anything else will be converted to {@code nil}.
* In order to provide a custom object with methods, one may return a {@link IDynamicLuaObject}, or an arbitrary
* class with {@link LuaFunction} annotations. Anything else will be converted to {@code nil}.
*
* @param value The value to return to the calling Lua function.
* @return A method result which returns immediately with the given value.
@ -85,8 +85,8 @@ public final class MethodResult
}
/**
* 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.
* 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.
* @param callback The callback to resume with the name of the event that occurred, and any event parameters.
@ -98,17 +98,15 @@ public final class MethodResult
{
Objects.requireNonNull( callback, "callback cannot be null" );
return new MethodResult( new Object[] { filter }, results -> {
if( results.length >= 1 && results[0].equals( "terminate" ) )
{
throw new LuaException( "Terminated", 0 );
}
if( results.length >= 1 && results[0].equals( "terminate" ) ) throw new LuaException( "Terminated", 0 );
return callback.resume( results );
} );
}
/**
* The same as {@link #pullEvent(String, ILuaCallback)}, 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.
* The same as {@link #pullEvent(String, ILuaCallback)}, 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.
* @param callback The callback to resume with the name of the event that occurred, and any event parameters.
@ -123,8 +121,8 @@ public final class MethodResult
}
/**
* 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.
* 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()
* @param callback The callback to resume with an array containing the return values from coroutine.yield()
@ -156,7 +154,8 @@ public final class MethodResult
}
/**
* Increase the Lua error by a specific amount. One should never need to use this function - it largely exists for some CC internal code.
* Increase the Lua error by a specific amount. One should never need to use this function - it largely exists for
* some CC internal code.
*
* @param adjust The amount to increase the level by.
* @return The new {@link MethodResult} with an adjusted error. This has no effect on immediate results.
@ -164,14 +163,8 @@ public final class MethodResult
@Nonnull
public MethodResult adjustError( int adjust )
{
if( adjust < 0 )
{
throw new IllegalArgumentException( "cannot adjust by a negative amount" );
}
if( adjust == 0 || callback == null )
{
return this;
}
if( adjust < 0 ) throw new IllegalArgumentException( "cannot adjust by a negative amount" );
if( adjust == 0 || callback == null ) return this;
return new MethodResult( result, callback, this.adjust + adjust );
}
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -36,41 +35,32 @@ public final class ObjectArguments implements IArguments
this.args = Objects.requireNonNull( args );
}
@Override
public IArguments drop( int count )
{
if( count < 0 )
{
throw new IllegalStateException( "count cannot be negative" );
}
if( count == 0 )
{
return this;
}
if( count >= args.size() )
{
return EMPTY;
}
return new ObjectArguments( args.subList( count, args.size() ) );
}
@Override
public Object[] getAll()
{
return args.toArray();
}
@Override
public int count()
{
return args.size();
}
@Override
public IArguments drop( int count )
{
if( count < 0 ) throw new IllegalStateException( "count cannot be negative" );
if( count == 0 ) return this;
if( count >= args.size() ) return EMPTY;
return new ObjectArguments( args.subList( count, args.size() ) );
}
@Nullable
@Override
public Object get( int index )
{
return index >= args.size() ? null : args.get( index );
}
@Override
public Object[] getAll()
{
return args.toArray();
}
}

View File

@ -0,0 +1,53 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. 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 java.util.Arrays;
final class TaskCallback implements ILuaCallback
{
private final MethodResult pull = MethodResult.pullEvent( "task_complete", this );
private final long task;
private TaskCallback( long task )
{
this.task = task;
}
@Nonnull
@Override
public MethodResult resume( Object[] response ) throws LuaException
{
if( response.length < 3 || !(response[1] instanceof Number) || !(response[2] instanceof Boolean) )
{
return pull;
}
if( ((Number) response[1]).longValue() != task ) return pull;
if( (Boolean) response[2] )
{
// Extract the return values from the event and return them
return MethodResult.of( Arrays.copyOfRange( response, 3, response.length ) );
}
else if( response.length >= 4 && response[3] instanceof String )
{
// Extract the error message from the event and raise it
throw new LuaException( (String) response[3] );
}
else
{
throw new LuaException( "error" );
}
}
static MethodResult make( ILuaContext context, ILuaTask func ) throws LuaException
{
long task = context.issueMainThreadTask( func );
return new TaskCallback( task ).pull;
}
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -18,7 +17,8 @@ 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}.
* 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
{
@ -44,7 +44,8 @@ public interface IMedia
}
/**
* If this disk represents an item with audio (like a record), get the readable name of the audio track. ie: "Jonathan Coulton - Still Alive"
* 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.
@ -68,13 +69,13 @@ public interface IMedia
}
/**
* 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.
* 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()
* @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(Level, String, long)

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.world.item.ItemStack;

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -38,8 +37,8 @@ public interface IPacketNetwork
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).
* 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.
@ -49,8 +48,8 @@ public interface IPacketNetwork
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.
* 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)

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.world.level.Level;
@ -22,7 +21,7 @@ public interface IPacketReceiver
* @return The receivers's world.
*/
@Nonnull
Level getWorld();
Level getLevel();
/**
* Get the position in the world at which this receiver exists.
@ -35,8 +34,9 @@ public interface IPacketReceiver
/**
* 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.
* 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()
@ -60,8 +60,8 @@ public interface IPacketReceiver
/**
* 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 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()
@ -73,8 +73,8 @@ public interface IPacketReceiver
/**
* 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.
* @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)

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.world.level.Level;
@ -22,7 +21,7 @@ public interface IPacketSender
* @return The sender's world.
*/
@Nonnull
Level getWorld();
Level getLevel();
/**
* Get the position in the world at which this sender exists.
@ -33,8 +32,8 @@ public interface IPacketSender
Vec3 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.
* 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.
*/

View File

@ -3,128 +3,28 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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}.
*
* @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.
* @see IPacketSender
* @see IPacketNetwork#transmitSameDimension(Packet, double)
* @see IPacketNetwork#transmitInterdimensional(Packet)
* @see IPacketReceiver#receiveDifferentDimension(Packet)
* @see IPacketReceiver#receiveSameDimension(Packet, double)
*/
public class Packet
public record Packet(
int channel,
int replyChannel,
Object payload,
IPacketSender sender
)
{
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 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;
}
@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 );
}
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -13,16 +12,18 @@ 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 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.
* 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.
* 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

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -12,14 +11,16 @@ 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.
* 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.
* 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}.
* 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()
*/
@ -58,10 +59,12 @@ public interface IWiredNetwork
/**
* 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.
* 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.
* @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()
*/
@ -70,7 +73,8 @@ public interface IWiredNetwork
/**
* 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.
* 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.

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -19,8 +18,8 @@ import java.util.Map;
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.
* 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.
*/
@ -28,8 +27,8 @@ public interface IWiredNetworkChange
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.
* 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.
*/

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -15,14 +14,15 @@ 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.
* 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.
* 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.
* 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
{
@ -34,6 +34,17 @@ public interface IWiredNode extends IPacketNetwork
@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.
*
@ -49,16 +60,6 @@ public interface IWiredNode extends IPacketNetwork
return getNetwork().connect( this, node );
}
/**
* 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();
/**
* Destroy a connection between this node and another.
*
@ -78,9 +79,11 @@ public interface IWiredNode extends IPacketNetwork
/**
* 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.
* 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.
* @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)
*/
@ -92,7 +95,8 @@ public interface IWiredNode extends IPacketNetwork
/**
* 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.
* 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)

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -13,14 +12,16 @@ 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.
* 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.
* 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.
*/

View File

@ -0,0 +1,45 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. 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.GenericSource;
import net.minecraft.world.Container;
import net.minecraft.world.level.block.entity.BlockEntity;
import javax.annotation.Nonnull;
/**
* A {@link GenericSource} which provides methods for a peripheral.
*
* Unlike a {@link GenericSource}, all methods <strong>should</strong> target the same type, for instance a
* {@link BlockEntity} subclass or a capability interface. This is not currently enforced.
*/
public interface GenericPeripheral extends GenericSource
{
/**
* Get the type of the exposed peripheral.
*
* Unlike normal {@link IPeripheral}s, {@link GenericPeripheral} do not have to have a type. By default, the
* resulting peripheral uses the resource name of the wrapped {@link BlockEntity} (for instance {@literal minecraft:chest}).
*
* However, in some cases it may be more appropriate to specify a more readable name. Overriding this method allows
* you to do so.
*
* When multiple {@link GenericPeripheral}s return a non-empty peripheral type for a single tile entity, the
* lexicographically smallest will be chosen. In order to avoid this conflict, this method should only be
* implemented when your peripheral targets a single tile entity <strong>AND</strong> it's likely that you're the
* only mod to do so. Similarly this should <strong>NOT</strong> be implemented when your methods target an
* interface (i.e. {@link Container}).
*
* @return The type of this peripheral or {@link PeripheralType#untyped()}.
* @see IPeripheral#getType()
*/
@Nonnull
default PeripheralType getType()
{
return PeripheralType.untyped();
}
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -20,8 +19,9 @@ import javax.annotation.Nullable;
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.
* 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
{
@ -30,8 +30,8 @@ public interface IComputerAccess
*
* @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.
* @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 NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see ComputerCraftAPI#createResourceMount(String, String)
@ -52,8 +52,8 @@ public interface IComputerAccess
* @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.
* @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 NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see ComputerCraftAPI#createResourceMount(String, String)
@ -65,24 +65,13 @@ public interface IComputerAccess
@Nullable
String mount( @Nonnull String desiredLocation, @Nonnull IMount mount, @Nonnull String driveName );
/**
* 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 NotAttachedException If the peripheral has been detached.
*/
@Nonnull
String 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.
* @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.
* @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 NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see ComputerCraftAPI#createResourceMount(String, String)
@ -102,8 +91,8 @@ public interface IComputerAccess
* @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.
* @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 NotAttachedException If the peripheral has been detached.
* @see ComputerCraftAPI#createSaveDirMount(Level, String, long)
* @see ComputerCraftAPI#createResourceMount(String, String)
@ -114,16 +103,18 @@ public interface IComputerAccess
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)}.
* 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.
* 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.
* @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 NotAttachedException If the peripheral has been detached.
* @throws IllegalStateException If the mount does not exist, or was mounted by another peripheral.
* @see #mount(String, IMount)
@ -134,22 +125,26 @@ public interface IComputerAccess
/**
* 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.
* 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.
* 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().
* @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 NotAttachedException If the peripheral has been detached.
@ -157,6 +152,19 @@ public interface IComputerAccess
*/
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 NotAttachedException 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.
*
@ -171,8 +179,8 @@ public interface IComputerAccess
Map<String, IPeripheral> getAvailablePeripherals();
/**
* Get a reachable peripheral with the given attachment name. This is a equivalent to {@link #getAvailablePeripherals()}{@code .get(name)}, though may
* be more efficient.
* 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.
@ -184,11 +192,13 @@ public interface IComputerAccess
/**
* 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.
* 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.
* 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.
* @throws NotAttachedException If the peripheral has been detached.

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.*;
@ -13,14 +12,14 @@ import javax.annotation.Nonnull;
/**
* A peripheral whose methods are not known at runtime.
*
* This behaves similarly to {@link IDynamicLuaObject}, though also accepting the current {@link IComputerAccess}. Generally one may use {@link LuaFunction}
* instead of implementing this interface.
* This behaves similarly to {@link IDynamicLuaObject}, though also accepting the current {@link IComputerAccess}.
* Generally one may use {@link LuaFunction} instead of implementing this interface.
*/
public interface IDynamicPeripheral extends IPeripheral
{
/**
* 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.
* 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
@ -29,19 +28,24 @@ public interface IDynamicPeripheral extends IPeripheral
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()}.
* 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.
* 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 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 The arguments for this method.
* @return A {@link MethodResult} containing the values to return or the action to perform.
* @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 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.
* @see #getMethodNames()
*/
@Nonnull

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.LuaFunction;
@ -17,12 +16,14 @@ import javax.annotation.Nullable;
* In order to expose a peripheral for your block or tile entity, you register a {@link IPeripheralProvider}. This <em>cannot</em> be implemented {@link
* IPeripheral} directly on the tile.
*
* Peripherals should provide a series of methods to the user, either using {@link LuaFunction} or by implementing {@link IDynamicPeripheral}.
* Peripherals should provide a series of methods to the user, either using {@link LuaFunction} or by implementing
* {@link IDynamicPeripheral}.
*/
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()}
* 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.
*/
@ -32,15 +33,19 @@ public interface IPeripheral
/**
* 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.
* 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.
* 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.
* 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.
* @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 )
@ -50,14 +55,18 @@ public interface IPeripheral
/**
* 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 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.
* 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.
* 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.
* @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 )
@ -65,7 +74,8 @@ public interface IPeripheral
}
/**
* 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...
* 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
*/
@ -78,8 +88,8 @@ public interface IPeripheral
/**
* 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.
* 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.

View File

@ -3,22 +3,18 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import javax.annotation.Nonnull;
import java.util.Optional;
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 expose the {@link IPeripheral} capability.
*
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
*/
@FunctionalInterface
@ -30,9 +26,9 @@ public interface IPeripheralProvider
* @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 {@link Optional#empty()} if there is not a peripheral here you'd like to handle.
* @return A peripheral or {@literal null} if there is not a peripheral here you'd like to handle.
* @see dan200.computercraft.api.ComputerCraftAPI#registerPeripheralProvider(IPeripheralProvider)
*/
@Nonnull
@Nullable
IPeripheral getPeripheral( @Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction side );
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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 javax.annotation.Nonnull;
@ -11,14 +10,15 @@ 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.
* 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).
* 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.
* 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.
*
@ -26,16 +26,31 @@ import java.util.concurrent.TimeUnit;
*/
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.
* 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.
*
@ -45,10 +60,7 @@ public interface IWorkMonitor
default boolean runWork( @Nonnull Runnable runnable )
{
Objects.requireNonNull( runnable, "runnable should not be null" );
if( !canWork() )
{
return false;
}
if( !canWork() ) return false;
long start = System.nanoTime();
try
@ -62,19 +74,4 @@ public interface IWorkMonitor
return true;
}
/**
* If the owning computer is currently allowed to execute work.
*
* @return If we can execute work right now.
*/
boolean canWork();
/**
* 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 );
}

View File

@ -3,11 +3,11 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
/**
* Thrown when performing operations on {@link IComputerAccess} when the current peripheral is no longer attached to the computer.
* Thrown when performing operations on {@link IComputerAccess} when the current peripheral is no longer attached to
* the computer.
*/
public class NotAttachedException extends IllegalStateException
{

View File

@ -0,0 +1,62 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. 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 com.google.common.base.Strings;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* The type of a {@link GenericPeripheral}.
*
* When determining the final type of the resulting peripheral, the union of all types is taken, with the
* lexicographically smallest non-empty name being chosen.
*/
public final class PeripheralType
{
private static final PeripheralType UNTYPED = new PeripheralType( null );
private final String type;
public PeripheralType( String type )
{
this.type = type;
}
/**
* An empty peripheral type, used when a {@link GenericPeripheral} does not have an explicit type.
*
* @return The empty peripheral type.
*/
public static PeripheralType untyped()
{
return UNTYPED;
}
/**
* Create a new non-empty peripheral type.
*
* @param type The name of the type.
* @return The constructed peripheral type.
*/
public static PeripheralType ofType( @Nonnull String type )
{
if( Strings.isNullOrEmpty( type ) ) throw new IllegalArgumentException( "type cannot be null or empty" );
return new PeripheralType( type );
}
/**
* Get the name of this peripheral type. This may be {@literal null}.
*
* @return The type of this peripheral.
*/
@Nullable
public String getPrimaryType()
{
return type;
}
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.shared.util.NonNullSupplier;

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -33,7 +32,8 @@ public interface IPocketAccess
/**
* 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.
* @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();
@ -41,8 +41,8 @@ public interface IPocketAccess
/**
* 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.
* @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 );
@ -50,7 +50,8 @@ public interface IPocketAccess
/**
* 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.
* @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();
@ -58,8 +59,8 @@ public interface IPocketAccess
/**
* 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.
* @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 );

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -24,8 +23,9 @@ public interface IPocketUpgrade extends IUpgradeBase
/**
* 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.
* 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.
@ -51,8 +51,9 @@ public interface IPocketUpgrade extends IUpgradeBase
* @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.
* @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 Level world, @Nonnull IPocketAccess access, @Nullable IPeripheral peripheral )

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.core.BlockPos;
@ -26,7 +25,8 @@ public interface IBundledRedstoneProvider
* @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.
* @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 Level world, @Nonnull BlockPos pos, @Nonnull Direction side );

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -24,7 +23,8 @@ 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}.
* This should not be implemented by your classes. Do not interact with turtles except via this interface and
* {@link ITurtleUpgrade}.
*/
public interface ITurtleAccess
{
@ -34,7 +34,7 @@ public interface ITurtleAccess
* @return the world in which the turtle resides.
*/
@Nonnull
Level getWorld();
Level getLevel();
/**
* Returns a vector containing the integer co-ordinates at which the turtle resides.
@ -47,18 +47,20 @@ public interface ITurtleAccess
/**
* 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)}.
* 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.
* @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 Level 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.
* 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.
@ -86,8 +88,8 @@ public interface ITurtleAccess
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.
* 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()
@ -106,30 +108,32 @@ public interface ITurtleAccess
/**
* 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.
* @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 );
/**
* 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();
/**
* 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.
* @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.
*
@ -138,6 +142,32 @@ public interface ITurtleAccess
@Nullable
GameProfile getOwningPlayer();
/**
* Get the inventory of this turtle.
*
* Note: this inventory should only be accessed and modified on the server thread.
*
* @return This turtle's inventory
* @see #getItemHandler()
*/
@Nonnull
Container getInventory();
/**
* Get the inventory of this turtle as an {@link ItemStorage}.
*
* Note: this inventory should only be accessed and modified on the server thread.
*
* @return This turtle's inventory
* @see #getInventory()
* @see ItemStorage
*/
@Nonnull
default ItemStorage getItemHandler()
{
return ItemStorage.wrap( getInventory() );
}
/**
* Determine whether this turtle will require fuel when performing actions.
*
@ -157,7 +187,8 @@ public interface ITurtleAccess
int getFuelLevel();
/**
* Set the fuel level to a new value. It is generally preferred to use {@link #consumeFuel(int)}} or {@link #addFuel(int)} instead.
* 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()
@ -178,8 +209,8 @@ public interface ITurtleAccess
* 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.
* @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 );
@ -193,13 +224,15 @@ public interface ITurtleAccess
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.
* 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 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.
* @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.
* @see ITurtleCommand
* @see MethodResult#pullEvent(String, ILuaCallback)
@ -208,7 +241,8 @@ public interface ITurtleAccess
MethodResult executeCommand( @Nonnull ITurtleCommand command );
/**
* Start playing a specific animation. This will prevent other turtle commands from executing until it is finished.
* 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.
@ -247,8 +281,8 @@ public interface ITurtleAccess
/**
* 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.
* 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.
@ -258,25 +292,11 @@ public interface ITurtleAccess
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.
* 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 );
default ItemStorage getItemHandler()
{
return ItemStorage.wrap( getInventory() );
}
/**
* Get the inventory of this turtle.
*
* Note: this inventory should only be accessed and modified on the server thread.
*
* @return This turtle's inventory
*/
@Nonnull
Container getInventory();
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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 javax.annotation.Nonnull;
@ -19,8 +18,8 @@ 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.
* 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.

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -18,7 +17,8 @@ import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* The primary interface for defining an update for Turtles. A turtle update can either be a new tool, or a new peripheral.
* 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)
*/
@ -36,12 +36,14 @@ public interface ITurtleUpgrade extends IUpgradeBase
/**
* 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.
* 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.
* @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 )
@ -50,16 +52,19 @@ public interface ITurtleUpgrade extends IUpgradeBase
}
/**
* 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.
* 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.
*
* @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.
* @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 )
@ -70,6 +75,10 @@ public interface ITurtleUpgrade extends IUpgradeBase
/**
* Called to obtain the model to be used when rendering a turtle peripheral.
*
* This can be obtained from {@link net.minecraft.client.renderer.ItemModelShaper#getItemModel(ItemStack)},
* {@link net.minecraft.client.resources.model.ModelManager#getModel(ModelResourceLocation)} 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.

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
/**
@ -24,34 +23,38 @@ public enum TurtleAnimation
NONE,
/**
* Make the turtle move forward. Note that the animation starts from the block <em>behind</em> it, and moves into this one.
* Make the turtle move forward. Note that the animation starts from the block <em>behind</em> it, and
* moves into this one.
*/
MOVE_FORWARD,
/**
* Make the turtle move backwards. Note that the animation starts from the block <em>in front</em> it, and moves into this one.
* Make the turtle move backwards. Note that the animation starts from the block <em>in front</em> it, and
* moves into this one.
*/
MOVE_BACK,
/**
* Make the turtle move backwards. Note that the animation starts from the block <em>above</em> it, and moves into this one.
* Make the turtle move backwards. Note that the animation starts from the block <em>above</em> it, and
* moves into this one.
*/
MOVE_UP,
/**
* Make the turtle move backwards. Note that the animation starts from the block <em>below</em> it, and moves into this one.
* Make the turtle move backwards. Note that the animation starts from the block <em>below</em> it, and
* moves into this one.
*/
MOVE_DOWN,
/**
* 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.
* 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.
*/
TURN_LEFT,
/**
* 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.
* 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.
*/
TURN_RIGHT,

View File

@ -3,9 +3,10 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.core.Direction;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -19,16 +20,6 @@ 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 );
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;
}
/**
* Create a successful command result with no result.
@ -50,10 +41,7 @@ public final class TurtleCommandResult
@Nonnull
public static TurtleCommandResult success( @Nullable Object[] results )
{
if( results == null || results.length == 0 )
{
return EMPTY_SUCCESS;
}
if( results == null || results.length == 0 ) return EMPTY_SUCCESS;
return new TurtleCommandResult( true, null, results );
}
@ -77,13 +65,21 @@ public final class TurtleCommandResult
@Nonnull
public static TurtleCommandResult failure( @Nullable String errorMessage )
{
if( errorMessage == null )
{
return EMPTY_FAILURE;
}
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.
*

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
/**

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
/**
@ -14,20 +13,21 @@ package dan200.computercraft.api.turtle;
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).
* 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).
* 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.
* 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;

View File

@ -3,11 +3,13 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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.core.Direction;
/**
* An enum representing the different actions that an {@link ITurtleUpgrade} of type Tool may be called on to perform by a turtle.
* 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)

View File

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

@ -1,85 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. 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 )
{
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;
}
public boolean isCancelled()
{
return cancelled;
}
}

View File

@ -1,73 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. 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.FakePlayer;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import net.minecraft.world.entity.Entity;
import javax.annotation.Nonnull;
import java.util.Objects;
/**
* Fired when a turtle attempts to attack an entity.
*
* @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

@ -1,224 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. 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.MethodResult;
import dan200.computercraft.api.turtle.FakePlayer;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import net.minecraft.core.BlockPos;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
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 Level world;
private final BlockPos pos;
protected TurtleBlockEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull Level 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 Level 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.
*
* @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 Level 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 Level 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 Level 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 Level 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 MethodResult#of(Object)}).
*/
public void addData( @Nonnull Map<String, ?> newData )
{
Objects.requireNonNull( newData, "newData cannot be null" );
data.putAll( newData );
}
}
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -13,12 +12,10 @@ 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.
* 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
{
@ -32,12 +29,6 @@ public abstract class TurtleEvent
this.turtle = turtle;
}
public static boolean post( TurtleActionEvent event )
{
EVENT_BUS.post( event );
return event.isCancelled();
}
/**
* Get the turtle which is performing this action.
*
@ -48,5 +39,4 @@ public abstract class TurtleEvent
{
return turtle;
}
}

View File

@ -1,90 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. 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.MethodResult;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.world.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 may be 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;
private final boolean mainThread;
@Deprecated
public TurtleInspectItemEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map<String, Object> data )
{
this( turtle, stack, data, false );
}
public TurtleInspectItemEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack, @Nonnull Map<String, Object> data, boolean mainThread )
{
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;
this.mainThread = mainThread;
}
/**
* 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;
}
/**
* If this event is being fired on the server thread. When true, information which relies on server state may be exposed.
*
* @return If this is run on the main thread.
*/
public boolean onMainThread()
{
return mainThread;
}
/**
* 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 MethodResult#of(Object)}).
*/
public void addData( @Nonnull Map<String, ?> newData )
{
Objects.requireNonNull( newData, "newData cannot be null" );
data.putAll( newData );
}
}

View File

@ -1,87 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. 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.FakePlayer;
import dan200.computercraft.api.turtle.ITurtleAccess;
import net.minecraft.core.BlockPos;
import net.minecraft.world.Container;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
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 Container handler;
protected TurtleInventoryEvent( @Nonnull ITurtleAccess turtle, @Nonnull TurtleAction action, @Nonnull FakePlayer player, @Nonnull Level world,
@Nonnull BlockPos pos, @Nullable Container 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 Container 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 Level world, @Nonnull BlockPos pos, @Nullable Container 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 Level world, @Nonnull BlockPos pos, @Nullable Container 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

@ -1,44 +0,0 @@
/*
* This file is part of the public ComputerCraft API - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. 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.FakePlayer;
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

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. 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;
@ -16,17 +15,16 @@ 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.
* One may use {@link #setHandler(Handler)} to register a custom fuel provider for a given item.
*/
public class TurtleRefuelEvent extends TurtleActionEvent
public class TurtleRefuelEvent extends TurtleEvent
{
private final ItemStack stack;
private Handler handler;
public TurtleRefuelEvent( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack stack )
{
super( turtle, TurtleAction.REFUEL );
super( turtle );
Objects.requireNonNull( turtle, "turtle cannot be null" );
this.stack = stack;
@ -59,7 +57,8 @@ public class TurtleRefuelEvent extends TurtleActionEvent
/**
* 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.
* 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()
@ -81,7 +80,8 @@ public class TurtleRefuelEvent extends TurtleActionEvent
* @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.
* @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 );

View File

@ -35,6 +35,7 @@ public abstract class ComputerAccess implements IComputerAccess
{
ComputerCraft.log.warn( "Peripheral or API called mount but did not call unmount for {}", mounts );
}
for( String mount : mounts )
{
fileSystem.unmount( mount );

View File

@ -68,6 +68,13 @@ public class FSAPI implements ILuaAPI
* @param path The path to list.
* @return A table with a list of files in the directory.
* @throws LuaException If the path doesn't exist.
* @cc.usage List all files under {@code /rom/}
* <pre>{@code
* local files = fs.list("/rom/")
* for i = 1, #files do
* print(files[i])
* end
* }</pre>
*/
@LuaFunction
public final String[] list( String path ) throws LuaException
@ -92,6 +99,12 @@ public class FSAPI implements ILuaAPI
* @throws LuaException On argument errors.
* @cc.tparam string path The first part of the path. For example, a parent directory path.
* @cc.tparam string ... Additional parts of the path to combine.
* @cc.changed 1.95.0 Now supports multiple arguments.
* @cc.usage Combine several file paths together
* <pre>{@code
* fs.combine("/rom/programs", "../apis", "parallel.lua")
* -- => rom/apis/parallel.lua
* }</pre>
*/
@LuaFunction
public final String combine( IArguments arguments ) throws LuaException
@ -114,6 +127,12 @@ public class FSAPI implements ILuaAPI
*
* @param path The path to get the name from.
* @return The final part of the path (the file name).
* @cc.since 1.2
* @cc.usage Get the file name of {@code rom/startup.lua}
* <pre>{@code
* fs.getName("rom/startup.lua")
* -- => startup.lua
* }</pre>
*/
@LuaFunction
public final String getName( String path )
@ -126,6 +145,12 @@ public class FSAPI implements ILuaAPI
*
* @param path The path to get the directory from.
* @return The path with the final part removed (the parent directory).
* @cc.since 1.63
* @cc.usage Get the directory name of {@code rom/startup.lua}
* <pre>{@code
* fs.getDir("rom/startup.lua")
* -- => rom
* }</pre>
*/
@LuaFunction
public final String getDir( String path )
@ -139,6 +164,7 @@ public class FSAPI implements ILuaAPI
* @param path The file to get the file size of.
* @return The size of the file, in bytes.
* @throws LuaException If the path doesn't exist.
* @cc.since 1.3
*/
@LuaFunction
public final long getSize( String path ) throws LuaException
@ -304,10 +330,15 @@ public class FSAPI implements ILuaAPI
/**
* Opens a file for reading or writing at a path.
*
* The mode parameter can be {@code r} to read, {@code w} to write (deleting
* all contents), or {@code a} to append (keeping contents). If {@code b} is
* added to the end, the file will be opened in binary mode; otherwise, it's
* opened in text mode.
* The {@code mode} string can be any of the following:
* <ul>
* <li><strong>"r"</strong>: Read mode</li>
* <li><strong>"w"</strong>: Write mode</li>
* <li><strong>"a"</strong>: Append mode</li>
* </ul>
*
* The mode may also have a "b" at the end, which opens the file in "binary
* mode". This allows you to read binary files, as well as seek within a file.
*
* @param path The path to the file to open.
* @param mode The mode to open the file with.
@ -316,6 +347,37 @@ public class FSAPI implements ILuaAPI
* @cc.treturn [1] table A file handle object for the file.
* @cc.treturn [2] nil If the file does not exist, or cannot be opened.
* @cc.treturn string|nil A message explaining why the file cannot be opened.
* @cc.usage Read the contents of a file.
* <pre>{@code
* local file = fs.open("/rom/help/intro.txt", "r")
* local contents = file.readAll()
* file.close()
*
* print(contents)
* }</pre>
* @cc.usage Open a file and read all lines into a table. @{io.lines} offers an alternative way to do this.
* <pre>{@code
* local file = fs.open("/rom/motd.txt", "r")
* local lines = {}
* while true do
* local line = file.readLine()
*
* -- If line is nil then we've reached the end of the file and should stop
* if not line then break end
*
* lines[#lines + 1] = line
* end
*
* file.close()
*
* print(lines[math.random(#lines)]) -- Pick a random line and print it.
* }</pre>
* @cc.usage Open a file and write some text to it. You can run {@code edit out.txt} to see the written text.
* <pre>{@code
* local file = fs.open("out.txt", "w")
* file.write("Just testing some code")
* file.close() -- Remember to call close, otherwise changes may not be written!
* }</pre>
*/
@LuaFunction
public final Object[] open( String path, String mode ) throws LuaException
@ -344,9 +406,11 @@ public class FSAPI implements ILuaAPI
return new Object[] { new EncodedWritableHandle( writer.get(), writer ) };
}
case "rb":
{
// Open the file for binary reading, then create a wrapper around the reader
FileSystemWrapper<ReadableByteChannel> reader = fileSystem.openForRead( path, Function.identity() );
return new Object[] { BinaryReadableHandle.of( reader.get(), reader ) };
}
case "wb":
{
// Open the file for binary writing, then create a wrapper around the writer
@ -354,9 +418,11 @@ public class FSAPI implements ILuaAPI
return new Object[] { BinaryWritableHandle.of( writer.get(), writer ) };
}
case "ab":
{
// Open the file for binary appending, then create a wrapper around the reader
FileSystemWrapper<WritableByteChannel> writer = fileSystem.openForWrite( path, true, Function.identity() );
return new Object[] { BinaryWritableHandle.of( writer.get(), writer ) };
}
default:
throw new LuaException( "Unsupported mode" );
}
@ -396,6 +462,8 @@ public class FSAPI implements ILuaAPI
* @return The amount of free space available, in bytes.
* @throws LuaException If the path doesn't exist.
* @cc.treturn number|"unlimited" The amount of free space available, in bytes, or "unlimited".
* @cc.since 1.4
* @see #getCapacity To get the capacity of this drive.
*/
@LuaFunction
public final Object getFreeSpace( String path ) throws LuaException
@ -422,6 +490,7 @@ public class FSAPI implements ILuaAPI
* @param path The wildcard-qualified path to search for.
* @return A list of paths that match the search string.
* @throws LuaException If the path doesn't exist.
* @cc.since 1.6
*/
@LuaFunction
public final String[] find( String path ) throws LuaException
@ -438,17 +507,15 @@ public class FSAPI implements ILuaAPI
}
/**
* Returns true if a path is mounted to the parent filesystem.
*
* The root filesystem "/" is considered a mount, along with disk folders and the rom folder. Other programs
* (such as network shares) can extend this to make other mount types by correctly assigning their return value for
* getDrive.
* Returns the capacity of the drive the path is located on.
*
* @param path The path of the drive to get.
* @return The drive's capacity.
* @throws LuaException If the capacity cannot be determined.
* @cc.treturn number|nil This drive's capacity. This will be nil for "read-only" drives, such as the ROM or
* treasure disks.
* @cc.since 1.87.0
* @see #getFreeSpace To get the free space available on this drive.
*/
@LuaFunction
public final Object getCapacity( String path ) throws LuaException
@ -477,6 +544,9 @@ public class FSAPI implements ILuaAPI
* @return The resulting attributes.
* @throws LuaException If the path does not exist.
* @cc.treturn { size = number, isDir = boolean, isReadOnly = boolean, created = number, modified = number } The resulting attributes.
* @cc.since 1.87.0
* @cc.changed 1.91.0 Renamed `modification` field to `modified`.
* @cc.changed 1.95.2 Added `isReadOnly` to attributes.
* @see #getSize If you only care about the file's size.
* @see #isDir If you only care whether a path is a directory or not.
*/

View File

@ -204,14 +204,15 @@ public class OSAPI implements ILuaAPI
}
/**
* Sets an alarm that will fire at the specified world time. When it fires,
* an {@code alarm} event will be added to the event queue with the ID
* returned from this function as the first parameter.
* Sets an alarm that will fire at the specified in-game time. When it
* fires, * an {@code alarm} event will be added to the event queue with the
* ID * returned from this function as the first parameter.
*
* @param time The time at which to fire the alarm, in the range [0.0, 24.0).
* @return The ID of the new alarm. This can be used to filter the
* {@code alarm} event, or {@link #cancelAlarm cancel the alarm}.
* @throws LuaException If the time is out of range.
* @cc.since 1.2
* @see #cancelAlarm To cancel an alarm.
*/
@LuaFunction
@ -232,6 +233,7 @@ public class OSAPI implements ILuaAPI
* alarm from firing.
*
* @param token The ID of the alarm to cancel.
* @cc.since 1.2
* @see #setAlarm To set an alarm.
*/
@LuaFunction
@ -277,6 +279,7 @@ public class OSAPI implements ILuaAPI
*
* @return The label of the computer.
* @cc.treturn string The label of the computer.
* @cc.since 1.3
*/
@LuaFunction( { "getComputerLabel", "computerLabel" } )
public final Object[] getComputerLabel()
@ -289,6 +292,7 @@ public class OSAPI implements ILuaAPI
* Set the label of this computer.
*
* @param label The new label. May be {@code nil} in order to clear it.
* @cc.since 1.3
*/
@LuaFunction
public final void setComputerLabel( Optional<String> label )
@ -300,6 +304,7 @@ public class OSAPI implements ILuaAPI
* Returns the number of seconds that the computer has been running.
*
* @return The computer's uptime.
* @cc.since 1.2
*/
@LuaFunction
public final double clock()
@ -311,7 +316,7 @@ public class OSAPI implements ILuaAPI
* Returns the current time depending on the string passed in. This will
* always be in the range [0.0, 24.0).
*
* * If called with {@code ingame}, the current world time will be returned.
* * If called with {@code dan200.computercraft.ingame}, the current world time will be returned.
* This is the default if nothing is passed.
* * If called with {@code utc}, returns the hour of the day in UTC time.
* * If called with {@code local}, returns the hour of the day in the
@ -321,10 +326,19 @@ public class OSAPI implements ILuaAPI
* which will convert the date fields into a UNIX timestamp (number of
* seconds since 1 January 1970).
*
* @param args The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} locale if not specified.
* @param args The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code dan200.computercraft.ingame} locale if not specified.
* @return The hour of the selected locale, or a UNIX timestamp from the table, depending on the argument passed in.
* @throws LuaException If an invalid locale is passed.
* @cc.tparam [opt] string|table locale The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code ingame} locale if not specified.
* @cc.tparam [opt] string|table locale The locale of the time, or a table filled by {@code os.date("*t")} to decode. Defaults to {@code dan200.computercraft.ingame} locale if not specified.
* @cc.see textutils.formatTime To convert times into a user-readable string.
* @cc.usage Print the current in-game time.
* <pre>{@code
* textutils.formatTime(os.time())
* }</pre>
* @cc.since 1.2
* @cc.changed 1.80pr1 Add support for getting the local local and UTC time.
* @cc.changed 1.82.0 Arguments are now case insensitive.
* @cc.changed 1.83.0 {@link #time(IArguments)} now accepts table arguments and converts them to UNIX timestamps.
* @see #date To get a date table that can be converted with this function.
*/
@LuaFunction
@ -333,14 +347,14 @@ public class OSAPI implements ILuaAPI
Object value = args.get( 0 );
if( value instanceof Map ) return LuaDateTime.fromTable( (Map<?, ?>) value );
String param = args.optString( 0, "ingame" );
String param = args.optString( 0, "dan200.computercraft.ingame" );
switch( param.toLowerCase( Locale.ROOT ) )
{
case "utc": // Get Hour of day (UTC)
return getTimeForCalendar( Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) );
case "local": // Get Hour of day (local time)
return getTimeForCalendar( Calendar.getInstance() );
case "ingame": // Get in-game hour
case "dan200.computercraft.ingame": // Get in-game hour
return time;
default:
throw new LuaException( "Unsupported operation" );
@ -350,27 +364,29 @@ public class OSAPI implements ILuaAPI
/**
* Returns the day depending on the locale specified.
*
* * If called with {@code ingame}, returns the number of days since the
* * If called with {@code dan200.computercraft.ingame}, returns the number of days since the
* world was created. This is the default.
* * If called with {@code utc}, returns the number of days since 1 January
* 1970 in the UTC timezone.
* * If called with {@code local}, returns the number of days since 1
* January 1970 in the server's local timezone.
*
* @param args The locale to get the day for. Defaults to {@code ingame} if not set.
* @param args The locale to get the day for. Defaults to {@code dan200.computercraft.ingame} if not set.
* @return The day depending on the selected locale.
* @throws LuaException If an invalid locale is passed.
* @cc.since 1.48
* @cc.changed 1.82.0 Arguments are now case insensitive.
*/
@LuaFunction
public final int day( Optional<String> args ) throws LuaException
{
switch( args.orElse( "ingame" ).toLowerCase( Locale.ROOT ) )
switch( args.orElse( "dan200.computercraft.ingame" ).toLowerCase( Locale.ROOT ) )
{
case "utc": // Get numbers of days since 1970-01-01 (utc)
return getDayForCalendar( Calendar.getInstance( TimeZone.getTimeZone( "UTC" ) ) );
case "local": // Get numbers of days since 1970-01-01 (local time)
return getDayForCalendar( Calendar.getInstance() );
case "ingame":// Get game day
case "dan200.computercraft.ingame":// Get game day
return day;
default:
throw new LuaException( "Unsupported operation" );
@ -380,21 +396,29 @@ public class OSAPI implements ILuaAPI
/**
* Returns the number of milliseconds since an epoch depending on the locale.
*
* * If called with {@code ingame}, returns the number of milliseconds since the
* * If called with {@code dan200.computercraft.ingame}, returns the number of milliseconds since the
* world was created. This is the default.
* * If called with {@code utc}, returns the number of milliseconds since 1
* January 1970 in the UTC timezone.
* * If called with {@code local}, returns the number of milliseconds since 1
* January 1970 in the server's local timezone.
*
* @param args The locale to get the milliseconds for. Defaults to {@code ingame} if not set.
* @param args The locale to get the milliseconds for. Defaults to {@code dan200.computercraft.ingame} if not set.
* @return The milliseconds since the epoch depending on the selected locale.
* @throws LuaException If an invalid locale is passed.
* @cc.since 1.80pr1
* @cc.usage Get the current time and use {@link #date} to convert it to a table.
* <pre>{@code
* -- Dividing by 1000 converts it from milliseconds to seconds.
* local time = os.epoch("local") / 1000
* local time_table = os.date("*t", time)
* print(textutils.serialize(time_table))
* }</pre>
*/
@LuaFunction
public final long epoch( Optional<String> args ) throws LuaException
{
switch( args.orElse( "ingame" ).toLowerCase( Locale.ROOT ) )
switch( args.orElse( "dan200.computercraft.ingame" ).toLowerCase( Locale.ROOT ) )
{
case "utc":
{
@ -403,10 +427,12 @@ public class OSAPI implements ILuaAPI
return getEpochForCalendar( c );
}
case "local":
{
// Get local epoch
Calendar c = Calendar.getInstance();
return getEpochForCalendar( c );
case "ingame":
}
case "dan200.computercraft.ingame":
// Get in-game epoch
synchronized( alarms )
{
@ -436,6 +462,11 @@ public class OSAPI implements ILuaAPI
* @param timeA The time to convert to a string. This defaults to the current time.
* @return The resulting format string.
* @throws LuaException If an invalid format is passed.
* @cc.since 1.83.0
* @cc.usage Print the current date in a user-friendly string.
* <pre>{@code
* os.date("%A %d %B %Y") -- See the reference above!
* }</pre>
*/
@LuaFunction
public final Object date( Optional<String> formatA, Optional<Long> timeA ) throws LuaException

View File

@ -30,15 +30,15 @@ import dan200.computercraft.core.computer.ComputerSide;
*
* @cc.usage Toggle the redstone signal above the computer every 0.5 seconds.
*
* <pre>
* <pre>{@code
* while true do
* redstone.setOutput("top", not redstone.getOutput("top"))
* sleep(0.5)
* end
* </pre>
* }</pre>
* @cc.usage Mimic a redstone comparator in [subtraction mode][comparator].
*
* <pre>
* <pre>{@code
* while true do
* local rear = rs.getAnalogueInput("back")
* local sides = math.max(rs.getAnalogueInput("left"), rs.getAnalogueInput("right"))
@ -46,7 +46,7 @@ import dan200.computercraft.core.computer.ComputerSide;
*
* os.pullEvent("redstone") -- Wait for a change to inputs.
* end
* </pre>
* }</pre>
*
* [comparator]: https://minecraft.gamepedia.com/Redstone_Comparator#Subtract_signal_strength "Redstone Comparator on
* the Minecraft wiki."
@ -72,6 +72,7 @@ public class RedstoneAPI implements ILuaAPI
* "back".
*
* @return A table of valid sides.
* @cc.since 1.2
*/
@LuaFunction
public final String[] getSides()
@ -122,6 +123,7 @@ public class RedstoneAPI implements ILuaAPI
* @param side The side to set.
* @param value The signal strength between 0 and 15.
* @throws LuaException If {@code value} is not betwene 0 and 15.
* @cc.since 1.51
*/
@LuaFunction( { "setAnalogOutput", "setAnalogueOutput" } )
public final void setAnalogOutput( ComputerSide side, int value ) throws LuaException
@ -135,6 +137,7 @@ public class RedstoneAPI implements ILuaAPI
*
* @param side The side to get.
* @return The output signal strength, between 0 and 15.
* @cc.since 1.51
* @see #setAnalogOutput
*/
@LuaFunction( { "getAnalogOutput", "getAnalogueOutput" } )
@ -148,6 +151,7 @@ public class RedstoneAPI implements ILuaAPI
*
* @param side The side to get.
* @return The input signal strength, between 0 and 15.
* @cc.since 1.51
*/
@LuaFunction( { "getAnalogInput", "getAnalogueInput" } )
public final int getAnalogInput( ComputerSide side )
@ -201,9 +205,9 @@ public class RedstoneAPI implements ILuaAPI
* @param mask The mask to test.
* @return If the colours are on.
* @cc.usage Check if @{colors.white} and @{colors.black} are on above the computer.
* <pre>
* <pre>{@code
* print(redstone.testBundledInput("top", colors.combine(colors.white, colors.black)))
* </pre>
* }</pre>
* @see #getBundledInput
*/
@LuaFunction

View File

@ -46,6 +46,7 @@ public class TermAPI extends TermMethods implements ILuaAPI
* @cc.treturn number The red channel, will be between 0 and 1.
* @cc.treturn number The green channel, will be between 0 and 1.
* @cc.treturn number The blue channel, will be between 0 and 1.
* @cc.since 1.81.0
* @see TermMethods#setPaletteColour(IArguments) To change the palette colour.
*/
@LuaFunction( { "nativePaletteColour", "nativePaletteColor" } )

View File

@ -112,6 +112,7 @@ public abstract class TermMethods
*
* @return If the cursor is blinking.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.since 1.80pr1.9
*/
@LuaFunction
public final boolean getCursorBlink() throws LuaException
@ -179,6 +180,7 @@ public abstract class TermMethods
* @return The current text colour.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.see colors For a list of colour constants, returned by this function.
* @cc.since 1.74
*/
@LuaFunction( { "getTextColour", "getTextColor" } )
public final int getTextColour() throws LuaException
@ -192,6 +194,8 @@ public abstract class TermMethods
* @param colourArg The new text colour.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.see colors For a list of colour constants.
* @cc.since 1.45
* @cc.changed 1.80pr1 Standard computers can now use all 16 colors, being changed to grayscale on screen.
*/
@LuaFunction( { "setTextColour", "setTextColor" } )
public final void setTextColour( int colourArg ) throws LuaException
@ -211,6 +215,7 @@ public abstract class TermMethods
* @return The current background colour.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.see colors For a list of colour constants, returned by this function.
* @cc.since 1.74
*/
@LuaFunction( { "getBackgroundColour", "getBackgroundColor" } )
public final int getBackgroundColour() throws LuaException
@ -225,6 +230,8 @@ public abstract class TermMethods
* @param colourArg The new background colour.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.see colors For a list of colour constants.
* @cc.since 1.45
* @cc.changed 1.80pr1 Standard computers can now use all 16 colors, being changed to grayscale on screen.
*/
@LuaFunction( { "setBackgroundColour", "setBackgroundColor" } )
public final void setBackgroundColour( int colourArg ) throws LuaException
@ -245,6 +252,7 @@ public abstract class TermMethods
*
* @return Whether this terminal supports colour.
* @throws LuaException (hidden) If the terminal cannot be found.
* @cc.since 1.45
*/
@LuaFunction( { "isColour", "isColor" } )
public final boolean getIsColour() throws LuaException
@ -267,6 +275,8 @@ public abstract class TermMethods
* @param backgroundColour The corresponding background colours.
* @throws LuaException If the three inputs are not the same length.
* @cc.see colors For a list of colour constants, and their hexadecimal values.
* @cc.since 1.74
* @cc.changed 1.80pr1 Standard computers can now use all 16 colors, being changed to grayscale on screen.
* @cc.usage Prints "Hello, world!" in rainbow text.
* <pre>{@code
* term.blit("Hello, world!","01234456789ab","0000000000000")
@ -319,6 +329,7 @@ public abstract class TermMethods
* }</pre>
* @cc.see colors.unpackRGB To convert from the 24-bit format to three separate channels.
* @cc.see colors.packRGB To convert from three separate channels to the 24-bit format.
* @cc.since 1.80pr1
*/
@LuaFunction( { "setPaletteColour", "setPaletteColor" } )
public final void setPaletteColour( IArguments args ) throws LuaException
@ -348,6 +359,7 @@ public abstract class TermMethods
* @cc.treturn number The red channel, will be between 0 and 1.
* @cc.treturn number The green channel, will be between 0 and 1.
* @cc.treturn number The blue channel, will be between 0 and 1.
* @cc.since 1.80pr1
*/
@LuaFunction( { "getPaletteColour", "getPaletteColor" } )
public final Object[] getPaletteColour( int colourArg ) throws LuaException

View File

@ -61,6 +61,7 @@ public class BinaryReadableHandle extends HandleGeneric
* @cc.treturn [1] nil If we are at the end of the file.
* @cc.treturn [2] number The value of the byte read. This is returned when the {@code count} is absent.
* @cc.treturn [3] string The bytes read as a string. This is returned when the {@code count} is given.
* @cc.changed 1.80pr1 Now accepts an integer argument to read multiple bytes, returning a string instead of a number.
*/
@LuaFunction
public final Object[] read( Optional<Integer> countArg ) throws LuaException
@ -145,6 +146,7 @@ public class BinaryReadableHandle extends HandleGeneric
* @return The file, or {@code null} if at the end of it.
* @throws LuaException If the file has been closed.
* @cc.treturn string|nil The remaining contents of the file, or {@code nil} if we are at the end.
* @cc.since 1.80pr1
*/
@LuaFunction
public final Object[] readAll() throws LuaException
@ -182,6 +184,8 @@ public class BinaryReadableHandle extends HandleGeneric
* @return The read string.
* @throws LuaException If the file has been closed.
* @cc.treturn string|nil The read line or {@code nil} if at the end of the file.
* @cc.since 1.80pr1.9
* @cc.changed 1.81.0 `\r` is now stripped.
*/
@LuaFunction
public final Object[] readLine( Optional<Boolean> withTrailingArg ) throws LuaException
@ -259,6 +263,7 @@ public class BinaryReadableHandle extends HandleGeneric
* @cc.treturn [1] number The new position.
* @cc.treturn [2] nil If seeking failed.
* @cc.treturn string The reason seeking failed.
* @cc.since 1.80pr1.9
*/
@LuaFunction
public final Object[] seek( Optional<String> whence, Optional<Long> offset ) throws LuaException

View File

@ -55,6 +55,7 @@ public class BinaryWritableHandle extends HandleGeneric
* @throws LuaException If the file has been closed.
* @cc.tparam [1] number The byte to write.
* @cc.tparam [2] string The string to write.
* @cc.changed 1.80pr1 Now accepts a string to write multiple bytes.
*/
@LuaFunction
public final void write( IArguments arguments ) throws LuaException
@ -130,6 +131,7 @@ public class BinaryWritableHandle extends HandleGeneric
* @cc.treturn [1] number The new position.
* @cc.treturn [2] nil If seeking failed.
* @cc.treturn string The reason seeking failed.
* @cc.since 1.80pr1.9
*/
@LuaFunction
public final Object[] seek( Optional<String> whence, Optional<Long> offset ) throws LuaException

View File

@ -50,6 +50,7 @@ public class EncodedReadableHandle extends HandleGeneric
* @return The read string.
* @throws LuaException If the file has been closed.
* @cc.treturn string|nil The read line or {@code nil} if at the end of the file.
* @cc.changed 1.81.0 Added option to return trailing newline.
*/
@LuaFunction
public final Object[] readLine( Optional<Boolean> withTrailingArg ) throws LuaException
@ -116,6 +117,7 @@ public class EncodedReadableHandle extends HandleGeneric
* @throws LuaException When trying to read a negative number of characters.
* @throws LuaException If the file has been closed.
* @cc.treturn string|nil The read characters, or {@code nil} if at the of the file.
* @cc.since 1.80pr1.4
*/
@LuaFunction
public final Object[] read( Optional<Integer> countA ) throws LuaException

View File

@ -201,7 +201,7 @@ public final class NetworkUtils
{
return "Timed out";
}
else if( cause instanceof SSLHandshakeException || cause instanceof DecoderException && cause.getCause() instanceof SSLHandshakeException )
else if( cause instanceof SSLHandshakeException || (cause instanceof DecoderException && cause.getCause() instanceof SSLHandshakeException) )
{
return "Could not create a secure connection";
}

View File

@ -75,7 +75,7 @@ public final class AddressRule
if( this.port != null && this.port != port ) return false;
return predicate.matches( domain )
|| predicate.matches( address )
|| ipv4Address != null && predicate.matches( ipv4Address );
|| (ipv4Address != null && predicate.matches( ipv4Address ));
}
public static Options apply( Iterable<? extends AddressRule> rules, String domain, InetSocketAddress socketAddress )

View File

@ -46,6 +46,7 @@ public class HttpResponseHandle implements ObjectSource
* @return The response code and message.
* @cc.treturn number The response code (i.e. 200)
* @cc.treturn string The response message (i.e. "OK")
* @cc.changed 1.80pr1.13 Added response message return value.
*/
@LuaFunction
public final Object[] getResponseCode()

View File

@ -55,6 +55,8 @@ public class WebsocketHandle implements Closeable
* @cc.treturn [1] string The received message.
* @cc.treturn boolean If this was a binary message.
* @cc.treturn [2] nil If the websocket was closed while waiting, or if we timed out.
* @cc.changed 1.80pr1.13 Added return value indicating whether the message was binary.
* @cc.changed 1.87.0 Added timeout argument.
*/
@LuaFunction
public final MethodResult receive( Optional<Double> timeout ) throws LuaException
@ -74,6 +76,7 @@ public class WebsocketHandle implements Closeable
* @param binary Whether this message should be treated as a
* @throws LuaException If the message is too large.
* @throws LuaException If the websocket has been closed.
* @cc.changed 1.81.0 Added argument for binary mode.
*/
@LuaFunction
public final void send( Object message, Optional<Boolean> binary ) throws LuaException

View File

@ -15,6 +15,7 @@ import dan200.computercraft.api.lua.IArguments;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.lua.MethodResult;
import dan200.computercraft.api.peripheral.PeripheralType;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Type;
@ -108,7 +109,7 @@ public final class Generator<T>
if( instance == null ) continue;
if( methods == null ) methods = new ArrayList<>();
addMethod( methods, method, annotation, instance );
addMethod( methods, method, annotation, null, instance );
}
for( GenericMethod method : GenericMethod.all() )
@ -119,7 +120,7 @@ public final class Generator<T>
if( instance == null ) continue;
if( methods == null ) methods = new ArrayList<>();
addMethod( methods, method.method, method.annotation, instance );
addMethod( methods, method.method, method.annotation, method.peripheralType, instance );
}
if( methods == null ) return Collections.emptyList();
@ -127,7 +128,7 @@ public final class Generator<T>
return Collections.unmodifiableList( methods );
}
private void addMethod( List<NamedMethod<T>> methods, Method method, LuaFunction annotation, T instance )
private void addMethod( List<NamedMethod<T>> methods, Method method, LuaFunction annotation, PeripheralType genericType, T instance )
{
if( annotation.mainThread() ) instance = wrap.apply( instance );
@ -135,13 +136,13 @@ public final class Generator<T>
boolean isSimple = method.getReturnType() != MethodResult.class && !annotation.mainThread();
if( names.length == 0 )
{
methods.add( new NamedMethod<>( method.getName(), instance, isSimple ) );
methods.add( new NamedMethod<>( method.getName(), instance, isSimple, genericType ) );
}
else
{
for( String name : names )
{
methods.add( new NamedMethod<>( name, instance, isSimple ) );
methods.add( new NamedMethod<>( name, instance, isSimple, genericType ) );
}
}
}

View File

@ -8,6 +8,8 @@ package dan200.computercraft.core.asm;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.GenericSource;
import dan200.computercraft.api.lua.LuaFunction;
import dan200.computercraft.api.peripheral.GenericPeripheral;
import dan200.computercraft.api.peripheral.PeripheralType;
import javax.annotation.Nonnull;
import java.lang.reflect.Method;
@ -18,6 +20,7 @@ import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* A generic method is a method belonging to a {@link GenericSource} with a known target.
@ -27,15 +30,17 @@ public class GenericMethod
final Method method;
final LuaFunction annotation;
final Class<?> target;
final PeripheralType peripheralType;
private static final List<GenericSource> sources = new ArrayList<>();
private static List<GenericMethod> cache;
GenericMethod( Method method, LuaFunction annotation, Class<?> target )
GenericMethod( Method method, LuaFunction annotation, Class<?> target, PeripheralType peripheralType )
{
this.method = method;
this.annotation = annotation;
this.target = target;
this.peripheralType = peripheralType;
}
/**
@ -46,10 +51,28 @@ public class GenericMethod
static List<GenericMethod> all()
{
if( cache != null ) return cache;
return cache = sources.stream()
.flatMap( x -> Arrays.stream( x.getClass().getDeclaredMethods() ) )
.map( method ->
{
return cache = sources.stream().flatMap( GenericMethod::getMethods ).collect( Collectors.toList() );
}
public static synchronized void register( @Nonnull GenericSource source )
{
Objects.requireNonNull( source, "Source cannot be null" );
if( cache != null )
{
ComputerCraft.log.warn( "Registering a generic source {} after cache has been built. This source will be ignored.", cache );
}
sources.add( source );
}
private static Stream<GenericMethod> getMethods( GenericSource source )
{
Class<?> klass = source.getClass();
PeripheralType type = source instanceof GenericPeripheral ? ((GenericPeripheral) source).getType() : null;
return Arrays.stream( klass.getDeclaredMethods() )
.map( method -> {
LuaFunction annotation = method.getAnnotation( LuaFunction.class );
if( annotation == null ) return null;
@ -69,22 +92,8 @@ public class GenericMethod
Class<?> target = Reflect.getRawType( method, types[0], false );
if( target == null ) return null;
return new GenericMethod( method, annotation, target );
return new GenericMethod( method, annotation, target, type );
} )
.filter( Objects::nonNull )
.collect( Collectors.toList() );
}
public static synchronized void register( @Nonnull GenericSource source )
{
Objects.requireNonNull( source, "Source cannot be null" );
if( cache != null )
{
ComputerCraft.log.warn( "Registering a generic source {} after cache has been built. This source will be ignored.", cache );
}
sources.add( source );
.filter( Objects::nonNull );
}
}

View File

@ -13,7 +13,7 @@ import java.util.Collections;
public interface LuaMethod
{
Generator<LuaMethod> GENERATOR = new Generator<>( LuaMethod.class, Collections.singletonList( ILuaContext.class ),
m -> ( target, context, args ) -> TaskCallback.make( context, () -> TaskCallback.checkUnwrap( m.apply( target, context, args ) ) )
m -> ( target, context, args ) -> context.executeMainThreadTask( () -> ResultHelpers.checkNormalResult( m.apply( target, context, args ) ) )
);
IntCache<LuaMethod> DYNAMIC = new IntCache<>(

View File

@ -5,7 +5,10 @@
*/
package dan200.computercraft.core.asm;
import dan200.computercraft.api.peripheral.PeripheralType;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public final class NamedMethod<T>
{
@ -13,11 +16,14 @@ public final class NamedMethod<T>
private final T method;
private final boolean nonYielding;
NamedMethod( String name, T method, boolean nonYielding )
private final PeripheralType genericType;
NamedMethod( String name, T method, boolean nonYielding, PeripheralType genericType )
{
this.name = name;
this.method = method;
this.nonYielding = nonYielding;
this.genericType = genericType;
}
@Nonnull
@ -36,4 +42,10 @@ public final class NamedMethod<T>
{
return nonYielding;
}
@Nullable
public PeripheralType getGenericType()
{
return genericType;
}
}

View File

@ -18,7 +18,7 @@ import java.util.Arrays;
public interface PeripheralMethod
{
Generator<PeripheralMethod> GENERATOR = new Generator<>( PeripheralMethod.class, Arrays.asList( ILuaContext.class, IComputerAccess.class ),
m -> ( target, context, computer, args ) -> TaskCallback.make( context, () -> TaskCallback.checkUnwrap( m.apply( target, context, computer, args ) ) )
m -> ( target, context, computer, args ) -> context.executeMainThreadTask( () -> ResultHelpers.checkNormalResult( m.apply( target, context, computer, args ) ) )
);
IntCache<PeripheralMethod> DYNAMIC = new IntCache<>(

View File

@ -0,0 +1,27 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.core.asm;
import dan200.computercraft.api.lua.MethodResult;
final class ResultHelpers
{
private ResultHelpers()
{
}
static Object[] checkNormalResult( MethodResult result )
{
if( result.getCallback() != null )
{
// Due to how tasks are implemented, we can't currently return a MethodResult. This is an
// entirely artificial limitation - we can remove it if it ever becomes an issue.
throw new IllegalStateException( "Must return MethodResult.of from mainThread function." );
}
return result.getResult();
}
}

View File

@ -309,9 +309,9 @@ public final class Environment implements IAPIEnvironment
{
int index = side.ordinal();
IPeripheral existing = peripherals[index];
if( existing == null && peripheral != null ||
existing != null && peripheral == null ||
existing != null && !existing.equals( peripheral ) )
if( (existing == null && peripheral != null) ||
(existing != null && peripheral == null) ||
(existing != null && !existing.equals( peripheral )) )
{
peripherals[index] = peripheral;
if( peripheralListener != null ) peripheralListener.onPeripheralChanged( side, peripheral );

View File

@ -93,7 +93,7 @@ public final class MainThread
executor.updateTime();
// We're not currently on the queue, so update its current execution time to
// ensure its at least as high as the minimum.
// ensure it's at least as high as the minimum.
long newRuntime = minimumTime;
// Slow down new computers a little bit.

View File

@ -7,7 +7,6 @@ package dan200.computercraft.core.filesystem;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.collect.MapMaker;
import com.google.common.io.ByteStreams;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.filesystem.IMount;
@ -15,10 +14,11 @@ import dan200.computercraft.core.apis.handles.ArrayByteChannel;
import dan200.computercraft.shared.util.IoUtil;
import net.minecraft.ResourceLocationException;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.minecraft.server.packs.resources.PreparableReloadListener;
import net.minecraft.server.packs.resources.Resource;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraft.server.packs.resources.ResourceManagerReloadListener;
import net.minecraft.server.packs.resources.SimplePreparableReloadListener;
import net.minecraft.util.profiling.ProfilerFiller;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -27,7 +27,9 @@ import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.util.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public final class ResourceMount implements IMount
@ -56,50 +58,37 @@ public final class ResourceMount implements IMount
.<FileEntry, byte[]>weigher( ( k, v ) -> v.length )
.build();
private static final MapMaker CACHE_TEMPLATE = new MapMaker().weakValues().concurrencyLevel( 1 );
/**
* Maintain a cache of currently loaded resource mounts. This cache is invalidated when currentManager changes.
*/
private static final Map<ReloadableResourceManager, Map<ResourceLocation, ResourceMount>> MOUNT_CACHE = new WeakHashMap<>( 2 );
private static final Map<ResourceLocation, ResourceMount> MOUNT_CACHE = new HashMap<>( 2 );
private final String namespace;
private final String subPath;
private final ReloadableResourceManager manager;
private ResourceManager manager;
@Nullable
private FileEntry root;
public static ResourceMount get( String namespace, String subPath, ReloadableResourceManager manager )
public static ResourceMount get( String namespace, String subPath, ResourceManager manager )
{
Map<ResourceLocation, ResourceMount> cache;
ResourceLocation path = new ResourceLocation( namespace, subPath );
synchronized( MOUNT_CACHE )
{
cache = MOUNT_CACHE.get( manager );
if( cache == null ) MOUNT_CACHE.put( manager, cache = CACHE_TEMPLATE.makeMap() );
}
ResourceLocation path = new ResourceLocation( namespace, subPath );
synchronized( cache )
{
ResourceMount mount = cache.get( path );
if( mount == null ) cache.put( path, mount = new ResourceMount( namespace, subPath, manager ) );
ResourceMount mount = MOUNT_CACHE.get( path );
if( mount == null ) MOUNT_CACHE.put( path, mount = new ResourceMount( namespace, subPath, manager ) );
return mount;
}
}
private ResourceMount( String namespace, String subPath, ReloadableResourceManager manager )
private ResourceMount( String namespace, String subPath, ResourceManager manager )
{
this.namespace = namespace;
this.subPath = subPath;
this.manager = manager;
Listener.INSTANCE.add( manager, this );
if( root == null ) load();
load( manager );
}
private void load()
private void load( ResourceManager manager )
{
boolean hasAny = false;
String existingNamespace = null;
@ -117,6 +106,7 @@ public final class ResourceMount implements IMount
hasAny = true;
}
this.manager = manager;
root = hasAny ? newRoot : null;
if( !hasAny )
@ -292,28 +282,30 @@ public final class ResourceMount implements IMount
}
/**
* A {@link ResourceReloader} which reloads any associated mounts.
*
* While people should really be keeping a permanent reference to this, some people construct it every
* method call, so let's make this as small as possible.
* A {@link PreparableReloadListener} which reloads any associated mounts and correctly updates the resource manager
* they point to.
*/
static class Listener implements ResourceManagerReloadListener
public static final SimplePreparableReloadListener<Void> RELOAD_LISTENER = new SimplePreparableReloadListener<>()
{
private static final Listener INSTANCE = new Listener();
private final Set<ResourceMount> mounts = Collections.newSetFromMap( new WeakHashMap<>() );
private final Set<ReloadableResourceManager> managers = Collections.newSetFromMap( new WeakHashMap<>() );
@Nonnull
@Override
protected Void prepare( @Nonnull ResourceManager manager, @Nonnull ProfilerFiller profiler )
{
profiler.push( "Reloading ComputerCraft mounts" );
try
{
for( ResourceMount mount : MOUNT_CACHE.values() ) mount.load( manager );
}
finally
{
profiler.pop();
}
return null;
}
@Override
public void onResourceManagerReload( @Nonnull ResourceManager manager )
protected void apply( @Nonnull Void result, @Nonnull ResourceManager manager, @Nonnull ProfilerFiller profiler )
{
for( ResourceMount mount : mounts ) mount.load();
}
synchronized void add( ReloadableResourceManager manager, ResourceMount mount )
{
if( managers.add( manager ) ) manager.registerReloadListener( this );
mounts.add( mount );
}
}
};
}

View File

@ -9,8 +9,6 @@ import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaTask;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.MethodResult;
import dan200.computercraft.core.asm.TaskCallback;
import dan200.computercraft.core.computer.Computer;
import dan200.computercraft.core.computer.MainThread;
@ -68,11 +66,4 @@ class LuaContext implements ILuaContext
throw new LuaException( "Task limit exceeded" );
}
}
@Nonnull
@Override
public MethodResult executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException
{
return TaskCallback.make( this, task );
}
}

View File

@ -24,7 +24,7 @@ class ResultInterpreterFunction extends ResumableVarArgFunction<ResultInterprete
static class Container
{
ILuaCallback callback;
int errorAdjust;
final int errorAdjust;
Container( ILuaCallback callback, int errorAdjust )
{

View File

@ -0,0 +1,155 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.core.tracking;
import com.google.common.base.CaseFormat;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.core.computer.Computer;
import net.minecraft.locale.Language;
import javax.annotation.Nonnull;
import javax.management.*;
import java.lang.management.ManagementFactory;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.LongSupplier;
public final class ComputerMBean implements DynamicMBean, Tracker
{
private static final Set<TrackingField> SKIP = new HashSet<>( Arrays.asList(
TrackingField.TASKS, TrackingField.TOTAL_TIME, TrackingField.AVERAGE_TIME, TrackingField.MAX_TIME,
TrackingField.SERVER_COUNT, TrackingField.SERVER_TIME
) );
private static ComputerMBean instance;
private final Map<String, LongSupplier> attributes = new HashMap<>();
private final Map<TrackingField, Counter> values = new HashMap<>();
private final MBeanInfo info;
private ComputerMBean()
{
List<MBeanAttributeInfo> attributes = new ArrayList<>();
for( Map.Entry<String, TrackingField> field : TrackingField.fields().entrySet() )
{
if( SKIP.contains( field.getValue() ) ) continue;
String name = CaseFormat.LOWER_UNDERSCORE.to( CaseFormat.LOWER_CAMEL, field.getKey() );
add( name, field.getValue(), attributes, null );
}
add( "task", TrackingField.TOTAL_TIME, attributes, TrackingField.TASKS );
add( "serverTask", TrackingField.SERVER_TIME, attributes, TrackingField.SERVER_COUNT );
info = new MBeanInfo(
ComputerMBean.class.getSimpleName(),
"metrics about all computers on the server",
attributes.toArray( new MBeanAttributeInfo[0] ), null, null, null
);
}
public static void register()
{
try
{
ManagementFactory.getPlatformMBeanServer().registerMBean( instance = new ComputerMBean(), new ObjectName( "dan200.computercraft:type=Computers" ) );
}
catch( InstanceAlreadyExistsException | MBeanRegistrationException | NotCompliantMBeanException | MalformedObjectNameException e )
{
ComputerCraft.log.warn( "Failed to register JMX bean", e );
}
}
public static void registerTracker()
{
if( instance != null ) Tracking.add( instance );
}
@Override
public Object getAttribute( String attribute ) throws AttributeNotFoundException
{
LongSupplier value = attributes.get( attribute );
if( value == null ) throw new AttributeNotFoundException();
return value.getAsLong();
}
@Override
public void setAttribute( Attribute attribute ) throws InvalidAttributeValueException
{
throw new InvalidAttributeValueException( "Cannot set attribute" );
}
@Override
public AttributeList getAttributes( String[] attributes )
{
return null;
}
@Override
public AttributeList setAttributes( AttributeList attributes )
{
return new AttributeList();
}
@Override
public Object invoke( String actionName, Object[] params, String[] signature )
{
return null;
}
@Override
@Nonnull
public MBeanInfo getMBeanInfo()
{
return info;
}
@Override
public void addTaskTiming( Computer computer, long time )
{
addValue( computer, TrackingField.TOTAL_TIME, time );
}
@Override
public void addServerTiming( Computer computer, long time )
{
addValue( computer, TrackingField.SERVER_TIME, time );
}
@Override
public void addValue( Computer computer, TrackingField field, long change )
{
Counter counter = values.get( field );
counter.value.addAndGet( change );
counter.count.incrementAndGet();
}
private MBeanAttributeInfo addAttribute( String name, String description, LongSupplier value )
{
attributes.put( name, value );
return new MBeanAttributeInfo( name, "long", description, true, false, false );
}
private void add( String name, TrackingField field, List<MBeanAttributeInfo> attributes, TrackingField count )
{
Counter counter = new Counter();
values.put( field, counter );
String prettyName = Language.getInstance().getOrDefault( field.translationKey() );
attributes.add( addAttribute( name, prettyName, counter.value::longValue ) );
if( count != null )
{
String countName = Language.getInstance().getOrDefault( count.translationKey() );
attributes.add( addAttribute( name + "Count", countName, counter.count::longValue ) );
}
}
private static class Counter
{
final AtomicLong value = new AtomicLong();
final AtomicLong count = new AtomicLong();
}
}

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.peripheral.modem;
import dan200.computercraft.api.lua.LuaException;
@ -28,9 +27,9 @@ import java.util.Set;
*/
public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPacketReceiver
{
private IPacketNetwork network;
private final Set<IComputerAccess> computers = new HashSet<>( 1 );
private final ModemState state;
private IPacketNetwork network;
protected ModemPeripheral( ModemState state )
{
@ -42,6 +41,20 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
return state;
}
private synchronized void setNetwork( IPacketNetwork network )
{
if( this.network == network ) return;
// Leave old network
if( this.network != null ) this.network.removeReceiver( this );
// Set new network
this.network = network;
// Join new network
if( this.network != null ) this.network.addReceiver( this );
}
public void destroy()
{
setNetwork( null );
@ -50,21 +63,14 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
@Override
public void receiveSameDimension( @Nonnull Packet packet, double distance )
{
if( packet.getSender() == this || !state.isOpen( packet.getChannel() ) )
{
return;
}
if( packet.sender() == this || !state.isOpen( packet.channel() ) ) return;
synchronized( computers )
{
for( IComputerAccess computer : computers )
{
computer.queueEvent( "modem_message",
computer.getAttachmentName(),
packet.getChannel(),
packet.getReplyChannel(),
packet.getPayload(),
distance );
computer.getAttachmentName(), packet.channel(), packet.replyChannel(), packet.payload(), distance );
}
}
}
@ -72,20 +78,20 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
@Override
public void receiveDifferentDimension( @Nonnull Packet packet )
{
if( packet.getSender() == this || !state.isOpen( packet.getChannel() ) )
{
return;
}
if( packet.sender() == this || !state.isOpen( packet.channel() ) ) return;
synchronized( computers )
{
for( IComputerAccess computer : computers )
{
computer.queueEvent( "modem_message", computer.getAttachmentName(), packet.getChannel(), packet.getReplyChannel(), packet.getPayload() );
computer.queueEvent( "modem_message",
computer.getAttachmentName(), packet.channel(), packet.replyChannel(), packet.payload() );
}
}
}
protected abstract IPacketNetwork getNetwork();
@Nonnull
@Override
public String getType()
@ -93,60 +99,15 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
return "modem";
}
@Override
public synchronized void attach( @Nonnull IComputerAccess computer )
private static int parseChannel( int channel ) throws LuaException
{
synchronized( computers )
{
computers.add( computer );
}
setNetwork( getNetwork() );
}
protected abstract IPacketNetwork getNetwork();
private synchronized void setNetwork( IPacketNetwork network )
{
if( this.network == network )
{
return;
}
// Leave old network
if( this.network != null )
{
this.network.removeReceiver( this );
}
// Set new network
this.network = network;
// Join new network
if( this.network != null )
{
this.network.addReceiver( this );
}
}
@Override
public synchronized void detach( @Nonnull IComputerAccess computer )
{
boolean empty;
synchronized( computers )
{
computers.remove( computer );
empty = computers.isEmpty();
}
if( empty )
{
setNetwork( null );
}
if( channel < 0 || channel > 65535 ) throw new LuaException( "Expected number in range 0-65535" );
return channel;
}
/**
* Open a channel on a modem. A channel must be open in order to receive messages. Modems can have up to 128 channels open at one time.
* Open a channel on a modem. A channel must be open in order to receive messages. Modems can have up to 128
* channels open at one time.
*
* @param channel The channel to open. This must be a number between 0 and 65535.
* @throws LuaException If the channel is out of range.
@ -158,15 +119,6 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
state.open( parseChannel( channel ) );
}
private static int parseChannel( int channel ) throws LuaException
{
if( channel < 0 || channel > 65535 )
{
throw new LuaException( "Expected number in range 0-65535" );
}
return channel;
}
/**
* Check if a channel is open.
*
@ -202,13 +154,14 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
}
/**
* Sends a modem message on a certain channel. Modems listening on the channel will queue a {@code modem_message} event on adjacent computers.
* Sends a modem message on a certain channel. Modems listening on the channel will queue a {@code modem_message}
* event on adjacent computers.
*
* <blockquote><strong>Note:</strong> The channel does not need be open to send a message.</blockquote>
*
* @param channel The channel to send messages on.
* @param replyChannel The channel that responses to this message should be sent on.
* @param payload The object to send. This can be a string, number, or table.
* @param payload The object to send. This can be a boolean, string, number, or table.
* @throws LuaException If the channel is out of range.
*/
@LuaFunction
@ -217,14 +170,11 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
parseChannel( channel );
parseChannel( replyChannel );
Level world = getWorld();
Level world = getLevel();
Vec3 position = getPosition();
IPacketNetwork network = this.network;
if( world == null || position == null || network == null )
{
return;
}
if( world == null || position == null || network == null ) return;
Packet packet = new Packet( channel, replyChannel, payload, this );
if( isInterdimensional() )
@ -240,7 +190,8 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
/**
* Determine if this is a wired or wireless modem.
*
* Some methods (namely those dealing with wired networks and remote peripherals) are only available on wired modems.
* Some methods (namely those dealing with wired networks and remote peripherals) are only available on wired
* modems.
*
* @return {@code true} if this is a wireless modem.
*/
@ -251,6 +202,30 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
return network != null && network.isWireless();
}
@Override
public synchronized void attach( @Nonnull IComputerAccess computer )
{
synchronized( computers )
{
computers.add( computer );
}
setNetwork( getNetwork() );
}
@Override
public synchronized void detach( @Nonnull IComputerAccess computer )
{
boolean empty;
synchronized( computers )
{
computers.remove( computer );
empty = computers.isEmpty();
}
if( empty ) setNetwork( null );
}
@Nonnull
@Override
public String getSenderID()
@ -263,8 +238,7 @@ public abstract class ModemPeripheral implements IPeripheral, IPacketSender, IPa
}
else
{
IComputerAccess computer = computers.iterator()
.next();
IComputerAccess computer = computers.iterator().next();
return computer.getID() + "_" + computer.getAttachmentName();
}
}

View File

@ -419,7 +419,7 @@ public class TileCable extends TileGeneric implements IPeripheralTile
{
@Nonnull
@Override
public Level getWorld()
public Level getLevel()
{
return TileCable.this.getLevel();
}

View File

@ -430,7 +430,7 @@ public class TileWiredModemFull extends TileGeneric implements IPeripheralTile
@Nonnull
@Override
public Level getWorld()
public Level getLevel()
{
return entity.getLevel();
}

View File

@ -122,9 +122,9 @@ public abstract class WiredModemPeripheral extends ModemPeripheral implements IW
@Nonnull
@Override
public Level getWorld()
public Level getLevel()
{
return modem.getWorld();
return modem.getLevel();
}
/**

View File

@ -121,7 +121,7 @@ public class TileWirelessModem extends TileGeneric implements IPeripheralTile
@Nonnull
@Override
public Level getWorld()
public Level getLevel()
{
return entity.getLevel();
}

View File

@ -32,7 +32,7 @@ public abstract class WirelessModemPeripheral extends ModemPeripheral
}
else
{
Level world = getWorld();
Level world = getLevel();
if( world != null )
{
Vec3 position = getPosition();

View File

@ -3,7 +3,6 @@
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.peripheral.modem.wireless;
import dan200.computercraft.api.network.IPacketNetwork;
@ -20,14 +19,10 @@ import java.util.concurrent.ConcurrentHashMap;
public class WirelessNetwork implements IPacketNetwork
{
private static WirelessNetwork universalNetwork = null;
private final Set<IPacketReceiver> receivers = Collections.newSetFromMap( new ConcurrentHashMap<>() );
public static WirelessNetwork getUniversal()
{
if( universalNetwork == null )
{
universalNetwork = new WirelessNetwork();
}
if( universalNetwork == null ) universalNetwork = new WirelessNetwork();
return universalNetwork;
}
@ -36,6 +31,8 @@ public class WirelessNetwork implements IPacketNetwork
universalNetwork = null;
}
private final Set<IPacketReceiver> receivers = Collections.newSetFromMap( new ConcurrentHashMap<>() );
@Override
public void addReceiver( @Nonnull IPacketReceiver receiver )
{
@ -50,40 +47,27 @@ public class WirelessNetwork implements IPacketNetwork
receivers.remove( receiver );
}
@Override
public boolean isWireless()
{
return true;
}
@Override
public void transmitSameDimension( @Nonnull Packet packet, double range )
{
Objects.requireNonNull( packet, "packet cannot be null" );
for( IPacketReceiver device : receivers )
{
tryTransmit( device, packet, range, false );
}
for( IPacketReceiver device : receivers ) tryTransmit( device, packet, range, false );
}
@Override
public void transmitInterdimensional( @Nonnull Packet packet )
{
Objects.requireNonNull( packet, "packet cannot be null" );
for( IPacketReceiver device : receivers )
{
tryTransmit( device, packet, 0, true );
}
for( IPacketReceiver device : receivers ) tryTransmit( device, packet, 0, true );
}
private static void tryTransmit( IPacketReceiver receiver, Packet packet, double range, boolean interdimensional )
{
IPacketSender sender = packet.getSender();
if( receiver.getWorld() == sender.getWorld() )
IPacketSender sender = packet.sender();
if( receiver.getLevel() == sender.getLevel() )
{
double receiveRange = Math.max( range, receiver.getRange() ); // Ensure range is symmetrical
double distanceSq = receiver.getPosition()
.distanceToSqr( sender.getPosition() );
double distanceSq = receiver.getPosition().distanceToSqr( sender.getPosition() );
if( interdimensional || receiver.isInterdimensional() || distanceSq <= receiveRange * receiveRange )
{
receiver.receiveSameDimension( packet, Math.sqrt( distanceSq ) );
@ -97,4 +81,10 @@ public class WirelessNetwork implements IPacketNetwork
}
}
}
@Override
public boolean isWireless()
{
return true;
}
}

View File

@ -32,7 +32,7 @@ public class PocketModemPeripheral extends WirelessModemPeripheral
@Nonnull
@Override
public Level getWorld()
public Level getLevel()
{
return world;
}

View File

@ -28,7 +28,6 @@ import dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods;
import dan200.computercraft.shared.peripheral.modem.wired.BlockCable;
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
import dan200.computercraft.shared.turtle.FurnaceRefuelHandler;
import dan200.computercraft.shared.turtle.SignInspectHandler;
import dan200.computercraft.shared.util.Config;
import dan200.computercraft.shared.util.TickScheduler;
import net.fabricmc.fabric.api.command.v1.CommandRegistrationCallback;
@ -139,7 +138,6 @@ public final class ComputerCraftProxyCommon
TurtleEvent.EVENT_BUS.register( FurnaceRefuelHandler.INSTANCE );
TurtleEvent.EVENT_BUS.register( new TurtlePermissions() );
TurtleEvent.EVENT_BUS.register( new SignInspectHandler() );
}
public static void registerLoot()

View File

@ -51,7 +51,7 @@ public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler
if( !remainder.isEmpty() )
{
WorldUtil.dropItemStack( remainder,
turtle.getWorld(),
turtle.getLevel(),
turtle.getPosition(),
turtle.getDirection()
.getOpposite() );

View File

@ -1,33 +0,0 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.turtle;
import com.google.common.eventbus.Subscribe;
import dan200.computercraft.api.turtle.event.TurtleBlockEvent;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.SignBlockEntity;
import java.util.HashMap;
import java.util.Map;
public class SignInspectHandler
{
@Subscribe
public void onTurtleInspect( TurtleBlockEvent.Inspect event )
{
BlockEntity be = event.getWorld().getBlockEntity( event.getPos() );
if( be instanceof SignBlockEntity )
{
SignBlockEntity sbe = (SignBlockEntity) be;
Map<Integer, String> textTable = new HashMap<>();
for( int k = 0; k < 4; k++ )
{
textTable.put( k + 1, sbe.getMessage( k, true ).getString() );
}
event.getData().put( "text", textTable );
}
}
}

View File

@ -11,9 +11,6 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleCommand;
import dan200.computercraft.api.turtle.TurtleCommandResult;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.turtle.event.TurtleActionEvent;
import dan200.computercraft.api.turtle.event.TurtleEvent;
import dan200.computercraft.api.turtle.event.TurtleInspectItemEvent;
import dan200.computercraft.core.apis.IAPIEnvironment;
import dan200.computercraft.core.asm.TaskCallback;
import dan200.computercraft.core.tracking.TrackingField;
@ -774,12 +771,6 @@ public class TurtleAPI implements ILuaAPI
? ItemData.fill( new HashMap<>(), stack )
: ItemData.fillBasicSafe( new HashMap<>(), stack );
TurtleActionEvent event = new TurtleInspectItemEvent( turtle, stack, table, detailed );
if( TurtleEvent.post( event ) )
{
return new Object[] { false, event.getFailureMessage() };
}
return new Object[] { table };
}
}

Some files were not shown because too many files have changed in this diff Show More