diff --git a/build.gradle b/build.gradle index 2d03a3708..9d847ea70 100644 --- a/build.gradle +++ b/build.gradle @@ -13,7 +13,8 @@ archivesBaseName = "cc-restiched" repositories { mavenCentral() - jcenter() + maven { url 'https://jitpack.io' } + maven { url "https://maven.shedaniel.me/" } maven { name "SquidDev" url "https://squiddev.cc/maven" @@ -30,40 +31,26 @@ dependencies { modImplementation "net.fabricmc:fabric-loader:${fabric_loader_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${fabric_api_version}" - compile 'com.electronwill.night-config:json:3.6.0' - - modImplementation "me.shedaniel.cloth:config-2:${cloth_config_version}" + modApi("me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}") { + exclude(group: "net.fabricmc.fabric-api") + } modImplementation "io.github.prospector:modmenu:${modmenu_version}" + modImplementation "me.shedaniel.cloth.api:cloth-utils-v1:${cloth_api_version}" - modApi "me.shedaniel.cloth.api:cloth-utils-v1:${project.cloth_api_version}" - include "me.shedaniel.cloth.api:cloth-utils-v1:${project.cloth_api_version}" - - implementation "blue.endless:jankson:${jankson_version}" + compile 'com.electronwill.night-config:toml:3.6.3' implementation 'com.google.code.findbugs:jsr305:3.0.2' - compileOnly 'com.google.auto.service:auto-service:1.0-rc7' - annotationProcessor 'com.google.auto.service:auto-service:1.0-rc7' - - include "me.shedaniel.cloth:config-2:${cloth_config_version}" - include "blue.endless:jankson:${jankson_version}" - include 'javax.vecmath:vecmath:1.5.2' - - compile 'javax.vecmath:vecmath:1.5.2' - shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT' + include "me.shedaniel.cloth.api:cloth-utils-v1:${cloth_api_version}" + include 'com.electronwill.night-config:core:3.6.3' + include 'com.electronwill.night-config:toml:3.6.3' + include "me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}" + modRuntime "me.shedaniel:RoughlyEnoughItems-api:5.8.9" modRuntime "me.shedaniel:RoughlyEnoughItems:5.8.9" } -sourceSets { - main { - java { - exclude 'dan200/computercraft/shared/integration' - } - } -} - processResources { inputs.property "version", project.version diff --git a/gradle.properties b/gradle.properties index 2475e54ba..628e28644 100644 --- a/gradle.properties +++ b/gradle.properties @@ -9,9 +9,9 @@ mc_version=1.16.5 mappings_version=9 # Dependencies -cloth_config_version=4.8.1 +cloth_config_version=4.11.26 fabric_loader_version=0.11.3 fabric_api_version=0.32.0+1.16 jankson_version=1.2.0 -modmenu_version=1.14.6+ +modmenu_version=1.16.9 cloth_api_version=1.4.5 diff --git a/src/main/java/dan200/computercraft/ComputerCraft.java b/src/main/java/dan200/computercraft/ComputerCraft.java index 1ed1ac999..0e5ff357b 100644 --- a/src/main/java/dan200/computercraft/ComputerCraft.java +++ b/src/main/java/dan200/computercraft/ComputerCraft.java @@ -9,18 +9,15 @@ package dan200.computercraft; import static dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks; import static dan200.computercraft.shared.ComputerCraftRegistry.init; -import java.nio.file.Paths; import java.util.Arrays; import java.util.Collections; import java.util.EnumSet; import java.util.List; import java.util.concurrent.TimeUnit; - import dan200.computercraft.api.turtle.event.TurtleAction; import dan200.computercraft.core.apis.http.options.Action; import dan200.computercraft.core.apis.http.options.AddressRule; -import dan200.computercraft.core.apis.http.websocket.Websocket; import dan200.computercraft.shared.common.ColourableRecipe; import dan200.computercraft.shared.computer.core.ClientComputerRegistry; import dan200.computercraft.shared.computer.core.ServerComputerRegistry; @@ -35,9 +32,7 @@ import dan200.computercraft.shared.pocket.recipes.PocketComputerUpgradeRecipe; import dan200.computercraft.shared.proxy.ComputerCraftProxyCommon; import dan200.computercraft.shared.turtle.recipes.TurtleRecipe; import dan200.computercraft.shared.turtle.recipes.TurtleUpgradeRecipe; -import dan200.computercraft.shared.util.Config; -import dan200.computercraft.shared.util.ImpostorRecipe; -import dan200.computercraft.shared.util.ImpostorShapelessRecipe; +import dan200.computercraft.shared.util.*; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -54,72 +49,76 @@ import net.fabricmc.loader.api.FabricLoader; public final class ComputerCraft implements ModInitializer { public static final String MOD_ID = "computercraft"; - // Configuration options - public static final int terminalWidth_computer = 51; - public static final int terminalHeight_computer = 19; - public static final int terminalWidth_turtle = 39; - public static final int terminalHeight_turtle = 13; - public static final int terminalWidth_pocketComputer = 26; - public static final int terminalHeight_pocketComputer = 20; - // Registries - public static final ClientComputerRegistry clientComputerRegistry = new ClientComputerRegistry(); - public static final ServerComputerRegistry serverComputerRegistry = new ServerComputerRegistry(); - // Logging - public static final Logger log = LogManager.getLogger(MOD_ID); - public static ItemGroup MAIN_GROUP = FabricItemGroupBuilder.build(new Identifier(MOD_ID, "main"), () -> new ItemStack(ModBlocks.COMPUTER_NORMAL)); - public static boolean commandRequireCreative = false; - public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST; + + // Configuration fields public static int computerSpaceLimit = 1000 * 1000; public static int floppySpaceLimit = 125 * 1000; public static int maximumFilesOpen = 128; - public static boolean disable_lua51_features = false; - public static String default_computer_settings = ""; - public static boolean debug_enable = true; - public static boolean logPeripheralErrors = false; - public static int computer_threads = 1; + public static boolean disableLua51Features = false; + public static String defaultComputerSettings = ""; + public static boolean debugEnable = true; + public static boolean logComputerErrors = true; + public static boolean commandRequireCreative = true; + + public static int computerThreads = 1; public static long maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(10); public static long maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(5); - public static boolean http_enable = true; - public static boolean http_websocket_enable = true; - public static int httpTimeout = 30000; + + public static boolean httpEnabled = true; + public static boolean httpWebsocketEnabled = true; + public static List httpRules = Collections.unmodifiableList( Arrays.asList( + AddressRule.parse( "$private", null, Action.DENY.toPartial() ), + AddressRule.parse( "*", null, Action.ALLOW.toPartial() ) + )); + public static int httpMaxRequests = 16; - public static long httpMaxDownload = 16 * 1024 * 1024; - public static long httpMaxUpload = 4 * 1024 * 1024; public static int httpMaxWebsockets = 4; - public static int httpMaxWebsocketMessage = Websocket.MAX_MESSAGE_SIZE; + public static boolean enableCommandBlock = false; - public static int modem_range = 64; - public static int modem_highAltitudeRange = 384; - public static int modem_rangeDuringStorm = 64; - public static int modem_highAltitudeRangeDuringStorm = 384; + public static int modemRange = 64; + public static int modemHighAltitudeRange = 384; + public static int modemRangeDuringStorm = 64; + public static int modemHighAltitudeRangeDuringStorm = 384; public static int maxNotesPerTick = 8; + public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST; + public static double monitorDistanceSq = 4096; + public static long monitorBandwidth = 1_000_000; + public static boolean turtlesNeedFuel = true; public static int turtleFuelLimit = 20000; public static int advancedTurtleFuelLimit = 100000; public static boolean turtlesObeyBlockProtection = true; public static boolean turtlesCanPush = true; public static EnumSet turtleDisabledActions = EnumSet.noneOf(TurtleAction.class); + + public static int computerTermWidth = 51; + public static int computerTermHeight = 19; + + public static final int turtleTermWidth = 39; + public static final int turtleTermHeight = 13; + + public static int pocketTermWidth = 26; + public static int pocketTermHeight = 20; + public static int monitorWidth = 8; public static int monitorHeight = 6; - public static double monitorDistanceSq = 4096; - public static List httpRules = Collections.unmodifiableList( Arrays.asList( - AddressRule.parse( "$private", null, Action.DENY.toPartial() ), - AddressRule.parse( "*", null, Action.ALLOW.toPartial() ) - ) ); + // Registries + public static final ClientComputerRegistry clientComputerRegistry = new ClientComputerRegistry(); + public static final ServerComputerRegistry serverComputerRegistry = new ServerComputerRegistry(); + + // Logging + public static final Logger log = LogManager.getLogger(MOD_ID); + + public static ItemGroup MAIN_GROUP = FabricItemGroupBuilder.build(new Identifier(MOD_ID, "main"), () -> new ItemStack(ModBlocks.COMPUTER_NORMAL)); @Override public void onInitialize() { - Config.load(Paths.get(FabricLoader.getInstance() - .getConfigDir() - .toFile() - .getPath(), MOD_ID + ".json5")); ComputerCraftProxyCommon.init(); + Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "colour"), ColourableRecipe.SERIALIZER); Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "computer_upgrade"), ComputerUpgradeRecipe.SERIALIZER); - Registry.register(Registry.RECIPE_SERIALIZER, - new Identifier(ComputerCraft.MOD_ID, "pocket_computer_upgrade"), - PocketComputerUpgradeRecipe.SERIALIZER); + Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "pocket_computer_upgrade"), PocketComputerUpgradeRecipe.SERIALIZER); Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "disk"), DiskRecipe.SERIALIZER); Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "printout"), PrintoutRecipe.SERIALIZER); Registry.register(Registry.RECIPE_SERIALIZER, new Identifier(ComputerCraft.MOD_ID, "turtle"), TurtleRecipe.SERIALIZER); @@ -132,8 +131,7 @@ public final class ComputerCraft implements ModInitializer { init(); FabricLoader.getInstance().getModContainer(MOD_ID).ifPresent(modContainer -> { ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "classic"), modContainer, ResourcePackActivationType.NORMAL); - ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "overhaul"), modContainer, ResourcePackActivationType.NORMAL); + ResourceManagerHelper.registerBuiltinResourcePack(new Identifier(MOD_ID, "overhaul"), modContainer, ResourcePackActivationType.NORMAL); }); } - -} +} \ No newline at end of file diff --git a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java index 2fbc0c7a2..64c8c5701 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiComputer.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiComputer.java @@ -48,11 +48,11 @@ public final class GuiComputer extends HandledS } public static GuiComputer create(ContainerComputer container, PlayerInventory inventory, Text component) { - return new GuiComputer<>(container, inventory, component, ComputerCraft.terminalWidth_computer, ComputerCraft.terminalHeight_computer); + return new GuiComputer<>(container, inventory, component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight); } public static GuiComputer createPocket(ContainerPocketComputer container, PlayerInventory inventory, Text component) { - return new GuiComputer<>(container, inventory, component, ComputerCraft.terminalWidth_pocketComputer, ComputerCraft.terminalHeight_pocketComputer); + return new GuiComputer<>(container, inventory, component, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight); } public static GuiComputer createView(ContainerViewComputer container, PlayerInventory inventory, Text component) { diff --git a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java index 74b01b34e..609c656ef 100644 --- a/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java +++ b/src/main/java/dan200/computercraft/client/gui/GuiTurtle.java @@ -48,10 +48,10 @@ public class GuiTurtle extends HandledScreen { super.init(); this.client.keyboard.setRepeatEvents(true); - int termPxWidth = ComputerCraft.terminalWidth_turtle * FixedWidthFontRenderer.FONT_WIDTH; - int termPxHeight = ComputerCraft.terminalHeight_turtle * FixedWidthFontRenderer.FONT_HEIGHT; + int termPxWidth = ComputerCraft.turtleTermWidth * FixedWidthFontRenderer.FONT_WIDTH; + int termPxHeight = ComputerCraft.turtleTermHeight * FixedWidthFontRenderer.FONT_HEIGHT; - this.terminal = new WidgetTerminal(this.client, () -> this.m_computer, ComputerCraft.terminalWidth_turtle, ComputerCraft.terminalHeight_turtle, 2, 2, 2, 2); + this.terminal = new WidgetTerminal(this.client, () -> this.m_computer, ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight, 2, 2, 2, 2); this.terminalWrapper = new WidgetWrapper(this.terminal, 2 + 8 + this.x, 2 + 8 + this.y, termPxWidth, termPxHeight); this.children.add(this.terminalWrapper); diff --git a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java index af142d3ff..fd1e78f7e 100644 --- a/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java +++ b/src/main/java/dan200/computercraft/client/proxy/ComputerCraftProxyClient.java @@ -34,7 +34,9 @@ import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer; import dan200.computercraft.shared.pocket.items.ItemPocketComputer; import dan200.computercraft.shared.turtle.inventory.ContainerTurtle; +import dan200.computercraft.shared.util.Config; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientBlockEntityEvents; +import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents; import net.minecraft.client.item.ModelPredicateProvider; import net.minecraft.client.render.RenderLayer; import net.minecraft.item.Item; @@ -63,6 +65,9 @@ public final class ComputerCraftProxyClient implements ClientModInitializer { }); ClientUnloadWorldEvent.EVENT.register( () -> ClientMonitor.destroyAll() ); + + // Config + ClientLifecycleEvents.CLIENT_STARTED.register(Config::clientStarted); } @Override diff --git a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java index 754f9684f..e0849849f 100644 --- a/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java +++ b/src/main/java/dan200/computercraft/client/render/ItemPocketRenderer.java @@ -50,8 +50,8 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer { int termWidth, termHeight; if (terminal == null) { - termWidth = ComputerCraft.terminalWidth_pocketComputer; - termHeight = ComputerCraft.terminalHeight_pocketComputer; + termWidth = ComputerCraft.pocketTermWidth; + termHeight = ComputerCraft.pocketTermHeight; } else { termWidth = terminal.getWidth(); termHeight = terminal.getHeight(); diff --git a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java index 0996e5300..698f783b4 100644 --- a/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java +++ b/src/main/java/dan200/computercraft/core/apis/HTTPAPI.java @@ -156,7 +156,7 @@ public class HTTPAPI implements ILuaAPI @LuaFunction public final Object[] websocket( String address, Optional> headerTbl ) throws LuaException { - if( !ComputerCraft.http_websocket_enable ) + if( !ComputerCraft.httpWebsocketEnabled) { throw new LuaException( "Websocket connections are disabled" ); } diff --git a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java index 6747d6c43..dba5b0e7b 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java +++ b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequest.java @@ -188,7 +188,7 @@ public class HttpRequest extends Resource { this.failure(e.getMessage()); } catch (Exception e) { this.failure("Could not connect"); - if (ComputerCraft.logPeripheralErrors) { + if (ComputerCraft.logComputerErrors) { ComputerCraft.log.error("Error in HTTP request", e); } } diff --git a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java index 845a185ee..59e833e4d 100644 --- a/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java +++ b/src/main/java/dan200/computercraft/core/apis/http/request/HttpRequestHandler.java @@ -182,7 +182,7 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler { this.failure(e.getMessage()); } catch (Exception e) { this.failure("Could not connect"); - if (ComputerCraft.logPeripheralErrors) { + if (ComputerCraft.logComputerErrors) { ComputerCraft.log.error("Error in websocket", e); } } diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java b/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java index c263f9cf0..6d4f8fe97 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerExecutor.java @@ -157,7 +157,7 @@ final class ComputerExecutor { this.apis.add(new FSAPI(environment)); this.apis.add(new PeripheralAPI(environment)); this.apis.add(new OSAPI(environment)); - if (ComputerCraft.http_enable) { + if (ComputerCraft.httpEnabled) { this.apis.add(new HTTPAPI(environment)); } diff --git a/src/main/java/dan200/computercraft/core/computer/ComputerThread.java b/src/main/java/dan200/computercraft/core/computer/ComputerThread.java index 4b5abbb71..ccebc9e2c 100644 --- a/src/main/java/dan200/computercraft/core/computer/ComputerThread.java +++ b/src/main/java/dan200/computercraft/core/computer/ComputerThread.java @@ -124,7 +124,7 @@ public final class ComputerThread { if (runners == null) { // TODO: Change the runners length on config reloads - runners = new TaskRunner[ComputerCraft.computer_threads]; + runners = new TaskRunner[ComputerCraft.computerThreads]; // latency and minPeriod are scaled by 1 + floor(log2(threads)). We can afford to execute tasks for // longer when executing on more than one thread. @@ -326,7 +326,7 @@ public final class ComputerThread { } private static void timeoutTask(ComputerExecutor executor, Thread thread, long time) { - if (!ComputerCraft.logPeripheralErrors) { + if (!ComputerCraft.logComputerErrors) { return; } diff --git a/src/main/java/dan200/computercraft/core/lua/BasicFunction.java b/src/main/java/dan200/computercraft/core/lua/BasicFunction.java index 9d49aac08..6b2dd4d4b 100644 --- a/src/main/java/dan200/computercraft/core/lua/BasicFunction.java +++ b/src/main/java/dan200/computercraft/core/lua/BasicFunction.java @@ -45,7 +45,7 @@ class BasicFunction extends VarArgFunction { } catch (LuaException e) { throw wrap(e); } catch (Throwable t) { - if (ComputerCraft.logPeripheralErrors) { + if (ComputerCraft.logComputerErrors) { ComputerCraft.log.error("Error calling " + this.name + " on " + this.instance, t); } throw new LuaError("Java Exception Thrown: " + t, 0); diff --git a/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java b/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java index f47bbcd66..486a59244 100644 --- a/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java +++ b/src/main/java/dan200/computercraft/core/lua/CobaltLuaMachine.java @@ -119,7 +119,7 @@ public class CobaltLuaMachine implements ILuaMachine { this.m_globals.load(state, new CoroutineLib()); this.m_globals.load(state, new Bit32Lib()); this.m_globals.load(state, new Utf8Lib()); - if (ComputerCraft.debug_enable) { + if (ComputerCraft.debugEnable) { this.m_globals.load(state, new DebugLib()); } @@ -135,8 +135,8 @@ public class CobaltLuaMachine implements ILuaMachine { valueOf(computer.getAPIEnvironment() .getComputerEnvironment() .getHostString())); - this.m_globals.rawset("_CC_DEFAULT_SETTINGS", valueOf(ComputerCraft.default_computer_settings)); - if (ComputerCraft.disable_lua51_features) { + this.m_globals.rawset("_CC_DEFAULT_SETTINGS", valueOf(ComputerCraft.defaultComputerSettings)); + if (ComputerCraft.disableLua51Features) { this.m_globals.rawset("_CC_DISABLE_LUA51_FEATURES", Constants.TRUE); } } @@ -436,7 +436,7 @@ public class CobaltLuaMachine implements ILuaMachine { return wrapped; } - if (ComputerCraft.logPeripheralErrors) { + if (ComputerCraft.logComputerErrors) { ComputerCraft.log.warn("Received unknown type '{}', returning nil.", object.getClass() .getName()); @@ -581,7 +581,7 @@ public class CobaltLuaMachine implements ILuaMachine { e.getMessage() }); } catch (Throwable t) { - if (ComputerCraft.logPeripheralErrors) { + if (ComputerCraft.logComputerErrors) { ComputerCraft.log.error("Error running task", t); } CobaltLuaMachine.this.m_computer.queueEvent("task_complete", new Object[] { diff --git a/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java b/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java index 5951670f5..12aacf219 100644 --- a/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java +++ b/src/main/java/dan200/computercraft/core/lua/ResultInterpreterFunction.java @@ -49,7 +49,7 @@ class ResultInterpreterFunction extends ResumableVarArgFunction getModConfigScreenFactory() { + return parent -> null; + } +} diff --git a/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java b/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java index 4184fbb00..3dd43457b 100644 --- a/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java +++ b/src/main/java/dan200/computercraft/shared/network/NetworkMessage.java @@ -14,9 +14,6 @@ import net.fabricmc.fabric.api.network.PacketContext; /** * The base interface for any message which will be sent to the client or server. - * - * @see dan200.computercraft.shared.network.client - * @see dan200.computercraft.shared.network.server */ public interface NetworkMessage { /** diff --git a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java index 767a3ab52..514264047 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/modem/wireless/WirelessModemPeripheral.java @@ -30,11 +30,11 @@ public abstract class WirelessModemPeripheral extends ModemPeripheral { World world = this.getWorld(); if (world != null) { Vec3d position = this.getPosition(); - double minRange = ComputerCraft.modem_range; - double maxRange = ComputerCraft.modem_highAltitudeRange; + double minRange = ComputerCraft.modemRange; + double maxRange = ComputerCraft.modemHighAltitudeRange; if (world.isRaining() && world.isThundering()) { - minRange = ComputerCraft.modem_rangeDuringStorm; - maxRange = ComputerCraft.modem_highAltitudeRangeDuringStorm; + minRange = ComputerCraft.modemRangeDuringStorm; + maxRange = ComputerCraft.modemHighAltitudeRangeDuringStorm; } if (position.y > 96.0 && maxRange > minRange) { return minRange + (position.y - 96.0) * ((maxRange - minRange) / ((world.getHeight() - 1) - 96.0)); diff --git a/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java b/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java index c5ab507ed..c6eeafde3 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java +++ b/src/main/java/dan200/computercraft/shared/pocket/core/PocketServerComputer.java @@ -42,7 +42,7 @@ public class PocketServerComputer extends ServerComputer implements IPocketAcces private ItemStack m_stack; public PocketServerComputer(World world, int computerID, String label, int instanceID, ComputerFamily family) { - super(world, computerID, label, instanceID, family, ComputerCraft.terminalWidth_pocketComputer, ComputerCraft.terminalHeight_pocketComputer); + super(world, computerID, label, instanceID, family, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight); } @Nullable diff --git a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java index 4a92d3e1f..09654af93 100644 --- a/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java +++ b/src/main/java/dan200/computercraft/shared/proxy/ComputerCraftProxyCommon.java @@ -28,6 +28,7 @@ import dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods; import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork; import dan200.computercraft.shared.turtle.FurnaceRefuelHandler; import dan200.computercraft.shared.turtle.SignInspectHandler; +import dan200.computercraft.shared.util.Config; import dan200.computercraft.shared.util.TickScheduler; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerBlockEntityEvents; @@ -117,6 +118,10 @@ public final class ComputerCraftProxyCommon { } }); + // Config + ServerLifecycleEvents.SERVER_STARTING.register(Config::serverStarting); + ServerLifecycleEvents.SERVER_STOPPING.register(Config::serverStopping); + TurtleEvent.EVENT_BUS.register(FurnaceRefuelHandler.INSTANCE); TurtleEvent.EVENT_BUS.register(new TurtlePermissions()); TurtleEvent.EVENT_BUS.register(new SignInspectHandler()); diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java index d1ad7c2d2..118de826c 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java @@ -312,8 +312,8 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default ServerComputer computer = new ServerComputer(this.getWorld(), id, this.label, instanceID, this.getFamily(), - ComputerCraft.terminalWidth_turtle, - ComputerCraft.terminalHeight_turtle); + ComputerCraft.turtleTermWidth, + ComputerCraft.turtleTermHeight); computer.setPosition(this.getPos()); computer.addAPI(new TurtleAPI(computer.getAPIEnvironment(), this.getAccess())); this.m_brain.setupComputer(computer); diff --git a/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java b/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java new file mode 100644 index 000000000..a1d972d19 --- /dev/null +++ b/src/main/java/dan200/computercraft/shared/util/CommentedConfigSpec.java @@ -0,0 +1,44 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ +package dan200.computercraft.shared.util; + +import com.electronwill.nightconfig.core.Config; +import com.electronwill.nightconfig.core.CommentedConfig; +import com.electronwill.nightconfig.core.ConfigSpec; + +import java.util.*; + +import static com.electronwill.nightconfig.core.utils.StringUtils.split; + +public class CommentedConfigSpec extends ConfigSpec { + private final Map, String> comments = new HashMap<>(); + + public void comment(List path, String comment) { + comments.put(path, comment); + } + + public void comment(String path, String comment) { + comment(split(path, '.'), comment); + } + + public int correct(Config config) { + return correct(config, (action, path, incorrectValue, correctedValue) -> {}); + } + + public int correct(Config config, ConfigSpec.CorrectionListener listener) { + int corrections = super.correct(config, listener); + if(config instanceof CommentedConfig) { + insertComments((CommentedConfig) config); + } + return corrections; + } + + private void insertComments(CommentedConfig config) { + for(Map.Entry, String> entry : comments.entrySet()) { + config.setComment(entry.getKey(), entry.getValue()); + } + } +} diff --git a/src/main/java/dan200/computercraft/shared/util/Config.java b/src/main/java/dan200/computercraft/shared/util/Config.java index 0cd64f846..fdf35bd77 100644 --- a/src/main/java/dan200/computercraft/shared/util/Config.java +++ b/src/main/java/dan200/computercraft/shared/util/Config.java @@ -1,223 +1,365 @@ +/* + * This file is part of ComputerCraft - http://www.computercraft.info + * Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission. + * Send enquiries to dratcliffe@gmail.com + */ package dan200.computercraft.shared.util; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Objects; -import java.util.concurrent.TimeUnit; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import blue.endless.jankson.Comment; -import blue.endless.jankson.Jankson; -import blue.endless.jankson.JsonObject; -import blue.endless.jankson.api.SyntaxError; +import com.electronwill.nightconfig.core.*; +import com.electronwill.nightconfig.core.file.CommentedFileConfig; +import com.electronwill.nightconfig.core.file.FileNotFoundAction; import com.google.common.base.CaseFormat; import com.google.common.base.Converter; import dan200.computercraft.ComputerCraft; import dan200.computercraft.api.turtle.event.TurtleAction; import dan200.computercraft.core.apis.http.options.Action; -import dan200.computercraft.core.apis.http.options.AddressRule; -import dan200.computercraft.core.apis.http.websocket.Websocket; +import dan200.computercraft.core.apis.http.options.AddressRuleConfig; +import dan200.computercraft.fabric.mixin.WorldSavePathAccess; +import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer; +import net.fabricmc.loader.FabricLoader; +import net.minecraft.client.MinecraftClient; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.WorldSavePath; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; public class Config { - public static final transient int MODEM_MAX_RANGE = 100000; - public static final transient Config defaultConfig = new Config(); - private static transient Path configPath; - private static transient Config config; - public General general = new General(); - @Comment ("\nControls execution behaviour of computers. This is largely intended for fine-tuning " + "servers, and generally shouldn't need to be " + "touched") public Execution execution = new Execution(); - @Comment ("\nControls the HTTP API") public Http http = new Http(); - @Comment ("\nVarious options relating to peripherals.") public Peripheral peripheral = new Peripheral(); - @Comment ("\nVarious options relating to turtles.") public Turtle turtle = new Turtle(); + private static final int MODEM_MAX_RANGE = 100000; - public static Config get() { - return config; + public static final String TRANSLATION_PREFIX = "gui.computercraft.config."; + + public static final CommentedConfigSpec serverSpec; + public static final CommentedConfigSpec clientSpec; + + public static CommentedConfig serverConfig; + public static CommentedConfig clientConfig; + + private static final WorldSavePath serverDir = WorldSavePathAccess.createWorldSavePath("serverconfig"); + private static final String serverFileName = "computercraft-server.toml"; + private static final Path clientPath = FabricLoader.INSTANCE.getConfigDir().resolve("computercraft-client.toml"); + + private Config() { } - public static void load(Path path) { - configPath = path; + static { + System.setProperty("nightconfig.preserveInsertionOrder", "true"); - if (Files.exists(configPath)) { - Jankson jankson = Jankson.builder() - .build(); - try { - JsonObject jsonObject = jankson.load(Files.newInputStream(configPath)); - config = jankson.fromJson(jsonObject, Config.class); - } catch (IOException | SyntaxError e) { - config = new Config(); - ComputerCraft.log.error("Failed to load config! Use default config."); - e.printStackTrace(); - return; - } - } else { - config = new Config(); + serverSpec = new CommentedConfigSpec(); + { // General computers + serverSpec.comment("computer_space_limit", + "The disk space limit for computers and turtles, in bytes"); + serverSpec.define("computer_space_limit", ComputerCraft.computerSpaceLimit); + + serverSpec.comment("floppy_space_limit", + "The disk space limit for floppy disks, in bytes"); + serverSpec.define("floppy_space_limit", ComputerCraft.floppySpaceLimit); + + serverSpec.comment("maximum_open_files", + "Set how many files a computer can have open at the same time. Set to 0 for unlimited."); + serverSpec.defineInRange("maximum_open_files", ComputerCraft.maximumFilesOpen, 0, Integer.MAX_VALUE); + + serverSpec.comment("disable_lua51_features", + "Set this to true to disable Lua 5.1 functions that will be removed in a future update. " + + "Useful for ensuring forward compatibility of your programs now."); + serverSpec.define("disable_lua51_features", ComputerCraft.disableLua51Features); + + serverSpec.comment("default_computer_settings", + "A comma separated list of default system settings to set on new computers. Example: " + + "\"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\" will disable all " + + "autocompletion"); + serverSpec.define("default_computer_settings", ComputerCraft.defaultComputerSettings); + + serverSpec.comment("debug_enabled", + "Enable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players."); + serverSpec.define("debug_enabled", ComputerCraft.debugEnable); + + serverSpec.comment("log_computer_errors", + "Log exceptions thrown by peripherals and other Lua objects.\n" + + "This makes it easier for mod authors to debug problems, but may result in log spam should people use buggy methods."); + serverSpec.define("log_computer_errors", ComputerCraft.logComputerErrors); + + serverSpec.comment("command_require_creative", + "Require players to be in creative mode and be opped in order to interact with command computers." + + "This is the default behaviour for vanilla's Command blocks."); + serverSpec.define("command_require_creative", ComputerCraft.commandRequireCreative); } - save(); - sync(); + + { // Execution + serverSpec.comment("execution", + "Controls execution behaviour of computers. This is largely intended for fine-tuning " + + "servers, and generally shouldn't need to be touched"); + + serverSpec.comment("execution.computer_threads", + "Set the number of threads computers can run on. A higher number means more computers can run " + + "at once, but may induce lag.\n" + + "Please note that some mods may not work with a thread count higher than 1. Use with caution."); + serverSpec.defineInRange("execution.computer_threads", ComputerCraft.computerThreads, 1, Integer.MAX_VALUE); + + serverSpec.comment("execution.max_main_global_time", + "The maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + + "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + + "- this aims to be the upper bound of the average time."); + serverSpec.defineInRange("execution.max_main_global_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainGlobalTime ), 1, Integer.MAX_VALUE); + + serverSpec.comment("execution.max_main_computer_time", + "The ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + + "Note, we will quite possibly go over this limit, as there's no way to tell how long a will take " + + "- this aims to be the upper bound of the average time."); + serverSpec.defineInRange("execution.max_main_computer_time", (int) TimeUnit.NANOSECONDS.toMillis( ComputerCraft.maxMainComputerTime ), 1, Integer.MAX_VALUE); + } + + { // HTTP + serverSpec.comment("http", "Controls the HTTP API"); + + serverSpec.comment("http.enabled", + "Enable the \"http\" API on Computers (see \"rules\" for more fine grained control than this)."); + serverSpec.define("http.enabled", ComputerCraft.httpEnabled); + + serverSpec.comment("http.websocket_enabled", + "Enable use of http websockets. This requires the \"http_enable\" option to also be true."); + serverSpec.define("http.websocket_enabled", ComputerCraft.httpWebsocketEnabled); + + serverSpec.comment("http.rules", + "A list of rules which control behaviour of the \"http\" API for specific domains or IPs.\n" + + "Each rule is an item with a 'host' to match against, and a series of properties. " + + "The host may be a domain name (\"pastebin.com\"),\n" + + "wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\"). If no rules, the domain is blocked."); + serverSpec.defineList("http.rules", Arrays.asList( + AddressRuleConfig.makeRule("$private", Action.DENY), + AddressRuleConfig.makeRule("*", Action.ALLOW) + ), x -> x instanceof UnmodifiableConfig && AddressRuleConfig.checkRule((UnmodifiableConfig) x)); + + serverSpec.comment("http.max_requests", + "The number of http requests a computer can make at one time. Additional requests will be queued, and sent when the running requests have finished. Set to 0 for unlimited."); + serverSpec.defineInRange("http.max_requests", ComputerCraft.httpMaxRequests, 0, Integer.MAX_VALUE); + + serverSpec.comment("http.max_websockets", + "The number of websockets a computer can have open at one time. Set to 0 for unlimited."); + serverSpec.defineInRange("http.max_websockets", ComputerCraft.httpMaxWebsockets, 1, Integer.MAX_VALUE); + } + + { // Peripherals + serverSpec.comment("peripheral", "Various options relating to peripherals."); + + serverSpec.comment("peripheral.command_block_enabled", + "Enable Command Block peripheral support"); + serverSpec.define("peripheral.command_block_enabled", ComputerCraft.enableCommandBlock); + + serverSpec.comment("peripheral.modem_range", + "The range of Wireless Modems at low altitude in clear weather, in meters"); + serverSpec.defineInRange("peripheral.modem_range", ComputerCraft.modemRange, 0, MODEM_MAX_RANGE); + + serverSpec.comment("peripheral.modem_high_altitude_range", + "The range of Wireless Modems at maximum altitude in clear weather, in meters"); + serverSpec.defineInRange("peripheral.modem_high_altitude_range", ComputerCraft.modemHighAltitudeRange, 0, MODEM_MAX_RANGE); + + serverSpec.comment("peripheral.modem_range_during_storm", + "The range of Wireless Modems at low altitude in stormy weather, in meters"); + serverSpec.defineInRange("peripheral.modem_range_during_storm", ComputerCraft.modemRangeDuringStorm, 0, MODEM_MAX_RANGE); + + serverSpec.comment("peripheral.modem_high_altitude_range_during_storm", + "The range of Wireless Modems at maximum altitude in stormy weather, in meters"); + serverSpec.defineInRange("peripheral.modem_high_altitude_range_during_storm", ComputerCraft.modemHighAltitudeRangeDuringStorm, 0, MODEM_MAX_RANGE); + + serverSpec.comment("peripheral.max_notes_per_tick", + "Maximum amount of notes a speaker can play at once"); + serverSpec.defineInRange("peripheral.max_notes_per_tick", ComputerCraft.maxNotesPerTick, 1, Integer.MAX_VALUE); + + serverSpec.comment("peripheral.monitor_bandwidth", + "The limit to how much monitor data can be sent *per tick*. Note:\n" + + " - Bandwidth is measured before compression, so the data sent to the client is smaller.\n" + + " - This ignores the number of players a packet is sent to. Updating a monitor for one player consumes " + + "the same bandwidth limit as sending to 20.\n" + + " - A full sized monitor sends ~25kb of data. So the default (1MB) allows for ~40 monitors to be updated " + + "in a single tick. \n" + + "Set to 0 to disable."); + serverSpec.defineInRange("peripheral.monitor_bandwidth", (int) ComputerCraft.monitorBandwidth, 0, Integer.MAX_VALUE); + } + + { // Turtles + serverSpec.comment("turtle", "Various options relating to turtles."); + + serverSpec.comment("turtle.need_fuel", + "Set whether Turtles require fuel to move"); + serverSpec.define("turtle.need_fuel", ComputerCraft.turtlesNeedFuel); + + serverSpec.comment("turtle.normal_fuel_limit", "The fuel limit for Turtles"); + serverSpec.defineInRange("turtle.normal_fuel_limit", ComputerCraft.turtleFuelLimit, 0, Integer.MAX_VALUE); + + serverSpec.comment("turtle.advanced_fuel_limit", + "The fuel limit for Advanced Turtles"); + serverSpec.defineInRange("turtle.advanced_fuel_limit", ComputerCraft.advancedTurtleFuelLimit, 0, Integer.MAX_VALUE); + + serverSpec.comment("turtle.obey_block_protection", + "If set to true, Turtles will be unable to build, dig, or enter protected areas (such as near the server spawn point)"); + serverSpec.define("turtle.obey_block_protection", ComputerCraft.turtlesObeyBlockProtection); + + serverSpec.comment("turtle.can_push", + "If set to true, Turtles will push entities out of the way instead of stopping if there is space to do so"); + serverSpec.define("turtle.can_push", ComputerCraft.turtlesCanPush); + + serverSpec.comment("turtle.disabled_actions", + "A list of turtle actions which are disabled."); + serverSpec.defineList("turtle.disabled_actions", Collections.emptyList(), x -> x instanceof String && getAction((String) x) != null); + } + + { + serverSpec.comment("term_sizes", "Configure the size of various computer's terminals.\n" + + "Larger terminals require more bandwidth, so use with care."); + + serverSpec.comment("term_sizes.computer", "Terminal size of computers"); + serverSpec.defineInRange("term_sizes.computer.width", ComputerCraft.computerTermWidth, 1, 255); + serverSpec.defineInRange("term_sizes.computer.height", ComputerCraft.computerTermHeight, 1, 255); + + serverSpec.comment("term_sizes.pocket_computer", "Terminal size of pocket computers"); + serverSpec.defineInRange("term_sizes.pocket_computer.width", ComputerCraft.pocketTermWidth, 1, 255); + serverSpec.defineInRange("term_sizes.pocket_computer.height", ComputerCraft.pocketTermHeight, 1, 255); + + serverSpec.comment("term_sizes.monitor", "Maximum size of monitors (in blocks)"); + serverSpec.defineInRange("term_sizes.monitor.width", ComputerCraft.monitorWidth, 1, 32); + serverSpec.defineInRange("term_sizes.monitor.height", ComputerCraft.monitorHeight, 1, 32); + } + + clientSpec = new CommentedConfigSpec(); + + clientSpec.comment("monitor_renderer", + "The renderer to use for monitors. Generally this should be kept at \"best\" - if " + + "monitors have performance issues, you may wish to experiment with alternative renderers."); + clientSpec.defineRestrictedEnum("monitor_renderer", MonitorRenderer.BEST, EnumSet.allOf(MonitorRenderer.class), EnumGetMethod.NAME_IGNORECASE); + + clientSpec.comment("monitor_distance", + "The maximum distance monitors will render at. This defaults to the standard tile entity limit, " + + "but may be extended if you wish to build larger monitors." ); + clientSpec.defineInRange("monitor_distance", 64, 16, 1024); } - public static void save() { - Jankson jankson = Jankson.builder() - .build(); - try { - String configData = jankson.toJson(config) - .toJson(true, true); - Files.write(configPath, configData.getBytes()); - } catch (IOException e) { - ComputerCraft.log.error("Failed to save config!"); - e.printStackTrace(); + private static final FileNotFoundAction MAKE_DIRECTORIES = (file, configFormat) -> { + Files.createDirectories(file.getParent()); + Files.createFile(file); + configFormat.initEmptyFile(file); + return false; + }; + + private static CommentedFileConfig buildFileConfig(Path path) { + return CommentedFileConfig.builder(path) + .onFileNotFound(MAKE_DIRECTORIES) + .preserveInsertionOrder() + .build(); + } + + public static void serverStarting(MinecraftServer server) { + Path serverPath = server.getSavePath(serverDir).resolve(serverFileName); + + try(CommentedFileConfig config = buildFileConfig(serverPath)) { + config.load(); + serverSpec.correct(config, Config::correctionListener); + config.save(); + serverConfig = config; + sync(); + } + } + + public static void serverStopping(MinecraftServer server) { + serverConfig = null; + } + + public static void clientStarted(MinecraftClient client) { + try (CommentedFileConfig config = buildFileConfig(clientPath)) { + config.load(); + clientSpec.correct(config, Config::correctionListener); + config.save(); + clientConfig = config; + sync(); + } + } + + private static void correctionListener(ConfigSpec.CorrectionAction action, List path, Object incorrectValue, Object correctedValue) { + String key = String.join(".", path); + switch(action) { + case ADD: + ComputerCraft.log.warn("Config key {} missing -> added default value.", key); break; + case REMOVE: + ComputerCraft.log.warn("Config key {} not defined -> removed from config.", key); break; + case REPLACE: + ComputerCraft.log.warn("Config key {} not valid -> replaced with default value.", key); } } public static void sync() { - // General - ComputerCraft.computerSpaceLimit = config.general.computer_space_limit; - ComputerCraft.floppySpaceLimit = config.general.floppy_space_limit; - ComputerCraft.maximumFilesOpen = Math.max(0, config.general.maximum_open_files); - ComputerCraft.disable_lua51_features = config.general.disable_lua51_features; - ComputerCraft.default_computer_settings = config.general.default_computer_settings; - ComputerCraft.debug_enable = config.general.debug_enabled; - ComputerCraft.logPeripheralErrors = config.general.log_computer_errors; + if(serverConfig != null) { + // General + ComputerCraft.computerSpaceLimit = serverConfig.get("computer_space_limit"); + ComputerCraft.floppySpaceLimit = serverConfig.get("floppy_space_limit"); + ComputerCraft.maximumFilesOpen = serverConfig.get("maximum_open_files"); + ComputerCraft.disableLua51Features = serverConfig.get("disable_lua51_features"); + ComputerCraft.defaultComputerSettings = serverConfig.get("default_computer_settings"); + ComputerCraft.debugEnable = serverConfig.get("debug_enabled"); + ComputerCraft.logComputerErrors = serverConfig.get("log_computer_errors"); + ComputerCraft.commandRequireCreative = serverConfig.get("command_require_creative"); - // Execution - ComputerCraft.computer_threads = Math.max(1, config.execution.computer_threads); - ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(Math.max(1, config.execution.max_main_global_time)); - ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(Math.max(1, config.execution.max_main_computer_time)); + // Execution + ComputerCraft.computerThreads = serverConfig.get("execution.computer_threads"); + ComputerCraft.maxMainGlobalTime = TimeUnit.MILLISECONDS.toNanos(serverConfig.get("execution.max_main_global_time")); + ComputerCraft.maxMainComputerTime = TimeUnit.MILLISECONDS.toNanos(serverConfig.get("execution.max_main_computer_time")); - // HTTP - ComputerCraft.http_enable = config.http.enabled; - ComputerCraft.http_websocket_enable = config.http.websocket_enabled; - ComputerCraft.httpRules = Stream.concat(Stream.of(config.http.blacklist) - .map( x -> AddressRule.parse( x, null, Action.DENY.toPartial())) - .filter(Objects::nonNull), - Stream.of(config.http.whitelist) - .map( x -> AddressRule.parse( x, null, Action.ALLOW.toPartial())) - .filter(Objects::nonNull)) - .collect(Collectors.toList()); + // HTTP + ComputerCraft.httpEnabled = serverConfig.get("http.enabled"); + ComputerCraft.httpWebsocketEnabled = serverConfig.get("http.websocket_enabled"); + ComputerCraft.httpRules = serverConfig.>get("http.rules").stream().map(AddressRuleConfig::parseRule) + .filter(Objects::nonNull).collect(Collectors.toList()); + ComputerCraft.httpMaxRequests = serverConfig.get("http.max_requests"); + ComputerCraft.httpMaxWebsockets = serverConfig.get("http.max_websockets"); - ComputerCraft.httpTimeout = Math.max(0, config.http.timeout); - ComputerCraft.httpMaxRequests = Math.max(1, config.http.max_requests); - ComputerCraft.httpMaxDownload = Math.max(0, config.http.max_download); - ComputerCraft.httpMaxUpload = Math.max(0, config.http.max_upload); - ComputerCraft.httpMaxWebsockets = Math.max(1, config.http.max_websockets); - ComputerCraft.httpMaxWebsocketMessage = Math.min(Math.max(0, config.http.max_websocket_message), Websocket.MAX_MESSAGE_SIZE); + // Peripherals + ComputerCraft.enableCommandBlock = serverConfig.get("peripheral.command_block_enabled"); + ComputerCraft.modemRange = serverConfig.get("peripheral.modem_range"); + ComputerCraft.modemHighAltitudeRange = serverConfig.get("peripheral.modem_high_altitude_range"); + ComputerCraft.modemRangeDuringStorm = serverConfig.get("peripheral.modem_range_during_storm"); + ComputerCraft.modemHighAltitudeRangeDuringStorm = serverConfig.get("peripheral.modem_high_altitude_range_during_storm"); + ComputerCraft.maxNotesPerTick = serverConfig.get("peripheral.max_notes_per_tick"); + ComputerCraft.monitorBandwidth = serverConfig.get("peripheral.monitor_bandwidth"); - // Peripheral - ComputerCraft.enableCommandBlock = config.peripheral.command_block_enabled; - ComputerCraft.maxNotesPerTick = Math.max(1, config.peripheral.max_notes_per_tick); - ComputerCraft.modem_range = Math.min(Math.max(0, config.peripheral.modem_range), MODEM_MAX_RANGE); - ComputerCraft.modem_highAltitudeRange = Math.min(Math.max(0, config.peripheral.modem_high_altitude_range), MODEM_MAX_RANGE); - ComputerCraft.modem_rangeDuringStorm = Math.min(Math.max(0, config.peripheral.modem_range_during_storm), MODEM_MAX_RANGE); - ComputerCraft.modem_highAltitudeRangeDuringStorm = Math.min(Math.max(0, config.peripheral.modem_high_altitude_range_during_storm), MODEM_MAX_RANGE); + // Turtles + ComputerCraft.turtlesNeedFuel = serverConfig.get("turtle.need_fuel"); + ComputerCraft.turtleFuelLimit = serverConfig.get("turtle.normal_fuel_limit"); + ComputerCraft.advancedTurtleFuelLimit = serverConfig.get("turtle.advanced_fuel_limit"); + ComputerCraft.turtlesObeyBlockProtection = serverConfig.get("turtle.obey_block_protection"); + ComputerCraft.turtlesCanPush = serverConfig.get("turtle.can_push"); - // Turtles - ComputerCraft.turtlesNeedFuel = config.turtle.need_fuel; - ComputerCraft.turtleFuelLimit = Math.max(0, config.turtle.normal_fuel_limit); - ComputerCraft.advancedTurtleFuelLimit = Math.max(0, config.turtle.advanced_fuel_limit); - ComputerCraft.turtlesObeyBlockProtection = config.turtle.obey_block_protection; - ComputerCraft.turtlesCanPush = config.turtle.can_push; - - ComputerCraft.turtleDisabledActions.clear(); - Converter converter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_UNDERSCORE); - for (String value : config.turtle.disabled_actions) { - try { - ComputerCraft.turtleDisabledActions.add(TurtleAction.valueOf(converter.convert(value))); - } catch (IllegalArgumentException e) { - ComputerCraft.log.error("Unknown turtle action " + value); + ComputerCraft.turtleDisabledActions.clear(); + for(String value : serverConfig.>get("turtle.disabled_actions")) { + ComputerCraft.turtleDisabledActions.add(getAction(value)); } + + // Terminal Size + ComputerCraft.computerTermWidth = serverConfig.get("term_sizes.computer.width"); + ComputerCraft.computerTermHeight = serverConfig.get("term_sizes.computer.height"); + ComputerCraft.pocketTermWidth = serverConfig.get("term_sizes.pocket_computer.width"); + ComputerCraft.pocketTermHeight = serverConfig.get("term_sizes.pocket_computer.height"); + ComputerCraft.monitorWidth = serverConfig.get("term_sizes.monitor.width"); + ComputerCraft.monitorHeight = serverConfig.get("term_sizes.monitor.height"); + } + + // Client + if(clientConfig != null) { + ComputerCraft.monitorRenderer = clientConfig.getEnum("monitor_renderer", MonitorRenderer.class); + int distance = clientConfig.get("monitor_distance"); + ComputerCraft.monitorDistanceSq = distance * distance; } } - public static class General { - @Comment ("\nThe disk space limit for computers and turtles, in bytes") public int computer_space_limit = ComputerCraft.computerSpaceLimit; + private static final Converter converter = CaseFormat.LOWER_CAMEL.converterTo(CaseFormat.UPPER_UNDERSCORE); - @Comment ("\nThe disk space limit for floppy disks, in bytes") public int floppy_space_limit = ComputerCraft.floppySpaceLimit; - - @Comment ("\nSet how many files a computer can have open at the same time. Set to 0 for unlimited.") public int maximum_open_files = - ComputerCraft.maximumFilesOpen; - - @Comment ("\nSet this to true to disable Lua 5.1 functions that will be removed in a future " + "update. Useful for ensuring forward " + - "compatibility of your programs now.") public boolean disable_lua51_features = ComputerCraft.disable_lua51_features; - - @Comment ("\nA comma separated list of default system settings to set on new computers. Example: " + "\"shell.autocomplete=false,lua" + - ".autocomplete=false,edit.autocomplete=false\" will disable all autocompletion") public String default_computer_settings = - ComputerCraft.default_computer_settings; - - @Comment ("\nEnable Lua's debug library. This is sandboxed to each computer, so is generally safe to be used by players.") public boolean debug_enabled = ComputerCraft.debug_enable; - - @Comment ("\nLog exceptions thrown by peripherals and other Lua objects.\n" + "This makes it easier for mod authors to debug problems, but may " + "result in log spam should people use buggy methods.") public boolean log_computer_errors = ComputerCraft.logPeripheralErrors; - } - - public static class Execution { - @Comment ("\nSet the number of threads computers can run on. A higher number means more computers can " + "run at once, but may induce lag.\n" + - "Please note that some mods may not work with a thread count higher than 1. Use with caution.") public int computer_threads = - ComputerCraft.computer_threads; - - @Comment ("\nThe maximum time that can be spent executing tasks in a single tick, in milliseconds.\n" + "Note, we will quite possibly go over " + "this limit, as there's no way to tell how long a will take - this aims " + "to be the upper bound of the average time.") public long max_main_global_time = TimeUnit.NANOSECONDS.toMillis( - ComputerCraft.maxMainGlobalTime); - - @Comment ("\nThe ideal maximum time a computer can execute for in a tick, in milliseconds.\n" + "Note, we will quite possibly go over this limit," - + " as there's no way to tell how long a will take - this aims " + "to be the upper bound of the average time.") public long max_main_computer_time = TimeUnit.NANOSECONDS.toMillis( - ComputerCraft.maxMainComputerTime); - } - - public static class Http { - @Comment ("\nEnable the \"http\" API on Computers (see \"http_whitelist\" and \"http_blacklist\" for " + "more fine grained control than this)") public boolean enabled = ComputerCraft.http_enable; - - @Comment ("\nEnable use of http websockets. This requires the \"http_enable\" option to also be true.") public boolean websocket_enabled = - ComputerCraft.http_websocket_enable; - - @Comment ("\nA list of wildcards for domains or IP ranges that can be accessed through the " + "\"http\" API on Computers.\n" + "Set this to " + - "\"*\" to access to the entire internet. Example: \"*.pastebin.com\" will restrict access to " + "just subdomains of pastebin.com.\n" + "You can use domain names (\"pastebin.com\"), wilcards (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\").") public String[] whitelist = new String[] {"*"}; - - @Comment ("\nA list of wildcards for domains or IP ranges that cannot be accessed through the " + "\"http\" API on Computers.\n" + "If this is " + "empty then all whitelisted domains will be accessible. Example: \"*.github.com\" will block " + "access to all subdomains of github" + ".com.\n" + "You can use domain names (\"pastebin.com\"), wilcards (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\").") public String[] blacklist = new String[] {"$private"}; - - @Comment ("\nThe period of time (in milliseconds) to wait before a HTTP request times out. Set to 0 for unlimited.") public int timeout = - ComputerCraft.httpTimeout; - - @Comment ("\nThe number of http requests a computer can make at one time. Additional requests " + "will be queued, and sent when the running " + - "requests have finished. Set to 0 for unlimited.") public int max_requests = ComputerCraft.httpMaxRequests; - - @Comment ("\nThe maximum size (in bytes) that a computer can download in a single request. " + "Note that responses may receive more data than " + "allowed, but this data will not be returned to the client.") public long max_download = ComputerCraft.httpMaxDownload; - - @Comment ("\nThe maximum size (in bytes) that a computer can upload in a single request. This " + "includes headers and POST text.") public long max_upload = ComputerCraft.httpMaxUpload; - - @Comment ("\nThe number of websockets a computer can have open at one time. Set to 0 for unlimited.") public int max_websockets = - ComputerCraft.httpMaxWebsockets; - - @Comment ("\nThe maximum size (in bytes) that a computer can send or receive in one websocket packet.") public int max_websocket_message = - ComputerCraft.httpMaxWebsocketMessage; - } - - public static class Peripheral { - @Comment ("\n\nEnable Command Block peripheral support") public boolean command_block_enabled = ComputerCraft.enableCommandBlock; - - @Comment ("\nThe range of Wireless Modems at low altitude in clear weather, in meters") public int modem_range = ComputerCraft.modem_range; - - @Comment ("\nThe range of Wireless Modems at maximum altitude in clear weather, in meters") public int modem_high_altitude_range = - ComputerCraft.modem_highAltitudeRange; - - @Comment ("\nThe range of Wireless Modems at low altitude in stormy weather, in meters") public int modem_range_during_storm = - ComputerCraft.modem_rangeDuringStorm; - - @Comment ("\nThe range of Wireless Modems at maximum altitude in stormy weather, in meters") public int modem_high_altitude_range_during_storm = - ComputerCraft.modem_highAltitudeRangeDuringStorm; - - @Comment ("\nMaximum amount of notes a speaker can play at once") public int max_notes_per_tick = ComputerCraft.maxNotesPerTick; - } - - public static class Turtle { - @Comment ("\nSet whether Turtles require fuel to move") public boolean need_fuel = ComputerCraft.turtlesNeedFuel; - - @Comment ("\nThe fuel limit for Turtles") public int normal_fuel_limit = ComputerCraft.turtleFuelLimit; - - @Comment ("\nThe fuel limit for Advanced Turtles") public int advanced_fuel_limit = ComputerCraft.advancedTurtleFuelLimit; - - @Comment ("\nIf set to true, Turtles will be unable to build, dig, or enter protected " + "areas (such as near the server spawn point)") public boolean obey_block_protection = ComputerCraft.turtlesObeyBlockProtection; - - @Comment ("\nIf set to true, Turtles will push entities out of the way instead of stopping if " + "there is space to do so") public boolean can_push = ComputerCraft.turtlesCanPush; - - @Comment ("\nA list of turtle actions which are disabled.") public String[] disabled_actions = new String[0]; + private static TurtleAction getAction(String value) { + try { + return TurtleAction.valueOf(converter.convert(value)); + } + catch(IllegalArgumentException e) { + return null; + } } } diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index e6fe41446..23229f630 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -33,6 +33,9 @@ ], "client": [ "dan200.computercraft.client.proxy.ComputerCraftProxyClient" + ], + "modmenu": [ + "dan200.computercraft.shared.integration.ModMenuIntegration" ] }, "mixins": [