1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2024-06-26 07:03:22 +00:00
CC-Tweaked/src/main/java/dan200/computercraft/shared/computer/apis/CommandAPI.java

328 lines
12 KiB
Java
Raw Normal View History

/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2017. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.apis;
import com.google.common.collect.ImmutableMap;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.ILuaTask;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.core.apis.ILuaAPI;
import dan200.computercraft.core.logger.Logger;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.util.WorldUtil;
import net.minecraft.block.Block;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.IBlockState;
import net.minecraft.command.ICommand;
import net.minecraft.command.ICommandManager;
import net.minecraft.command.ICommandSender;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
2017-05-06 23:07:42 +00:00
import javax.annotation.Nonnull;
import java.util.HashMap;
import java.util.Map;
public class CommandAPI implements ILuaAPI
{
private TileCommandComputer m_computer;
public CommandAPI( TileCommandComputer computer )
{
m_computer = computer;
}
// ILuaAPI implementation
@Override
public String[] getNames()
{
return new String[] {
"commands"
};
}
@Override
public void startup()
{
}
@Override
public void advance( double dt )
{
}
@Override
public void shutdown()
{
}
2017-05-06 23:07:42 +00:00
@Nonnull
@Override
public String[] getMethodNames()
{
return new String[] {
"exec",
"execAsync",
"list",
"getBlockPosition",
"getBlockInfos",
"getBlockInfo"
};
}
private Map<Object, Object> createOutput( String output )
{
Map<Object, Object> result = new HashMap<Object, Object>( 1 );
result.put( 1, output );
return result;
}
private Object[] doCommand( String command )
{
MinecraftServer server = m_computer.getWorld().getMinecraftServer();
if( server != null && server.isCommandBlockEnabled() )
{
ICommandManager commandManager = server.getCommandManager();
try
{
TileCommandComputer.CommandSender sender = m_computer.getCommandSender();
sender.clearOutput();
int result = commandManager.executeCommand( sender, command );
return new Object[]{ (result > 0), sender.copyOutput() };
}
catch( Throwable t )
{
Logger.error( "Error running command.", t );
return new Object[]{ false, createOutput( "Java Exception Thrown: " + t.toString() ) };
}
}
else
{
return new Object[] { false, createOutput( "Command blocks disabled by server" ) };
}
}
private Object getBlockInfo( World world, BlockPos pos )
{
// Get the details of the block
IBlockState state = world.getBlockState( pos );
Block block = state.getBlock();
String name = Block.REGISTRY.getNameForObject( block ).toString();
int metadata = block.getMetaFromState( state );
Map<Object, Object> table = new HashMap<Object, Object>();
table.put( "name", name );
table.put( "metadata", metadata );
Map<Object, Object> stateTable = new HashMap<Object, Object>();
for( ImmutableMap.Entry<IProperty<?>, Comparable<?>> entry : state.getActualState( world, pos ).getProperties().entrySet() )
{
String propertyName = entry.getKey().getName();
Object value = entry.getValue();
if( value instanceof String || value instanceof Number || value instanceof Boolean )
{
stateTable.put( propertyName, value );
}
else
{
stateTable.put( propertyName, value.toString() );
}
}
table.put( "state", stateTable );
// TODO: NBT data?
return table;
}
@Override
2017-05-06 23:07:42 +00:00
public Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
{
switch( method )
{
case 0:
{
// exec
if( arguments.length < 1 || !(arguments[0] instanceof String) )
{
throw new LuaException( "Expected string" );
}
final String command = (String)arguments[0];
return context.executeMainThreadTask( new ILuaTask()
{
@Override
public Object[] execute() throws LuaException
{
return doCommand( command );
}
} );
}
case 1:
{
// execAsync
if( arguments.length < 1 || !(arguments[0] instanceof String) )
{
throw new LuaException( "Expected string" );
}
final String command = (String)arguments[0];
long taskID = context.issueMainThreadTask( new ILuaTask()
{
@Override
public Object[] execute() throws LuaException
{
return doCommand( command );
}
} );
return new Object[] { taskID };
}
case 2:
{
// list
return context.executeMainThreadTask( new ILuaTask()
{
@Override
public Object[] execute() throws LuaException
{
int i = 1;
Map<Object, Object> result = new HashMap<Object, Object>();
MinecraftServer server = m_computer.getWorld().getMinecraftServer();
if( server != null )
{
ICommandManager commandManager = server.getCommandManager();
ICommandSender commmandSender = m_computer.getCommandSender();
Map<String, ICommand> commands = commandManager.getCommands();
for( Map.Entry<String, ICommand> entry : commands.entrySet() )
{
String name = entry.getKey();
ICommand command = entry.getValue();
try
{
if( command.checkPermission( server, commmandSender ) )
{
result.put( i++, name );
}
}
catch( Throwable t )
{
// Ignore buggy command
Logger.error( "Error running command.", t );
}
}
}
return new Object[]{ result };
}
} );
}
case 3:
{
// getBlockPosition
// This is probably safe to do on the Lua thread. Probably.
BlockPos pos = m_computer.getPos();
return new Object[] { pos.getX(), pos.getY(), pos.getZ() };
}
case 4:
{
// getBlockInfos
if( arguments.length < 6 ||
!(arguments[0] instanceof Number) ||
!(arguments[1] instanceof Number) ||
!(arguments[2] instanceof Number) ||
!(arguments[3] instanceof Number) ||
!(arguments[4] instanceof Number) ||
!(arguments[5] instanceof Number) )
{
throw new LuaException( "Expected number, number, number, number, number, number" );
}
final int minx = ((Number)arguments[0]).intValue();
final int miny = ((Number)arguments[1]).intValue();
final int minz = ((Number)arguments[2]).intValue();
final int maxx = ((Number)arguments[3]).intValue();
final int maxy = ((Number)arguments[4]).intValue();
final int maxz = ((Number)arguments[5]).intValue();
return context.executeMainThreadTask( new ILuaTask()
{
@Override
public Object[] execute() throws LuaException
{
// Get the details of the block
World world = m_computer.getWorld();
BlockPos min = new BlockPos(
Math.min( minx, maxx ),
Math.min( miny, maxy ),
Math.min( minz, maxz )
);
BlockPos max = new BlockPos(
Math.max( minx, maxx ),
Math.max( miny, maxy ),
Math.max( minz, maxz )
);
if( !WorldUtil.isBlockInWorld( world, min ) || !WorldUtil.isBlockInWorld( world, max ) )
{
throw new LuaException( "Co-ordinates out or range" );
}
if( ( max.getX() - min.getX() + 1 ) * ( max.getY() - min.getY() + 1 ) * ( max.getZ() - min.getZ() + 1 ) > 4096 )
{
throw new LuaException( "Too many blocks" );
}
int i=1;
Map<Object, Object> results = new HashMap<Object, Object>();
for( int y=min.getY(); y<= max.getY(); ++y )
{
for( int z = min.getZ(); z <= max.getZ(); ++z )
{
for( int x = min.getX(); x <= max.getX(); ++x )
{
BlockPos pos = new BlockPos( x, y, z );
results.put( i++, getBlockInfo( world, pos ) );
}
}
}
return new Object[]{ results };
}
} );
}
case 5:
{
// getBlockInfo
if( arguments.length < 3 ||
!(arguments[0] instanceof Number) ||
!(arguments[1] instanceof Number) ||
!(arguments[2] instanceof Number) )
{
throw new LuaException( "Expected number, number, number" );
}
final int x = ((Number)arguments[0]).intValue();
final int y = ((Number)arguments[1]).intValue();
final int z = ((Number)arguments[2]).intValue();
return context.executeMainThreadTask( new ILuaTask()
{
@Override
public Object[] execute() throws LuaException
{
// Get the details of the block
World world = m_computer.getWorld();
BlockPos position = new BlockPos( x, y, z );
if( WorldUtil.isBlockInWorld( world, position ) )
{
return new Object[]{ getBlockInfo( world, position ) };
}
else
{
throw new LuaException( "co-ordinates out or range" );
}
}
} );
}
default:
{
return null;
}
}
}
}