CC-Tweaked/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java

415 lines
10 KiB
Java

/**
* 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.inventory.Container;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.math.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 )
{
// Allow Computer/Tile updates as they may happen at any time.
if (packet.requiresContainer()) {
if (sender == null) return;
Container container = sender.openContainer;
if (!(container instanceof IContainerComputer)) return;
IComputer computer = ((IContainerComputer) container).getComputer();
if (computer != this) return;
}
// 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;
}
}
}
}