Require the player to be interacting with the computer when typing

Packets will be discarded if the sending player is not currently
interacting with the appropriate computer. This ensures players cannot
control other people's computers.

This is enforced by checking if the current container is a "computer
container", and this container holds the correct computer.
This commit is contained in:
SquidDev 2017-05-01 17:07:32 +01:00
parent ec7a251c09
commit b2542289f0
9 changed files with 121 additions and 3 deletions

View File

@ -20,6 +20,7 @@
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
@ -325,7 +326,7 @@ public Object getPrintoutGUI( EntityPlayer player, EnumHand hand )
@Override
public Object getPocketComputerGUI( EntityPlayer player, EnumHand hand )
{
ContainerHeldItem container = new ContainerHeldItem( player, hand );
ContainerPocketComputer container = new ContainerPocketComputer( player, hand );
if( container.getStack() != null && container.getStack().getItem() instanceof ItemPocketComputer )
{
return new GuiPocketComputer( container );

View File

@ -0,0 +1,20 @@
package dan200.computercraft.shared.computer.core;
import javax.annotation.Nullable;
/**
* An instance of {@link net.minecraft.inventory.Container} which provides a computer. You should implement this
* if you provide custom computers/GUIs to interact with them.
*/
public interface IContainerComputer
{
/**
* Get the computer you are interacting with.
*
* This will only be called on the server.
*
* @return The computer you are interacting with.
*/
@Nullable
IComputer getComputer();
}

View File

@ -20,6 +20,7 @@
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;
@ -351,6 +352,17 @@ public void writeDescription( NBTTagCompound nbttagcompound )
@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 )
{

View File

@ -7,10 +7,15 @@
package dan200.computercraft.shared.computer.inventory;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.computer.core.IContainerComputer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import javax.annotation.Nullable;
public class ContainerComputer extends Container
implements IContainerComputer
{
private TileComputer m_computer;
@ -24,4 +29,11 @@ public boolean canInteractWith( EntityPlayer player )
{
return m_computer.isUseableByPlayer( player );
}
@Nullable
@Override
public IComputer getComputer()
{
return m_computer.getServerComputer();
}
}

View File

@ -224,4 +224,12 @@ public void fromBytes( ByteBuf buffer )
}
}
}
/**
* Determine whether this packet requires the player to be interacting with the
* target.
*/
public boolean requiresContainer() {
return m_packetType != RequestComputerUpdate && m_packetType != RequestTileEntityUpdate;
}
}

View File

@ -0,0 +1,35 @@
package dan200.computercraft.shared.pocket.inventory;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.media.inventory.ContainerHeldItem;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumHand;
import javax.annotation.Nullable;
public class ContainerPocketComputer extends ContainerHeldItem
implements IContainerComputer
{
public ContainerPocketComputer( EntityPlayer player, EnumHand hand )
{
super( player, hand );
}
@Nullable
@Override
public IComputer getComputer()
{
ItemStack stack = getStack();
if( stack != null && stack.getItem() instanceof ItemPocketComputer )
{
return ((ItemPocketComputer) stack.getItem()).getServerComputer( stack );
}
else
{
return null;
}
}
}

View File

@ -279,6 +279,16 @@ private ServerComputer createServerComputer( final World world, IInventory inven
return computer;
}
public ServerComputer getServerComputer( ItemStack stack )
{
int instanceID = getInstanceID( stack );
if( instanceID >= 0 )
{
return ComputerCraft.serverComputerRegistry.get( instanceID );
}
return null;
}
public ClientComputer createClientComputer( ItemStack stack )
{
int instanceID = getInstanceID( stack );

View File

@ -42,6 +42,7 @@
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.pocket.items.PocketComputerItemFactory;
import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe;
@ -540,7 +541,7 @@ public Object getServerGuiElement( int id, EntityPlayer player, World world, int
if (tile != null && tile instanceof TileTurtle)
{
TileTurtle turtle = (TileTurtle) tile;
return new ContainerTurtle( player.inventory, turtle.getAccess() );
return new ContainerTurtle( player.inventory, turtle.getAccess(), turtle.getServerComputer() );
}
break;
}
@ -550,7 +551,7 @@ public Object getServerGuiElement( int id, EntityPlayer player, World world, int
}
case ComputerCraft.pocketComputerGUIID:
{
return new ContainerHeldItem( player, x == 0 ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND );
return new ContainerPocketComputer( player, x == 0 ? EnumHand.MAIN_HAND : EnumHand.OFF_HAND );
}
}
return null;

View File

@ -7,6 +7,8 @@
package dan200.computercraft.shared.turtle.inventory;
import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.shared.computer.core.IComputer;
import dan200.computercraft.shared.computer.core.IContainerComputer;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.turtle.core.TurtleBrain;
import net.minecraft.entity.player.EntityPlayer;
@ -16,7 +18,10 @@
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import javax.annotation.Nullable;
public class ContainerTurtle extends Container
implements IContainerComputer
{
private static final int PROGRESS_ID_SELECTED_SLOT = 0;
@ -24,6 +29,7 @@ public class ContainerTurtle extends Container
public final int m_turtleInvStartX;
protected ITurtleAccess m_turtle;
private IComputer m_computer;
private int m_selectedSlot;
protected ContainerTurtle( IInventory playerInventory, ITurtleAccess turtle, int playerInvStartY, int turtleInvStartX )
@ -71,6 +77,12 @@ public ContainerTurtle( IInventory playerInventory, ITurtleAccess turtle )
this( playerInventory, turtle, 134, 175 );
}
public ContainerTurtle( IInventory playerInventory, ITurtleAccess turtle, IComputer computer )
{
this( playerInventory, turtle );
m_computer = computer;
}
public int getSelectedSlot()
{
return m_selectedSlot;
@ -178,4 +190,11 @@ else if( slotNum >= 16 )
}
return null;
}
@Nullable
@Override
public IComputer getComputer()
{
return m_computer;
}
}