From b2542289f0af1c176e9ed55fba7e9768a067bb62 Mon Sep 17 00:00:00 2001 From: SquidDev Date: Mon, 1 May 2017 17:07:32 +0100 Subject: [PATCH] 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. --- .../proxy/ComputerCraftProxyClient.java | 3 +- .../computer/core/IContainerComputer.java | 20 +++++++++++ .../shared/computer/core/ServerComputer.java | 12 +++++++ .../computer/inventory/ContainerComputer.java | 12 +++++++ .../shared/network/ComputerCraftPacket.java | 8 +++++ .../inventory/ContainerPocketComputer.java | 35 +++++++++++++++++++ .../pocket/items/ItemPocketComputer.java | 10 ++++++ .../proxy/ComputerCraftProxyCommon.java | 5 +-- .../turtle/inventory/ContainerTurtle.java | 19 ++++++++++ 9 files changed, 121 insertions(+), 3 deletions(-) create mode 100644 src/main/java/dan200/computercraft/shared/computer/core/IContainerComputer.java create mode 100644 src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java diff --git a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java index 58ce252e5..f6a438eb5 100644 --- a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java +++ b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java @@ -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 ); diff --git a/src/main/java/dan200/computercraft/shared/computer/core/IContainerComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/IContainerComputer.java new file mode 100644 index 000000000..67f13f7d9 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/computer/core/IContainerComputer.java @@ -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(); +} diff --git a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java index 5f1c0ba17..4161afb7d 100644 --- a/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/core/ServerComputer.java @@ -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 ) { diff --git a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java index 4ff378a1c..d99c4ca8a 100644 --- a/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java +++ b/src/main/java/dan200/computercraft/shared/computer/inventory/ContainerComputer.java @@ -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(); + } } diff --git a/src/main/java/dan200/computercraft/shared/network/ComputerCraftPacket.java b/src/main/java/dan200/computercraft/shared/network/ComputerCraftPacket.java index 9b3ca1693..fdb16f8d9 100644 --- a/src/main/java/dan200/computercraft/shared/network/ComputerCraftPacket.java +++ b/src/main/java/dan200/computercraft/shared/network/ComputerCraftPacket.java @@ -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; + } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java b/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java new file mode 100644 index 000000000..2ec110ef3 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/pocket/inventory/ContainerPocketComputer.java @@ -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; + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java index 484c9ecdc..1e9371667 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/items/ItemPocketComputer.java @@ -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 ); diff --git a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java index 4bafb6f5d..d51ac0393 100644 --- a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java +++ b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java @@ -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; diff --git a/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java index 7c869215c..780144989 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/inventory/ContainerTurtle.java @@ -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; + } }