1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-08-23 05:58:14 +00:00

Merge branch 'mc-1.20.x' into mc-1.21.x

This commit is contained in:
Jonathan Coates 2025-06-15 16:31:51 +01:00
commit 89dd521930
No known key found for this signature in database
GPG Key ID: B9E431FF07C98D06
16 changed files with 161 additions and 71 deletions

View File

@ -59,8 +59,8 @@ jmh = "1.37"
# Build tools
cctJavadoc = "1.8.4"
checkstyle = "10.21.4"
errorProne-core = "2.37.0"
checkstyle = "10.23.1"
errorProne-core = "2.38.0"
errorProne-plugin = "4.1.0"
fabric-loom = "1.10.4"
githubRelease = "2.5.2"
@ -70,7 +70,7 @@ illuaminate = "0.1.0-83-g1131f68"
lwjgl = "3.3.3"
minotaur = "2.8.7"
modDevGradle = "2.0.78"
nullAway = "0.12.4"
nullAway = "0.12.7"
shadow = "8.3.1"
spotless = "7.0.2"
taskTree = "2.1.1"

View File

@ -0,0 +1,40 @@
// SPDX-FileCopyrightText: 2025 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.client.gui;
import org.lwjgl.glfw.GLFW;
/**
* Supports for converting/translating key codes.
*/
public class KeyConverter {
/**
* GLFW's key events refer to the physical key code, rather than the "actual" key code (with keyboard layout
* applied).
* <p>
* This makes sense for WASD-style input, but is a right pain for keyboard shortcuts this function attempts to
* translate those keys back to their "actual" key code. See also
* <a href="https://github.com/glfw/glfw/issues/1502"> this discussion on GLFW's GitHub.</a>
*
* @param key The current key code.
* @param scanCode The current scan code.
* @return The translated key code.
*/
public static int physicalToActual(int key, int scanCode) {
var name = GLFW.glfwGetKeyName(key, scanCode);
if (name == null || name.length() != 1) return key;
// If we've got a single character as the key name, treat that as the ASCII value of the key,
// and map that back to a key code.
var character = name.charAt(0);
// 0-9 and A-Z map directly to their GLFW key (they're the same ASCII code).
if ((character >= '0' && character <= '9') || (character >= 'A' && character <= 'Z')) return character;
// a-z map to GLFW_KEY_{A,Z}
if (character >= 'a' && character <= 'z') return GLFW.GLFW_KEY_A + (character - 'a');
return key;
}
}

View File

@ -4,6 +4,7 @@
package dan200.computercraft.client.gui.widgets;
import dan200.computercraft.client.gui.KeyConverter;
import dan200.computercraft.client.render.RenderTypes;
import dan200.computercraft.client.render.text.FixedWidthFontRenderer;
import dan200.computercraft.core.terminal.Terminal;
@ -83,7 +84,7 @@ public class TerminalWidget extends AbstractWidget {
}
if ((modifiers & GLFW.GLFW_MOD_CONTROL) != 0) {
switch (key) {
switch (KeyConverter.physicalToActual(key, scancode)) {
case GLFW.GLFW_KEY_T -> {
if (terminateTimer < 0) terminateTimer = 0;
}
@ -119,7 +120,7 @@ public class TerminalWidget extends AbstractWidget {
computer.keyUp(key);
}
switch (key) {
switch (KeyConverter.physicalToActual(key, scancode)) {
case GLFW.GLFW_KEY_T -> terminateTimer = -1;
case GLFW.GLFW_KEY_R -> rebootTimer = -1;
case GLFW.GLFW_KEY_S -> shutdownTimer = -1;

View File

@ -62,8 +62,8 @@ public class TurtleBlockEntityRenderer implements BlockEntityRenderer<TurtleBloc
var matrix = transform.last().pose();
var opacity = (int) (mc.options.getBackgroundOpacity(0.25f) * 255) << 24;
var width = -font.width(label) / 2.0f;
font.drawInBatch(label, width, (float) 0, 0x20ffffff, false, matrix, buffers, Font.DisplayMode.SEE_THROUGH, opacity, lightmapCoord);
font.drawInBatch(label, width, (float) 0, CommonColors.WHITE, false, matrix, buffers, Font.DisplayMode.NORMAL, 0, lightmapCoord);
font.drawInBatch(label, width, 0, 0x20ffffff, false, matrix, buffers, Font.DisplayMode.SEE_THROUGH, opacity, lightmapCoord);
font.drawInBatch(label, width, 0, CommonColors.WHITE, false, matrix, buffers, Font.DisplayMode.NORMAL, 0, lightmapCoord);
transform.popPose();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 148 B

After

Width:  |  Height:  |  Size: 136 B

View File

@ -76,6 +76,7 @@ public abstract class AbstractHandle {
* @cc.treturn [2] nil If seeking failed.
* @cc.treturn string The reason seeking failed.
* @cc.since 1.80pr1.9
* @cc.changed 1.109.0 Now available on all file handles, not just binary-mode handles.
*/
public Object @Nullable [] seek(Optional<String> whence, Optional<Long> offset) throws LuaException {
checkOpen();
@ -179,6 +180,8 @@ public abstract class AbstractHandle {
* @throws LuaException If the file has been closed.
* @cc.treturn string|nil The remaining contents of the file, or {@code nil} in the event of an error.
* @cc.since 1.80pr1
* @cc.changed 1.109.0 Binary-mode handles are now consistent with non-binary files, and return an empty string at
* the end of the file, rather than {@code nil}.
*/
public Object @Nullable [] readAll() throws LuaException {
checkOpen();

View File

@ -120,7 +120,7 @@ public final class StringUtil {
var idx = 0;
var iterator = clipboard.codePoints().iterator();
while (iterator.hasNext() && idx <= output.length) {
while (iterator.hasNext() && idx < output.length) {
var chr = unicodeToTerminal(iterator.next());
if (chr < 0) continue; // Strip out unconvertible characters
if (!isTypableChar(chr)) break; // Stop at untypable ones.

View File

@ -371,7 +371,7 @@ function toBlit(color)
local hex = color_hex_lookup[color]
if hex then return hex end
if color < 0 or color > 0xffff then error("Colour out of range", 2) end
if color < 1 or color > 0xffff then error("Colour out of range", 2) end
return string.format("%x", math.floor(math.log(color, 2)))
end

View File

@ -65,7 +65,7 @@ local function parse_color(color)
return expect(1, color, "number")
end
if color < 0 or color > 0xffff then error("Colour out of range", 3) end
if color < 1 or color > 0xffff then error("Colour out of range", 3) end
return 2 ^ math.floor(math.log(color, 2))
end

View File

@ -238,7 +238,7 @@ local function lex_token(context, str, pos)
if end_pos then return tokens.STRING, end_pos end
context.report(errors.unfinished_long_string, pos, boundary_pos, boundary_pos - pos)
return tokens.ERROR, #str
return tokens.STRING, #str
elseif pos + 1 == boundary_pos then -- Just a "["
return tokens.OSQUARE, pos
else -- Malformed long string, for instance "[="
@ -260,7 +260,7 @@ local function lex_token(context, str, pos)
if end_pos then return tokens.COMMENT, end_pos end
context.report(errors.unfinished_long_comment, pos, boundary_pos, boundary_pos - comment_pos)
return tokens.ERROR, #str
return tokens.COMMENT, #str
end
end

View File

@ -175,63 +175,62 @@ local function save(_sPath, fWrite)
return ok, err, fileerr
end
local tKeywords = {
["and"] = true,
["break"] = true,
["do"] = true,
["else"] = true,
["elseif"] = true,
["end"] = true,
["false"] = true,
["for"] = true,
["function"] = true,
["if"] = true,
["in"] = true,
["local"] = true,
["nil"] = true,
["not"] = true,
["or"] = true,
["repeat"] = true,
["return"] = true,
["then"] = true,
["true"] = true,
["until"] = true,
["while"] = true,
}
local function tryWrite(sLine, regex, colour)
local match = string.match(sLine, regex)
if match then
if type(colour) == "number" then
term.setTextColour(colour)
else
term.setTextColour(colour(match))
end
term.write(match)
term.setTextColour(textColour)
return string.sub(sLine, #match + 1)
end
return nil
local tokens = require "cc.internal.syntax.parser".tokens
local lex_one = require "cc.internal.syntax.lexer".lex_one
local token_colours = {
[tokens.STRING] = stringColour,
[tokens.COMMENT] = commentColour,
-- Keywords
[tokens.AND] = keywordColour,
[tokens.BREAK] = keywordColour,
[tokens.DO] = keywordColour,
[tokens.ELSE] = keywordColour,
[tokens.ELSEIF] = keywordColour,
[tokens.END] = keywordColour,
[tokens.FALSE] = keywordColour,
[tokens.FOR] = keywordColour,
[tokens.FUNCTION] = keywordColour,
[tokens.GOTO] = keywordColour,
[tokens.IF] = keywordColour,
[tokens.IN] = keywordColour,
[tokens.LOCAL] = keywordColour,
[tokens.NIL] = keywordColour,
[tokens.NOT] = keywordColour,
[tokens.OR] = keywordColour,
[tokens.REPEAT] = keywordColour,
[tokens.RETURN] = keywordColour,
[tokens.THEN] = keywordColour,
[tokens.TRUE] = keywordColour,
[tokens.UNTIL] = keywordColour,
[tokens.WHILE] = keywordColour,
}
-- Fill in the remaining tokens.
for _, token in pairs(tokens) do
if not token_colours[token] then token_colours[token] = textColour end
end
local function writeHighlighted(sLine)
while #sLine > 0 do
sLine =
tryWrite(sLine, "^%-%-%[%[.-%]%]", commentColour) or
tryWrite(sLine, "^%-%-.*", commentColour) or
tryWrite(sLine, "^\"\"", stringColour) or
tryWrite(sLine, "^\".-[^\\]\"", stringColour) or
tryWrite(sLine, "^\'\'", stringColour) or
tryWrite(sLine, "^\'.-[^\\]\'", stringColour) or
tryWrite(sLine, "^%[%[.-%]%]", stringColour) or
tryWrite(sLine, "^[%w_]+", function(match)
if tKeywords[match] then
return keywordColour
end
return textColour
end) or
tryWrite(sLine, "^[^%w_]", textColour)
local lex_context = { line = function() end, report = function() end }
local function writeHighlighted(line)
local pos, colour = 1, nil
while true do
local token, _, finish = lex_one(lex_context, line, pos)
if not token then break end
local new_colour = token_colours[token]
if new_colour ~= colour then
term.setTextColor(new_colour)
colour = new_colour
end
term.write(line:sub(pos, finish))
pos = finish + 1
end
term.write(line:sub(pos))
end
local tCompletions
@ -352,7 +351,7 @@ local tMenuFuncs = {
if bReadOnly then
set_status("Access denied", false)
else
local ok, _, fileerr = save(sPath, function(file)
local ok, _, fileerr = save(sPath, function(file)
for _, sLine in ipairs(tLines) do
file.write(sLine .. "\n")
end
@ -547,7 +546,7 @@ local function acceptCompletion()
-- Append the completion
local sCompletion = tCompletions[nCompletion]
tLines[y] = tLines[y] .. sCompletion
setCursor(x + #sCompletion , y)
setCursor(x + #sCompletion, y)
end
end
@ -805,7 +804,7 @@ while bRunning do
-- Input text
local sLine = tLines[y]
tLines[y] = string.sub(sLine, 1, x - 1) .. param .. string.sub(sLine, x)
setCursor(x + #param , y)
setCursor(x + #param, y)
end
elseif sEvent == "mouse_click" then

View File

@ -191,7 +191,7 @@ end
-- Show MOTD
if settings.get("motd.enable") then
shell.run("motd")
shell.run("/rom/programs/motd")
end
-- Run the user created startup, either from disk drives or the root

View File

@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: 2025 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.core.util;
import dan200.computercraft.api.lua.LuaValues;
import dan200.computercraft.test.core.ReplaceUnderscoresDisplayNameGenerator;
import org.junit.jupiter.api.DisplayNameGeneration;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
@DisplayNameGeneration(ReplaceUnderscoresDisplayNameGenerator.class)
class StringUtilTest {
@ParameterizedTest
@ValueSource(strings = { "hello\nworld", "hello\n\rworld", "hello\rworld" })
public void getClipboardString_returns_a_single_line(String input) {
var result = StringUtil.getClipboardString(input);
assertEquals(LuaValues.encode("hello"), result);
}
@Test
public void getClipboardString_limits_length() {
var input = "abcdefghijklmnop".repeat(50);
var result = StringUtil.getClipboardString(input);
assertEquals(StringUtil.MAX_PASTE_LENGTH, result.limit());
assertEquals(
LuaValues.encode(input.substring(0, StringUtil.MAX_PASTE_LENGTH)),
result
);
}
}

View File

@ -94,6 +94,7 @@ describe("The colors library", function()
end)
it("errors on out-of-range colours", function()
expect.error(colors.toBlit, 0):eq("Colour out of range")
expect.error(colors.toBlit, -120):eq("Colour out of range")
expect.error(colors.toBlit, 0x10000):eq("Colour out of range")
end)

View File

@ -59,6 +59,16 @@ describe("The window library", function()
expect.error(w.setTextColour, nil):eq("bad argument #1 (number expected, got nil)")
expect.error(w.setTextColour, -5):eq("Colour out of range")
expect.error(w.setTextColour, 0):eq("Colour out of range")
expect.error(w.setTextColour, 0x10000):eq("Colour out of range")
end)
it("accepts valid colours", function()
local w = mk()
for i = 0, 15 do
w.setBackgroundColour(2 ^ i)
expect(w.getBackgroundColour()):eq(2 ^ i)
end
end)
it("supports invalid combined colours", function()

View File

@ -67,7 +67,7 @@ This comment was never finished.
1 | --[=[
| ^^^^^ Comment was started here.
We expected a closing delimiter (]=]) somewhere after this comment was started.
1:1-1:5 ERROR --[=[
1:1-1:5 COMMENT --[=[
```
Nested comments are rejected, just as Lua 5.1 does:
@ -191,7 +191,7 @@ This string was never finished.
1 | return [[
| ^^ String was started here.
We expected a closing delimiter (]]) somewhere after this string was started.
1:8-1:9 ERROR [[
1:8-1:9 STRING [[
```
We also handle malformed opening strings: