ComputerCraft 1.79 initial upload

Added the complete source code to ComputerCraft 1.79 for Minecraft
1.8.9, plus newly written README and LICENSE files for the open source
release.
This commit is contained in:
Daniel Ratcliffe
2017-05-01 14:32:39 +01:00
parent 38623b31c4
commit e85cdacbc5
1123 changed files with 191332 additions and 3 deletions
@@ -0,0 +1,325 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. 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.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.BlockPos;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
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()
{
}
@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 = MinecraftServer.getServer();
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 )
{
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 = ((ResourceLocation)Block.blockRegistry.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( Object o : block.getActualState( state, world, pos ).getProperties().entrySet() )
{
ImmutableMap.Entry<IProperty, Object> entry = (ImmutableMap.Entry<IProperty, Object>)o;
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
public Object[] callMethod( ILuaContext context, int method, 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 = MinecraftServer.getServer();
if( server != null )
{
ICommandManager commandManager = server.getCommandManager();
ICommandSender commmandSender = m_computer.getCommandSender();
Map commands = commandManager.getCommands();
for( Object entryObject : commands.entrySet() )
{
Map.Entry entry = (Map.Entry)entryObject;
String name = (String)entry.getKey();
ICommand command = (ICommand)entry.getValue();
try
{
if( command.canCommandSenderUseCommand( commmandSender ) )
{
result.put( i++, name );
}
}
catch( Throwable t )
{
// Ignore buggy command
}
}
}
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;
}
}
}
}
@@ -0,0 +1,147 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.peripheral.common.TilePeripheralBase;
import dan200.computercraft.shared.util.DirectionUtil;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockCommandComputer extends BlockComputerBase
{
// Statics
public static class Properties
{
public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);
public static final PropertyEnum STATE = PropertyEnum.create("state", ComputerState.class);
}
// Members
public BlockCommandComputer()
{
super( Material.iron );
setBlockUnbreakable();
setResistance( 6000000.0F );
setUnlocalizedName( "computercraft:command_computer" );
setCreativeTab( ComputerCraft.mainCreativeTab );
setDefaultState( this.blockState.getBaseState()
.withProperty( Properties.FACING, EnumFacing.NORTH )
.withProperty( Properties.STATE, ComputerState.Off )
);
}
@Override
protected BlockState createBlockState()
{
return new BlockState(this, new IProperty[] {
Properties.FACING,
Properties.STATE
});
}
@Override
public IBlockState getStateFromMeta( int meta )
{
EnumFacing dir = EnumFacing.getFront( meta & 0x7 );
if( dir.getAxis() == EnumFacing.Axis.Y )
{
dir = EnumFacing.NORTH;
}
return getDefaultState().withProperty( Properties.FACING, dir );
}
@Override
public int getMetaFromState( IBlockState state )
{
return ((EnumFacing)state.getValue( Properties.FACING )).getIndex();
}
@Override
public IBlockState getActualState( IBlockState state, IBlockAccess world, BlockPos pos )
{
TileEntity tile = world.getTileEntity( pos );
if( tile != null && tile instanceof IComputerTile )
{
IComputer computer = ((IComputerTile)tile).getComputer();
if( computer != null && computer.isOn() )
{
if( computer.isCursorDisplayed() )
{
return state.withProperty( Properties.STATE, ComputerState.Blinking );
}
else
{
return state.withProperty( Properties.STATE, ComputerState.On );
}
}
}
return state.withProperty( Properties.STATE, ComputerState.Off );
}
@Override
protected IBlockState getDefaultBlockState( ComputerFamily family, EnumFacing placedSide )
{
if( placedSide.getAxis() != EnumFacing.Axis.Y )
{
return getDefaultState().withProperty( Properties.FACING, placedSide );
}
else
{
return getDefaultState();
}
}
@Override
public ComputerFamily getFamily( int damage )
{
return ComputerFamily.Command;
}
@Override
public ComputerFamily getFamily( IBlockState state )
{
return ComputerFamily.Command;
}
@Override
protected TileComputer createTile( ComputerFamily family )
{
return new TileCommandComputer();
}
@Override
public void onBlockPlacedBy( World world, BlockPos pos, IBlockState state, EntityLivingBase player, ItemStack itemstack )
{
// Not sure why this is necessary
TileEntity tile = world.getTileEntity( pos );
if( tile != null && tile instanceof TileCommandComputer )
{
tile.setWorldObj( world ); // Not sure why this is necessary
tile.setPos( pos ); // Not sure why this is necessary
}
// Set direction
EnumFacing dir = DirectionUtil.fromEntityRot( player );
setDirection( world, pos, dir );
}
}
@@ -0,0 +1,179 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.computer.items.ItemComputer;
import dan200.computercraft.shared.util.DirectionUtil;
import net.minecraft.block.material.Material;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.properties.PropertyDirection;
import net.minecraft.block.properties.PropertyEnum;
import net.minecraft.block.state.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockComputer extends BlockComputerBase
{
// Statics
public static class Properties
{
public static final PropertyDirection FACING = PropertyDirection.create("facing", EnumFacing.Plane.HORIZONTAL);
public static final PropertyBool ADVANCED = PropertyBool.create("advanced");
public static final PropertyEnum STATE = PropertyEnum.create("state", ComputerState.class);
}
// Members
public BlockComputer()
{
super( Material.rock );
setHardness( 2.0f );
setUnlocalizedName( "computercraft:computer" );
setCreativeTab( ComputerCraft.mainCreativeTab );
setDefaultState( this.blockState.getBaseState()
.withProperty( Properties.FACING, EnumFacing.NORTH )
.withProperty( Properties.ADVANCED, false )
.withProperty( Properties.STATE, ComputerState.Off )
);
}
@Override
protected BlockState createBlockState()
{
return new BlockState(this, new IProperty[] {
Properties.FACING,
Properties.ADVANCED,
Properties.STATE
});
}
@Override
public IBlockState getStateFromMeta( int meta )
{
EnumFacing dir = EnumFacing.getFront( meta & 0x7 );
if( dir.getAxis() == EnumFacing.Axis.Y )
{
dir = EnumFacing.NORTH;
}
IBlockState state = getDefaultState().withProperty( Properties.FACING, dir );
if( meta > 8 )
{
state = state.withProperty( Properties.ADVANCED, true );
}
else
{
state = state.withProperty( Properties.ADVANCED, false );
}
return state;
}
@Override
public int getMetaFromState( IBlockState state )
{
int meta = ((EnumFacing)state.getValue( Properties.FACING )).getIndex();
if( (Boolean)state.getValue( Properties.ADVANCED ) )
{
meta += 8;
}
return meta;
}
@Override
protected IBlockState getDefaultBlockState( ComputerFamily family, EnumFacing placedSide )
{
IBlockState state = getDefaultState();
if( placedSide.getAxis() != EnumFacing.Axis.Y )
{
state = state.withProperty( Properties.FACING, placedSide );
}
switch( family )
{
case Normal:
default:
{
return state.withProperty( Properties.ADVANCED, false );
}
case Advanced:
{
return state.withProperty( Properties.ADVANCED, true );
}
}
}
@Override
public IBlockState getActualState( IBlockState state, IBlockAccess world, BlockPos pos )
{
TileEntity tile = world.getTileEntity( pos );
if( tile != null && tile instanceof IComputerTile )
{
IComputer computer = ((IComputerTile)tile).getComputer();
if( computer != null && computer.isOn() )
{
if( computer.isCursorDisplayed() )
{
return state.withProperty( Properties.STATE, ComputerState.Blinking );
}
else
{
return state.withProperty( Properties.STATE, ComputerState.On );
}
}
}
return state.withProperty( Properties.STATE, ComputerState.Off );
}
@Override
public ComputerFamily getFamily( int damage )
{
return ((ItemComputer) Item.getItemFromBlock(this)).getFamily( damage );
}
@Override
public ComputerFamily getFamily( IBlockState state )
{
if( (Boolean)state.getValue( Properties.ADVANCED ) ) {
return ComputerFamily.Advanced;
} else {
return ComputerFamily.Normal;
}
}
@Override
protected TileComputer createTile( ComputerFamily family )
{
return new TileComputer();
}
@Override
public void onBlockPlacedBy( World world, BlockPos pos, IBlockState state, EntityLivingBase player, ItemStack stack )
{
// Not sure why this is necessary
TileEntity tile = world.getTileEntity( pos );
if( tile != null && tile instanceof TileComputer )
{
tile.setWorldObj( world ); // Not sure why this is necessary
tile.setPos( pos ); // Not sure why this is necessary
}
// Set direction
EnumFacing dir = DirectionUtil.fromEntityRot( player );
setDirection( world, pos, dir );
}
}
@@ -0,0 +1,80 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.shared.common.BlockDirectional;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.items.ItemComputerBase;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.Item;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public abstract class BlockComputerBase extends BlockDirectional
{
public BlockComputerBase( Material material )
{
super( material );
}
@Override
public void onBlockAdded( World world, BlockPos pos, IBlockState state )
{
super.onBlockAdded( world, pos, state );
updateInput( world, pos );
}
@Override
public void setDirection( World world, BlockPos pos, EnumFacing dir )
{
super.setDirection( world, pos, dir );
updateInput( world, pos );
}
protected abstract IBlockState getDefaultBlockState( ComputerFamily family, EnumFacing placedSide );
protected abstract ComputerFamily getFamily( int damage );
protected abstract ComputerFamily getFamily( IBlockState state );
protected abstract TileComputerBase createTile( ComputerFamily family );
@Override
protected final IBlockState getDefaultBlockState( int damage, EnumFacing placedSide )
{
ItemComputerBase item = (ItemComputerBase)Item.getItemFromBlock( this );
return getDefaultBlockState( item.getFamily( damage ), placedSide );
}
@Override
public final TileComputerBase createTile( IBlockState state )
{
return createTile( getFamily( state ) );
}
@Override
public final TileComputerBase createTile( int damage )
{
return createTile( getFamily( damage ) );
}
public final ComputerFamily getFamily( IBlockAccess world, BlockPos pos )
{
return getFamily( world.getBlockState( pos ) );
}
protected void updateInput( IBlockAccess world, BlockPos pos )
{
TileEntity tile = world.getTileEntity( pos );
if( tile != null && tile instanceof TileComputerBase )
{
TileComputerBase computer = (TileComputerBase)tile;
computer.updateInput();
}
}
}
@@ -0,0 +1,104 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.shared.computer.core.ServerComputer;
public class ComputerPeripheral
implements IPeripheral
{
private final String m_type;
private final ServerComputer m_computer;
public ComputerPeripheral( String type, ServerComputer computer )
{
m_type = type;
m_computer = computer;
}
// IPeripheral implementation
@Override
public String getType()
{
return m_type;
}
@Override
public String[] getMethodNames()
{
return new String[] {
"turnOn",
"shutdown",
"reboot",
"getID",
"isOn",
};
}
@Override
public Object[] callMethod( IComputerAccess computer, ILuaContext context, int method, Object[] arguments ) throws LuaException
{
switch( method )
{
case 0:
{
// turnOn
m_computer.turnOn();
return null;
}
case 1:
{
// shutdown
m_computer.shutdown();
return null;
}
case 2:
{
// reboot
m_computer.reboot();
return null;
}
case 3:
{
// getID
return new Object[] {
m_computer.assignID()
};
}
case 4:
{
// isOn
return new Object[] { m_computer.isOn() };
}
default:
{
return null;
}
}
}
@Override
public void attach( IComputerAccess computer )
{
}
@Override
public void detach( IComputerAccess computer )
{
}
@Override
public boolean equals( IPeripheral other )
{
return (other != null && other.getClass() == this.getClass());
}
}
@@ -0,0 +1,36 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.blocks;
import net.minecraft.util.IStringSerializable;
public enum ComputerState implements IStringSerializable
{
Off( "off" ),
On( "on" ),
Blinking( "blinking" );
private String m_name;
private ComputerState( String name )
{
m_name = name;
}
@Override
public String getName()
{
return m_name;
}
@Override
public String toString()
{
return getName();
}
}
@@ -0,0 +1,20 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.shared.common.ITerminalTile;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.IComputer;
public interface IComputerTile extends ITerminalTile
{
public void setComputerID( int id );
public void setLabel( String label );
public IComputer getComputer();
public IComputer createComputer();
public ComputerFamily getFamily();
}
@@ -0,0 +1,182 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.apis.CommandAPI;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.computer.core.ServerComputer;
import io.netty.buffer.ByteBuf;
import net.minecraft.block.state.IBlockState;
import net.minecraft.command.server.CommandBlockLogic;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.*;
import net.minecraft.world.World;
import java.util.HashMap;
import java.util.Map;
public class TileCommandComputer extends TileComputer
{
public class CommandSender extends CommandBlockLogic
{
private Map<Integer, String> m_outputTable;
public CommandSender()
{
m_outputTable = new HashMap<Integer, String>();
}
public void clearOutput()
{
m_outputTable.clear();
}
public Map<Integer, String> getOutput()
{
return m_outputTable;
}
public Map<Integer, String> copyOutput()
{
return new HashMap<Integer, String>( m_outputTable );
}
// ICommandSender
@Override
public IChatComponent getDisplayName()
{
IComputer computer = TileCommandComputer.this.getComputer();
if( computer != null )
{
String label = computer.getLabel();
if( label != null )
{
return new ChatComponentText( computer.getLabel() );
}
}
return new ChatComponentText( "@" );
}
@Override
public void addChatMessage( IChatComponent chatComponent )
{
m_outputTable.put( m_outputTable.size() + 1, chatComponent.getUnformattedText() );
}
@Override
public boolean canCommandSenderUseCommand( int level, String command )
{
return level <= 2;
}
@Override
public BlockPos getPosition()
{
return TileCommandComputer.this.getPos();
}
@Override
public Vec3 getPositionVector()
{
BlockPos pos = getPosition();
return new Vec3( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5 );
}
@Override
public World getEntityWorld()
{
return TileCommandComputer.this.worldObj;
}
@Override
public Entity getCommandSenderEntity()
{
return null;
}
// CommandBlockLogic members intentionally left empty
// The only reason we extend it at all is so that "gameRule commandBlockOutput" applies to us
@Override
public void updateCommand()
{
}
@Override
public int func_145751_f()
{
return 0;
}
@Override
public void func_145757_a( ByteBuf p_145757_1_ )
{
}
}
private CommandSender m_commandSender;
public TileCommandComputer()
{
m_commandSender = new CommandSender();
}
@Override
public EnumFacing getDirection()
{
IBlockState state = getBlockState();
return (EnumFacing)state.getValue( BlockCommandComputer.Properties.FACING );
}
@Override
public void setDirection( EnumFacing dir )
{
if( dir.getAxis() == EnumFacing.Axis.Y )
{
dir = EnumFacing.NORTH;
}
setBlockState( getBlockState().withProperty( BlockCommandComputer.Properties.FACING, dir ) );
updateInput();
}
public CommandSender getCommandSender()
{
return m_commandSender;
}
@Override
protected ServerComputer createComputer( int instanceID, int id )
{
ServerComputer computer = super.createComputer( instanceID, id );
computer.addAPI( new CommandAPI( this ) );
return computer;
}
@Override
public boolean isUsable( EntityPlayer player, boolean ignoreRange )
{
MinecraftServer server = MinecraftServer.getServer();
if( server == null || !server.isCommandBlockEnabled() )
{
player.addChatMessage( new ChatComponentTranslation( "advMode.notEnabled" ) );
return false;
}
else if( ComputerCraft.canPlayerUseCommands( player ) && player.capabilities.isCreativeMode )
{
return super.isUsable( player, ignoreRange );
}
else
{
player.addChatMessage( new ChatComponentTranslation( "advMode.notAllowed" ) );
return false;
}
}
}
@@ -0,0 +1,111 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.computer.items.ComputerItemFactory;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import java.util.List;
public class TileComputer extends TileComputerBase
{
// Statics
// Members
public TileComputer()
{
}
@Override
protected ServerComputer createComputer( int instanceID, int id )
{
ComputerFamily family = getFamily();
ServerComputer computer = new ServerComputer(
worldObj,
id,
m_label,
instanceID,
family,
ComputerCraft.terminalWidth_computer,
ComputerCraft.terminalHeight_computer
);
computer.setPosition( getPos() );
return computer;
}
@Override
public void getDroppedItems( List<ItemStack> drops, int fortune, boolean creative, boolean silkTouch )
{
IComputer computer = getComputer();
if( !creative || (computer != null && computer.getLabel() != null) )
{
drops.add( ComputerItemFactory.create( this ) );
}
}
@Override
public ItemStack getPickedItem()
{
return ComputerItemFactory.create( this );
}
@Override
public void openGUI( EntityPlayer player )
{
ComputerCraft.openComputerGUI( player, this );
}
@Override
public final void readDescription( NBTTagCompound nbttagcompound )
{
super.readDescription( nbttagcompound );
updateBlock();
}
public boolean isUseableByPlayer( EntityPlayer player )
{
return isUsable( player, false );
}
// IDirectionalTile
@Override
public EnumFacing getDirection()
{
IBlockState state = getBlockState();
return (EnumFacing)state.getValue( BlockComputer.Properties.FACING );
}
@Override
public void setDirection( EnumFacing dir )
{
if( dir.getAxis() == EnumFacing.Axis.Y )
{
dir = EnumFacing.NORTH;
}
setBlockState( getBlockState().withProperty( BlockComputer.Properties.FACING, dir ) );
updateInput();
}
// For legacy reasons, computers invert the meaning of "left" and "right"
private static final int[] s_remapSide = { 0, 1, 2, 3, 5, 4 };
@Override
protected int remapLocalSide( int localSide )
{
return s_remapSide[ localSide ];
}
}
@@ -0,0 +1,511 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.blocks;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.common.IDirectionalTile;
import dan200.computercraft.shared.common.ITerminal;
import dan200.computercraft.shared.common.TileGeneric;
import dan200.computercraft.shared.computer.core.ClientComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.util.DirectionUtil;
import dan200.computercraft.shared.util.PeripheralUtil;
import dan200.computercraft.shared.util.RedstoneUtil;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ITickable;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
public abstract class TileComputerBase extends TileGeneric
implements IComputerTile, IDirectionalTile, ITickable
{
protected int m_instanceID;
protected int m_computerID;
protected String m_label;
protected boolean m_on;
protected boolean m_startOn;
protected TileComputerBase()
{
m_instanceID = -1;
m_computerID = -1;
m_label = null;
m_on = false;
m_startOn = false;
}
@Override
public BlockComputerBase getBlock()
{
Block block = super.getBlock();
if( block != null && block instanceof BlockComputerBase )
{
return (BlockComputerBase)block;
}
return null;
}
protected void unload()
{
if( m_instanceID >= 0 )
{
if( !worldObj.isRemote )
{
ComputerCraft.serverComputerRegistry.remove( m_instanceID );
}
m_instanceID = -1;
}
}
@Override
public void destroy()
{
unload();
for( EnumFacing dir : EnumFacing.VALUES )
{
RedstoneUtil.propogateRedstoneOutput( worldObj, getPos(), dir );
}
}
@Override
public void onChunkUnload()
{
unload();
}
@Override
public void invalidate()
{
unload();
super.invalidate();
}
public abstract void openGUI( EntityPlayer player );
protected boolean canNameWithTag( EntityPlayer player )
{
return false;
}
protected boolean onDefaultComputerInteract( EntityPlayer player )
{
if( !worldObj.isRemote )
{
if( isUsable( player, false ) )
{
createServerComputer().turnOn();
openGUI( player );
}
}
return true;
}
@Override
public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ )
{
ItemStack currentItem = player.getCurrentEquippedItem();
if( currentItem != null && currentItem.getItem() == Items.name_tag && canNameWithTag( player ) )
{
// Label to rename computer
if( !worldObj.isRemote )
{
if( currentItem.hasDisplayName() )
{
setLabel( currentItem.getDisplayName() );
}
else
{
setLabel( null );
}
currentItem.stackSize--;
}
return true;
}
else if( !player.isSneaking() )
{
// Regular right click to activate computer
return onDefaultComputerInteract( player );
}
return false;
}
@Override
public boolean getRedstoneConnectivity( EnumFacing side )
{
int localDir = remapLocalSide( DirectionUtil.toLocal( this, side ) );
return !isRedstoneBlockedOnSide( localDir );
}
@Override
public int getRedstoneOutput( EnumFacing side )
{
int localDir = remapLocalSide( DirectionUtil.toLocal( this, side ) );
if( !isRedstoneBlockedOnSide( localDir ) )
{
if( worldObj != null && !worldObj.isRemote )
{
ServerComputer computer = getServerComputer();
if( computer != null )
{
return computer.getRedstoneOutput( localDir );
}
}
}
return 0;
}
@Override
public boolean getBundledRedstoneConnectivity( EnumFacing side )
{
int localDir = remapLocalSide( DirectionUtil.toLocal( this, side ) );
return !isRedstoneBlockedOnSide( localDir );
}
@Override
public int getBundledRedstoneOutput( EnumFacing side )
{
int localDir = remapLocalSide( DirectionUtil.toLocal( this, side ) );
if( !isRedstoneBlockedOnSide( localDir ) )
{
if( !worldObj.isRemote )
{
ServerComputer computer = getServerComputer();
if( computer != null )
{
return computer.getBundledRedstoneOutput( localDir );
}
}
}
return 0;
}
@Override
public void onNeighbourChange()
{
updateInput();
}
@Override
public void update()
{
if( !worldObj.isRemote )
{
ServerComputer computer = createServerComputer();
if( computer != null )
{
if( m_startOn )
{
computer.turnOn();
m_startOn = false;
}
computer.keepAlive();
if( computer.hasOutputChanged() )
{
updateOutput();
}
m_computerID = computer.getID();
m_label = computer.getLabel();
m_on = computer.isOn();
}
}
else
{
ClientComputer computer = createClientComputer();
if( computer != null )
{
if( computer.hasOutputChanged() )
{
updateBlock();
}
}
}
}
@Override
public void writeToNBT( NBTTagCompound nbttagcompound )
{
super.writeToNBT( nbttagcompound );
// Save ID, label and power state
if( m_computerID >= 0 )
{
nbttagcompound.setInteger( "computerID", m_computerID );
}
if( m_label != null )
{
nbttagcompound.setString( "label", m_label );
}
nbttagcompound.setBoolean( "on", m_on );
}
@Override
public void readFromNBT( NBTTagCompound nbttagcompound )
{
super.readFromNBT( nbttagcompound );
// Load ID
int id = -1;
if( nbttagcompound.hasKey( "computerID" ) )
{
// Post-1.6 computers
id = nbttagcompound.getInteger( "computerID" );
}
else if( nbttagcompound.hasKey( "userDir" ) )
{
// Pre-1.6 computers
String userDir = nbttagcompound.getString( "userDir" );
try
{
id = Integer.parseInt( userDir );
}
catch( NumberFormatException e )
{
// Ignore badly formatted data
}
}
m_computerID = id;
// Load label
if( nbttagcompound.hasKey( "label" ) )
{
m_label = nbttagcompound.getString( "label" );
}
else
{
m_label = null;
}
// Load power state
m_startOn = nbttagcompound.getBoolean( "on" );
m_on = m_startOn;
}
protected boolean isPeripheralBlockedOnSide( int localSide )
{
return false;
}
protected boolean isRedstoneBlockedOnSide( int localSide )
{
return false;
}
protected int remapLocalSide( int localSide )
{
return localSide;
}
public void updateInput()
{
if( worldObj == null || worldObj.isRemote )
{
return;
}
// Update redstone and peripherals
ServerComputer computer = getServerComputer();
if( computer != null )
{
BlockPos pos = computer.getPosition();
for( EnumFacing dir : EnumFacing.VALUES )
{
BlockPos offset = pos.offset( dir );
EnumFacing offsetSide = dir.getOpposite();
int localDir = remapLocalSide( DirectionUtil.toLocal( this, dir ) );
if( !isRedstoneBlockedOnSide( localDir ) )
{
computer.setRedstoneInput( localDir, RedstoneUtil.getRedstoneOutput( worldObj, offset, offsetSide ) );
computer.setBundledRedstoneInput( localDir, RedstoneUtil.getBundledRedstoneOutput( worldObj, offset, offsetSide ) );
}
if( !isPeripheralBlockedOnSide( localDir ) )
{
computer.setPeripheral( localDir, PeripheralUtil.getPeripheral( worldObj, offset, offsetSide ) );
}
}
}
}
public void updateOutput()
{
// Update redstone
updateBlock();
for( EnumFacing dir : EnumFacing.VALUES )
{
RedstoneUtil.propogateRedstoneOutput( worldObj, getPos(), dir );
}
}
protected abstract ServerComputer createComputer( int instanceID, int id );
// ITerminalTile
@Override
public ITerminal getTerminal()
{
return getComputer();
}
// IComputerTile
@Override
public void setComputerID( int id )
{
if( !worldObj.isRemote && m_computerID != id )
{
m_computerID = id;
ServerComputer computer = getServerComputer();
if( computer != null )
{
computer.setID( m_computerID );
}
markDirty();
}
}
@Override
public void setLabel( String label )
{
if( !worldObj.isRemote )
{
createServerComputer().setLabel( label );
}
}
@Override
public IComputer createComputer()
{
if( worldObj.isRemote )
{
return createClientComputer();
}
else
{
return createServerComputer();
}
}
@Override
public IComputer getComputer()
{
if( worldObj.isRemote )
{
return getClientComputer();
}
else
{
return getServerComputer();
}
}
@Override
public ComputerFamily getFamily()
{
BlockComputerBase block = getBlock();
if( block != null )
{
return block.getFamily( worldObj, getPos() );
}
return ComputerFamily.Normal;
}
public ServerComputer createServerComputer()
{
if( !worldObj.isRemote )
{
boolean changed = false;
if( m_instanceID < 0 )
{
m_instanceID = ComputerCraft.serverComputerRegistry.getUnusedInstanceID();
changed = true;
}
if( !ComputerCraft.serverComputerRegistry.contains( m_instanceID ) )
{
ServerComputer computer = createComputer( m_instanceID, m_computerID );
ComputerCraft.serverComputerRegistry.add( m_instanceID, computer );
changed = true;
}
if( changed )
{
updateBlock();
updateInput();
}
return ComputerCraft.serverComputerRegistry.get( m_instanceID );
}
return null;
}
public ServerComputer getServerComputer()
{
if( !worldObj.isRemote )
{
return ComputerCraft.serverComputerRegistry.get( m_instanceID );
}
return null;
}
public ClientComputer createClientComputer()
{
if( worldObj.isRemote )
{
if( m_instanceID >= 0 )
{
if( !ComputerCraft.clientComputerRegistry.contains( m_instanceID ) )
{
ComputerCraft.clientComputerRegistry.add( m_instanceID, new ClientComputer( m_instanceID ) );
}
return ComputerCraft.clientComputerRegistry.get( m_instanceID );
}
}
return null;
}
public ClientComputer getClientComputer()
{
if( worldObj.isRemote )
{
return ComputerCraft.clientComputerRegistry.get( m_instanceID );
}
return null;
}
// Networking stuff
@Override
public void writeDescription( NBTTagCompound nbttagcompound )
{
super.writeDescription( nbttagcompound );
nbttagcompound.setInteger( "instanceID", createServerComputer().getInstanceID() );
}
@Override
public void readDescription( NBTTagCompound nbttagcompound )
{
super.readDescription( nbttagcompound );
m_instanceID = nbttagcompound.getInteger( "instanceID" );
}
protected void transferStateFrom( TileComputerBase copy )
{
if( copy.m_computerID != m_computerID || copy.m_instanceID != m_instanceID )
{
unload();
m_instanceID = copy.m_instanceID;
m_computerID = copy.m_computerID;
m_label = copy.m_label;
m_on = copy.m_on;
m_startOn = copy.m_startOn;
updateBlock();
}
copy.m_instanceID = -1;
}
}
@@ -0,0 +1,197 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.core;
import com.google.common.base.Objects;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.common.ClientTerminal;
import dan200.computercraft.shared.network.ComputerCraftPacket;
import dan200.computercraft.shared.network.INetworkedThing;
import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
public class ClientComputer extends ClientTerminal
implements IComputer, INetworkedThing
{
private final int m_instanceID;
private int m_computerID;
private String m_label;
private boolean m_on;
private boolean m_blinking;
private boolean m_changed;
private NBTTagCompound m_userData;
private boolean m_changedLastFrame;
public ClientComputer( int instanceID )
{
super( false );
m_instanceID = instanceID;
m_computerID = -1;
m_label = null;
m_on = false;
m_blinking = false;
m_changed = true;
m_userData = null;
m_changedLastFrame = false;
}
@Override
public void update()
{
super.update();
m_changedLastFrame = m_changed;
m_changed = false;
}
public boolean hasOutputChanged()
{
return m_changedLastFrame;
}
public NBTTagCompound getUserData()
{
return m_userData;
}
public void requestState()
{
// Request state from server
ComputerCraftPacket packet = new ComputerCraftPacket();
packet.m_packetType = ComputerCraftPacket.RequestComputerUpdate;
packet.m_dataInt = new int[] { getInstanceID() };
ComputerCraft.sendToServer( packet );
}
// IComputer
@Override
public int getInstanceID()
{
return m_instanceID;
}
@Override
public int getID()
{
return m_computerID;
}
@Override
public String getLabel()
{
return m_label;
}
@Override
public boolean isOn()
{
return m_on;
}
@Override
public boolean isCursorDisplayed()
{
return m_on && m_blinking;
}
@Override
public void turnOn()
{
// Send turnOn to server
ComputerCraftPacket packet = new ComputerCraftPacket();
packet.m_packetType = ComputerCraftPacket.TurnOn;
packet.m_dataInt = new int[] { m_instanceID };
ComputerCraft.sendToServer( packet );
}
@Override
public void shutdown()
{
// Send shutdown to server
ComputerCraftPacket packet = new ComputerCraftPacket();
packet.m_packetType = ComputerCraftPacket.Shutdown;
packet.m_dataInt = new int[] { m_instanceID };
ComputerCraft.sendToServer( packet );
}
@Override
public void reboot()
{
// Send reboot to server
ComputerCraftPacket packet = new ComputerCraftPacket();
packet.m_packetType = ComputerCraftPacket.Reboot;
packet.m_dataInt = new int[] { m_instanceID };
ComputerCraft.sendToServer( packet );
}
@Override
public void queueEvent( String event )
{
queueEvent( event, null );
}
@Override
public void queueEvent( String event, Object[] arguments )
{
// Send event to server
ComputerCraftPacket packet = new ComputerCraftPacket();
packet.m_packetType = ComputerCraftPacket.QueueEvent;
packet.m_dataInt = new int[] { m_instanceID };
packet.m_dataString = new String[] { event };
if( arguments != null )
{
packet.m_dataNBT = NBTUtil.encodeObjects( arguments );
}
ComputerCraft.sendToServer( packet );
}
public void readDescription( NBTTagCompound nbttagcompound )
{
super.readDescription( nbttagcompound );
int oldID = m_computerID;
String oldLabel = m_label;
boolean oldOn = m_on;
boolean oldBlinking = m_blinking;
NBTTagCompound oldUserData = m_userData;
m_computerID = nbttagcompound.getInteger( "id" );
m_label = nbttagcompound.hasKey( "label" ) ? nbttagcompound.getString( "label" ) : null;
m_on = nbttagcompound.getBoolean( "on" );
m_blinking = nbttagcompound.getBoolean( "blinking" );
if( nbttagcompound.hasKey( "userData" ) )
{
m_userData = (NBTTagCompound)(nbttagcompound.getCompoundTag( "userData" )).copy();
}
else
{
m_userData = null;
}
if( m_computerID != oldID || m_on != oldOn || m_blinking != oldBlinking || !Objects.equal( m_label, oldLabel ) || !Objects.equal( m_userData, oldUserData ) )
{
m_changed = true;
}
}
@Override
public void handlePacket( ComputerCraftPacket packet, EntityPlayer sender )
{
switch( packet.m_packetType )
{
case ComputerCraftPacket.ComputerChanged:
{
readDescription( packet.m_dataNBT );
break;
}
}
}
}
@@ -0,0 +1,47 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.core;
public class ClientComputerRegistry extends ComputerRegistry<ClientComputer>
{
public ClientComputerRegistry()
{
}
public void update()
{
for( ClientComputer computer : getComputers() )
{
computer.update();
}
}
@Override
public void add( int instanceID, ClientComputer computer )
{
//System.out.println( "ADD CLIENT COMPUTER " + instanceID );
super.add( instanceID, computer );
computer.requestState();
//System.out.println( getComputers().size() + " CLIENT COMPUTERS" );
}
@Override
public void remove( int instanceID )
{
//System.out.println( "REMOVE CLIENT COMPUTER " + instanceID );
super.remove( instanceID );
//System.out.println( getComputers().size() + " CLIENT COMPUTERS" );
}
@Override
public void reset()
{
//System.out.println( "RESET CLIENT COMPUTERS" );
super.reset();
//System.out.println( getComputers().size() + " CLIENT COMPUTERS" );
}
}
@@ -0,0 +1,15 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.core;
public enum ComputerFamily
{
Normal,
Advanced,
Beginners,
Command
}
@@ -0,0 +1,97 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.core;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
public class ComputerRegistry<TComputer extends IComputer>
{
private Map<Integer, TComputer> m_computers;
private int m_nextUnusedInstanceID;
private int m_sessionID;
protected ComputerRegistry()
{
m_computers = new HashMap<Integer, TComputer>();
reset();
}
public int getSessionID()
{
return m_sessionID;
}
public int getUnusedInstanceID()
{
return m_nextUnusedInstanceID++;
}
public Collection<TComputer> getComputers()
{
return m_computers.values();
}
public TComputer get( int instanceID )
{
if( instanceID >= 0 )
{
if( m_computers.containsKey( instanceID ) )
{
return m_computers.get( instanceID );
}
}
return null;
}
public TComputer lookup( int computerID )
{
if( computerID >= 0 )
{
for( TComputer computer : getComputers() )
{
if( computer.getID() == computerID )
{
return computer;
}
}
}
return null;
}
public boolean contains( int instanceID )
{
return m_computers.containsKey( instanceID );
}
public void add( int instanceID, TComputer computer )
{
if( m_computers.containsKey( instanceID ) )
{
remove( instanceID );
}
m_computers.put( instanceID, computer );
m_nextUnusedInstanceID = Math.max( m_nextUnusedInstanceID, instanceID + 1 );
}
public void remove( int instanceID )
{
if( m_computers.containsKey( instanceID ) )
{
m_computers.remove( instanceID );
}
}
public void reset()
{
m_computers.clear();
m_nextUnusedInstanceID = 0;
m_sessionID = (new Random().nextInt());
}
}
@@ -0,0 +1,25 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.core;
import dan200.computercraft.shared.common.ITerminal;
public interface IComputer extends ITerminal
{
public int getInstanceID();
public int getID();
public String getLabel();
public boolean isOn();
public boolean isCursorDisplayed();
public void turnOn();
public void shutdown();
public void reboot();
public void queueEvent( String event );
public void queueEvent( String event, Object[] arguments );
}
@@ -0,0 +1,12 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.core;
public interface IComputerContainer
{
public IComputer getComputer();
}
@@ -0,0 +1,402 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.core;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.filesystem.IWritableMount;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.apis.IAPIEnvironment;
import dan200.computercraft.core.apis.ILuaAPI;
import dan200.computercraft.core.computer.Computer;
import dan200.computercraft.core.computer.IComputerEnvironment;
import dan200.computercraft.shared.common.ServerTerminal;
import dan200.computercraft.shared.network.ComputerCraftPacket;
import dan200.computercraft.shared.network.INetworkedThing;
import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.Loader;
public class ServerComputer extends ServerTerminal
implements IComputer, IComputerEnvironment, INetworkedThing
{
private final int m_instanceID;
private World m_world;
private BlockPos m_position;
private final Computer m_computer;
private NBTTagCompound m_userData;
private boolean m_changed;
private boolean m_changedLastFrame;
private int m_ticksSincePing;
public ServerComputer( World world, int computerID, String label, int instanceID, ComputerFamily family, int terminalWidth, int terminalHeight )
{
super( family != ComputerFamily.Normal, terminalWidth, terminalHeight );
m_instanceID = instanceID;
m_world = world;
m_position = null;
m_computer = new Computer( this, getTerminal(), computerID );
m_computer.setLabel( label );
m_userData = null;
m_changed = false;
m_changedLastFrame = false;
m_ticksSincePing = 0;
}
public World getWorld()
{
return m_world;
}
public void setWorld( World world )
{
m_world = world;
}
public BlockPos getPosition()
{
return m_position;
}
public void setPosition( BlockPos pos )
{
m_position = new BlockPos( pos );
}
public IAPIEnvironment getAPIEnvironment()
{
return m_computer.getAPIEnvironment();
}
@Override
public void update()
{
super.update();
m_computer.advance( 0.05 );
m_changedLastFrame = m_changed || m_computer.pollChanged();
m_computer.clearChanged();
m_changed = false;
m_ticksSincePing++;
}
public void keepAlive()
{
m_ticksSincePing = 0;
}
public boolean hasTimedOut()
{
return m_ticksSincePing > 100;
}
public boolean hasOutputChanged()
{
return m_changedLastFrame;
}
public void unload()
{
m_computer.unload();
}
public NBTTagCompound getUserData()
{
if( m_userData == null )
{
m_userData = new NBTTagCompound();
}
return m_userData;
}
public void updateUserData()
{
m_changed = true;
}
public void broadcastState()
{
// Send state to client
ComputerCraftPacket packet = new ComputerCraftPacket();
packet.m_packetType = ComputerCraftPacket.ComputerChanged;
packet.m_dataInt = new int[] { getInstanceID() };
packet.m_dataNBT = new NBTTagCompound();
writeDescription( packet.m_dataNBT );
ComputerCraft.sendToAllPlayers( packet );
}
public void sendState( EntityPlayer player )
{
// Send state to client
ComputerCraftPacket packet = new ComputerCraftPacket();
packet.m_packetType = ComputerCraftPacket.ComputerChanged;
packet.m_dataInt = new int[] { getInstanceID() };
packet.m_dataNBT = new NBTTagCompound();
writeDescription( packet.m_dataNBT );
ComputerCraft.sendToPlayer( player, packet );
}
public void broadcastDelete()
{
// Send deletion to client
ComputerCraftPacket packet = new ComputerCraftPacket();
packet.m_packetType = ComputerCraftPacket.ComputerDeleted;
packet.m_dataInt = new int[] { getInstanceID() };
ComputerCraft.sendToAllPlayers( packet );
}
public IWritableMount getRootMount()
{
return m_computer.getRootMount();
}
public int assignID()
{
return m_computer.assignID();
}
public void setID( int id )
{
m_computer.setID( id );
}
// IComputer
@Override
public int getInstanceID()
{
return m_instanceID;
}
@Override
public int getID()
{
return m_computer.getID();
}
@Override
public String getLabel()
{
return m_computer.getLabel();
}
@Override
public boolean isOn()
{
return m_computer.isOn();
}
@Override
public boolean isCursorDisplayed()
{
return m_computer.isOn() && m_computer.isBlinking();
}
@Override
public void turnOn()
{
// Turn on
m_computer.turnOn();
}
@Override
public void shutdown()
{
// Shutdown
m_computer.shutdown();
}
@Override
public void reboot()
{
// Reboot
m_computer.reboot();
}
@Override
public void queueEvent( String event )
{
// Queue event
queueEvent( event, null );
}
@Override
public void queueEvent( String event, Object[] arguments )
{
// Queue event
m_computer.queueEvent( event, arguments );
}
public int getRedstoneOutput( int side )
{
return m_computer.getRedstoneOutput( side );
}
public void setRedstoneInput( int side, int level )
{
m_computer.setRedstoneInput( side, level );
}
public int getBundledRedstoneOutput( int side )
{
return m_computer.getBundledRedstoneOutput( side );
}
public void setBundledRedstoneInput( int side, int combination )
{
m_computer.setBundledRedstoneInput( side, combination );
}
public void addAPI( ILuaAPI api )
{
m_computer.addAPI( api );
}
public void setPeripheral( int side, IPeripheral peripheral )
{
m_computer.setPeripheral( side, peripheral );
}
public IPeripheral getPeripheral( int side )
{
return m_computer.getPeripheral( side );
}
public void setLabel( String label )
{
m_computer.setLabel( label );
}
// IComputerEnvironment implementation
@Override
public double getTimeOfDay()
{
return (double)((m_world.getWorldTime() + 6000) % 24000) / 1000.0;
}
@Override
public int getDay()
{
return (int)((m_world.getWorldTime() + 6000) / 24000) + 1;
}
@Override
public IWritableMount createSaveDirMount( String subPath, long capacity )
{
return ComputerCraftAPI.createSaveDirMount( m_world, subPath, capacity );
}
@Override
public IMount createResourceMount( String domain, String subPath )
{
return ComputerCraftAPI.createResourceMount( ComputerCraft.class, domain, subPath );
}
@Override
public long getComputerSpaceLimit()
{
return ComputerCraft.computerSpaceLimit;
}
@Override
public String getHostString()
{
return "ComputerCraft ${version} (Minecraft " + Loader.MC_VERSION + ")";
}
@Override
public int assignNewID()
{
return ComputerCraft.createUniqueNumberedSaveDir( m_world, "computer" );
}
// Networking stuff
public void writeDescription( NBTTagCompound nbttagcompound )
{
super.writeDescription( nbttagcompound );
nbttagcompound.setInteger( "id", m_computer.getID() );
String label = m_computer.getLabel();
if( label != null )
{
nbttagcompound.setString( "label", label );
}
nbttagcompound.setBoolean( "on", m_computer.isOn() );
nbttagcompound.setBoolean( "blinking", m_computer.isBlinking() );
if( m_userData != null )
{
nbttagcompound.setTag( "userData", m_userData.copy() );
}
}
// INetworkedThing
@Override
public void handlePacket( ComputerCraftPacket packet, EntityPlayer sender )
{
// Receive packets sent from the client to the server
switch( packet.m_packetType )
{
case ComputerCraftPacket.TurnOn:
{
// A player has turned the computer on
turnOn();
break;
}
case ComputerCraftPacket.Reboot:
{
// A player has held down ctrl+r
reboot();
break;
}
case ComputerCraftPacket.Shutdown:
{
// A player has held down ctrl+s
shutdown();
break;
}
case ComputerCraftPacket.QueueEvent:
{
// A player has caused a UI event to be fired
String event = packet.m_dataString[0];
Object[] arguments = null;
if( packet.m_dataNBT != null )
{
arguments = NBTUtil.decodeObjects( packet.m_dataNBT );
}
queueEvent( event, arguments );
break;
}
case ComputerCraftPacket.SetLabel:
{
// A player wants to relabel a computer
String label = (packet.m_dataString != null && packet.m_dataString.length >= 1) ? packet.m_dataString[0] : null;
setLabel( label );
break;
}
case ComputerCraftPacket.RequestComputerUpdate:
{
// A player asked for an update on the state of the terminal
sendState( sender );
break;
}
}
}
}
@@ -0,0 +1,76 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.core;
import java.util.Iterator;
public class ServerComputerRegistry extends ComputerRegistry<ServerComputer>
{
public ServerComputerRegistry()
{
}
public void update()
{
Iterator<ServerComputer> it = getComputers().iterator();
while( it.hasNext() )
{
ServerComputer computer = it.next();
if( computer.hasTimedOut() )
{
//System.out.println( "TIMED OUT SERVER COMPUTER " + computer.getInstanceID() );
computer.unload();
computer.broadcastDelete();
it.remove();
//System.out.println( getComputers().size() + " SERVER COMPUTERS" );
}
else
{
computer.update();
if( computer.hasTerminalChanged() || computer.hasOutputChanged() )
{
computer.broadcastState();
}
}
}
}
@Override
public void add( int instanceID, ServerComputer computer )
{
//System.out.println( "ADD SERVER COMPUTER " + instanceID );
super.add( instanceID, computer );
computer.broadcastState();
//System.out.println( getComputers().size() + " SERVER COMPUTERS" );
}
@Override
public void remove( int instanceID )
{
//System.out.println( "REMOVE SERVER COMPUTER " + instanceID );
ServerComputer computer = get( instanceID );
if( computer != null )
{
computer.unload();
computer.broadcastDelete();
}
super.remove( instanceID );
//System.out.println( getComputers().size() + " SERVER COMPUTERS" );
}
@Override
public void reset()
{
//System.out.println( "RESET SERVER COMPUTERS" );
for( ServerComputer computer : getComputers() )
{
computer.unload();
}
super.reset();
//System.out.println( getComputers().size() + " SERVER COMPUTERS" );
}
}
@@ -0,0 +1,27 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.inventory;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
public class ContainerComputer extends Container
{
private TileComputer m_computer;
public ContainerComputer( TileComputer computer )
{
m_computer = computer;
}
@Override
public boolean canInteractWith( EntityPlayer player )
{
return m_computer.isUseableByPlayer( player );
}
}
@@ -0,0 +1,51 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.items;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.blocks.IComputerTile;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.IComputer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
public class ComputerItemFactory
{
public static ItemStack create( IComputerTile computerTile )
{
IComputer computer = computerTile.getComputer();
if( computer != null )
{
String label = computer.getLabel();
int id = (label != null) ? computer.getID() : -1;
return create( id, label, computerTile.getFamily() );
}
else
{
return create( -1, null, computerTile.getFamily() );
}
}
public static ItemStack create( int id, String label, ComputerFamily family )
{
ItemComputer computer = ((ItemComputer)Item.getItemFromBlock( ComputerCraft.Blocks.computer ));
ItemCommandComputer commandComputer = ((ItemCommandComputer)Item.getItemFromBlock( ComputerCraft.Blocks.commandComputer ));
switch( family )
{
case Normal:
case Advanced:
{
return computer.create( id, label, family );
}
case Command:
{
return commandComputer.create( id, label, family );
}
}
return null;
}
}
@@ -0,0 +1,17 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.items;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import net.minecraft.item.ItemStack;
public interface IComputerItem
{
public int getComputerID( ItemStack stack );
public String getLabel( ItemStack stack );
public ComputerFamily getFamily( ItemStack stack );
}
@@ -0,0 +1,76 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.items;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import net.minecraft.block.Block;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import java.util.List;
public class ItemCommandComputer extends ItemComputer
{
public ItemCommandComputer( Block block )
{
super( block );
setMaxStackSize( 64 );
setHasSubtypes( true );
setUnlocalizedName( "computercraft:command_computer" );
setCreativeTab( ComputerCraft.mainCreativeTab );
}
public ItemStack create( int id, String label, ComputerFamily family )
{
// Ignore types we can't handle
if( family != ComputerFamily.Command )
{
return null;
}
// Build the stack
ItemStack result = new ItemStack( this, 1, 0 );
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger( "computerID", id );
result.setTagCompound( nbt );
if( label != null )
{
result.setStackDisplayName( label );
}
return result;
}
@Override
public void getSubItems( Item itemID, CreativeTabs tabs, List list )
{
list.add( ComputerItemFactory.create( -1, null, ComputerFamily.Command ) );
}
// IComputerItem implementation
@Override
public int getComputerID( ItemStack stack )
{
if( stack.hasTagCompound() && stack.getTagCompound().hasKey( "computerID" ) )
{
return stack.getTagCompound().getInteger( "computerID" );
}
return -1;
}
@Override
public ComputerFamily getFamily( int damage )
{
return ComputerFamily.Command;
}
}
@@ -0,0 +1,159 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.items;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.shared.computer.blocks.IComputerTile;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.world.World;
import java.util.List;
public class ItemComputer extends ItemComputerBase
{
public static int HIGHEST_DAMAGE_VALUE_ID = 16382;
public ItemComputer( Block block )
{
super( block );
setMaxStackSize( 64 );
setHasSubtypes( true );
setUnlocalizedName( "computercraft:computer" );
setCreativeTab( ComputerCraft.mainCreativeTab );
}
public ItemStack create( int id, String label, ComputerFamily family )
{
// Ignore types we can't handle
if( family != ComputerFamily.Normal && family != ComputerFamily.Advanced )
{
return null;
}
// Build the damage
int damage = 0;
if( id >= 0 && id <= ItemComputer.HIGHEST_DAMAGE_VALUE_ID )
{
damage = id + 1;
}
if( family == ComputerFamily.Advanced )
{
damage += 0x4000;
}
// Return the stack
ItemStack result = new ItemStack( this, 1, damage );
if( id > ItemComputer.HIGHEST_DAMAGE_VALUE_ID )
{
NBTTagCompound nbt = new NBTTagCompound();
nbt.setInteger( "computerID", id );
result.setTagCompound( nbt );
}
if( label != null )
{
result.setStackDisplayName( label );
}
return result;
}
@Override
public void getSubItems( Item itemID, CreativeTabs tabs, List list )
{
list.add( ComputerItemFactory.create( -1, null, ComputerFamily.Normal ) );
list.add( ComputerItemFactory.create( -1, null, ComputerFamily.Advanced ) );
}
@Override
public boolean placeBlockAt( ItemStack stack, EntityPlayer player, World world, BlockPos pos, EnumFacing side, float hitX, float hitY, float hitZ, IBlockState newState )
{
if( super.placeBlockAt( stack, player, world, pos, side, hitX, hitY, hitZ, newState ) )
{
TileEntity tile = world.getTileEntity( pos );
if( tile != null && tile instanceof IComputerTile )
{
IComputerTile computer = (IComputerTile)tile;
setupComputerAfterPlacement( stack, computer );
}
return true;
}
return false;
}
private void setupComputerAfterPlacement( ItemStack stack, IComputerTile computer )
{
// Set ID
int id = getComputerID( stack );
if( id >= 0 )
{
computer.setComputerID( id );
}
// Set Label
String label = getLabel( stack );
if( label != null )
{
computer.setLabel( label );
}
}
@Override
public String getUnlocalizedName( ItemStack stack )
{
switch( getFamily( stack ) )
{
case Normal:
default:
{
return "tile.computercraft:computer";
}
case Advanced:
{
return "tile.computercraft:advanced_computer";
}
case Command:
{
return "tile.computercraft:command_computer";
}
}
}
// IComputerItem implementation
@Override
public int getComputerID( ItemStack stack )
{
if( stack.hasTagCompound() && stack.getTagCompound().hasKey( "computerID" ) )
{
return stack.getTagCompound().getInteger( "computerID" );
}
else
{
int damage = stack.getItemDamage() & 0x3fff;
return ( damage - 1 );
}
}
@Override
public ComputerFamily getFamily( int damage )
{
if( (damage & 0x4000) != 0 )
{
return ComputerFamily.Advanced;
}
return ComputerFamily.Normal;
}
}
@@ -0,0 +1,114 @@
/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.computer.items;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.filesystem.IMount;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
import java.util.List;
public abstract class ItemComputerBase extends ItemBlock implements IComputerItem, IMedia
{
protected ItemComputerBase( Block block )
{
super( block );
}
public abstract ComputerFamily getFamily( int damage );
@Override
public final int getMetadata( int damage )
{
return damage;
}
@Override
public void addInformation( ItemStack stack, EntityPlayer player, List list, boolean debug )
{
if( debug )
{
int id = getComputerID( stack );
if( id >= 0 )
{
list.add( "(Computer ID: " + id + ")" );
}
}
}
// IComputerItem implementation
@Override
public abstract int getComputerID( ItemStack stack );
@Override
public String getLabel( ItemStack stack )
{
if( stack.hasDisplayName() )
{
return stack.getDisplayName();
}
return null;
}
@Override
public final ComputerFamily getFamily( ItemStack stack )
{
int damage = stack.getItemDamage();
return getFamily( damage );
}
// IMedia implementation
@Override
public boolean setLabel( ItemStack stack, String label )
{
if( label != null )
{
stack.setStackDisplayName( label );
}
else
{
stack.clearCustomName();
}
return true;
}
@Override
public String getAudioTitle( ItemStack stack )
{
return null;
}
@Override
public String getAudioRecordName( ItemStack stack )
{
return null;
}
@Override
public IMount createDataMount( ItemStack stack, World world )
{
ComputerFamily family = getFamily( stack );
if( family != ComputerFamily.Command )
{
int id = getComputerID( stack );
if( id >= 0 )
{
return ComputerCraft.createSaveDirMount( world, "computer/" + id, ComputerCraft.computerSpaceLimit );
}
}
return null;
}
}