diff --git a/build.gradle.kts b/build.gradle.kts index 4d5991ea0..296916aea 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -18,7 +18,8 @@ plugins { val isUnstable = project.properties["isUnstable"] == "true" val modVersion: String by extra -val mcVersion: String by extra +val mcVersion = project.extensions.getByType().named("libs") + .findVersion("minecraft").get().toString() githubRelease { token(findProperty("githubApiKey") as String? ?: "") diff --git a/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts b/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts index 630affb87..8232b5d0b 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.fabric.gradle.kts @@ -17,8 +17,6 @@ plugins { plugins.apply(CCTweakedPlugin::class.java) -val mcVersion: String by extra - repositories { maven("https://maven.parchmentmc.org/") { name = "Parchment" @@ -42,7 +40,7 @@ extensions.configure(CCTweakedExtension::class.java) { dependencies { val libs = project.extensions.getByType().named("libs") - minecraft("com.mojang:minecraft:$mcVersion") + minecraft("com.mojang:minecraft:${libs.findVersion("minecraft").get()}") mappings( loom.layered { officialMojangMappings() diff --git a/buildSrc/src/main/kotlin/cc-tweaked.forge.gradle.kts b/buildSrc/src/main/kotlin/cc-tweaked.forge.gradle.kts index e917296d5..a7bfe2006 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.forge.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.forge.gradle.kts @@ -15,8 +15,6 @@ plugins { plugins.apply(CCTweakedPlugin::class.java) -val mcVersion: String by extra - neoForge { val libs = project.extensions.getByType().named("libs") version = libs.findVersion("neoForge").get().toString() 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 9ffe10815..cc96eeb52 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.java-convention.gradle.kts @@ -22,12 +22,12 @@ plugins { } val modVersion: String by extra -val mcVersion: String by extra + +val libs = project.extensions.getByType().named("libs") group = "cc.tweaked" version = modVersion - -base.archivesName.convention("cc-tweaked-$mcVersion-${project.name}") +base.archivesName.set("cc-tweaked-${libs.findVersion("minecraft").get()}-${project.name}") java { toolchain { languageVersion = CCTweakedPlugin.JDK_VERSION } @@ -63,7 +63,6 @@ repositories { } dependencies { - val libs = project.extensions.getByType().named("libs") checkstyle(libs.findLibrary("checkstyle").get()) constraints { diff --git a/buildSrc/src/main/kotlin/cc-tweaked.mod-publishing.gradle.kts b/buildSrc/src/main/kotlin/cc-tweaked.mod-publishing.gradle.kts index ec1254e6f..5f2451d0c 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.mod-publishing.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.mod-publishing.gradle.kts @@ -21,7 +21,8 @@ val modPublishing = project.extensions.create("modPublishing", ModPublishingExte val isUnstable = project.properties["isUnstable"] == "true" val modVersion: String by extra -val mcVersion: String by extra +val mcVersion = project.extensions.getByType().named("libs") + .findVersion("minecraft").get().toString() modrinth { token = findProperty("modrinthApiKey") as String? ?: "" diff --git a/buildSrc/src/main/kotlin/cc-tweaked.vanilla.gradle.kts b/buildSrc/src/main/kotlin/cc-tweaked.vanilla.gradle.kts index efcc7dbf5..785ef5e99 100644 --- a/buildSrc/src/main/kotlin/cc-tweaked.vanilla.gradle.kts +++ b/buildSrc/src/main/kotlin/cc-tweaked.vanilla.gradle.kts @@ -15,12 +15,10 @@ plugins { plugins.apply(CCTweakedPlugin::class.java) -val mcVersion: String by extra - val libs = project.extensions.getByType().named("libs") minecraft { - version(mcVersion) + version(libs.findVersion("minecraft").get().toString()) mappings { parchment(libs.findVersion("parchmentMc").get().toString(), libs.findVersion("parchment").get().toString()) diff --git a/gradle.properties b/gradle.properties index ca9be67e2..6530bbdd3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,6 +12,3 @@ kotlin.jvm.target.validation.mode=error modVersion=1.120.2 isUnstable=true - -# Minecraft properties: We want to configure this here so we can read it in settings.gradle -mcVersion=1.21.1 diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 56cfb40b2..09138d63d 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -5,8 +5,8 @@ [versions] # Minecraft -# MC version is specified in gradle.properties, as we need that in settings.gradle. # Remember to update corresponding versions in fabric.mod.json/neoforge.mods.toml +minecraft = "1.21.1" fabric-api = "0.116.12+1.21.1" fabric-loader = "0.18.4" neoForge = "21.1.9" diff --git a/projects/common-api/build.gradle.kts b/projects/common-api/build.gradle.kts index b5649f8c1..961974e61 100644 --- a/projects/common-api/build.gradle.kts +++ b/projects/common-api/build.gradle.kts @@ -8,7 +8,8 @@ plugins { id("cc-tweaked.vanilla") } -val mcVersion: String by extra +val mcVersion = project.extensions.getByType().named("libs") + .findVersion("minecraft").get().toString() java { withJavadocJar() diff --git a/projects/common-api/src/overview.html b/projects/common-api/src/overview.html index 87676ed72..e046a5a1f 100644 --- a/projects/common-api/src/overview.html +++ b/projects/common-api/src/overview.html @@ -14,6 +14,7 @@ SPDX-License-Identifier: MPL-2.0

Quick links

diff --git a/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java b/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java index c8101234b..a58bdc876 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java @@ -219,8 +219,10 @@ public class TurtlePlaceCommand implements TurtleCommand { } } - var useOnResult = stack.useOn(new UseOnContext(player, InteractionHand.MAIN_HAND, hit)); - if (useOnResult != InteractionResult.PASS) return useOnResult; + if (canUse.item()) { + var useOnResult = stack.useOn(new UseOnContext(player, InteractionHand.MAIN_HAND, hit)); + if (useOnResult != InteractionResult.PASS) return useOnResult; + } } } diff --git a/projects/common/src/main/resources/assets/computercraft/lang/fr_fr.json b/projects/common/src/main/resources/assets/computercraft/lang/fr_fr.json index e47a8a202..b83c08f8e 100644 --- a/projects/common/src/main/resources/assets/computercraft/lang/fr_fr.json +++ b/projects/common/src/main/resources/assets/computercraft/lang/fr_fr.json @@ -205,6 +205,7 @@ "item.computercraft.treasure_disk": "Disquette", "itemGroup.computercraft": "ComputerCraft", "tag.item.computercraft.computer": "Ordinateurs", + "tag.item.computercraft.disks": "Disques", "tag.item.computercraft.monitor": "Moniteurs", "tag.item.computercraft.turtle": "Tortues", "tag.item.computercraft.wired_modem": "Modems câblés", diff --git a/projects/common/src/main/resources/assets/computercraft/lang/ru_ru.json b/projects/common/src/main/resources/assets/computercraft/lang/ru_ru.json index de8609777..a1be9534b 100644 --- a/projects/common/src/main/resources/assets/computercraft/lang/ru_ru.json +++ b/projects/common/src/main/resources/assets/computercraft/lang/ru_ru.json @@ -1,5 +1,8 @@ { "argument.computercraft.argument_expected": "Ожидается аргумент", + "argument.computercraft.computer.distance": "Дистанция до существа", + "argument.computercraft.computer.family": "Группа компьютеров", + "argument.computercraft.computer.id": "ID компьютера", "argument.computercraft.computer.many_matching": "Несколько компьютеров соответствуют с '%s' (экземпляры %s)", "argument.computercraft.computer.no_matching": "Нет соответствующих компьютеров с '%s'", "argument.computercraft.tracking_field.no_field": "Неизвестное поле '%s'", @@ -11,6 +14,7 @@ "block.computercraft.monitor_advanced": "Продвинутый монитор", "block.computercraft.monitor_normal": "Монитор", "block.computercraft.printer": "Принтер", + "block.computercraft.redstone_relay": "Редстоуновый релей", "block.computercraft.speaker": "Колонка", "block.computercraft.turtle_advanced": "Продвинутая черепашка", "block.computercraft.turtle_advanced.upgraded": "Продвинутая черепашка: %s", @@ -104,11 +108,13 @@ "gui.computercraft.config.http.proxy.type.tooltip": "Тип используемого прокси-сервера.", "gui.computercraft.config.http.rules": "Разрешающие/запрещающие правила", "gui.computercraft.config.http.rules.tooltip": "Список правил, которые контролируют поведение «http» API для определенных доменов или\nIP-адресов. Каждое правило представляет собой элемент с «узлом» для сопоставления и набором\nсвойств. Правила оцениваются по порядку, то есть более ранние правила перевешивают\nболее поздние.\nХост может быть доменным именем (\"pastebin.com\"), wildcard-сертификатом (\"*.pastebin.com\") или\nнотацией CIDR (\"127.0.0.0/8\").\nЕсли правил нет, домен блокируется.", + "gui.computercraft.config.http.tooltip": "Контроль HTTP API", "gui.computercraft.config.http.websocket_enabled": "Включить веб-сокеты", "gui.computercraft.config.http.websocket_enabled.tooltip": "Включить использование http веб-сокетов. Для этого необходимо, чтобы параметр «http_enable» был true.", "gui.computercraft.config.log_computer_errors": "Регистрировать ошибки компьютера", "gui.computercraft.config.log_computer_errors.tooltip": "Регистрировать исключения, вызванные периферийными устройствами и другими объектами Lua. Это облегчает\nдля авторам модов устранение проблем, но может привести к спаму в логах, если люди будут использовать\nглючные методы.", "gui.computercraft.config.maximum_open_files": "Максимальное количество файлов, открытых на одном компьютере", + "gui.computercraft.config.monitor_renderer": "Рендер монитора", "gui.computercraft.config.peripheral": "Периферия", "gui.computercraft.config.term_sizes": "Размер терминала", "gui.computercraft.config.term_sizes.computer": "Компьютер", @@ -129,6 +135,7 @@ "gui.computercraft.config.turtle.normal_fuel_limit": "Лимит топлива Черепашек", "gui.computercraft.config.turtle.normal_fuel_limit.tooltip": "Лимит топлива для Черепашек", "gui.computercraft.config.turtle.tooltip": "Разные настройки, связанные с черепашками.", + "gui.computercraft.config.upload_max_size": "Лимит размера загрузки (в байтах)", "gui.computercraft.pocket_computer_overlay": "Карманный компьютер открыт. Чтобы закрыть, нажми ESC.", "gui.computercraft.terminal": "Компьютерный терминал", "gui.computercraft.tooltip.computer_id": "Идентификатор компьютера: %s", @@ -158,6 +165,9 @@ "item.computercraft.printed_pages": "Напечатанные страницы", "item.computercraft.treasure_disk": "Дискета", "itemGroup.computercraft": "ComputerCraft", + "tag.item.computercraft.computer": "Компьютеры", + "tag.item.computercraft.disks": "Диски", + "tag.item.computercraft.monitor": "Мониторы", "tracking_field.computercraft.avg": "%s (среднее)", "tracking_field.computercraft.computer_tasks.name": "Задачи", "tracking_field.computercraft.count": "%s (количество)", diff --git a/projects/common/src/main/resources/assets/computercraft/lang/zh_cn.json b/projects/common/src/main/resources/assets/computercraft/lang/zh_cn.json index b94e42cc5..2e64afa10 100644 --- a/projects/common/src/main/resources/assets/computercraft/lang/zh_cn.json +++ b/projects/common/src/main/resources/assets/computercraft/lang/zh_cn.json @@ -20,11 +20,11 @@ "block.computercraft.redstone_relay": "红石继电器", "block.computercraft.speaker": "扬声器", "block.computercraft.turtle_advanced": "高级海龟", - "block.computercraft.turtle_advanced.upgraded": "高级%s海龟", - "block.computercraft.turtle_advanced.upgraded_twice": "高级%s%s海龟", + "block.computercraft.turtle_advanced.upgraded": "高级海龟(%s)", + "block.computercraft.turtle_advanced.upgraded_twice": "高级海龟(%s)%s", "block.computercraft.turtle_normal": "海龟", - "block.computercraft.turtle_normal.upgraded": "%s海龟", - "block.computercraft.turtle_normal.upgraded_twice": "%s%s海龟", + "block.computercraft.turtle_normal.upgraded": "海龟(%s)", + "block.computercraft.turtle_normal.upgraded_twice": "海龟(%s)%s", "block.computercraft.wired_modem": "有线调制解调器", "block.computercraft.wired_modem_full": "有线调制解调器", "block.computercraft.wireless_modem_advanced": "末影调制解调器", diff --git a/projects/core/src/main/resources/data/computercraft/lua/bios.lua b/projects/core/src/main/resources/data/computercraft/lua/bios.lua index 2ba511e82..f9c90d316 100644 --- a/projects/core/src/main/resources/data/computercraft/lua/bios.lua +++ b/projects/core/src/main/resources/data/computercraft/lua/bios.lua @@ -628,12 +628,12 @@ settings.define("shell.autocomplete", { settings.define("edit.autocomplete", { default = true, description = "Autocomplete API and function names in the editor.", - type = "boolean", + type = "boolean", }) settings.define("lua.autocomplete", { default = true, description = "Autocomplete API and function names in the Lua REPL.", - type = "boolean", + type = "boolean", }) settings.define("edit.default_extension", { diff --git a/projects/core/src/main/resources/data/computercraft/lua/rom/programs/advanced/multishell.lua b/projects/core/src/main/resources/data/computercraft/lua/rom/programs/advanced/multishell.lua index f2cd68b88..56728be43 100644 --- a/projects/core/src/main/resources/data/computercraft/lua/rom/programs/advanced/multishell.lua +++ b/projects/core/src/main/resources/data/computercraft/lua/rom/programs/advanced/multishell.lua @@ -127,6 +127,17 @@ local function cullProcess(nProcess) return false end +--[[- Resume and then cull a process. + +This helps avoid the pattern where one calls +`resumeProcess(nCurrentProcess, ...); cullProcess(nCurrentProcess)`, and the +current process changes while the code is running. +]] +local function resumeAndCullProcess(process, ...) + resumeProcess(process, ...) + return cullProcess(process) +end + local function cullProcesses() local culled = false for n = #tProcesses, 1, -1 do @@ -341,8 +352,7 @@ while #tProcesses > 0 do elseif sEvent == "char" or sEvent == "key" or sEvent == "key_up" or sEvent == "paste" or sEvent == "terminate" or sEvent == "file_transfer" then -- Basic input, just passthrough to current process - resumeProcess(nCurrentProcess, table.unpack(tEventData, 1, tEventData.n)) - if cullProcess(nCurrentProcess) then + if resumeAndCullProcess(nCurrentProcess, table.unpack(tEventData, 1, tEventData.n)) then setMenuVisible(#tProcesses >= 2) redrawMenu() end @@ -375,8 +385,7 @@ while #tProcesses > 0 do end else -- Passthrough to current process - resumeProcess(nCurrentProcess, sEvent, button, x, bShowMenu and y - 1 or y) - if cullProcess(nCurrentProcess) then + if resumeAndCullProcess(nCurrentProcess, sEvent, button, x, bShowMenu and y - 1 or y) then setMenuVisible(#tProcesses >= 2) redrawMenu() end @@ -395,8 +404,7 @@ while #tProcesses > 0 do end elseif not (bShowMenu and y == 1) then -- Passthrough to current process - resumeProcess(nCurrentProcess, sEvent, p1, x, bShowMenu and y - 1 or y) - if cullProcess(nCurrentProcess) then + if resumeAndCullProcess(nCurrentProcess, sEvent, p1, x, bShowMenu and y - 1 or y) then setMenuVisible(#tProcesses >= 2) redrawMenu() end @@ -405,8 +413,7 @@ while #tProcesses > 0 do else -- Other event -- Passthrough to all processes - local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event - for n = 1, nLimit do + for n = 1, #tProcesses do resumeProcess(n, table.unpack(tEventData, 1, tEventData.n)) end if cullProcesses() then @@ -417,8 +424,7 @@ while #tProcesses > 0 do if bWindowsResized then -- Pass term_resize to all processes - local nLimit = #tProcesses -- Storing this ensures any new things spawned don't get the event - for n = 1, nLimit do + for n = 1, #tProcesses do resumeProcess(n, "term_resize") end bWindowsResized = false diff --git a/projects/core/src/test/resources/test-rom/spec/programs/advanced/multishell_spec.lua b/projects/core/src/test/resources/test-rom/spec/programs/advanced/multishell_spec.lua index f06904fcb..1fcbf6e72 100644 --- a/projects/core/src/test/resources/test-rom/spec/programs/advanced/multishell_spec.lua +++ b/projects/core/src/test/resources/test-rom/spec/programs/advanced/multishell_spec.lua @@ -31,4 +31,48 @@ describe("The multishell program", function() expect.error(multishell.launch, _ENV, nil):eq("bad argument #2 (string expected, got nil)") end) end) + + describe("the main loop", function() + it("culls a process after exiting", function() + local function find_local(co, find) + for level = 1, 10 do + for var = 1, 255 do + local name, value = debug.getlocal(co, level, var) + if name == nil then break end + if find == name then return value end + end + end + + fail("Cannot find local " .. find) + end + + -- We create a very awkward program here which pulls an event (so we can inspect the intermediate state), + -- then switches to a different tab before exiting, causing nCurrentProcess to change in the multishell + -- loop. + io.open("/test-files/a.lua", "w"):write([[os.pullEvent("mouse_click"); multishell.setFocus(1)]]):close() + + local window = window.create(term.current(), 1, 1, 51, 19, false) + local co = coroutine.create(function() os.run({ shell = shell }, "rom/programs/advanced/multishell.lua") end) + local function resume(...) + local old = term.redirect(window) + local ok, err = coroutine.resume(co, ...) + term.redirect(old) + if not ok then fail("Coroutine failed: " .. err) end + end + + resume() + local multishell = find_local(co, "multishell") + expect(multishell.getFocus()):eq(1) + expect(multishell.getCount()):eq(1) + + resume("paste", "fg /test-files/a.lua") + resume("key", keys.enter, false) + expect(multishell.getFocus()):eq(2) + expect(multishell.getCount()):eq(2) + + resume("mouse_click", 1, 1, 2) + expect(multishell.getFocus()):eq(1) + expect(multishell.getCount()):eq(1) + end) + end) end) diff --git a/settings.gradle.kts b/settings.gradle.kts index 38302d6b1..1c9fb6ba6 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -30,8 +30,7 @@ plugins { id("org.gradle.toolchains.foojay-resolver-convention") version("1.0.0") } -val mcVersion: String by settings -rootProject.name = "cc-tweaked-$mcVersion" +rootProject.name = "cc-tweaked" include(":core-api") include(":core")