diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java b/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java index 5fbff7920..0b9cafd4c 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/AbstractComputerScreen.java @@ -55,6 +55,7 @@ public abstract class AbstractComputerScreen ext protected final int sidebarYOffset; private long uploadNagDeadline = Long.MAX_VALUE; + private final int uploadMaxSize; private final ItemStack displayStack; public AbstractComputerScreen(T container, Inventory player, Component title, int sidebarYOffset) { @@ -62,6 +63,7 @@ public abstract class AbstractComputerScreen ext terminalData = container.getTerminal(); family = container.getFamily(); displayStack = container.getDisplayStack(); + uploadMaxSize = container.getUploadMaxSize(); input = new ClientInputHandler(menu); this.sidebarYOffset = sidebarYOffset; } @@ -161,7 +163,7 @@ public abstract class AbstractComputerScreen ext try (var sbc = Files.newByteChannel(file)) { var fileSize = sbc.size(); - if (fileSize > UploadFileMessage.MAX_SIZE || (size += fileSize) >= UploadFileMessage.MAX_SIZE) { + if (fileSize > uploadMaxSize || (size += fileSize) >= uploadMaxSize) { alert(UploadResult.FAILED_TITLE, UploadResult.TOO_MUCH_MSG); return; } diff --git a/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java b/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java index 925614a6e..9b8b545aa 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java @@ -208,6 +208,7 @@ public final class LanguageProvider implements DataProvider { // Config options addConfigEntry(ConfigSpec.computerSpaceLimit, "Computer space limit (bytes)"); addConfigEntry(ConfigSpec.floppySpaceLimit, "Floppy Disk space limit (bytes)"); + addConfigEntry(ConfigSpec.uploadMaxSize, "File upload size limit (bytes)"); addConfigEntry(ConfigSpec.maximumFilesOpen, "Maximum files open per computer"); addConfigEntry(ConfigSpec.disableLua51Features, "Disable Lua 5.1 features"); addConfigEntry(ConfigSpec.defaultComputerSettings, "Default Computer settings"); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/inventory/AbstractComputerMenu.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/inventory/AbstractComputerMenu.java index c4d6d333e..6d1544dec 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/inventory/AbstractComputerMenu.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/inventory/AbstractComputerMenu.java @@ -5,6 +5,7 @@ package dan200.computercraft.shared.computer.inventory; import dan200.computercraft.core.terminal.Terminal; +import dan200.computercraft.shared.config.Config; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.menu.ComputerMenu; @@ -26,6 +27,7 @@ import java.util.function.Predicate; public abstract class AbstractComputerMenu extends AbstractContainerMenu implements ComputerMenu { public static final int SIDEBAR_WIDTH = 17; + private final int uploadMaxSize; private final Predicate canUse; private final ComputerFamily family; @@ -52,6 +54,7 @@ public abstract class AbstractComputerMenu extends AbstractContainerMenu impleme input = computer == null ? null : new ServerInputState<>(this); terminal = containerData == null ? null : containerData.terminal().create(); displayStack = containerData == null ? ItemStack.EMPTY : containerData.displayStack(); + uploadMaxSize = containerData == null ? Config.uploadMaxSize : containerData.uploadMaxSize(); } @Override @@ -67,6 +70,10 @@ public abstract class AbstractComputerMenu extends AbstractContainerMenu impleme return data.get(0) != 0; } + public int getUploadMaxSize() { + return uploadMaxSize; + } + @Override public ServerComputer getComputer() { if (computer == null) throw new UnsupportedOperationException("Cannot access server computer on the client"); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/config/Config.java b/projects/common/src/main/java/dan200/computercraft/shared/config/Config.java index a98bb657e..b18d7cafd 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/config/Config.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/config/Config.java @@ -14,6 +14,7 @@ import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; public final class Config { public static int computerSpaceLimit = 1000 * 1000; public static int floppySpaceLimit = 125 * 1000; + public static int uploadMaxSize = 512 * 1024; // 512 KB public static boolean commandRequireCreative = true; public static boolean enableCommandBlock = false; diff --git a/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigSpec.java b/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigSpec.java index 019890ea0..5e2150952 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigSpec.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigSpec.java @@ -32,6 +32,7 @@ public final class ConfigSpec { public static final ConfigFile.Value defaultComputerSettings; public static final ConfigFile.Value logComputerErrors; public static final ConfigFile.Value commandRequireCreative; + public static final ConfigFile.Value uploadMaxSize; public static final ConfigFile.Value computerThreads; public static final ConfigFile.Value maxMainGlobalTime; @@ -96,6 +97,13 @@ public final class ConfigSpec { .comment("The disk space limit for floppy disks, in bytes.") .define("floppy_space_limit", Config.floppySpaceLimit); + uploadMaxSize = builder + .comment(""" + The file upload size limit, in bytes. Must be in range of 1 KiB and 16 MiB. + Keep in mind that uploads are processed in a single tick - large files or + poor network performance can stall the networking thread. And mind the disk space!""") + .defineInRange("upload_max_size", Config.uploadMaxSize, 1024, 16 * 1024 * 1024); + maximumFilesOpen = builder .comment("Set how many files a computer can have open at the same time. Set to 0 for unlimited.") .defineInRange("maximum_open_files", CoreConfig.maximumFilesOpen, 0, Integer.MAX_VALUE); @@ -334,6 +342,7 @@ public final class ConfigSpec { // General Config.computerSpaceLimit = computerSpaceLimit.get(); Config.floppySpaceLimit = floppySpaceLimit.get(); + Config.uploadMaxSize = uploadMaxSize.get(); CoreConfig.maximumFilesOpen = maximumFilesOpen.get(); CoreConfig.disableLua51Features = disableLua51Features.get(); CoreConfig.defaultComputerSettings = defaultComputerSettings.get(); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java b/projects/common/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java index 96160d8e6..9e658faed 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/container/ComputerContainerData.java @@ -7,6 +7,7 @@ package dan200.computercraft.shared.network.container; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.terminal.TerminalState; +import dan200.computercraft.shared.config.Config; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.item.ItemStack; @@ -14,17 +15,20 @@ public class ComputerContainerData implements ContainerData { private final ComputerFamily family; private final TerminalState terminal; private final ItemStack displayStack; + private final int uploadMaxSize; public ComputerContainerData(ServerComputer computer, ItemStack displayStack) { family = computer.getFamily(); terminal = computer.getTerminalState(); this.displayStack = displayStack; + uploadMaxSize = Config.uploadMaxSize; } public ComputerContainerData(FriendlyByteBuf buf) { family = buf.readEnum(ComputerFamily.class); terminal = new TerminalState(buf); displayStack = buf.readItem(); + uploadMaxSize = buf.readInt(); } @Override @@ -32,6 +36,7 @@ public class ComputerContainerData implements ContainerData { buf.writeEnum(family); terminal.write(buf); buf.writeItem(displayStack); + buf.writeInt(uploadMaxSize); } public ComputerFamily family() { @@ -50,4 +55,8 @@ public class ComputerContainerData implements ContainerData { public ItemStack displayStack() { return displayStack; } + + public int uploadMaxSize() { + return uploadMaxSize; + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/network/server/UploadFileMessage.java b/projects/common/src/main/java/dan200/computercraft/shared/network/server/UploadFileMessage.java index 89adb8227..384a0093c 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/network/server/UploadFileMessage.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/network/server/UploadFileMessage.java @@ -8,6 +8,7 @@ import com.google.common.annotations.VisibleForTesting; import dan200.computercraft.shared.computer.menu.ComputerMenu; import dan200.computercraft.shared.computer.upload.FileSlice; import dan200.computercraft.shared.computer.upload.FileUpload; +import dan200.computercraft.shared.config.Config; import io.netty.handler.codec.DecoderException; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.inventory.AbstractContainerMenu; @@ -22,7 +23,6 @@ import java.util.function.Consumer; import static dan200.computercraft.core.util.Nullability.assertNonNull; public class UploadFileMessage extends ComputerServerMessage { - public static final int MAX_SIZE = 512 * 1024; static final int MAX_PACKET_SIZE = 30 * 1024; // Max packet size is 32767. private static final int HEADER_SIZE = 16 + 1; // 16 bytes for the UUID, 4 for the flag. @@ -60,7 +60,7 @@ public class UploadFileMessage extends ComputerServerMessage { for (var i = 0; i < nFiles; i++) { var name = buf.readUtf(MAX_FILE_NAME); var size = buf.readVarInt(); - if (size > MAX_SIZE || (totalSize += size) > MAX_SIZE) { + if (size > Config.uploadMaxSize || (totalSize += size) > Config.uploadMaxSize) { throw new DecoderException("Files are too large"); } diff --git a/projects/common/src/test/java/dan200/computercraft/shared/network/server/UploadFileMessageTest.java b/projects/common/src/test/java/dan200/computercraft/shared/network/server/UploadFileMessageTest.java index 9ea3e5d53..1add6e2d9 100644 --- a/projects/common/src/test/java/dan200/computercraft/shared/network/server/UploadFileMessageTest.java +++ b/projects/common/src/test/java/dan200/computercraft/shared/network/server/UploadFileMessageTest.java @@ -5,6 +5,7 @@ package dan200.computercraft.shared.network.server; import dan200.computercraft.shared.computer.upload.FileUpload; +import dan200.computercraft.shared.config.Config; import dan200.computercraft.test.core.ArbitraryByteBuffer; import dan200.computercraft.test.shared.FakeContainer; import dan200.computercraft.test.shared.WithMinecraft; @@ -114,7 +115,7 @@ public class UploadFileMessageTest { Arbitraries.strings().ofMinLength(1).ascii().ofMaxLength(MAX_FILE_NAME), Arbitraries.strings().ofMinLength(1).ofMaxLength(MAX_FILE_NAME / 4) )), - ArbitraryByteBuffer.bytes().ofMaxSize(MAX_SIZE) + ArbitraryByteBuffer.bytes().ofMaxSize(Config.uploadMaxSize) ).as(UploadFileMessageTest::file); } @@ -122,7 +123,7 @@ public class UploadFileMessageTest { Arbitrary> fileUploads() { return fileUpload().list() .ofMinSize(1).ofMaxSize(MAX_FILES) - .filter(us -> us.stream().mapToInt(u -> u.getBytes().remaining()).sum() <= MAX_SIZE); + .filter(us -> us.stream().mapToInt(u -> u.getBytes().remaining()).sum() <= Config.uploadMaxSize); } private static FileUpload file(String name, ByteBuffer buffer) { diff --git a/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json b/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json index da9579c83..4c1351f43 100644 --- a/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json +++ b/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json @@ -163,6 +163,8 @@ "gui.computercraft.config.turtle.normal_fuel_limit": "Turtle fuel limit", "gui.computercraft.config.turtle.normal_fuel_limit.tooltip": "The fuel limit for Turtles.\nRange: > 0", "gui.computercraft.config.turtle.tooltip": "Various options relating to turtles.", + "gui.computercraft.config.upload_max_size": "File upload size limit (bytes)", + "gui.computercraft.config.upload_max_size.tooltip": "The file upload size limit, in bytes. Must be in range of 1 KiB and 16 MiB.\nKeep in mind that uploads are processed in a single tick - large files or\npoor network performance can stall the networking thread. And mind the disk space!\nRange: 1024 ~ 16777216", "gui.computercraft.config.upload_nag_delay": "Upload nag delay", "gui.computercraft.config.upload_nag_delay.tooltip": "The delay in seconds after which we'll notify about unhandled imports. Set to 0 to disable.\nRange: 0 ~ 60", "gui.computercraft.pocket_computer_overlay": "Pocket computer open. Press ESC to close.", diff --git a/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json b/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json index da9579c83..4c1351f43 100644 --- a/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json +++ b/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json @@ -163,6 +163,8 @@ "gui.computercraft.config.turtle.normal_fuel_limit": "Turtle fuel limit", "gui.computercraft.config.turtle.normal_fuel_limit.tooltip": "The fuel limit for Turtles.\nRange: > 0", "gui.computercraft.config.turtle.tooltip": "Various options relating to turtles.", + "gui.computercraft.config.upload_max_size": "File upload size limit (bytes)", + "gui.computercraft.config.upload_max_size.tooltip": "The file upload size limit, in bytes. Must be in range of 1 KiB and 16 MiB.\nKeep in mind that uploads are processed in a single tick - large files or\npoor network performance can stall the networking thread. And mind the disk space!\nRange: 1024 ~ 16777216", "gui.computercraft.config.upload_nag_delay": "Upload nag delay", "gui.computercraft.config.upload_nag_delay.tooltip": "The delay in seconds after which we'll notify about unhandled imports. Set to 0 to disable.\nRange: 0 ~ 60", "gui.computercraft.pocket_computer_overlay": "Pocket computer open. Press ESC to close.",