mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2024-06-24 22:23:21 +00:00
d5f82fa458
When creating a peripheral or custom Lua object, one must implement two methods: - getMethodNames(): String[] - Returns the name of the methods - callMethod(int, ...): Object[] - Invokes the method using an index in the above array. This has a couple of problems: - It's somewhat unwieldy to use - you need to keep track of array indices, which leads to ugly code. - Functions which yield (for instance, those which run on the main thread) are blocking. This means we need to spawn new threads for each CC-side yield. We replace this system with a few changes: - @LuaFunction annotation: One may annotate a public instance method with this annotation. This then exposes a peripheral/lua object method. Furthermore, this method can accept and return a variety of types, which often makes functions cleaner (e.g. can return an int rather than an Object[], and specify and int argument rather than Object[]). - MethodResult: Instead of returning an Object[] and having blocking yields, functions return a MethodResult. This either contains an immediate return, or an instruction to yield with some continuation to resume with. MethodResult is then interpreted by the Lua runtime (i.e. Cobalt), rather than our weird bodgey hacks before. This means we no longer spawn new threads when yielding within CC. - Methods accept IArguments instead of a raw Object array. This has a few benefits: - Consistent argument handling - people no longer need to use ArgumentHelper (as it doesn't exist!), or even be aware of its existence - you're rather forced into using it. - More efficient code in some cases. We provide a Cobalt-specific implementation of IArguments, which avoids the boxing/unboxing when handling numbers and binary strings.
209 lines
5.7 KiB
Java
209 lines
5.7 KiB
Java
/*
|
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
* Copyright Daniel Ratcliffe, 2011-2020. Do not distribute without permission.
|
|
* Send enquiries to dratcliffe@gmail.com
|
|
*/
|
|
package dan200.computercraft.core.apis;
|
|
|
|
import dan200.computercraft.api.lua.LuaException;
|
|
import dan200.computercraft.api.lua.LuaValues;
|
|
|
|
import javax.annotation.Nonnull;
|
|
import javax.annotation.Nullable;
|
|
import java.util.Map;
|
|
|
|
import static dan200.computercraft.api.lua.LuaValues.getNumericType;
|
|
|
|
/**
|
|
* Various helpers for tables.
|
|
*/
|
|
public final class TableHelper
|
|
{
|
|
private TableHelper()
|
|
{
|
|
throw new IllegalStateException( "Cannot instantiate singleton " + getClass().getName() );
|
|
}
|
|
|
|
@Nonnull
|
|
public static LuaException badKey( @Nonnull String key, @Nonnull String expected, @Nullable Object actual )
|
|
{
|
|
return badKey( key, expected, LuaValues.getType( actual ) );
|
|
}
|
|
|
|
@Nonnull
|
|
public static LuaException badKey( @Nonnull String key, @Nonnull String expected, @Nonnull String actual )
|
|
{
|
|
return new LuaException( "bad field '" + key + "' (" + expected + " expected, got " + actual + ")" );
|
|
}
|
|
|
|
public static double getNumberField( @Nonnull Map<?, ?> table, @Nonnull String key ) throws LuaException
|
|
{
|
|
Object value = table.get( key );
|
|
if( value instanceof Number )
|
|
{
|
|
return ((Number) value).doubleValue();
|
|
}
|
|
else
|
|
{
|
|
throw badKey( key, "number", value );
|
|
}
|
|
}
|
|
|
|
public static int getIntField( @Nonnull Map<?, ?> table, @Nonnull String key ) throws LuaException
|
|
{
|
|
Object value = table.get( key );
|
|
if( value instanceof Number )
|
|
{
|
|
return (int) ((Number) value).longValue();
|
|
}
|
|
else
|
|
{
|
|
throw badKey( key, "number", value );
|
|
}
|
|
}
|
|
|
|
public static double getRealField( @Nonnull Map<?, ?> table, @Nonnull String key ) throws LuaException
|
|
{
|
|
return checkReal( key, getNumberField( table, key ) );
|
|
}
|
|
|
|
public static boolean getBooleanField( @Nonnull Map<?, ?> table, @Nonnull String key ) throws LuaException
|
|
{
|
|
Object value = table.get( key );
|
|
if( value instanceof Boolean )
|
|
{
|
|
return (Boolean) value;
|
|
}
|
|
else
|
|
{
|
|
throw badKey( key, "boolean", value );
|
|
}
|
|
}
|
|
|
|
@Nonnull
|
|
public static String getStringField( @Nonnull Map<?, ?> table, @Nonnull String key ) throws LuaException
|
|
{
|
|
Object value = table.get( key );
|
|
if( value instanceof String )
|
|
{
|
|
return (String) value;
|
|
}
|
|
else
|
|
{
|
|
throw badKey( key, "string", value );
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings( "unchecked" )
|
|
@Nonnull
|
|
public static Map<Object, Object> getTableField( @Nonnull Map<?, ?> table, @Nonnull String key ) throws LuaException
|
|
{
|
|
Object value = table.get( key );
|
|
if( value instanceof Map )
|
|
{
|
|
return (Map<Object, Object>) value;
|
|
}
|
|
else
|
|
{
|
|
throw badKey( key, "table", value );
|
|
}
|
|
}
|
|
|
|
public static double optNumberField( @Nonnull Map<?, ?> table, @Nonnull String key, double def ) throws LuaException
|
|
{
|
|
Object value = table.get( key );
|
|
if( value == null )
|
|
{
|
|
return def;
|
|
}
|
|
else if( value instanceof Number )
|
|
{
|
|
return ((Number) value).doubleValue();
|
|
}
|
|
else
|
|
{
|
|
throw badKey( key, "number", value );
|
|
}
|
|
}
|
|
|
|
public static int optIntField( @Nonnull Map<?, ?> table, @Nonnull String key, int def ) throws LuaException
|
|
{
|
|
Object value = table.get( key );
|
|
if( value == null )
|
|
{
|
|
return def;
|
|
}
|
|
else if( value instanceof Number )
|
|
{
|
|
return (int) ((Number) value).longValue();
|
|
}
|
|
else
|
|
{
|
|
throw badKey( key, "number", value );
|
|
}
|
|
}
|
|
|
|
public static double optRealField( @Nonnull Map<?, ?> table, @Nonnull String key, double def ) throws LuaException
|
|
{
|
|
return checkReal( key, optNumberField( table, key, def ) );
|
|
}
|
|
|
|
public static boolean optBooleanField( @Nonnull Map<?, ?> table, @Nonnull String key, boolean def ) throws LuaException
|
|
{
|
|
Object value = table.get( key );
|
|
if( value == null )
|
|
{
|
|
return def;
|
|
}
|
|
else if( value instanceof Boolean )
|
|
{
|
|
return (Boolean) value;
|
|
}
|
|
else
|
|
{
|
|
throw badKey( key, "boolean", value );
|
|
}
|
|
}
|
|
|
|
public static String optStringField( @Nonnull Map<?, ?> table, @Nonnull String key, String def ) throws LuaException
|
|
{
|
|
Object value = table.get( key );
|
|
if( value == null )
|
|
{
|
|
return def;
|
|
}
|
|
else if( value instanceof String )
|
|
{
|
|
return (String) value;
|
|
}
|
|
else
|
|
{
|
|
throw badKey( key, "string", value );
|
|
}
|
|
}
|
|
|
|
@SuppressWarnings( "unchecked" )
|
|
public static Map<Object, Object> optTableField( @Nonnull Map<?, ?> table, @Nonnull String key, Map<Object, Object> def ) throws LuaException
|
|
{
|
|
Object value = table.get( key );
|
|
if( value == null )
|
|
{
|
|
return def;
|
|
}
|
|
else if( value instanceof Map )
|
|
{
|
|
return (Map<Object, Object>) value;
|
|
}
|
|
else
|
|
{
|
|
throw badKey( key, "table", value );
|
|
}
|
|
}
|
|
|
|
private static double checkReal( @Nonnull String key, double value ) throws LuaException
|
|
{
|
|
if( !Double.isFinite( value ) ) throw badKey( key, "number", getNumericType( value ) );
|
|
return value;
|
|
}
|
|
}
|