From ea670cc358ba3c96ac66a8133e8b48c5f7540428 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sun, 24 Nov 2024 21:53:04 +0000 Subject: [PATCH 1/4] Try to unify our config files a bit I've tried so many rewrites of the config system over the last few months, in an attempt to get started on #1727. All of them stink, so this is an attempt to apply some of the cleanup. - Move some of the common logic into ConfigFile. This means we now store more information ourselves for Forge, rather than reading it out of the ForgeConfigSpec. - Don't include the Range/Allowed keys in the translation key. This was mostly there because of how we read comments from Forge, but it never made much sense. - Remove our separate Trie structure, and just encode the tree as part of the children of a Group. --- .../assets/computercraft/lang/en_us.json | 56 +++---- .../shared/config/ConfigFile.java | 138 ++++++++++++++--- .../shared/config/ConfigSpec.java | 12 +- .../computercraft/shared/util/Trie.java | 46 ------ .../shared/platform/FabricConfigFile.java | 146 +++++------------- .../shared/platform/ForgeConfigFile.java | 120 ++++---------- 6 files changed, 217 insertions(+), 301 deletions(-) delete mode 100644 projects/common/src/main/java/dan200/computercraft/shared/util/Trie.java diff --git a/projects/common/src/generated/resources/assets/computercraft/lang/en_us.json b/projects/common/src/generated/resources/assets/computercraft/lang/en_us.json index 0802004c44..3b9807e286 100644 --- a/projects/common/src/generated/resources/assets/computercraft/lang/en_us.json +++ b/projects/common/src/generated/resources/assets/computercraft/lang/en_us.json @@ -83,35 +83,35 @@ "gui.computercraft.config.disabled_generic_methods.tooltip": "A list of generic methods or method sources to disable. Generic methods are\nmethods added to a block/block entity when there is no explicit peripheral\nprovider. This includes inventory methods (i.e. inventory.getItemDetail,\ninventory.pushItems), and (if on Forge), the fluid_storage and energy_storage\nmethods.\nMethods in this list can either be a whole group of methods (computercraft:inventory)\nor a single method (computercraft:inventory#pushItems).\n", "gui.computercraft.config.execution": "Execution", "gui.computercraft.config.execution.computer_threads": "Computer threads", - "gui.computercraft.config.execution.computer_threads.tooltip": "Set the number of threads computers can run on. A higher number means more\ncomputers can run at once, but may induce lag. Please note that some mods may\nnot work with a thread count higher than 1. Use with caution.\nRange: > 1", + "gui.computercraft.config.execution.computer_threads.tooltip": "Set the number of threads computers can run on. A higher number means more\ncomputers can run at once, but may induce lag. Please note that some mods may\nnot work with a thread count higher than 1. Use with caution.", "gui.computercraft.config.execution.max_main_computer_time": "Server tick computer time limit", - "gui.computercraft.config.execution.max_main_computer_time.tooltip": "The ideal maximum time a computer can execute for in a tick, in milliseconds.\nNote, we will quite possibly go over this limit, as there's no way to tell how\nlong a will take - this aims to be the upper bound of the average time.\nRange: > 1", + "gui.computercraft.config.execution.max_main_computer_time.tooltip": "The ideal maximum time a computer can execute for in a tick, in milliseconds.\nNote, we will quite possibly go over this limit, as there's no way to tell how\nlong a will take - this aims to be the upper bound of the average time.", "gui.computercraft.config.execution.max_main_global_time": "Server tick global time limit", - "gui.computercraft.config.execution.max_main_global_time.tooltip": "The maximum time that can be spent executing tasks in a single tick, in\nmilliseconds.\nNote, we will quite possibly go over this limit, as there's no way to tell how\nlong a will take - this aims to be the upper bound of the average time.\nRange: > 1", + "gui.computercraft.config.execution.max_main_global_time.tooltip": "The maximum time that can be spent executing tasks in a single tick, in\nmilliseconds.\nNote, we will quite possibly go over this limit, as there's no way to tell how\nlong a will take - this aims to be the upper bound of the average time.", "gui.computercraft.config.execution.tooltip": "Controls execution behaviour of computers. This is largely intended for\nfine-tuning servers, and generally shouldn't need to be touched.", "gui.computercraft.config.floppy_space_limit": "Floppy Disk space limit (bytes)", "gui.computercraft.config.floppy_space_limit.tooltip": "The disk space limit for floppy disks, in bytes.", "gui.computercraft.config.http": "HTTP", "gui.computercraft.config.http.bandwidth": "Bandwidth", "gui.computercraft.config.http.bandwidth.global_download": "Global download limit", - "gui.computercraft.config.http.bandwidth.global_download.tooltip": "The number of bytes which can be downloaded in a second. This is shared across all computers. (bytes/s).\nRange: > 1", + "gui.computercraft.config.http.bandwidth.global_download.tooltip": "The number of bytes which can be downloaded in a second. This is shared across all computers. (bytes/s).", "gui.computercraft.config.http.bandwidth.global_upload": "Global upload limit", - "gui.computercraft.config.http.bandwidth.global_upload.tooltip": "The number of bytes which can be uploaded in a second. This is shared across all computers. (bytes/s).\nRange: > 1", + "gui.computercraft.config.http.bandwidth.global_upload.tooltip": "The number of bytes which can be uploaded in a second. This is shared across all computers. (bytes/s).", "gui.computercraft.config.http.bandwidth.tooltip": "Limits bandwidth used by computers.", "gui.computercraft.config.http.enabled": "Enable the HTTP API", "gui.computercraft.config.http.enabled.tooltip": "Enable the \"http\" API on Computers. Disabling this also disables the \"pastebin\" and\n\"wget\" programs, that many users rely on. It's recommended to leave this on and use\nthe \"rules\" config option to impose more fine-grained control.", "gui.computercraft.config.http.max_requests": "Maximum concurrent requests", - "gui.computercraft.config.http.max_requests.tooltip": "The number of http requests a computer can make at one time. Additional requests\nwill be queued, and sent when the running requests have finished. Set to 0 for\nunlimited.\nRange: > 0", + "gui.computercraft.config.http.max_requests.tooltip": "The number of http requests a computer can make at one time. Additional requests\nwill be queued, and sent when the running requests have finished. Set to 0 for\nunlimited.", "gui.computercraft.config.http.max_websockets": "Maximum concurrent websockets", - "gui.computercraft.config.http.max_websockets.tooltip": "The number of websockets a computer can have open at one time.\nRange: > 1", + "gui.computercraft.config.http.max_websockets.tooltip": "The number of websockets a computer can have open at one time.", "gui.computercraft.config.http.proxy": "Proxy", "gui.computercraft.config.http.proxy.host": "Host name", "gui.computercraft.config.http.proxy.host.tooltip": "The hostname or IP address of the proxy server.", "gui.computercraft.config.http.proxy.port": "Port", - "gui.computercraft.config.http.proxy.port.tooltip": "The port of the proxy server.\nRange: 1 ~ 65536", + "gui.computercraft.config.http.proxy.port.tooltip": "The port of the proxy server.", "gui.computercraft.config.http.proxy.tooltip": "Tunnels HTTP and websocket requests through a proxy server. Only affects HTTP\nrules with \"use_proxy\" set to true (off by default).\nIf authentication is required for the proxy, create a \"computercraft-proxy.pw\"\nfile in the same directory as \"computercraft-server.toml\", containing the\nusername and password separated by a colon, e.g. \"myuser:mypassword\". For\nSOCKS4 proxies only the username is required.", "gui.computercraft.config.http.proxy.type": "Proxy type", - "gui.computercraft.config.http.proxy.type.tooltip": "The type of proxy to use.\nAllowed Values: HTTP, HTTPS, SOCKS4, SOCKS5", + "gui.computercraft.config.http.proxy.type.tooltip": "The type of proxy to use.", "gui.computercraft.config.http.rules": "Allow/deny rules", "gui.computercraft.config.http.rules.tooltip": "A list of rules which control behaviour of the \"http\" API for specific domains or\nIPs. Each rule matches against a hostname and an optional port, and then sets several\nproperties for the request. Rules are evaluated in order, meaning earlier rules override\nlater ones.\n\nValid properties:\n - \"host\" (required): The domain or IP address this rule matches. This may be a domain name\n (\"pastebin.com\"), wildcard (\"*.pastebin.com\") or CIDR notation (\"127.0.0.0/8\").\n - \"port\" (optional): Only match requests for a specific port, such as 80 or 443.\n\n - \"action\" (optional): Whether to allow or deny this request.\n - \"max_download\" (optional): The maximum size (in bytes) that a computer can download in this\n request.\n - \"max_upload\" (optional): The maximum size (in bytes) that a computer can upload in a this request.\n - \"max_websocket_message\" (optional): The maximum size (in bytes) that a computer can send or\n receive in one websocket packet.\n - \"use_proxy\" (optional): Enable use of the HTTP/SOCKS proxy if it is configured.", "gui.computercraft.config.http.tooltip": "Controls the HTTP API", @@ -120,61 +120,61 @@ "gui.computercraft.config.log_computer_errors": "Log computer errors", "gui.computercraft.config.log_computer_errors.tooltip": "Log exceptions thrown by peripherals and other Lua objects. This makes it easier\nfor mod authors to debug problems, but may result in log spam should people use\nbuggy methods.", "gui.computercraft.config.maximum_open_files": "Maximum files open per computer", - "gui.computercraft.config.maximum_open_files.tooltip": "Set how many files a computer can have open at the same time. Set to 0 for unlimited.\nRange: > 0", + "gui.computercraft.config.maximum_open_files.tooltip": "Set how many files a computer can have open at the same time. Set to 0 for unlimited.", "gui.computercraft.config.monitor_distance": "Monitor distance", - "gui.computercraft.config.monitor_distance.tooltip": "The maximum distance monitors will render at. This defaults to the standard tile\nentity limit, but may be extended if you wish to build larger monitors.\nRange: 16 ~ 1024", + "gui.computercraft.config.monitor_distance.tooltip": "The maximum distance monitors will render at. This defaults to the standard tile\nentity limit, but may be extended if you wish to build larger monitors.", "gui.computercraft.config.monitor_renderer": "Monitor renderer", - "gui.computercraft.config.monitor_renderer.tooltip": "The renderer to use for monitors. Generally this should be kept at \"best\" - if\nmonitors have performance issues, you may wish to experiment with alternative\nrenderers.\nAllowed Values: BEST, TBO, VBO", + "gui.computercraft.config.monitor_renderer.tooltip": "The renderer to use for monitors. Generally this should be kept at \"best\" - if\nmonitors have performance issues, you may wish to experiment with alternative\nrenderers.", "gui.computercraft.config.peripheral": "Peripherals", "gui.computercraft.config.peripheral.command_block_enabled": "Enable command block peripheral", "gui.computercraft.config.peripheral.command_block_enabled.tooltip": "Enable Command Block peripheral support", "gui.computercraft.config.peripheral.max_notes_per_tick": "Maximum notes that a computer can play at once", - "gui.computercraft.config.peripheral.max_notes_per_tick.tooltip": "Maximum amount of notes a speaker can play at once.\nRange: > 1", + "gui.computercraft.config.peripheral.max_notes_per_tick.tooltip": "Maximum amount of notes a speaker can play at once.", "gui.computercraft.config.peripheral.modem_high_altitude_range": "Modem range (high-altitude)", - "gui.computercraft.config.peripheral.modem_high_altitude_range.tooltip": "The range of Wireless Modems at maximum altitude in clear weather, in meters.\nRange: 0 ~ 100000", + "gui.computercraft.config.peripheral.modem_high_altitude_range.tooltip": "The range of Wireless Modems at maximum altitude in clear weather, in meters.", "gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm": "Modem range (high-altitude, bad weather)", - "gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm.tooltip": "The range of Wireless Modems at maximum altitude in stormy weather, in meters.\nRange: 0 ~ 100000", + "gui.computercraft.config.peripheral.modem_high_altitude_range_during_storm.tooltip": "The range of Wireless Modems at maximum altitude in stormy weather, in meters.", "gui.computercraft.config.peripheral.modem_range": "Modem range (default)", - "gui.computercraft.config.peripheral.modem_range.tooltip": "The range of Wireless Modems at low altitude in clear weather, in meters.\nRange: 0 ~ 100000", + "gui.computercraft.config.peripheral.modem_range.tooltip": "The range of Wireless Modems at low altitude in clear weather, in meters.", "gui.computercraft.config.peripheral.modem_range_during_storm": "Modem range (bad weather)", - "gui.computercraft.config.peripheral.modem_range_during_storm.tooltip": "The range of Wireless Modems at low altitude in stormy weather, in meters.\nRange: 0 ~ 100000", + "gui.computercraft.config.peripheral.modem_range_during_storm.tooltip": "The range of Wireless Modems at low altitude in stormy weather, in meters.", "gui.computercraft.config.peripheral.monitor_bandwidth": "Monitor bandwidth", - "gui.computercraft.config.peripheral.monitor_bandwidth.tooltip": "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\n smaller.\n - This ignores the number of players a packet is sent to. Updating a monitor for\n 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\n monitors to be updated in a single tick.\nSet to 0 to disable.\nRange: > 0", + "gui.computercraft.config.peripheral.monitor_bandwidth.tooltip": "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\n smaller.\n - This ignores the number of players a packet is sent to. Updating a monitor for\n 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\n monitors to be updated in a single tick.\nSet to 0 to disable.", "gui.computercraft.config.peripheral.tooltip": "Various options relating to peripherals.", "gui.computercraft.config.term_sizes": "Terminal sizes", "gui.computercraft.config.term_sizes.computer": "Computer", "gui.computercraft.config.term_sizes.computer.height": "Terminal height", - "gui.computercraft.config.term_sizes.computer.height.tooltip": "Range: 1 ~ 255", + "gui.computercraft.config.term_sizes.computer.height.tooltip": "Height of computer terminal", "gui.computercraft.config.term_sizes.computer.tooltip": "Terminal size of computers.", "gui.computercraft.config.term_sizes.computer.width": "Terminal width", - "gui.computercraft.config.term_sizes.computer.width.tooltip": "Range: 1 ~ 255", + "gui.computercraft.config.term_sizes.computer.width.tooltip": "Width of computer terminal", "gui.computercraft.config.term_sizes.monitor": "Monitor", "gui.computercraft.config.term_sizes.monitor.height": "Max monitor height", - "gui.computercraft.config.term_sizes.monitor.height.tooltip": "Range: 1 ~ 32", + "gui.computercraft.config.term_sizes.monitor.height.tooltip": "Maximum height of monitors", "gui.computercraft.config.term_sizes.monitor.tooltip": "Maximum size of monitors (in blocks).", "gui.computercraft.config.term_sizes.monitor.width": "Max monitor width", - "gui.computercraft.config.term_sizes.monitor.width.tooltip": "Range: 1 ~ 32", + "gui.computercraft.config.term_sizes.monitor.width.tooltip": "Maximum width of monitors", "gui.computercraft.config.term_sizes.pocket_computer": "Pocket Computer", "gui.computercraft.config.term_sizes.pocket_computer.height": "Terminal height", - "gui.computercraft.config.term_sizes.pocket_computer.height.tooltip": "Range: 1 ~ 255", + "gui.computercraft.config.term_sizes.pocket_computer.height.tooltip": "Height of pocket computer terminal", "gui.computercraft.config.term_sizes.pocket_computer.tooltip": "Terminal size of pocket computers.", "gui.computercraft.config.term_sizes.pocket_computer.width": "Terminal width", - "gui.computercraft.config.term_sizes.pocket_computer.width.tooltip": "Range: 1 ~ 255", + "gui.computercraft.config.term_sizes.pocket_computer.width.tooltip": "Width of pocket computer terminal", "gui.computercraft.config.term_sizes.tooltip": "Configure the size of various computer's terminals.\nLarger terminals require more bandwidth, so use with care.", "gui.computercraft.config.turtle": "Turtles", "gui.computercraft.config.turtle.advanced_fuel_limit": "Advanced Turtle fuel limit", - "gui.computercraft.config.turtle.advanced_fuel_limit.tooltip": "The fuel limit for Advanced Turtles.\nRange: > 0", + "gui.computercraft.config.turtle.advanced_fuel_limit.tooltip": "The fuel limit for Advanced Turtles.", "gui.computercraft.config.turtle.can_push": "Turtles can push entities", "gui.computercraft.config.turtle.can_push.tooltip": "If set to true, Turtles will push entities out of the way instead of stopping if\nthere is space to do so.", "gui.computercraft.config.turtle.need_fuel": "Enable fuel", "gui.computercraft.config.turtle.need_fuel.tooltip": "Set whether Turtles require fuel to move.", "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.normal_fuel_limit.tooltip": "The fuel limit for Turtles.", "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_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!", "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.config.upload_nag_delay.tooltip": "The delay in seconds after which we'll notify about unhandled imports. Set to 0 to disable.", "gui.computercraft.pocket_computer_overlay": "Pocket computer open. Press ESC to close.", "gui.computercraft.terminal": "Computer terminal", "gui.computercraft.tooltip.computer_id": "Computer ID: %s", diff --git a/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigFile.java b/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigFile.java index 7a55c8284d..7dc998520b 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigFile.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/config/ConfigFile.java @@ -9,9 +9,7 @@ import javax.annotation.Nullable; import javax.annotation.OverridingMethodsMustInvokeSuper; import java.nio.file.Path; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.List; +import java.util.*; import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Stream; @@ -19,27 +17,47 @@ /** * A config file which the user can modify. */ -public interface ConfigFile { - String TRANSLATION_PREFIX = "gui.computercraft.config."; - Splitter SPLITTER = Splitter.on('.'); +public abstract class ConfigFile { + public static final String TRANSLATION_PREFIX = "gui.computercraft.config."; + public static final Splitter SPLITTER = Splitter.on('.'); /** * An entry in the config file, either a {@link Value} or {@linkplain Group group of other entries}. */ - sealed interface Entry permits Group, Value { + public abstract static sealed class Entry permits Group, Value { + protected final String path; + private final String translationKey; + private final String comment; + + protected Entry(String path, String comment) { + this.path = path; + this.translationKey = TRANSLATION_PREFIX + path; + this.comment = comment; + } + + public final String path() { + return path; + } + /** * Get the translation key of this config entry. * * @return This entry's translation key. */ - String translationKey(); + public final String translationKey() { + return translationKey; + } /** * Get the comment about this config entry. * * @return The comment for this config entry. */ - String comment(); + public final String comment() { + return comment; + } + + abstract Stream entries(); } /** @@ -47,13 +65,38 @@ sealed interface Entry permits Group, Value { * * @param The type of the stored value. */ - non-sealed interface Value extends Entry, Supplier { + public abstract static non-sealed class Value extends Entry implements Supplier { + protected Value(String translationKey, String comment) { + super(translationKey, comment); + } + + @Override + Stream entries() { + return Stream.of(this); + } } /** * A group of config entries. */ - non-sealed interface Group extends Entry { + public static final class Group extends Entry { + private final Map children; + + public Group(String translationKey, String comment, Map children) { + super(translationKey, comment); + this.children = children; + } + + @Override + Stream entries() { + return Stream.concat(Stream.of(this), children.values().stream().flatMap(Entry::entries)); + } + } + + protected final Map entries; + + protected ConfigFile(Map entries) { + this.entries = entries; } /** @@ -61,16 +104,46 @@ non-sealed interface Group extends Entry { * * @return All config keys. */ - Stream entries(); + public final Stream entries() { + return entries.values().stream().flatMap(Entry::entries); + } + + public final @Nullable Entry getEntry(String path) { + var iterator = SPLITTER.split(path).iterator(); - @Nullable - Entry getEntry(String path); + var entry = entries.get(iterator.next()); + while (iterator.hasNext()) { + if (!(entry instanceof Group group)) return null; + entry = group.children.get(iterator.next()); + } + + return entry; + } /** * A builder which can be used to generate a config object. */ - abstract class Builder { - protected final Deque groupStack = new ArrayDeque<>(); + public abstract static class Builder { + protected record RootGroup(String path, Map children) { + public RootGroup { + } + } + + protected final Deque groupStack = new ArrayDeque<>(); + private @Nullable String pendingComment; + + protected Builder() { + groupStack.addLast(new RootGroup("", new HashMap<>())); + } + + protected final String getPath() { + return groupStack.getLast().path(); + } + + protected final String getPath(String name) { + var path = groupStack.getLast().path(); + return path.isEmpty() ? name : path + "." + name; + } protected String getTranslation(String name) { var key = new StringBuilder(TRANSLATION_PREFIX); @@ -86,7 +159,19 @@ protected String getTranslation(String name) { * @param comment The comment. * @return The current object, for chaining. */ - public abstract Builder comment(String comment); + @OverridingMethodsMustInvokeSuper + public ConfigFile.Builder comment(String comment) { + if (pendingComment != null) throw new IllegalStateException("Already have a comment"); + pendingComment = comment; + return this; + } + + protected String takeComment() { + var comment = pendingComment; + if (comment == null) throw new IllegalStateException("No comment specified"); + pendingComment = null; + return comment; + } /** * Push a new config group. @@ -95,7 +180,10 @@ protected String getTranslation(String name) { */ @OverridingMethodsMustInvokeSuper public void push(String name) { - groupStack.addLast(name); + var path = getPath(name); + Map children = new HashMap<>(); + groupStack.getLast().children().put(name, new Group(path, takeComment(), children)); + groupStack.addLast(new RootGroup(path, children)); } /** @@ -113,22 +201,22 @@ public void pop() { */ public abstract Builder worldRestart(); - public abstract ConfigFile.Value define(String path, T defaultValue); + public abstract ConfigFile.Value define(String name, T defaultValue); /** * A boolean-specific override of the above {@link #define(String, Object)} method. * - * @param path The path to the value we're defining. + * @param name The name of the value we're defining. * @param defaultValue The default value. * @return The accessor for this config option. */ - public abstract ConfigFile.Value define(String path, boolean defaultValue); + public abstract ConfigFile.Value define(String name, boolean defaultValue); - public abstract ConfigFile.Value defineInRange(String path, int defaultValue, int min, int max); + public abstract ConfigFile.Value defineInRange(String name, int defaultValue, int min, int max); - public abstract ConfigFile.Value> defineList(String path, List defaultValue, Predicate elementValidator); + public abstract ConfigFile.Value> defineList(String name, List defaultValue, Predicate elementValidator); - public abstract > ConfigFile.Value defineEnum(String path, V defaultValue); + public abstract > ConfigFile.Value defineEnum(String name, V defaultValue); /** * Finalise this config file. @@ -140,7 +228,7 @@ public void pop() { } @FunctionalInterface - interface ConfigListener { + public interface ConfigListener { /** * The function called then a config file is changed. * 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 0be520ba5c..eaa17523aa 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 @@ -344,18 +344,18 @@ or a single method (computercraft:inventory#pushItems). .push("term_sizes"); builder.comment("Terminal size of computers.").push("computer"); - computerTermWidth = builder.defineInRange("width", Config.computerTermWidth, 1, 255); - computerTermHeight = builder.defineInRange("height", Config.computerTermHeight, 1, 255); + computerTermWidth = builder.comment("Width of computer terminal").defineInRange("width", Config.computerTermWidth, 1, 255); + computerTermHeight = builder.comment("Height of computer terminal").defineInRange("height", Config.computerTermHeight, 1, 255); builder.pop(); builder.comment("Terminal size of pocket computers.").push("pocket_computer"); - pocketTermWidth = builder.defineInRange("width", Config.pocketTermWidth, 1, 255); - pocketTermHeight = builder.defineInRange("height", Config.pocketTermHeight, 1, 255); + pocketTermWidth = builder.comment("Width of pocket computer terminal").defineInRange("width", Config.pocketTermWidth, 1, 255); + pocketTermHeight = builder.comment("Height of pocket computer terminal").defineInRange("height", Config.pocketTermHeight, 1, 255); builder.pop(); builder.comment("Maximum size of monitors (in blocks).").push("monitor"); - monitorWidth = builder.defineInRange("width", Config.monitorWidth, 1, 32); - monitorHeight = builder.defineInRange("height", Config.monitorHeight, 1, 32); + monitorWidth = builder.comment("Maximum width of monitors").defineInRange("width", Config.monitorWidth, 1, 32); + monitorHeight = builder.comment("Maximum height of monitors").defineInRange("height", Config.monitorHeight, 1, 32); builder.pop(); builder.pop(); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/util/Trie.java b/projects/common/src/main/java/dan200/computercraft/shared/util/Trie.java deleted file mode 100644 index 70037585b7..0000000000 --- a/projects/common/src/main/java/dan200/computercraft/shared/util/Trie.java +++ /dev/null @@ -1,46 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.shared.util; - -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Stream; - -/** - * A key-value map, where the key is a list of values. - * - * @param The type of keys in this trie. - * @param The values in this map. - */ -public class Trie { - private @Nullable V current; - private @Nullable Map> children; - - public Trie getChild(Iterable key) { - var self = this; - for (var keyElement : key) { - if (self.children == null) self.children = new HashMap<>(1); - self = self.children.computeIfAbsent(keyElement, x -> new Trie<>()); - } - - return self; - } - - public @Nullable V getValue(Iterable key) { - return getChild(key).current; - } - - public void setValue(Iterable key, V value) { - getChild(key).current = value; - } - - public Stream stream() { - return Stream.concat( - current == null ? Stream.empty() : Stream.of(current), - children == null ? Stream.empty() : children.values().stream().flatMap(Trie::stream) - ); - } -} diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricConfigFile.java b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricConfigFile.java index 0536d8e279..b31f6ba2ba 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricConfigFile.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/FabricConfigFile.java @@ -11,7 +11,6 @@ import com.electronwill.nightconfig.core.io.WritingMode; import com.google.errorprone.annotations.concurrent.GuardedBy; import dan200.computercraft.shared.config.ConfigFile; -import dan200.computercraft.shared.util.Trie; import org.apache.commons.lang3.function.TriFunction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -22,6 +21,7 @@ import java.nio.file.Path; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -29,18 +29,17 @@ /** * A {@link ConfigFile} which sits directly on top of NightConfig. */ -public class FabricConfigFile implements ConfigFile { +public final class FabricConfigFile extends ConfigFile { private static final Logger LOG = LoggerFactory.getLogger(FabricConfigFile.class); private final ConfigSpec spec; - private final Trie entries; private final ConfigListener onChange; private @Nullable CommentedFileConfig config; - public FabricConfigFile(ConfigSpec spec, Trie entries, ConfigListener onChange) { + private FabricConfigFile(ConfigSpec spec, Map entries, ConfigListener onChange) { + super(entries); this.spec = spec; - this.entries = entries; this.onChange = onChange; } @@ -64,7 +63,7 @@ public synchronized void load(Path path) { @SuppressWarnings("unchecked") private Stream> values() { - return (Stream>) (Stream) entries.stream().filter(ValueImpl.class::isInstance); + return (Stream>) (Stream) entries().filter(ValueImpl.class::isInstance); } public synchronized void unload() { @@ -92,7 +91,7 @@ private synchronized boolean loadConfig() { // Ensure the config file matches the spec var isNewFile = config.isEmpty(); - entries.stream().forEach(x -> config.setComment(x.path, x.comment)); + entries().forEach(x -> config.setComment(x.path(), x instanceof ValueImpl v ? v.fullComment : x.comment())); var corrected = isNewFile ? spec.correct(config) : spec.correct(config, (action, entryPath, oldValue, newValue) -> { LOG.warn("Incorrect key {} was corrected from {} to {}", String.join(".", entryPath), oldValue, newValue); }); @@ -104,148 +103,77 @@ private synchronized boolean loadConfig() { return corrected > 0; } - @Override - public Stream entries() { - return entries.stream().map(x -> (ConfigFile.Entry) x); - } - - @Nullable - @Override - public ConfigFile.Entry getEntry(String path) { - return (ConfigFile.Entry) entries.getValue(SPLITTER.split(path)); - } - static class Builder extends ConfigFile.Builder { private final ConfigSpec spec = new ConfigSpec(); - private final Trie entries = new Trie<>(); - - private @Nullable String pendingComment; - - private String getFullPath(String path) { - var key = new StringBuilder(); - for (var group : groupStack) key.append(group).append('.'); - key.append(path); - return key.toString(); - } - - @Override - public ConfigFile.Builder comment(String comment) { - if (pendingComment != null) throw new IllegalStateException("Already have a comment"); - pendingComment = comment; - return this; - } - - private String takeComment() { - var comment = pendingComment; - if (comment == null) throw new IllegalStateException("No comment specified"); - pendingComment = null; - return comment; - } - - private String takeComment(String suffix) { - var comment = pendingComment == null ? "" : pendingComment + "\n"; - pendingComment = null; - return comment + suffix; - } - - @Override - public void push(String name) { - var path = getFullPath(name); - var splitPath = SPLITTER.split(path); - entries.setValue(splitPath, new GroupImpl(path, takeComment())); - - super.push(name); - } @Override public ConfigFile.Builder worldRestart() { return this; } - private Value defineValue(String fullPath, String comment, T defaultValue, TriFunction getter) { - var value = new ValueImpl(fullPath, comment, defaultValue, getter); - entries.setValue(SPLITTER.split(fullPath), value); + private Value defineValue(String name, String comment, @Nullable String suffix, T defaultValue, TriFunction getter) { + var fullComment = suffix == null ? comment : comment + "\n" + suffix; + var value = new ValueImpl(getPath(name), comment, fullComment, defaultValue, getter); + groupStack.getLast().children().put(name, value); return value; } @Override - public Value define(String path, T defaultValue) { - var fullPath = getFullPath(path); - spec.define(fullPath, defaultValue); - return defineValue(fullPath, takeComment(), defaultValue, Config::getOrElse); + public Value define(String name, T defaultValue) { + var path = getPath(name); + spec.define(path, defaultValue); + return defineValue(name, takeComment(), null, defaultValue, Config::getOrElse); } @Override - public Value define(String path, boolean defaultValue) { - var fullPath = getFullPath(path); - spec.define(fullPath, defaultValue, x -> x instanceof Boolean); - return defineValue(fullPath, takeComment(), defaultValue, UnmodifiableConfig::getOrElse); + public Value define(String name, boolean defaultValue) { + var path = getPath(name); + spec.define(path, defaultValue, x -> x instanceof Boolean); + return defineValue(name, takeComment(), null, defaultValue, UnmodifiableConfig::getOrElse); } @Override - public Value defineInRange(String path, int defaultValue, int min, int max) { - var fullPath = getFullPath(path); - spec.defineInRange(fullPath, defaultValue, min, max); + public Value defineInRange(String name, int defaultValue, int min, int max) { + var path = getPath(name); + spec.defineInRange(path, defaultValue, min, max); var suffix = max == Integer.MAX_VALUE ? "Range: > " + min : "Range: " + min + " ~ " + max; - return defineValue(fullPath, takeComment(suffix), defaultValue, UnmodifiableConfig::getIntOrElse); + return defineValue(name, takeComment(), suffix, defaultValue, UnmodifiableConfig::getIntOrElse); } @Override - public Value> defineList(String path, List defaultValue, Predicate elementValidator) { - var fullPath = getFullPath(path); - spec.defineList(fullPath, defaultValue, elementValidator); - return defineValue(fullPath, takeComment(), defaultValue, Config::getOrElse); + public Value> defineList(String name, List defaultValue, Predicate elementValidator) { + var path = getPath(name); + spec.defineList(path, defaultValue, elementValidator); + return defineValue(name, takeComment(), null, defaultValue, Config::getOrElse); } @Override - public > Value defineEnum(String path, V defaultValue) { - var fullPath = getFullPath(path); - spec.define(fullPath, defaultValue, o -> o != null && o != NullObject.NULL_OBJECT && EnumGetMethod.NAME_IGNORECASE.validate(o, defaultValue.getDeclaringClass())); + public > Value defineEnum(String name, V defaultValue) { + var path = getPath(name); + spec.define(path, defaultValue, o -> o != null && o != NullObject.NULL_OBJECT && EnumGetMethod.NAME_IGNORECASE.validate(o, defaultValue.getDeclaringClass())); var suffix = "Allowed Values: " + Arrays.stream(defaultValue.getDeclaringClass().getEnumConstants()).map(Enum::name).collect(Collectors.joining(", ")); - return defineValue(fullPath, takeComment(suffix), defaultValue, (c, p, d) -> c.getEnumOrElse(p, d, EnumGetMethod.NAME_IGNORECASE)); + return defineValue(name, takeComment(), suffix, defaultValue, (c, p, d) -> c.getEnumOrElse(p, d, EnumGetMethod.NAME_IGNORECASE)); } @Override public ConfigFile build(ConfigListener onChange) { - return new FabricConfigFile(spec, entries, onChange); - } - } - - private static class Entry { - final String path; - final String comment; - - Entry(String path, String comment) { - this.path = path; - this.comment = comment; - } - - @SuppressWarnings("UnusedMethod") - public final String translationKey() { - return TRANSLATION_PREFIX + path; - } - - @SuppressWarnings("UnusedMethod") - public final String comment() { - return comment; - } - } - - private static final class GroupImpl extends Entry implements Group { - private GroupImpl(String path, String comment) { - super(path, comment); + var children = groupStack.removeLast().children(); + if (!groupStack.isEmpty()) throw new IllegalStateException("Mismatched config push/pop"); + return new FabricConfigFile(spec, children, onChange); } } - private static final class ValueImpl extends Entry implements Value { + private static final class ValueImpl extends Value { private @Nullable T value; private final T defaultValue; private final TriFunction get; + private final String fullComment; - private ValueImpl(String path, String comment, T defaultValue, TriFunction get) { + private ValueImpl(String path, String comment, String fullComment, T defaultValue, TriFunction get) { super(path, comment); + this.fullComment = fullComment; this.defaultValue = defaultValue; this.get = get; } diff --git a/projects/forge/src/main/java/dan200/computercraft/shared/platform/ForgeConfigFile.java b/projects/forge/src/main/java/dan200/computercraft/shared/platform/ForgeConfigFile.java index ca74c4a9b8..07bfab3c18 100644 --- a/projects/forge/src/main/java/dan200/computercraft/shared/platform/ForgeConfigFile.java +++ b/projects/forge/src/main/java/dan200/computercraft/shared/platform/ForgeConfigFile.java @@ -5,48 +5,32 @@ package dan200.computercraft.shared.platform; import dan200.computercraft.shared.config.ConfigFile; -import dan200.computercraft.shared.util.Trie; import net.minecraftforge.common.ForgeConfigSpec; -import javax.annotation.Nullable; -import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.function.Predicate; -import java.util.stream.Stream; /** * A {@link ConfigFile} which wraps Forge's config implementation. */ -public final class ForgeConfigFile implements ConfigFile { +public final class ForgeConfigFile extends ConfigFile { private final ForgeConfigSpec spec; - private final Trie entries; - public ForgeConfigFile(ForgeConfigSpec spec, Trie entries) { + private ForgeConfigFile(ForgeConfigSpec spec, Map entries) { + super(entries); this.spec = spec; - this.entries = entries; } public ForgeConfigSpec spec() { return spec; } - @Override - public Stream entries() { - return entries.stream(); - } - - @Nullable - @Override - public Entry getEntry(String path) { - return entries.getValue(SPLITTER.split(path)); - } - /** * Wraps {@link ForgeConfigSpec.Builder} into our own config builder abstraction. */ static class Builder extends ConfigFile.Builder { private final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); - private final Trie entries = new Trie<>(); private void translation(String name) { builder.translation(getTranslation(name)); @@ -54,24 +38,23 @@ private void translation(String name) { @Override public ConfigFile.Builder comment(String comment) { + super.comment(comment); builder.comment(comment); return this; } @Override public void push(String name) { + super.push(name); + translation(name); builder.push(name); - super.push(name); } @Override public void pop() { - var path = new ArrayList<>(groupStack); - entries.setValue(path, new GroupImpl(path)); - - builder.pop(); super.pop(); + builder.pop(); } @Override @@ -80,100 +63,63 @@ public ConfigFile.Builder worldRestart() { return this; } - private ConfigFile.Value defineValue(ForgeConfigSpec.ConfigValue value) { - var wrapped = new ValueImpl<>(value); - entries.setValue(value.getPath(), wrapped); + private ConfigFile.Value defineValue(String name, ForgeConfigSpec.ConfigValue value) { + var wrapped = new ValueImpl<>(getPath(name), takeComment(), value); + groupStack.getLast().children().put(name, wrapped); return wrapped; } @Override - public ConfigFile.Value define(String path, T defaultValue) { - translation(path); - return defineValue(builder.define(path, defaultValue)); + public ConfigFile.Value define(String name, T defaultValue) { + translation(name); + return defineValue(name, builder.define(name, defaultValue)); } @Override - public ConfigFile.Value define(String path, boolean defaultValue) { - translation(path); - return defineValue(builder.define(path, defaultValue)); + public ConfigFile.Value define(String name, boolean defaultValue) { + translation(name); + return defineValue(name, builder.define(name, defaultValue)); } @Override - public ConfigFile.Value defineInRange(String path, int defaultValue, int min, int max) { - translation(path); - return defineValue(builder.defineInRange(path, defaultValue, min, max)); + public ConfigFile.Value defineInRange(String name, int defaultValue, int min, int max) { + translation(name); + return defineValue(name, builder.defineInRange(name, defaultValue, min, max)); } @Override - public ConfigFile.Value> defineList(String path, List defaultValue, Predicate elementValidator) { - translation(path); - return defineValue(builder.defineList(path, defaultValue, elementValidator)); + public ConfigFile.Value> defineList(String name, List defaultValue, Predicate elementValidator) { + translation(name); + return defineValue(name, builder.defineList(name, defaultValue, elementValidator)); } @Override - public > ConfigFile.Value defineEnum(String path, V defaultValue) { - translation(path); - return defineValue(builder.defineEnum(path, defaultValue)); + public > ConfigFile.Value defineEnum(String name, V defaultValue) { + translation(name); + return defineValue(name, builder.defineEnum(name, defaultValue)); } @Override public ConfigFile build(ConfigListener onChange) { - var spec = builder.build(); - entries.stream().forEach(x -> { - if (x instanceof ValueImpl value) value.owner = spec; - if (x instanceof GroupImpl value) value.owner = spec; - }); - return new ForgeConfigFile(spec, entries); - } - } - - private static final class GroupImpl implements ConfigFile.Group { - private final List path; - private @Nullable ForgeConfigSpec owner; + var children = groupStack.removeLast().children(); + if (!groupStack.isEmpty()) throw new IllegalStateException("Mismatched config push/pop"); - private GroupImpl(List path) { - this.path = path; - } - - @Override - public String translationKey() { - if (owner == null) throw new IllegalStateException("Config has not been built yet"); - return owner.getLevelTranslationKey(path); - } - - @Override - public String comment() { - if (owner == null) throw new IllegalStateException("Config has not been built yet"); - return owner.getLevelComment(path); + var spec = builder.build(); + return new ForgeConfigFile(spec, children); } } - private static final class ValueImpl implements ConfigFile.Value { + private static final class ValueImpl extends Value { private final ForgeConfigSpec.ConfigValue value; - private @Nullable ForgeConfigSpec owner; - private ValueImpl(ForgeConfigSpec.ConfigValue value) { + private ValueImpl(String path, String comment, ForgeConfigSpec.ConfigValue value) { + super(path, comment); this.value = value; } - private ForgeConfigSpec.ValueSpec spec() { - if (owner == null) throw new IllegalStateException("Config has not been built yet"); - return owner.getSpec().get(value.getPath()); - } - @Override public T get() { return value.get(); } - - @Override - public String translationKey() { - return spec().getTranslationKey(); - } - - @Override - public String comment() { - return spec().getComment(); - } } } From fdb65c93685cd34e0e7abe44fc0b9d2e248df4b6 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Thu, 28 Nov 2024 10:31:36 +0000 Subject: [PATCH 2/4] Link to monitor events from the main monitor page --- doc/events/monitor_resize.md | 2 +- doc/events/monitor_touch.md | 2 +- .../shared/peripheral/monitor/MonitorPeripheral.java | 9 ++++++++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/doc/events/monitor_resize.md b/doc/events/monitor_resize.md index 0bd4ef98ee..bbc72be080 100644 --- a/doc/events/monitor_resize.md +++ b/doc/events/monitor_resize.md @@ -8,7 +8,7 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers SPDX-License-Identifier: MPL-2.0 --> -The [`monitor_resize`] event is fired when an adjacent or networked monitor's size is changed. +The [`monitor_resize`] event is fired when an adjacent or networked [monitor's][`monitor`] size is changed. ## Return Values 1. [`string`]: The event name. diff --git a/doc/events/monitor_touch.md b/doc/events/monitor_touch.md index 400b57881d..099ffd7192 100644 --- a/doc/events/monitor_touch.md +++ b/doc/events/monitor_touch.md @@ -8,7 +8,7 @@ SPDX-FileCopyrightText: 2021 The CC: Tweaked Developers SPDX-License-Identifier: MPL-2.0 --> -The [`monitor_touch`] event is fired when an adjacent or networked Advanced Monitor is right-clicked. +The [`monitor_touch`] event is fired when an adjacent or networked [Advanced Monitor][`monitor`] is right-clicked. ## Return Values 1. [`string`]: The event name. diff --git a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java index 8e44aa0e0c..c07bfb41ee 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/peripheral/monitor/MonitorPeripheral.java @@ -21,7 +21,11 @@ * Monitors act as [terminal redirects][`term.Redirect`] and so expose the same methods, as well as several additional * ones, which are documented below. *

- * Like computers, monitors come in both normal (no colour) and advanced (colour) varieties. + * If the monitor is resized (by adding new blocks to the monitor, or by calling {@link setTextScale}), then a + * [`monitor_resize`] event will be queued. + *

+ * Like computers, monitors come in both normal (no colour) and advanced (colour) varieties. Advanced monitors be right + * clicked, which will trigger a [`monitor_touch`] event. *

* ## Recipes *

@@ -37,6 +41,9 @@ * monitor.setCursorPos(1, 1) * monitor.write("Hello, world!") * } + * + * @cc.see monitor_resize Queued when a monitor is resized. + * @cc.see monitor_touch Queued when an advanced monitor is clicked. */ public class MonitorPeripheral extends TermMethods implements IPeripheral { private final MonitorBlockEntity monitor; From 7c02979c2200b18c38cdf3585c2c59f5f8987281 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sat, 30 Nov 2024 12:07:55 +0000 Subject: [PATCH 3/4] Upload jars in CI earlier This means they're uploaded even if the linters or tests fail. --- .github/workflows/main-ci.yml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/main-ci.yml b/.github/workflows/main-ci.yml index 3da0267261..6d3675c455 100644 --- a/.github/workflows/main-ci.yml +++ b/.github/workflows/main-ci.yml @@ -30,6 +30,18 @@ jobs: - name: ⚒️ Build run: ./gradlew assemble || ./gradlew assemble + - name: 📦 Prepare Jars + run: | + # Find the main jar and append the git hash onto it. + mkdir -p jars + find projects/forge/build/libs projects/fabric/build/libs -type f -regex '.*[0-9.]+\(-SNAPSHOT\)?\.jar$' -exec bash -c 'cp {} "jars/$(basename {} .jar)-$(git rev-parse HEAD).jar"' \; + + - name: 📤 Upload Jar + uses: actions/upload-artifact@v4 + with: + name: CC-Tweaked + path: ./jars + - name: Cache pre-commit uses: actions/cache@v4 with: @@ -54,18 +66,6 @@ jobs: run: ./tools/parse-reports.py if: ${{ failure() }} - - name: 📦 Prepare Jars - run: | - # Find the main jar and append the git hash onto it. - mkdir -p jars - find projects/forge/build/libs projects/fabric/build/libs -type f -regex '.*[0-9.]+\(-SNAPSHOT\)?\.jar$' -exec bash -c 'cp {} "jars/$(basename {} .jar)-$(git rev-parse HEAD).jar"' \; - - - name: 📤 Upload Jar - uses: actions/upload-artifact@v4 - with: - name: CC-Tweaked - path: ./jars - build-core: strategy: fail-fast: false From 9bbf3f3e1d1e927cc894ba583971664868a4eb88 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Thu, 5 Dec 2024 11:58:03 +0000 Subject: [PATCH 4/4] Move datagen to its own source set MC 1.21.4 means we have to move more data generation code into the client source set. Given all this code movement, it probably makes sense to put data generation in a separate source set instead. 1.21.4 also has split data generators for client and server, but neither mod loader recommends this. This means we can/should merge DataProviders and ClientDataProviders into a single class. Data generators are no longer bundled with the jar, which does reduce file size, but by a tiny amount (~70KiB). --- REUSE.toml | 2 +- ...t.gradle.kts => cc-tweaked.mod.gradle.kts} | 24 +++++---- .../cc/tweaked/gradle/CCTweakedExtension.kt | 7 ++- projects/common/build.gradle.kts | 2 +- .../computercraft/client/gui/GuiSprites.java | 2 - .../data/client/ClientDataProviders.java | 50 ------------------- .../data/BlockModelProvider.java | 0 .../computercraft/data/DataProviders.java | 43 +++++++++++++--- .../computercraft/data/ItemModelProvider.java | 0 .../computercraft/data/LanguageProvider.java | 0 .../computercraft/data/LootTableProvider.java | 0 .../computercraft/data/ModelProvider.java | 0 .../data/PocketUpgradeProvider.java | 0 .../data/PrettyDataProvider.java | 1 + .../computercraft/data/RecipeProvider.java | 0 .../computercraft/data/RecipeWrapper.java | 0 .../computercraft/data/TagProvider.java | 2 +- .../data/TurtleUpgradeProvider.java | 0 .../util}/PrettyJsonWriter.java | 4 +- .../dan200/computercraft/export/Exporter.java | 2 +- projects/fabric/build.gradle.kts | 4 +- .../data/FabricDataProviders.java} | 2 +- .../data/MoreConventionalTagsProvider.java | 0 .../src/datagen/resources/fabric.mod.json | 13 +++++ .../fabric/src/main/resources/fabric.mod.json | 3 -- .../src/testMod/resources/fabric.mod.json | 2 +- projects/forge/build.gradle.kts | 6 ++- .../data/ForgeDataProviders.java} | 2 +- 28 files changed, 84 insertions(+), 87 deletions(-) rename buildSrc/src/main/kotlin/{cc-tweaked.gametest.gradle.kts => cc-tweaked.mod.gradle.kts} (67%) delete mode 100644 projects/common/src/client/java/dan200/computercraft/data/client/ClientDataProviders.java rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/BlockModelProvider.java (100%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/DataProviders.java (55%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/ItemModelProvider.java (100%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/LanguageProvider.java (100%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/LootTableProvider.java (100%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/ModelProvider.java (100%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/PocketUpgradeProvider.java (100%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/PrettyDataProvider.java (96%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/RecipeProvider.java (100%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/RecipeWrapper.java (100%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/TagProvider.java (98%) rename projects/common/src/{main => datagen}/java/dan200/computercraft/data/TurtleUpgradeProvider.java (100%) rename projects/common/src/main/java/dan200/computercraft/{data => shared/util}/PrettyJsonWriter.java (99%) rename projects/fabric/src/{main/java/dan200/computercraft/data/FabricDataGenerators.java => datagen/java/dan200/computercraft/data/FabricDataProviders.java} (98%) rename projects/fabric/src/{main => datagen}/java/dan200/computercraft/data/MoreConventionalTagsProvider.java (100%) create mode 100644 projects/fabric/src/datagen/resources/fabric.mod.json rename projects/forge/src/{main/java/dan200/computercraft/data/Generators.java => datagen/java/dan200/computercraft/data/ForgeDataProviders.java} (99%) diff --git a/REUSE.toml b/REUSE.toml index 401bf6c60e..0c43beba15 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -40,8 +40,8 @@ path = [ "projects/core/src/main/resources/data/computercraft/lua/rom/modules/main/.ignoreme", "projects/core/src/main/resources/data/computercraft/lua/rom/modules/turtle/.ignoreme", "projects/core/src/main/resources/data/computercraft/lua/rom/motd.txt", - "projects/fabric-api/src/main/modJson/fabric.mod.json", "projects/fabric/src/client/resources/computercraft-client.fabric.mixins.json", + "projects/fabric/src/datagen/resources/fabric.mod.json", "projects/fabric/src/main/resources/computercraft.fabric.mixins.json", "projects/fabric/src/main/resources/fabric.mod.json", "projects/fabric/src/testMod/resources/computercraft-gametest.fabric.mixins.json", diff --git a/buildSrc/src/main/kotlin/cc-tweaked.gametest.gradle.kts b/buildSrc/src/main/kotlin/cc-tweaked.mod.gradle.kts similarity index 67% rename from buildSrc/src/main/kotlin/cc-tweaked.gametest.gradle.kts rename to buildSrc/src/main/kotlin/cc-tweaked.mod.gradle.kts index 712b5e857b..fb12f8120f 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.gametest.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.mod.gradle.kts @@ -19,26 +19,32 @@ plugins { val main = sourceSets["main"] val client = sourceSets["client"] -// Both testMod and testFixtures inherit from the main and client classpath, just so we have access to Minecraft classes. +// datagen and testMod inherit from the main and client classpath, just so we have access to Minecraft classes. +val datagen by sourceSets.creating { + compileClasspath += main.compileClasspath + client.compileClasspath + runtimeClasspath += main.runtimeClasspath + client.runtimeClasspath +} + val testMod by sourceSets.creating { compileClasspath += main.compileClasspath + client.compileClasspath runtimeClasspath += main.runtimeClasspath + client.runtimeClasspath } -configurations { - named(testMod.compileClasspathConfigurationName) { - shouldResolveConsistentlyWith(compileClasspath.get()) - } +val extraConfigurations = listOf(datagen, testMod) - named(testMod.runtimeClasspathConfigurationName) { - shouldResolveConsistentlyWith(runtimeClasspath.get()) +configurations { + for (config in extraConfigurations) { + named(config.compileClasspathConfigurationName) { shouldResolveConsistentlyWith(compileClasspath.get()) } + named(config.runtimeClasspathConfigurationName) { shouldResolveConsistentlyWith(runtimeClasspath.get()) } } } // Like the main test configurations, we're safe to depend on source set outputs. dependencies { - add(testMod.implementationConfigurationName, main.output) - add(testMod.implementationConfigurationName, client.output) + for (config in extraConfigurations) { + add(config.implementationConfigurationName, main.output) + add(config.implementationConfigurationName, client.output) + } } // Similar to java-test-fixtures, but tries to avoid putting the obfuscated jar on the classpath. diff --git a/buildSrc/src/main/kotlin/cc/tweaked/gradle/CCTweakedExtension.kt b/buildSrc/src/main/kotlin/cc/tweaked/gradle/CCTweakedExtension.kt index 70b3d1f3e9..0124fee5ce 100644 --- a/buildSrc/src/main/kotlin/cc/tweaked/gradle/CCTweakedExtension.kt +++ b/buildSrc/src/main/kotlin/cc/tweaked/gradle/CCTweakedExtension.kt @@ -109,14 +109,13 @@ abstract class CCTweakedExtension( val otherJava = otherProject.extensions.getByType(JavaPluginExtension::class.java) val main = otherJava.sourceSets.getByName("main") val client = otherJava.sourceSets.getByName("client") - val testMod = otherJava.sourceSets.findByName("testMod") - val testFixtures = otherJava.sourceSets.findByName("testFixtures") // Pull in sources from the other project. extendSourceSet(otherProject, main) extendSourceSet(otherProject, client) - if (testMod != null) extendSourceSet(otherProject, testMod) - if (testFixtures != null) extendSourceSet(otherProject, testFixtures) + for (sourceSet in listOf("datagen", "testMod", "testFixtures")) { + otherJava.sourceSets.findByName(sourceSet)?.let { extendSourceSet(otherProject, it) } + } // The extra source-processing tasks should include these files too. project.tasks.named(main.javadocTaskName, Javadoc::class.java) { source(main.allJava, client.allJava) } diff --git a/projects/common/build.gradle.kts b/projects/common/build.gradle.kts index 6599ee140a..7826e59daf 100644 --- a/projects/common/build.gradle.kts +++ b/projects/common/build.gradle.kts @@ -6,8 +6,8 @@ import cc.tweaked.gradle.* plugins { id("cc-tweaked.vanilla") - id("cc-tweaked.gametest") id("cc-tweaked.illuaminate") + id("cc-tweaked.mod") id("cc-tweaked.publishing") } diff --git a/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java b/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java index 63b152dfef..ffed5a1af4 100644 --- a/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java +++ b/projects/common/src/client/java/dan200/computercraft/client/gui/GuiSprites.java @@ -6,7 +6,6 @@ import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.client.render.ComputerBorderRenderer; -import dan200.computercraft.data.client.ClientDataProviders; import dan200.computercraft.shared.computer.core.ComputerFamily; import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.renderer.texture.TextureManager; @@ -113,7 +112,6 @@ public Stream textures() { * @param pocketBottom The texture for the bottom of a pocket computer. * @param sidebar The texture for the computer sidebar. * @see ComputerBorderRenderer - * @see ClientDataProviders */ public record ComputerTextures( ResourceLocation border, diff --git a/projects/common/src/client/java/dan200/computercraft/data/client/ClientDataProviders.java b/projects/common/src/client/java/dan200/computercraft/data/client/ClientDataProviders.java deleted file mode 100644 index b318826d0e..0000000000 --- a/projects/common/src/client/java/dan200/computercraft/data/client/ClientDataProviders.java +++ /dev/null @@ -1,50 +0,0 @@ -// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers -// -// SPDX-License-Identifier: MPL-2.0 - -package dan200.computercraft.data.client; - -import dan200.computercraft.client.gui.GuiSprites; -import dan200.computercraft.client.model.LecternPrintoutModel; -import dan200.computercraft.data.DataProviders; -import dan200.computercraft.shared.turtle.inventory.UpgradeSlot; -import net.minecraft.client.renderer.texture.atlas.SpriteSource; -import net.minecraft.client.renderer.texture.atlas.SpriteSources; -import net.minecraft.client.renderer.texture.atlas.sources.SingleFile; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.PackType; - -import java.util.List; -import java.util.Optional; -import java.util.stream.Stream; - -/** - * A version of {@link DataProviders} which relies on client-side classes. - *

- * This is called from {@link DataProviders#add(DataProviders.GeneratorSink)}. - */ -public final class ClientDataProviders { - private ClientDataProviders() { - } - - public static void add(DataProviders.GeneratorSink generator) { - generator.addFromCodec("Block atlases", PackType.CLIENT_RESOURCES, "atlases", SpriteSources.FILE_CODEC, out -> { - out.accept(new ResourceLocation("blocks"), List.of( - new SingleFile(UpgradeSlot.LEFT_UPGRADE, Optional.empty()), - new SingleFile(UpgradeSlot.RIGHT_UPGRADE, Optional.empty()), - new SingleFile(LecternPrintoutModel.TEXTURE, Optional.empty()) - )); - out.accept(GuiSprites.SPRITE_SHEET, Stream.of( - // Buttons - GuiSprites.TURNED_OFF.textures(), - GuiSprites.TURNED_ON.textures(), - GuiSprites.TERMINATE.textures(), - // Computers - GuiSprites.COMPUTER_NORMAL.textures(), - GuiSprites.COMPUTER_ADVANCED.textures(), - GuiSprites.COMPUTER_COMMAND.textures(), - GuiSprites.COMPUTER_COLOUR.textures() - ).flatMap(x -> x).map(x -> new SingleFile(x, Optional.empty())).toList()); - }); - } -} diff --git a/projects/common/src/main/java/dan200/computercraft/data/BlockModelProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/BlockModelProvider.java similarity index 100% rename from projects/common/src/main/java/dan200/computercraft/data/BlockModelProvider.java rename to projects/common/src/datagen/java/dan200/computercraft/data/BlockModelProvider.java diff --git a/projects/common/src/main/java/dan200/computercraft/data/DataProviders.java b/projects/common/src/datagen/java/dan200/computercraft/data/DataProviders.java similarity index 55% rename from projects/common/src/main/java/dan200/computercraft/data/DataProviders.java rename to projects/common/src/datagen/java/dan200/computercraft/data/DataProviders.java index a68f15e61d..d58aeaf9b4 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/DataProviders.java +++ b/projects/common/src/datagen/java/dan200/computercraft/data/DataProviders.java @@ -5,6 +5,12 @@ package dan200.computercraft.data; import com.mojang.serialization.Codec; +import dan200.computercraft.client.gui.GuiSprites; +import dan200.computercraft.client.model.LecternPrintoutModel; +import dan200.computercraft.shared.turtle.inventory.UpgradeSlot; +import net.minecraft.client.renderer.texture.atlas.SpriteSource; +import net.minecraft.client.renderer.texture.atlas.SpriteSources; +import net.minecraft.client.renderer.texture.atlas.sources.SingleFile; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; import net.minecraft.data.tags.TagsProvider; @@ -13,9 +19,14 @@ import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; /** * All data providers for ComputerCraft. We require a mod-loader abstraction {@link GeneratorSink} (instead of @@ -39,14 +50,30 @@ public static void add(GeneratorSink generator) { generator.add(out -> new LanguageProvider(out, turtleUpgrades, pocketUpgrades)); - // Unfortunately we rely on some client-side classes in this code. We just load in the client side data provider - // and invoke that. - try { - Class.forName("dan200.computercraft.data.client.ClientDataProviders") - .getMethod("add", GeneratorSink.class).invoke(null, generator); - } catch (ReflectiveOperationException e) { - throw new RuntimeException(e); - } + generator.addFromCodec("Block atlases", PackType.CLIENT_RESOURCES, "atlases", SpriteSources.FILE_CODEC, out -> { + out.accept(new ResourceLocation("blocks"), makeSprites(Stream.of( + UpgradeSlot.LEFT_UPGRADE, + UpgradeSlot.RIGHT_UPGRADE, + LecternPrintoutModel.TEXTURE + ))); + out.accept(GuiSprites.SPRITE_SHEET, makeSprites( + // Buttons + GuiSprites.TURNED_OFF.textures(), + GuiSprites.TURNED_ON.textures(), + GuiSprites.TERMINATE.textures(), + // Computers + GuiSprites.COMPUTER_NORMAL.textures(), + GuiSprites.COMPUTER_ADVANCED.textures(), + GuiSprites.COMPUTER_COMMAND.textures(), + GuiSprites.COMPUTER_COLOUR.textures() + )); + }); + } + + @SafeVarargs + @SuppressWarnings("varargs") + private static List makeSprites(final Stream... files) { + return Arrays.stream(files).flatMap(Function.identity()).map(x -> new SingleFile(x, Optional.empty())).toList(); } public interface GeneratorSink { diff --git a/projects/common/src/main/java/dan200/computercraft/data/ItemModelProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/ItemModelProvider.java similarity index 100% rename from projects/common/src/main/java/dan200/computercraft/data/ItemModelProvider.java rename to projects/common/src/datagen/java/dan200/computercraft/data/ItemModelProvider.java diff --git a/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/LanguageProvider.java similarity index 100% rename from projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java rename to projects/common/src/datagen/java/dan200/computercraft/data/LanguageProvider.java diff --git a/projects/common/src/main/java/dan200/computercraft/data/LootTableProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/LootTableProvider.java similarity index 100% rename from projects/common/src/main/java/dan200/computercraft/data/LootTableProvider.java rename to projects/common/src/datagen/java/dan200/computercraft/data/LootTableProvider.java diff --git a/projects/common/src/main/java/dan200/computercraft/data/ModelProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/ModelProvider.java similarity index 100% rename from projects/common/src/main/java/dan200/computercraft/data/ModelProvider.java rename to projects/common/src/datagen/java/dan200/computercraft/data/ModelProvider.java diff --git a/projects/common/src/main/java/dan200/computercraft/data/PocketUpgradeProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/PocketUpgradeProvider.java similarity index 100% rename from projects/common/src/main/java/dan200/computercraft/data/PocketUpgradeProvider.java rename to projects/common/src/datagen/java/dan200/computercraft/data/PocketUpgradeProvider.java diff --git a/projects/common/src/main/java/dan200/computercraft/data/PrettyDataProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/PrettyDataProvider.java similarity index 96% rename from projects/common/src/main/java/dan200/computercraft/data/PrettyDataProvider.java rename to projects/common/src/datagen/java/dan200/computercraft/data/PrettyDataProvider.java index 9c78e245ca..fc2ef47e3a 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/PrettyDataProvider.java +++ b/projects/common/src/datagen/java/dan200/computercraft/data/PrettyDataProvider.java @@ -7,6 +7,7 @@ import com.google.common.hash.HashCode; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; +import dan200.computercraft.shared.util.PrettyJsonWriter; import net.minecraft.data.CachedOutput; import net.minecraft.data.DataProvider; diff --git a/projects/common/src/main/java/dan200/computercraft/data/RecipeProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/RecipeProvider.java similarity index 100% rename from projects/common/src/main/java/dan200/computercraft/data/RecipeProvider.java rename to projects/common/src/datagen/java/dan200/computercraft/data/RecipeProvider.java diff --git a/projects/common/src/main/java/dan200/computercraft/data/RecipeWrapper.java b/projects/common/src/datagen/java/dan200/computercraft/data/RecipeWrapper.java similarity index 100% rename from projects/common/src/main/java/dan200/computercraft/data/RecipeWrapper.java rename to projects/common/src/datagen/java/dan200/computercraft/data/RecipeWrapper.java diff --git a/projects/common/src/main/java/dan200/computercraft/data/TagProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/TagProvider.java similarity index 98% rename from projects/common/src/main/java/dan200/computercraft/data/TagProvider.java rename to projects/common/src/datagen/java/dan200/computercraft/data/TagProvider.java index 04cf493da4..4250f6a644 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/TagProvider.java +++ b/projects/common/src/datagen/java/dan200/computercraft/data/TagProvider.java @@ -148,7 +148,7 @@ public TagAppender addTag(TagKey tag) { /** * A wrapper over {@link ItemTagsProvider}. */ - interface ItemTagConsumer extends TagConsumer { + public interface ItemTagConsumer extends TagConsumer { void copy(TagKey block, TagKey item); } } diff --git a/projects/common/src/main/java/dan200/computercraft/data/TurtleUpgradeProvider.java b/projects/common/src/datagen/java/dan200/computercraft/data/TurtleUpgradeProvider.java similarity index 100% rename from projects/common/src/main/java/dan200/computercraft/data/TurtleUpgradeProvider.java rename to projects/common/src/datagen/java/dan200/computercraft/data/TurtleUpgradeProvider.java diff --git a/projects/common/src/main/java/dan200/computercraft/data/PrettyJsonWriter.java b/projects/common/src/main/java/dan200/computercraft/shared/util/PrettyJsonWriter.java similarity index 99% rename from projects/common/src/main/java/dan200/computercraft/data/PrettyJsonWriter.java rename to projects/common/src/main/java/dan200/computercraft/shared/util/PrettyJsonWriter.java index 38ee71e852..d52459accc 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/PrettyJsonWriter.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/util/PrettyJsonWriter.java @@ -2,7 +2,7 @@ // // SPDX-License-Identifier: MPL-2.0 -package dan200.computercraft.data; +package dan200.computercraft.shared.util; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -23,7 +23,7 @@ /** * Alternative version of {@link JsonWriter} which attempts to lay out the JSON in a more compact format. * - * @see PrettyDataProvider + * @see dan200.computercraft.data.PrettyDataProvider */ public class PrettyJsonWriter extends JsonWriter { private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create(); diff --git a/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java b/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java index d852c8774d..56d7e32e4d 100644 --- a/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java +++ b/projects/common/src/testMod/java/dan200/computercraft/export/Exporter.java @@ -14,9 +14,9 @@ import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.data.PrettyJsonWriter; import dan200.computercraft.gametest.core.TestHooks; import dan200.computercraft.shared.platform.RegistryWrappers; +import dan200.computercraft.shared.util.PrettyJsonWriter; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; diff --git a/projects/fabric/build.gradle.kts b/projects/fabric/build.gradle.kts index 69bc0d041a..4896ef955b 100644 --- a/projects/fabric/build.gradle.kts +++ b/projects/fabric/build.gradle.kts @@ -8,7 +8,7 @@ import java.util.* plugins { id("cc-tweaked.fabric") - id("cc-tweaked.gametest") + id("cc-tweaked.mod") id("cc-tweaked.mod-publishing") } @@ -146,6 +146,8 @@ loom { configName = "Datagen" client() + source(sourceSets.datagen.get()) + runDir("run/dataGen") property("fabric-api.datagen") property("fabric-api.datagen.output-dir", layout.buildDirectory.dir("generatedResources").getAbsolutePath()) diff --git a/projects/fabric/src/main/java/dan200/computercraft/data/FabricDataGenerators.java b/projects/fabric/src/datagen/java/dan200/computercraft/data/FabricDataProviders.java similarity index 98% rename from projects/fabric/src/main/java/dan200/computercraft/data/FabricDataGenerators.java rename to projects/fabric/src/datagen/java/dan200/computercraft/data/FabricDataProviders.java index 48983dbda3..881b9eda3b 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/data/FabricDataGenerators.java +++ b/projects/fabric/src/datagen/java/dan200/computercraft/data/FabricDataProviders.java @@ -26,7 +26,7 @@ import java.util.function.BiConsumer; import java.util.function.Consumer; -public class FabricDataGenerators implements DataGeneratorEntrypoint { +public class FabricDataProviders implements DataGeneratorEntrypoint { @Override public void onInitializeDataGenerator(FabricDataGenerator generator) { var pack = new PlatformGeneratorsImpl(generator.createPack()); diff --git a/projects/fabric/src/main/java/dan200/computercraft/data/MoreConventionalTagsProvider.java b/projects/fabric/src/datagen/java/dan200/computercraft/data/MoreConventionalTagsProvider.java similarity index 100% rename from projects/fabric/src/main/java/dan200/computercraft/data/MoreConventionalTagsProvider.java rename to projects/fabric/src/datagen/java/dan200/computercraft/data/MoreConventionalTagsProvider.java diff --git a/projects/fabric/src/datagen/resources/fabric.mod.json b/projects/fabric/src/datagen/resources/fabric.mod.json new file mode 100644 index 0000000000..1daa9ec5f5 --- /dev/null +++ b/projects/fabric/src/datagen/resources/fabric.mod.json @@ -0,0 +1,13 @@ +{ + "schemaVersion": 1, + "id": "cc-datagen", + "version": "1.0.0", + "entrypoints": { + "fabric-datagen": [ + "dan200.computercraft.data.FabricDataProviders" + ] + }, + "depends": { + "computercraft": "*" + } +} diff --git a/projects/fabric/src/main/resources/fabric.mod.json b/projects/fabric/src/main/resources/fabric.mod.json index 89ab2882d0..7a48156a17 100644 --- a/projects/fabric/src/main/resources/fabric.mod.json +++ b/projects/fabric/src/main/resources/fabric.mod.json @@ -23,9 +23,6 @@ "client": [ "dan200.computercraft.client.ComputerCraftClient::init" ], - "fabric-datagen": [ - "dan200.computercraft.data.FabricDataGenerators" - ], "jei_mod_plugin": [ "dan200.computercraft.client.integration.jei.JEIComputerCraft" ], diff --git a/projects/fabric/src/testMod/resources/fabric.mod.json b/projects/fabric/src/testMod/resources/fabric.mod.json index 9b8648888e..ffc442bec6 100644 --- a/projects/fabric/src/testMod/resources/fabric.mod.json +++ b/projects/fabric/src/testMod/resources/fabric.mod.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "id": "cctest", + "id": "cc-datagen", "version": "1.0.0", "entrypoints": { "main": [ diff --git a/projects/forge/build.gradle.kts b/projects/forge/build.gradle.kts index 1457aae787..7caf8de4a3 100644 --- a/projects/forge/build.gradle.kts +++ b/projects/forge/build.gradle.kts @@ -7,7 +7,7 @@ import net.minecraftforge.gradle.common.util.RunConfig plugins { id("cc-tweaked.forge") - id("cc-tweaked.gametest") + id("cc-tweaked.mod") id("cc-tweaked.mod-publishing") } @@ -57,6 +57,10 @@ minecraft { "--existing", project(":common").file("src/main/resources/"), "--existing", file("src/main/resources/"), ) + + mods.named("computercraft") { + source(sourceSets["datagen"]) + } } fun RunConfig.configureForGameTest() { diff --git a/projects/forge/src/main/java/dan200/computercraft/data/Generators.java b/projects/forge/src/datagen/java/dan200/computercraft/data/ForgeDataProviders.java similarity index 99% rename from projects/forge/src/main/java/dan200/computercraft/data/Generators.java rename to projects/forge/src/datagen/java/dan200/computercraft/data/ForgeDataProviders.java index 3a003ca093..6ea8480f58 100644 --- a/projects/forge/src/main/java/dan200/computercraft/data/Generators.java +++ b/projects/forge/src/datagen/java/dan200/computercraft/data/ForgeDataProviders.java @@ -32,7 +32,7 @@ import java.util.function.Consumer; @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) -public class Generators { +public class ForgeDataProviders { @SubscribeEvent public static void gather(GatherDataEvent event) { var generator = event.getGenerator();