From 9ca3efff3c8ad29272cfec2e9dc9cee3ef2f3fa8 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sun, 9 Jul 2023 14:09:44 +0100 Subject: [PATCH 1/6] Add data generator support for required mods We've supported resource conditions in the upgrade JSON for an age, but don't expose it in our data generators at all. Indeed, using these hooks is a bit of a pain to do in multi-loader setups, as the JSON is different between the two loaders. We could generate the JSON for all loaders at once, but it feels nicer to use the per-loader APIs to add the conditions. For now, we just support generating a single condition - whether a mod is loaded not, via the requireMod(...) method. --- .../api/upgrades/UpgradeDataProvider.java | 22 ++++++++++++++----- .../computercraft/impl/PlatformHelper.java | 11 ++++++++++ .../computercraft/TestPlatformHelper.java | 7 +++++- .../shared/platform/PlatformHelperImpl.java | 14 ++++++++++++ .../shared/platform/PlatformHelperImpl.java | 15 +++++++++++++ 5 files changed, 63 insertions(+), 6 deletions(-) diff --git a/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeDataProvider.java b/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeDataProvider.java index 7178e8a3a..8e634239e 100644 --- a/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeDataProvider.java +++ b/projects/common-api/src/main/java/dan200/computercraft/api/upgrades/UpgradeDataProvider.java @@ -23,11 +23,7 @@ import org.apache.logging.log4j.Logger; import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; import java.util.function.Function; @@ -167,5 +163,21 @@ public record Upgrade>( public void add(Consumer> add) { add.accept(this); } + + /** + * Return a new {@link Upgrade} which requires the given mod to be present. + *

+ * This uses mod-loader-specific hooks (Forge's crafting conditions and Fabric's resource conditions). If using + * this in a multi-loader setup, you must generate resources separately for the two loaders. + * + * @param modId The id of the mod. + * @return A new upgrade instance. + */ + public Upgrade requireMod(String modId) { + return new Upgrade<>(id, serialiser, json -> { + PlatformHelper.get().addRequiredModCondition(json, modId); + serialise.accept(json); + }); + } } } diff --git a/projects/common-api/src/main/java/dan200/computercraft/impl/PlatformHelper.java b/projects/common-api/src/main/java/dan200/computercraft/impl/PlatformHelper.java index 2ed4b230b..a7ab333d4 100644 --- a/projects/common-api/src/main/java/dan200/computercraft/impl/PlatformHelper.java +++ b/projects/common-api/src/main/java/dan200/computercraft/impl/PlatformHelper.java @@ -4,6 +4,8 @@ package dan200.computercraft.impl; +import com.google.gson.JsonObject; +import dan200.computercraft.api.upgrades.UpgradeDataProvider; import net.minecraft.core.Registry; import net.minecraft.nbt.CompoundTag; import net.minecraft.resources.ResourceKey; @@ -63,6 +65,15 @@ default CompoundTag getShareTag(ItemStack item) { return item.getTag(); } + /** + * Add a resource condition which requires a mod to be loaded. This should be used by data providers such as + * {@link UpgradeDataProvider}. + * + * @param object The JSON object we're generating. + * @param modId The mod ID that we require. + */ + void addRequiredModCondition(JsonObject object, String modId); + final class Instance { static final @Nullable PlatformHelper INSTANCE; static final @Nullable Throwable ERROR; diff --git a/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java b/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java index d898d5928..60b75ce13 100644 --- a/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java +++ b/projects/common/src/test/java/dan200/computercraft/TestPlatformHelper.java @@ -96,7 +96,12 @@ public T tryGetRegistryObject(ResourceKey> registry, ResourceLoc @Override public boolean shouldLoadResource(JsonObject object) { - throw new UnsupportedOperationException("Cannot use loot conditions"); + throw new UnsupportedOperationException("Cannot use resource conditions"); + } + + @Override + public void addRequiredModCondition(JsonObject object, String modId) { + throw new UnsupportedOperationException("Cannot use resource conditions"); } @Override diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java index 7f0f5fb30..3c0ee5318 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java @@ -5,6 +5,7 @@ package dan200.computercraft.shared.platform; import com.google.auto.service.AutoService; +import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.arguments.ArgumentType; @@ -27,6 +28,7 @@ import net.fabricmc.fabric.api.lookup.v1.block.BlockApiLookup; import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder; import net.fabricmc.fabric.api.registry.FuelRegistry; +import net.fabricmc.fabric.api.resource.conditions.v1.DefaultResourceConditions; import net.fabricmc.fabric.api.resource.conditions.v1.ResourceConditions; import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerType; @@ -49,6 +51,7 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.ItemTags; import net.minecraft.tags.TagKey; +import net.minecraft.util.GsonHelper; import net.minecraft.world.Container; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -134,6 +137,17 @@ public boolean shouldLoadResource(JsonObject object) { return ResourceConditions.objectMatchesConditions(object); } + @Override + public void addRequiredModCondition(JsonObject object, String modId) { + var conditions = GsonHelper.getAsJsonArray(object, ResourceConditions.CONDITIONS_KEY, null); + if (conditions == null) { + conditions = new JsonArray(); + object.add(ResourceConditions.CONDITIONS_KEY, conditions); + } + + conditions.add(DefaultResourceConditions.allModsLoaded(modId).toJson()); + } + @Override public BlockEntityType createBlockEntityType(BiFunction factory, Block block) { return FabricBlockEntityTypeBuilder.create(factory::apply).addBlock(block).build(); diff --git a/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java b/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java index 02a644bb1..d7f3a74b3 100644 --- a/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java +++ b/projects/forge/src/main/java/dan200/computercraft/shared/platform/PlatformHelperImpl.java @@ -5,6 +5,7 @@ package dan200.computercraft.shared.platform; import com.google.auto.service.AutoService; +import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.mojang.authlib.GameProfile; import com.mojang.brigadier.arguments.ArgumentType; @@ -32,6 +33,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.TagKey; +import net.minecraft.util.GsonHelper; import net.minecraft.world.*; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; @@ -56,7 +58,9 @@ import net.minecraftforge.common.ToolActions; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.ForgeCapabilities; +import net.minecraftforge.common.crafting.CraftingHelper; import net.minecraftforge.common.crafting.conditions.ICondition; +import net.minecraftforge.common.crafting.conditions.ModLoadedCondition; import net.minecraftforge.common.extensions.IForgeMenuType; import net.minecraftforge.common.util.NonNullConsumer; import net.minecraftforge.event.ForgeEventFactory; @@ -122,6 +126,17 @@ public boolean shouldLoadResource(JsonObject object) { return ICondition.shouldRegisterEntry(object); } + @Override + public void addRequiredModCondition(JsonObject object, String modId) { + var conditions = GsonHelper.getAsJsonArray(object, "forge:conditions", null); + if (conditions == null) { + conditions = new JsonArray(); + object.add("forge:conditions", conditions); + } + + conditions.add(CraftingHelper.serialize(new ModLoadedCondition(modId))); + } + @Override public BlockEntityType createBlockEntityType(BiFunction factory, Block block) { return new BlockEntityType<>(factory::apply, Set.of(block), null); From 7f25c9a66bb62eb61f1fd4a852b1613989d06bb6 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sun, 9 Jul 2023 18:44:33 +0100 Subject: [PATCH 2/6] Only load client config on the client --- gradle/libs.versions.toml | 2 +- .../dan200/computercraft/client/ComputerCraftClient.java | 6 ++++++ .../java/dan200/computercraft/shared/ComputerCraft.java | 3 --- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d3e1f4fc4..83a180782 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -62,7 +62,7 @@ librarian = "1.+" minotaur = "2.+" mixinGradle = "0.7.+" nullAway = "0.9.9" -quiltflower = "1.8.0" +quiltflower = "1.10.0" spotless = "6.17.0" taskTree = "2.1.1" vanillaGradle = "0.2.1-SNAPSHOT" diff --git a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java index 170034086..45c127f17 100644 --- a/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java +++ b/projects/fabric/src/client/java/dan200/computercraft/client/ComputerCraftClient.java @@ -4,11 +4,14 @@ package dan200.computercraft.client; +import dan200.computercraft.api.ComputerCraftAPI; import dan200.computercraft.client.model.EmissiveComputerModel; import dan200.computercraft.client.model.turtle.TurtleModelLoader; import dan200.computercraft.shared.ModRegistry; +import dan200.computercraft.shared.config.ConfigSpec; import dan200.computercraft.shared.network.client.ClientNetworkContext; import dan200.computercraft.shared.peripheral.modem.wired.CableBlock; +import dan200.computercraft.shared.platform.FabricConfigFile; import dan200.computercraft.shared.platform.NetworkHandler; import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; @@ -17,6 +20,7 @@ import net.fabricmc.fabric.api.client.rendering.v1.ColorProviderRegistry; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; import net.fabricmc.fabric.api.event.client.player.ClientPickBlockGatherCallback; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.RenderType; import net.minecraft.world.item.ItemStack; @@ -68,5 +72,7 @@ public static void init() { return cable.getCloneItemStack(state, hit, level, pos, player); }); + + ((FabricConfigFile) ConfigSpec.clientSpec).load(FabricLoader.getInstance().getConfigDir().resolve(ComputerCraftAPI.MOD_ID + "-client.toml")); } } diff --git a/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java b/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java index d4587a7a1..1b311694e 100644 --- a/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java +++ b/projects/fabric/src/main/java/dan200/computercraft/shared/ComputerCraft.java @@ -30,7 +30,6 @@ import net.fabricmc.fabric.api.loot.v2.LootTableEvents; import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener; import net.fabricmc.fabric.api.resource.ResourceManagerHelper; -import net.fabricmc.loader.api.FabricLoader; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.packs.PackType; import net.minecraft.server.packs.resources.PreparableReloadListener; @@ -100,8 +99,6 @@ public static void init() { CommonHooks.onDatapackReload((name, listener) -> ResourceManagerHelper.get(PackType.SERVER_DATA).registerReloadListener(new ReloadListener(name, listener))); - ((FabricConfigFile) ConfigSpec.clientSpec).load(FabricLoader.getInstance().getConfigDir().resolve(ComputerCraftAPI.MOD_ID + "-client.toml")); - FabricDetailRegistries.FLUID_VARIANT.addProvider(FluidDetails::fill); ComputerCraftAPI.registerGenericSource(new InventoryMethods()); From af3263dec2aede9413373f4e8b7b844c2f9445cd Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Sun, 9 Jul 2023 19:58:34 +0100 Subject: [PATCH 3/6] Allow disabling generic methods Suddenly so easy as of the refactoring in 910a63214e395ecae6993d8e0487384c725b3dd3! Closes #1382 --- .../computercraft/data/LanguageProvider.java | 1 + .../dan200/computercraft/impl/GenericSources.java | 9 ++++++++- .../computercraft/shared/config/ConfigSpec.java | 14 ++++++++++++++ .../computercraft/core/asm/GenericMethod.java | 10 ++++++++-- .../resources/assets/computercraft/lang/en_us.json | 2 ++ .../resources/assets/computercraft/lang/en_us.json | 2 ++ 6 files changed, 35 insertions(+), 3 deletions(-) diff --git a/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java b/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java index c5dcdb70d..9a12a77e1 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java @@ -214,6 +214,7 @@ private void addTranslations() { addConfigEntry(ConfigSpec.defaultComputerSettings, "Default Computer settings"); addConfigEntry(ConfigSpec.logComputerErrors, "Log computer errors"); addConfigEntry(ConfigSpec.commandRequireCreative, "Command computers require creative"); + addConfigEntry(ConfigSpec.disabledGenericMethods, "Disabled generic methods"); addConfigGroup(ConfigSpec.serverSpec, "execution", "Execution"); addConfigEntry(ConfigSpec.computerThreads, "Computer threads"); diff --git a/projects/common/src/main/java/dan200/computercraft/impl/GenericSources.java b/projects/common/src/main/java/dan200/computercraft/impl/GenericSources.java index 0ba250c9c..253cc03e2 100644 --- a/projects/common/src/main/java/dan200/computercraft/impl/GenericSources.java +++ b/projects/common/src/main/java/dan200/computercraft/impl/GenericSources.java @@ -6,10 +6,12 @@ import dan200.computercraft.api.lua.GenericSource; import dan200.computercraft.core.asm.GenericMethod; +import dan200.computercraft.shared.config.ConfigSpec; import java.util.Collection; import java.util.LinkedHashSet; import java.util.Objects; +import java.util.Set; /** * The global registry for {@link GenericSource}s. @@ -29,6 +31,11 @@ static synchronized void register(GenericSource source) { } public static Collection getAllMethods() { - return sources.stream().flatMap(GenericMethod::getMethods).toList(); + var disabledMethods = Set.copyOf(ConfigSpec.disabledGenericMethods.get()); + return sources.stream() + .filter(x -> !disabledMethods.contains(x.id())) + .flatMap(GenericMethod::getMethods) + .filter(x -> !disabledMethods.contains(x.id())) + .toList(); } } 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 347f7fff0..205b10310 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 @@ -35,6 +35,7 @@ public final class ConfigSpec { public static final ConfigFile.Value logComputerErrors; public static final ConfigFile.Value commandRequireCreative; public static final ConfigFile.Value uploadMaxSize; + public static final ConfigFile.Value> disabledGenericMethods; public static final ConfigFile.Value computerThreads; public static final ConfigFile.Value maxMainGlobalTime; @@ -139,6 +140,19 @@ private ConfigSpec() { 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.""") .define("command_require_creative", Config.commandRequireCreative); + + disabledGenericMethods = builder + .comment(""" + A list of generic methods or method sources to disable. Generic methods are + methods added to a block/block entity when there is no explicit peripheral + provider. This includes inventory methods (i.e. inventory.getItemDetail, + inventory.pushItems), and (if on Forge), the fluid_storage and energy_storage + methods. + Methods in this list can either be a whole group of methods (computercraft:inventory) + or a single method (computercraft:inventory#pushItems). + """) + .worldRestart() + .defineList("disabled_generic_methods", List.of(), x -> x instanceof String); } { diff --git a/projects/core/src/main/java/dan200/computercraft/core/asm/GenericMethod.java b/projects/core/src/main/java/dan200/computercraft/core/asm/GenericMethod.java index 1e18b0a0b..ff81bc65e 100644 --- a/projects/core/src/main/java/dan200/computercraft/core/asm/GenericMethod.java +++ b/projects/core/src/main/java/dan200/computercraft/core/asm/GenericMethod.java @@ -24,18 +24,24 @@ public final class GenericMethod { private static final Logger LOG = LoggerFactory.getLogger(GenericMethod.class); + final GenericSource source; final Method method; final LuaFunction annotation; final Class target; final @Nullable PeripheralType peripheralType; - private GenericMethod(Method method, LuaFunction annotation, Class target, @Nullable PeripheralType peripheralType) { + private GenericMethod(GenericSource source, Method method, LuaFunction annotation, Class target, @Nullable PeripheralType peripheralType) { + this.source = source; this.method = method; this.annotation = annotation; this.target = target; this.peripheralType = peripheralType; } + public String id() { + return source.id() + "#" + name(); + } + public String name() { return method.getName(); } @@ -69,7 +75,7 @@ public static Stream getMethods(GenericSource source) { var target = Reflect.getRawType(method, types[0], false); if (target == null) return null; - return new GenericMethod(method, annotation, target, type); + return new GenericMethod(source, method, annotation, target, type); }) .filter(Objects::nonNull); } diff --git a/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json b/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json index 77fe60ee0..ca14707a5 100644 --- a/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json +++ b/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json @@ -81,6 +81,8 @@ "gui.computercraft.config.default_computer_settings.tooltip": "A comma separated list of default system settings to set on new computers.\nExample: \"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\"\nwill disable all autocompletion.", "gui.computercraft.config.disable_lua51_features": "Disable Lua 5.1 features", "gui.computercraft.config.disable_lua51_features.tooltip": "Set this to true to disable Lua 5.1 functions that will be removed in a future\nupdate. Useful for ensuring forward compatibility of your programs now.", + "gui.computercraft.config.disabled_generic_methods": "Disabled generic methods", + "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", diff --git a/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json b/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json index 77fe60ee0..ca14707a5 100644 --- a/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json +++ b/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json @@ -81,6 +81,8 @@ "gui.computercraft.config.default_computer_settings.tooltip": "A comma separated list of default system settings to set on new computers.\nExample: \"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\"\nwill disable all autocompletion.", "gui.computercraft.config.disable_lua51_features": "Disable Lua 5.1 features", "gui.computercraft.config.disable_lua51_features.tooltip": "Set this to true to disable Lua 5.1 functions that will be removed in a future\nupdate. Useful for ensuring forward compatibility of your programs now.", + "gui.computercraft.config.disabled_generic_methods": "Disabled generic methods", + "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", From b94e34f3728e2032ffbe21412bf30c9c5d85d272 Mon Sep 17 00:00:00 2001 From: Weblate Date: Mon, 10 Jul 2023 15:03:03 +0000 Subject: [PATCH 4/6] Translations for Italian Co-authored-by: Alessandro --- .../assets/computercraft/lang/it_it.json | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/projects/common/src/main/resources/assets/computercraft/lang/it_it.json b/projects/common/src/main/resources/assets/computercraft/lang/it_it.json index 191490f93..b898679c9 100644 --- a/projects/common/src/main/resources/assets/computercraft/lang/it_it.json +++ b/projects/common/src/main/resources/assets/computercraft/lang/it_it.json @@ -131,7 +131,7 @@ "tracking_field.computercraft.peripheral.name": "Chiamate alle periferiche", "tracking_field.computercraft.websocket_incoming.name": "Websocket in arrivo", "tracking_field.computercraft.websocket_outgoing.name": "Websocket in uscita", - "upgrade.computercraft.speaker.adjective": "Che Produce Rumori", + "upgrade.computercraft.speaker.adjective": "Rumoroso", "upgrade.computercraft.wireless_modem_advanced.adjective": "Ender", "upgrade.computercraft.wireless_modem_normal.adjective": "Wireless", "upgrade.minecraft.crafting_table.adjective": "Artigiana", @@ -176,8 +176,8 @@ "gui.computercraft.config.default_computer_settings.tooltip": "Una lista di impostazioni predefinite per i nuovi computer, separate da virgola.\nEsempio: \"shell.autocomplete=false,lua.autocomplete=false,edit.autocomplete=false\"\ndisattiverà tutti gli autocompletamenti.", "gui.computercraft.config.execution.computer_threads.tooltip": "Imposta la quantità di thread che possono eseguire i computer. Un numero più alto significa\nche più computer possono essere eseguiti alla volta, ma può indurre a lag. Alcune mod potrebbero\nnon funzionare con numeri di thread maggiore a 1. Usare con cautela.\nRange: > 1", "gui.computercraft.config.execution.max_main_global_time.tooltip": "Il limite massimo di tempo che può essere usato per eseguire task in un singolo tick,\nin millisecondi.\nNota, potremmo andare ben sopra questo limite, perché non c'è modo di sapere\nquanto impiega, questa configurazione mira ad essere il limite maggiore del tempo medio.\nRange: > 1", - "gui.computercraft.config.http.enabled.tooltip": "Attiva l'API \"http\" sui computer. Questo disabilita i programmi \"pastebin\" e \"wget\", \nche molti utenti dipendono. È raccomandato lasciarlo attivo ed utlizzare l'opzione \n\"rules\" per imporre controlli più adeguati.", - "gui.computercraft.config.http.rules.tooltip": "Una lista di regole che controllano il comportamento dell'API \"http\" per specifici domini\no indirizzi IP. Ogni regola è un elemento con un 'host' da confrontare, e una serie di\nproprietà. Le regole sono valutate in ordine, cioè le prime regole sovvrascrivono le successive.\nL'host può essere un dominio (\"pastebin.com\"), wildcard (\"*.pastebin.com\") oppure\nuna notazione CIDR (\"127.0.0.0/8\").\nSe non è presente nessuna regola, il dominio è bloccato.", + "gui.computercraft.config.http.enabled.tooltip": "Attiva l'API \"http\" sui computer. Disattivandolo, vengono disattivati anche i programmi \"pastebin\" e \"wget\", \ndi cui molti utenti dipendono. È raccomandato lasciarlo attivo ed utilizzare l'opzione \n\"rules\" per imporre controlli più adeguati.", + "gui.computercraft.config.http.rules.tooltip": "Una lista di regole che controllano il comportamento dell'API \"http\" per specifici domini\no indirizzi IP. Ogni regola corrisponde ad un nome host ed una porta opzionale, e poi imposta varie\nproprietà per la richiesta. Le regole sono valutate in ordine, cioè le prime regole sovvrascrivono le successive.\n\nProprietà valide:\n - \"host\" (richiesto): Il dominio o l'indirizzo IP della regola. Può essere un nome di dominio\n (\"pastebin.com\"), jolly (\"*.pastebin.com\") o notazione CIDR (\"127.0.0.0/8\").\n - \"port\" (opzionale): Corrisponde solo a richieste con una specifica porta, come 80 o 443.\n\n - \"action\" (opzionale): Se consentire o negare la richiesta.\n - \"max_download\" (opzionale): Quantità massima (in byte) che un computer può scaricare in\n questa richiesta.\n - \"max_upload\" (opzionale): Quantità massima (in byte) che un computer può caricare in\n questa richiesta.\n - \"max_websocket_message\" (opzionale): Quantità massima (in byte) che un computer può inviare o\n ricevere in un pacchetto websocket.\n - \"use_proxy\" (opzionale): Attiva l'uso di un proxy HTTP/SOCKS se configurato.", "gui.computercraft.config.http.tooltip": "Controlla l'API HTTP", "gui.computercraft.config.http.websocket_enabled.tooltip": "Attiva l'uso di websocket http. Questo richiede che l'opzione \"http_enable\" sia attiva.", "gui.computercraft.config.log_computer_errors.tooltip": "Registra le eccezioni lanciate dalle periferiche e altri oggetti di Lua. Questo rende più facile\nper gli autori di mod per il debug di problemi, ma potrebbe risultare in spam di log durante\nl'uso di metodi buggati.", @@ -217,5 +217,15 @@ "gui.computercraft.config.upload_nag_delay": "Ritardo nel caricamento", "gui.computercraft.config.term_sizes.tooltip": "Configura le dimensioni dei terminali di vari computer.\nTerminali più grandi richiedono più banda larga, usa con cautela.", "gui.computercraft.config.upload_nag_delay.tooltip": "Ritardo in secondi dopo il quale verranno notificate le importazioni non gestite. Imposta a 0 per disattivare.\nRange: 0 ~ 60", - "gui.computercraft.upload.no_response.msg": "Il tuo computer non ha usato i tuoi file trasferiti. Potresti aver bisogno di eseguire il programma %s e riprovare di nuovo." + "gui.computercraft.upload.no_response.msg": "Il tuo computer non ha usato i tuoi file trasferiti. Potresti aver bisogno di eseguire il programma %s e riprovare di nuovo.", + "gui.computercraft.config.upload_max_size.tooltip": "Il limite delle dimensioni dei file da caricare, in byte. Deve essere in range di 1KiB e 16 MiB.\nRicorda che i caricamenti sono processati in un singolo tick - i file grandi o\nuna rete di bassa qualità può bloccare il thread di rete. E ricorda anche lo spazio di archiviazione dei dischi!\nRange: 1024 ~ 16777216", + "gui.computercraft.config.http.proxy": "Proxy", + "gui.computercraft.config.http.proxy.host": "Nome host", + "gui.computercraft.config.http.proxy.host.tooltip": "Il nome dell'host o l'indirizzo IP del server proxy.", + "gui.computercraft.config.http.proxy.port": "Porta", + "gui.computercraft.config.http.proxy.port.tooltip": "La porta del server proxy.\nRange: 1 ~ 65536", + "gui.computercraft.config.http.proxy.tooltip": "Transmetti richieste HTTP e websocket attraverso un server proxy. Ha effetto solo\nsu regole HTTP con \"use_proxy\" attivo (disattivato di default).\nSe l'autenticazione è richiesta per il proxy, creare un file \"computercraft-proxy.pw\"\nnella stessa cartella di \"computercraft-server.toml\", contenendo il nome utente e\npassword separati dal carattere due punti, per esempio: \"myuser:mypassword\".\nI proxy SOCKS4 necessitano solo il nome utente.", + "gui.computercraft.config.http.proxy.type": "Tipo proxy", + "gui.computercraft.config.http.proxy.type.tooltip": "Il tipo di proxy da usare.\nValori consentiti: HTTP, HTTPS, SOCKS4, SOCKS5", + "gui.computercraft.config.upload_max_size": "Limite delle dimensioni dei file da caricare (byte)" } From ec0765ead13a193f7e7b1192d2dc59d2ec38eac7 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Mon, 10 Jul 2023 08:42:01 +0100 Subject: [PATCH 5/6] Bump Cobalt to 0.7.1 - Fix numbers ending in "f" or "d" being lexed. - Fix string.pack's "z" causing out-of-bounds errors. --- .../src/main/kotlin/cc-tweaked.java-convention.gradle.kts | 5 +++-- gradle/libs.versions.toml | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts b/buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts index 75c739613..398d1e429 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts @@ -56,13 +56,14 @@ repositories { if (fg != null) forRepositories(fg.repository) filter { - includeGroup("org.squiddev") includeGroup("cc.tweaked") + includeModule("org.squiddev", "Cobalt") // Things we mirror includeGroup("dev.architectury") + includeGroup("dev.emi") includeGroup("maven.modrinth") - includeGroup("me.shedaniel") includeGroup("me.shedaniel.cloth") + includeGroup("me.shedaniel") includeGroup("mezz.jei") includeModule("com.terraformersmc", "modmenu") } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 83a180782..a5cf9b2e8 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -19,8 +19,8 @@ parchmentMc = "1.19.3" asm = "9.3" autoService = "1.0.1" checkerFramework = "3.32.0" -cobalt = "0.7.0" -cobalt-next = "0.7.1" # Not a real version, used to constrain the version we accept. +cobalt = "0.7.1" +cobalt-next = "0.7.2" # Not a real version, used to constrain the version we accept. fastutil = "8.5.9" guava = "31.1-jre" jetbrainsAnnotations = "24.0.1" From c2988366d82e4115aae39636b8973f2c28975941 Mon Sep 17 00:00:00 2001 From: Jonathan Coates Date: Mon, 10 Jul 2023 20:31:06 +0100 Subject: [PATCH 6/6] Add EMI compatibility This just adds stack comparisons, so that upgrades are considered (much like JEI and REI). No dynamic recipes, as EMI doesn't support those :(. --- gradle/libs.versions.toml | 2 + projects/common/build.gradle.kts | 1 + .../integration/emi/EMIComputerCraft.java | 45 +++++++++++++++++++ .../computercraft/data/LanguageProvider.java | 12 +++++ .../shared/turtle/upgrades/TurtleTool.java | 5 +-- .../apis/http/options/AddressPredicate.java | 3 +- projects/fabric/build.gradle.kts | 1 + .../assets/computercraft/lang/en_us.json | 4 ++ .../fabric/src/main/resources/fabric.mod.json | 3 ++ projects/forge/build.gradle.kts | 1 + .../assets/computercraft/lang/en_us.json | 4 ++ 11 files changed, 76 insertions(+), 5 deletions(-) create mode 100644 projects/common/src/client/java/dan200/computercraft/client/integration/emi/EMIComputerCraft.java diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index a5cf9b2e8..3c49dc26b 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -33,6 +33,7 @@ nightConfig = "3.6.5" slf4j = "1.7.36" # Minecraft mods +emi = "1.0.8+1.19.4" iris = "1.5.2+1.19.4" jei = "13.1.0.11" modmenu = "6.1.0-rc.1" @@ -92,6 +93,7 @@ slf4j = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" } # Minecraft mods fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric-api" } fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric-loader" } +emi = { module = "dev.emi:emi-xplat-mojmap", version.ref = "emi" } iris = { module = "maven.modrinth:iris", version.ref = "iris" } jei-api = { module = "mezz.jei:jei-1.19.4-common-api", version.ref = "jei" } jei-fabric = { module = "mezz.jei:jei-1.19.4-fabric", version.ref = "jei" } diff --git a/projects/common/build.gradle.kts b/projects/common/build.gradle.kts index c4f40639e..b9d8fa399 100644 --- a/projects/common/build.gradle.kts +++ b/projects/common/build.gradle.kts @@ -26,6 +26,7 @@ dependencies { clientImplementation(clientClasses(project(":common-api"))) compileOnly(libs.bundles.externalMods.common) + clientCompileOnly(variantOf(libs.emi) { classifier("api") }) compileOnly(libs.mixin) annotationProcessorEverywhere(libs.autoService) diff --git a/projects/common/src/client/java/dan200/computercraft/client/integration/emi/EMIComputerCraft.java b/projects/common/src/client/java/dan200/computercraft/client/integration/emi/EMIComputerCraft.java new file mode 100644 index 000000000..fde7b83c5 --- /dev/null +++ b/projects/common/src/client/java/dan200/computercraft/client/integration/emi/EMIComputerCraft.java @@ -0,0 +1,45 @@ +// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.client.integration.emi; + +import dan200.computercraft.api.turtle.TurtleSide; +import dan200.computercraft.shared.ModRegistry; +import dan200.computercraft.shared.pocket.items.PocketComputerItem; +import dan200.computercraft.shared.turtle.items.TurtleItem; +import dev.emi.emi.api.EmiEntrypoint; +import dev.emi.emi.api.EmiPlugin; +import dev.emi.emi.api.EmiRegistry; +import dev.emi.emi.api.stack.Comparison; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; + +import java.util.function.BiPredicate; + +@EmiEntrypoint +public class EMIComputerCraft implements EmiPlugin { + @Override + public void register(EmiRegistry registry) { + registry.setDefaultComparison(ModRegistry.Items.TURTLE_NORMAL.get(), turtleComparison); + registry.setDefaultComparison(ModRegistry.Items.TURTLE_ADVANCED.get(), turtleComparison); + + registry.setDefaultComparison(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get(), pocketComparison); + registry.setDefaultComparison(ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get(), pocketComparison); + } + + private static final Comparison turtleComparison = compareStacks((left, right) -> + left.getItem() instanceof TurtleItem turtle + && turtle.getUpgrade(left, TurtleSide.LEFT) == turtle.getUpgrade(right, TurtleSide.LEFT) + && turtle.getUpgrade(left, TurtleSide.RIGHT) == turtle.getUpgrade(right, TurtleSide.RIGHT)); + + private static final Comparison pocketComparison = compareStacks((left, right) -> + left.getItem() instanceof PocketComputerItem && PocketComputerItem.getUpgrade(left) == PocketComputerItem.getUpgrade(right)); + + private static Comparison compareStacks(BiPredicate test) { + return Comparison.of((left, right) -> { + ItemStack leftStack = left.getItemStack(), rightStack = right.getItemStack(); + return leftStack.getItem() == rightStack.getItem() && test.test(leftStack, rightStack); + }); + } +} diff --git a/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java b/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java index 9a12a77e1..0fd88c9ef 100644 --- a/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java +++ b/projects/common/src/main/java/dan200/computercraft/data/LanguageProvider.java @@ -6,6 +6,7 @@ import com.google.gson.JsonObject; import dan200.computercraft.api.ComputerCraftAPI; +import dan200.computercraft.api.ComputerCraftTags; import dan200.computercraft.api.pocket.PocketUpgradeDataProvider; import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider; import dan200.computercraft.api.upgrades.UpgradeBase; @@ -20,6 +21,7 @@ import net.minecraft.data.CachedOutput; import net.minecraft.data.DataProvider; import net.minecraft.data.PackOutput; +import net.minecraft.tags.TagKey; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; @@ -97,6 +99,12 @@ private void addTranslations() { add(ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get(), "Advanced Pocket Computer"); add(ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get().getDescriptionId() + ".upgraded", "Advanced %s Pocket Computer"); + // Tags (for EMI) + add(ComputerCraftTags.Items.COMPUTER, "Computers"); + add(ComputerCraftTags.Items.TURTLE, "Turtles"); + add(ComputerCraftTags.Items.WIRED_MODEM, "Wired modems"); + add(ComputerCraftTags.Items.MONITOR, "Monitors"); + // Turtle/pocket upgrades add("upgrade.minecraft.diamond_sword.adjective", "Melee"); add("upgrade.minecraft.diamond_shovel.adjective", "Digging"); @@ -299,6 +307,10 @@ private void add(Metric metric, String text) { add(AggregatedMetric.TRANSLATION_PREFIX + metric.name() + ".name", text); } + private void add(TagKey tag, String text) { + add("tag.item." + tag.location().getNamespace() + "." + tag.location().getPath(), text); + } + private void addConfigGroup(ConfigFile spec, String path, String text) { var entry = spec.getEntry(path); if (!(entry instanceof ConfigFile.Group)) throw new IllegalArgumentException("Cannot find group " + path); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java index ad24abff9..5ca3fd87f 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java @@ -82,7 +82,7 @@ private static boolean isEnchanted(ItemStack stack) { private static boolean isEnchanted(@Nullable CompoundTag tag) { if (tag == null || tag.isEmpty()) return false; return (tag.contains(ItemStack.TAG_ENCH, TAG_LIST) && !tag.getList(ItemStack.TAG_ENCH, TAG_COMPOUND).isEmpty()) - || (tag.contains("AttributeModifiers", TAG_LIST) && !tag.getList("AttributeModifiers", TAG_COMPOUND).isEmpty()); + || (tag.contains("AttributeModifiers", TAG_LIST) && !tag.getList("AttributeModifiers", TAG_COMPOUND).isEmpty()); } @Override @@ -321,8 +321,7 @@ private TurtleCommandResult dig(ITurtleAccess turtle, TurtleSide side, Direction } private static boolean isTriviallyBreakable(BlockGetter reader, BlockPos pos, BlockState state) { - return - state.is(ComputerCraftTags.Blocks.TURTLE_ALWAYS_BREAKABLE) + return state.is(ComputerCraftTags.Blocks.TURTLE_ALWAYS_BREAKABLE) // Allow breaking any "instabreak" block. || state.getDestroySpeed(reader, pos) == 0; } diff --git a/projects/core/src/main/java/dan200/computercraft/core/apis/http/options/AddressPredicate.java b/projects/core/src/main/java/dan200/computercraft/core/apis/http/options/AddressPredicate.java index 2ebed272c..eb1d284ef 100644 --- a/projects/core/src/main/java/dan200/computercraft/core/apis/http/options/AddressPredicate.java +++ b/projects/core/src/main/java/dan200/computercraft/core/apis/http/options/AddressPredicate.java @@ -119,8 +119,7 @@ final class PrivatePattern implements AddressPredicate { @Override public boolean matches(InetAddress socketAddress) { - return - socketAddress.isAnyLocalAddress() // 0.0.0.0, ::0 + return socketAddress.isAnyLocalAddress() // 0.0.0.0, ::0 || socketAddress.isLoopbackAddress() // 127.0.0.0/8, ::1 || socketAddress.isLinkLocalAddress() // 169.254.0.0/16, fe80::/10 || socketAddress.isSiteLocalAddress() // 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, fec0::/10 diff --git a/projects/fabric/build.gradle.kts b/projects/fabric/build.gradle.kts index bd1d4981f..bfdc31621 100644 --- a/projects/fabric/build.gradle.kts +++ b/projects/fabric/build.gradle.kts @@ -47,6 +47,7 @@ addRemappedConfiguration("testWithSodium") addRemappedConfiguration("testWithIris") dependencies { + clientCompileOnly(variantOf(libs.emi) { classifier("api") }) modImplementation(libs.bundles.externalMods.fabric) modCompileOnly(libs.bundles.externalMods.fabric.compile) { exclude("net.fabricmc", "fabric-loader") diff --git a/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json b/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json index ca14707a5..d2af43c73 100644 --- a/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json +++ b/projects/fabric/src/generated/resources/assets/computercraft/lang/en_us.json @@ -206,6 +206,10 @@ "item.computercraft.printed_pages": "Printed Pages", "item.computercraft.treasure_disk": "Floppy Disk", "itemGroup.computercraft": "ComputerCraft", + "tag.item.computercraft.computer": "Computers", + "tag.item.computercraft.monitor": "Monitors", + "tag.item.computercraft.turtle": "Turtles", + "tag.item.computercraft.wired_modem": "Wired modems", "tracking_field.computercraft.avg": "%s (avg)", "tracking_field.computercraft.computer_tasks.name": "Tasks", "tracking_field.computercraft.count": "%s (count)", diff --git a/projects/fabric/src/main/resources/fabric.mod.json b/projects/fabric/src/main/resources/fabric.mod.json index 189e29bcd..e9caa6453 100644 --- a/projects/fabric/src/main/resources/fabric.mod.json +++ b/projects/fabric/src/main/resources/fabric.mod.json @@ -31,6 +31,9 @@ ], "rei_client": [ "dan200.computercraft.client.integration.rei.REIComputerCraft" + ], + "emi": [ + "dan200.computercraft.client.integration.emi.EMIComputerCraft" ] }, "mixins": [ diff --git a/projects/forge/build.gradle.kts b/projects/forge/build.gradle.kts index 0437e531f..4dcb48ecb 100644 --- a/projects/forge/build.gradle.kts +++ b/projects/forge/build.gradle.kts @@ -127,6 +127,7 @@ dependencies { compileOnly(libs.jetbrainsAnnotations) annotationProcessorEverywhere(libs.autoService) + clientCompileOnly(variantOf(libs.emi) { classifier("api") }) libs.bundles.externalMods.forge.compile.get().map { compileOnly(fg.deobf(it)) } libs.bundles.externalMods.forge.runtime.get().map { runtimeOnly(fg.deobf(it)) } diff --git a/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json b/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json index ca14707a5..d2af43c73 100644 --- a/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json +++ b/projects/forge/src/generated/resources/assets/computercraft/lang/en_us.json @@ -206,6 +206,10 @@ "item.computercraft.printed_pages": "Printed Pages", "item.computercraft.treasure_disk": "Floppy Disk", "itemGroup.computercraft": "ComputerCraft", + "tag.item.computercraft.computer": "Computers", + "tag.item.computercraft.monitor": "Monitors", + "tag.item.computercraft.turtle": "Turtles", + "tag.item.computercraft.wired_modem": "Wired modems", "tracking_field.computercraft.avg": "%s (avg)", "tracking_field.computercraft.computer_tasks.name": "Tasks", "tracking_field.computercraft.count": "%s (count)",