mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2026-06-30 16:48:50 +00:00
Merge branch 'mc-1.21.x' into mc-26.1
This commit is contained in:
@@ -10,9 +10,9 @@ body:
|
||||
description: |
|
||||
What version of Minecraft are you using? If your version is not listed, please try to reproduce on one of the supported versions.
|
||||
options:
|
||||
- 1.20.1
|
||||
- 1.21.1
|
||||
- 1.21.7
|
||||
- "1.20.1"
|
||||
- "1.21.1"
|
||||
- "26.1"
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
|
||||
@@ -55,7 +55,6 @@ repositories {
|
||||
includeGroup("me.shedaniel.cloth")
|
||||
includeGroup("me.shedaniel")
|
||||
includeGroup("mezz.jei")
|
||||
includeGroup("org.teavm")
|
||||
includeModule("com.terraformersmc", "modmenu")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,12 @@ compatibility for these newer versions.
|
||||
| Remove `*` from `file:read` modes | ✔ | |
|
||||
| Metamethods respected in `table.*`, `ipairs` | ✔ | |
|
||||
|
||||
## Lua 5.5
|
||||
| Feature | Supported? | Notes |
|
||||
|------------------------------------|------------|-------|
|
||||
| `table.create` | ✔ | |
|
||||
| `utf8.offset` returns end position | ✔ | |
|
||||
|
||||
## Lua 5.0
|
||||
| Feature | Supported? | Notes |
|
||||
|----------------------------------|------------|--------------------------------------------------|
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ neogradle.subsystems.conventions.runs.enabled=false
|
||||
|
||||
# Mod properties
|
||||
isUnstable=true
|
||||
modVersion=1.118.1
|
||||
modVersion=1.119.0
|
||||
|
||||
# Minecraft properties: We want to configure this here so we can read it in settings.gradle
|
||||
mcVersion=26.1.2
|
||||
|
||||
+17
-17
@@ -22,14 +22,14 @@ slf4j = "2.0.17"
|
||||
# Core dependencies (independent of Minecraft)
|
||||
asm = "9.9.1"
|
||||
autoService = "1.1.1"
|
||||
checkerFramework = "3.51.1"
|
||||
cobalt = { strictly = "0.9.7" }
|
||||
commonsCli = "1.10.0"
|
||||
jetbrainsAnnotations = "26.0.2-1"
|
||||
checkerFramework = "4.0.0"
|
||||
cobalt = { strictly = "0.9.9" }
|
||||
commonsCli = "1.11.0"
|
||||
jetbrainsAnnotations = "26.1.0"
|
||||
jspecify = "1.0.0"
|
||||
kotlin = "2.3.20"
|
||||
kotlin = "2.3.21"
|
||||
kotlin-coroutines = "1.10.2"
|
||||
nightConfig = "3.8.3"
|
||||
nightConfig = "3.8.4"
|
||||
|
||||
# Minecraft mods
|
||||
fabricPermissions = "0.3.3"
|
||||
@@ -47,29 +47,29 @@ create-fabric = "6.0.7.0+mc1.20.1-build.1716"
|
||||
# Testing
|
||||
hamcrest = "3.0"
|
||||
jqwik = "1.9.3"
|
||||
junit = "6.0.1"
|
||||
junitPlatform = "6.0.1"
|
||||
junit = "6.0.3"
|
||||
junitPlatform = "6.0.3"
|
||||
jmh = "1.37"
|
||||
|
||||
# Build tools
|
||||
cctJavadoc = "1.9.0"
|
||||
checkstyle = "12.1.1"
|
||||
errorProne-core = "2.45.0"
|
||||
checkstyle = "13.4.1"
|
||||
errorProne-core = "2.49.0"
|
||||
errorProne-plugin = "4.3.0"
|
||||
fabric-loom = "1.16.1"
|
||||
githubRelease = "2.5.2"
|
||||
gradleVersions = "0.53.0"
|
||||
gradleVersions = "0.54.0"
|
||||
ideaExt = "1.3"
|
||||
illuaminate = "0.1.0-83-g1131f68"
|
||||
lwjgl = "3.3.6"
|
||||
lwjgl = "3.4.1"
|
||||
minotaur = "2.8.7"
|
||||
modDevGradle = "2.0.141"
|
||||
nullAway = "0.12.14"
|
||||
shadow = "9.2.2"
|
||||
spotless = "8.0.0"
|
||||
teavm = "0.14.0-SQUID.1"
|
||||
nullAway = "0.13.4"
|
||||
shadow = "9.4.1"
|
||||
spotless = "8.4.0"
|
||||
teavm = "0.14.0"
|
||||
vanillaExtract = "0.3.1"
|
||||
versionCatalogUpdate = "1.0.1"
|
||||
versionCatalogUpdate = "1.1.0"
|
||||
|
||||
[libraries]
|
||||
# Normal dependencies
|
||||
|
||||
Vendored
BIN
Binary file not shown.
+3
-1
@@ -1,7 +1,9 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.4.1-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-9.5.0-bin.zip
|
||||
networkTimeout=10000
|
||||
retries=0
|
||||
retryBackOffMs=500
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# https://github.com/gradle/gradle/blob/3d91ce3b8caaf77ad09f381f43615b715b53f72c/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
|
||||
Vendored
+10
-21
@@ -23,8 +23,8 @@
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
@rem Set local scope for the variables, and ensure extensions are enabled
|
||||
setlocal EnableExtensions
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@@ -51,7 +51,7 @@ echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
@@ -65,7 +65,7 @@ echo. 1>&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||
echo location of your Java installation. 1>&2
|
||||
|
||||
goto fail
|
||||
"%COMSPEC%" /c exit 1
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
@@ -73,21 +73,10 @@ goto fail
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||
@rem endlocal doesn't take effect until after the line is parsed and variables are expanded
|
||||
@rem which allows us to clear the local environment before executing the java command
|
||||
endlocal & "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* & call :exitWithErrorLevel
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
:exitWithErrorLevel
|
||||
@rem Use "%COMSPEC%" /c exit to allow operators to work properly in scripts
|
||||
"%COMSPEC%" /c exit %ERRORLEVEL%
|
||||
|
||||
Generated
+51
-51
@@ -971,9 +971,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.30.tgz",
|
||||
"integrity": "sha512-R8VQbQY1BZcbIF2p3gjlTCwAQzx1A194ugWfwld5y+WgVVWqVKm7eURGGOVbQVubgKWzidP2agomBbg96rZilQ==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core/-/core-1.15.32.tgz",
|
||||
"integrity": "sha512-/eWL0n43D64QWEUHLtTE+jDqjkJhyidjkDhv6f0uJohOUAhywxQ9wXYp845DNNds0JpCdI4Uo0a9bl+vbXf+ew==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "Apache-2.0",
|
||||
@@ -989,18 +989,18 @@
|
||||
"url": "https://opencollective.com/swc"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-darwin-arm64": "1.15.30",
|
||||
"@swc/core-darwin-x64": "1.15.30",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.15.30",
|
||||
"@swc/core-linux-arm64-gnu": "1.15.30",
|
||||
"@swc/core-linux-arm64-musl": "1.15.30",
|
||||
"@swc/core-linux-ppc64-gnu": "1.15.30",
|
||||
"@swc/core-linux-s390x-gnu": "1.15.30",
|
||||
"@swc/core-linux-x64-gnu": "1.15.30",
|
||||
"@swc/core-linux-x64-musl": "1.15.30",
|
||||
"@swc/core-win32-arm64-msvc": "1.15.30",
|
||||
"@swc/core-win32-ia32-msvc": "1.15.30",
|
||||
"@swc/core-win32-x64-msvc": "1.15.30"
|
||||
"@swc/core-darwin-arm64": "1.15.32",
|
||||
"@swc/core-darwin-x64": "1.15.32",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.15.32",
|
||||
"@swc/core-linux-arm64-gnu": "1.15.32",
|
||||
"@swc/core-linux-arm64-musl": "1.15.32",
|
||||
"@swc/core-linux-ppc64-gnu": "1.15.32",
|
||||
"@swc/core-linux-s390x-gnu": "1.15.32",
|
||||
"@swc/core-linux-x64-gnu": "1.15.32",
|
||||
"@swc/core-linux-x64-musl": "1.15.32",
|
||||
"@swc/core-win32-arm64-msvc": "1.15.32",
|
||||
"@swc/core-win32-ia32-msvc": "1.15.32",
|
||||
"@swc/core-win32-x64-msvc": "1.15.32"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@swc/helpers": ">=0.5.17"
|
||||
@@ -1012,9 +1012,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-arm64": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.30.tgz",
|
||||
"integrity": "sha512-VvpP+vq08HmGYewMWvrdsxh9s2lthz/808zXm8Yu5kaqeR8Yia2b0eYXleHQ3VAjoStUDk6LzTheBW9KXYQdMA==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.32.tgz",
|
||||
"integrity": "sha512-/YWMvJDPu+AAwuUsM2G+DNQ/7zhodURGzdQyewEqcvgklAdDHs3LwQmLLnyn6SJl8DT8UOxkbzK+D1PmPeelRg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1029,9 +1029,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-darwin-x64": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.30.tgz",
|
||||
"integrity": "sha512-WiJA0hiZI3nwQAO6mu5RqigtWGDtth4Hiq6rbZxAaQyhIcqKIg5IoMRc1Y071lrNJn29eEDMC86Rq58xgUxlDg==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.15.32.tgz",
|
||||
"integrity": "sha512-KOTXJXdAhWL+hZ77MYP3z+4pcMFaQhQ74yqyN1uz093q0YnbxpqMtYpPISbYvMHzVRNNx5kN+9RZAXEaadhWVA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1046,9 +1046,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm-gnueabihf": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.30.tgz",
|
||||
"integrity": "sha512-YANuFUo48kIT6plJgCD0keae9HFXfjxsbvsgevqc0hr/07X/p7sAWTFOGYEc2SXcASaK7UvuQqzlbW8pr7R79g==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.15.32.tgz",
|
||||
"integrity": "sha512-oOoxLweljlc0A4X8ybsgxV7cVaYTwBOg2iMDJcFR3Sr48C+lsv9VzSmqdK/IVIXF4W4GjLc3VqTAdSMXlfVLuQ==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
@@ -1063,9 +1063,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-gnu": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-VndG8jaR4ugY6u+iVOT0Q+d2fZd7sLgjPgN8W/Le+3EbZKl+cRfFxV7Eoz4gfLqhmneZPdcIzf9T3LkgkmqNLg==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.15.32.tgz",
|
||||
"integrity": "sha512-oDzEkdl6D6BAWdMtU5KGO7y3HR5fJcvByNLyEk9+ugj8nP5Ovb7P4kBcStBXc4MPExFGQryehiINMlmY8HlclA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1083,9 +1083,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-arm64-musl": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.30.tgz",
|
||||
"integrity": "sha512-1SYGs2l0Yyyi0pR/P/NKz/x0kqxkoiw+BXeJjLUdecSk/KasncWlJrc6hOvFSgKHOBrzgM5jwuluKtlT8dnrcA==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.15.32.tgz",
|
||||
"integrity": "sha512-omcqjoZP/b8D8PuczVoRwJieC6ibj7qIxTftNYokz4/aSmKFHvsd7nIFfPk5ZvtzncbH4AY7+Dkr/Lp2gWxYeA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1103,9 +1103,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-ppc64-gnu": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-TXREtiXeRhbfDFbmhnkIsXpKfzbfT73YkV2ZF6w0sfxgjC5zI2ZAbaCOq25qxvegofj2K93DtOpm9RLaBgqR2g==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-ppc64-gnu/-/core-linux-ppc64-gnu-1.15.32.tgz",
|
||||
"integrity": "sha512-KGkTMyz/Tbn3PBNu0AVZ4GTDFKnICrYcTiNPZq8DrvK42pnFsf3GNDrIG9E5AtQlTmC0YigkWKmu0eMcfTrmgA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
@@ -1123,9 +1123,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-s390x-gnu": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-DCR2YYeyd6DQE4OuDhImouuNcjXEiEdnn1Y0DyGteugPEDvVuvYk8Xddi+4o2SgWH6jiW8/I+3emZvbep1NC+g==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-s390x-gnu/-/core-linux-s390x-gnu-1.15.32.tgz",
|
||||
"integrity": "sha512-G3Aa4tVS/3OGZBkoNIwUF9F6RAy+Osb4GOlo62SinLmDiErz/ykmM7KH0wkz6l9kM8jJq1HyAM6atJTUEbBk7g==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
@@ -1143,9 +1143,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-gnu": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.30.tgz",
|
||||
"integrity": "sha512-5Pizw3NgfOJ5BJOBK8TIRa59xFW2avESTOBDPTAYwZYa1JNDs+KMF9lUfjJiJLM5HiMs/wPheA9eiT0q9m2AoA==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.15.32.tgz",
|
||||
"integrity": "sha512-ERsjfGcj6CBmj3vJnGDO8m8rTvw6RqMcWo1dogOtNx3/+/0+NNpJiXDobJrr1GwInI/BHAEkvSFIH6d2LqPcUQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1163,9 +1163,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-linux-x64-musl": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.30.tgz",
|
||||
"integrity": "sha512-qyqydP/wyH8alcIP4a2hnGSjHLJjm9H7yDFup+CPy9oTahFgLLwnNcv5UHXqO2Qs3AIND+cls5f/Bb6hqpxdgA==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.15.32.tgz",
|
||||
"integrity": "sha512-N4Ggahe/8SUbTX50P6EdhbW9YWcgbZVb52R4cq6MK+zsoMjRq7rGvV5ztA05QnbaCYqMYx8rTY7KAIA3Crdo4Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
@@ -1183,9 +1183,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-arm64-msvc": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.30.tgz",
|
||||
"integrity": "sha512-CaQENgDHVGOg1mSF5sQVgvfFHG9kjMor2rkLMLeLOkfZYNj13ppnJ9+lfaBZLZUMMbnlGQnavCJb8PVBUOso7Q==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.15.32.tgz",
|
||||
"integrity": "sha512-01yN0o9jvo8xBTP12aPK2wW8b41jmOlGbDDlAnoynotc4pO6xA0zby9f1z6j++qXDpGBttLySq1omgVrlQKYcw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
@@ -1200,9 +1200,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-ia32-msvc": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.30.tgz",
|
||||
"integrity": "sha512-30VdLeGk6fugiUs/kUdJ/pAg7z/zpvVbR11RH60jZ0Z42WIeIniYx0rLEWN7h/pKJ3CopqsQ3RsogCAkRKiA2g==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.15.32.tgz",
|
||||
"integrity": "sha512-fLagI9XZYNpTcmlqAcp3KBtmj7E19WCmYD80Jxj1Kn5tGNa7yxNLd3NNdWxuZGUPl5iC0/KqZru7g08gF6Fsrw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
@@ -1217,9 +1217,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/@swc/core-win32-x64-msvc": {
|
||||
"version": "1.15.30",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.30.tgz",
|
||||
"integrity": "sha512-4iObHPR+Q4oDY110EF5SF5eIaaVJNpMdG9C0q3Q92BsJ5y467uHz7sYQhP60WYlLFsLQ1el2YrIPUItUAQGOKg==",
|
||||
"version": "1.15.32",
|
||||
"resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.15.32.tgz",
|
||||
"integrity": "sha512-gbc2bQ/T2CiR+w0OvcVKwLOFAcPZBvmWmolbwpg1E8UrpeC03DGtyMUApOHNXNYWA3SHFrYXCQtosrcMza1YFg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
|
||||
+13
-1
@@ -165,6 +165,18 @@ public class CommandAPI implements ILuaAPI {
|
||||
return Collections.unmodifiableList(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name of the dimension the current command computer is in, such as {@code minecraft:overworld}.
|
||||
*
|
||||
* @return The dimension the computer is in.
|
||||
* @see #getBlockPosition()
|
||||
* @since 1.119.0
|
||||
*/
|
||||
@LuaFunction
|
||||
public final String getDimension() {
|
||||
return computer.getLevel().dimension().identifier().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the position of the current command computer.
|
||||
*
|
||||
@@ -173,10 +185,10 @@ public class CommandAPI implements ILuaAPI {
|
||||
* @cc.treturn number This computer's y position.
|
||||
* @cc.treturn number This computer's z position.
|
||||
* @cc.see gps.locate To get the position of a non-command computer.
|
||||
* @see #getDimension()
|
||||
*/
|
||||
@LuaFunction
|
||||
public final Object[] getBlockPosition() {
|
||||
// This is probably safe to do on the Lua thread. Probably.
|
||||
var pos = computer.getPosition();
|
||||
return new Object[]{ pos.getX(), pos.getY(), pos.getZ() };
|
||||
}
|
||||
|
||||
+7
-8
@@ -43,6 +43,7 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
@@ -277,19 +278,17 @@ public interface PlatformHelper {
|
||||
/**
|
||||
* Interact with an entity, for instance feeding cows.
|
||||
* <p>
|
||||
* Implementations should follow Minecraft behaviour - we try {@link Entity#interactAt(Player, Vec3, InteractionHand)}
|
||||
* and then {@link Player#interactOn(Entity, InteractionHand)}. Loader-specific hooks should also be called.
|
||||
* Implementations should call {@link Player#interactOn(Entity, InteractionHand, Vec3)} and any loader-specific
|
||||
* hooks.
|
||||
*
|
||||
* @param player The player which is interacting with the entity.
|
||||
* @param entity The entity we're interacting with.
|
||||
* @param hitPos The position our ray trace hit the entity. This is a position in-world, unlike
|
||||
* {@link Entity#interactAt(Player, Vec3, InteractionHand)} which is relative to the entity.
|
||||
* @param hit The entity and position we're interacting with. Note the hit's position is world-relative,
|
||||
* unlike {@link Entity#interact(Player, InteractionHand, Vec3)} which is relative to the entity.
|
||||
* @return Whether any interaction occurred.
|
||||
* @see Entity#interactAt(Player, Vec3, InteractionHand)
|
||||
* @see Player#interactOn(Entity, InteractionHand)
|
||||
* @see Player#interactOn(Entity, InteractionHand, Vec3)
|
||||
* @see ServerGamePacketListenerImpl#handleInteract
|
||||
*/
|
||||
boolean interactWithEntity(ServerPlayer player, Entity entity, Vec3 hitPos);
|
||||
boolean interactWithEntity(ServerPlayer player, EntityHitResult hit);
|
||||
|
||||
/**
|
||||
* The result of attempting to use an item on a block.
|
||||
|
||||
+2
-5
@@ -102,11 +102,8 @@ public class TurtlePlaceCommand implements TurtleCommand {
|
||||
if (!(hit instanceof EntityHitResult entityHit)) return false;
|
||||
|
||||
// Start claiming entity drops
|
||||
var hitEntity = entityHit.getEntity();
|
||||
var hitPos = entityHit.getLocation();
|
||||
|
||||
DropConsumer.set(hitEntity);
|
||||
var placed = PlatformHelper.get().interactWithEntity(turtlePlayer.player(), hitEntity, hitPos);
|
||||
DropConsumer.set(entityHit.getEntity());
|
||||
var placed = PlatformHelper.get().interactWithEntity(turtlePlayer.player(), entityHit);
|
||||
TurtleUtil.stopConsumingPlayer(turtle, turtlePlayer);
|
||||
return placed;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.nio.file.Path;
|
||||
@@ -143,7 +143,7 @@ public class TestPlatformHelper extends AbstractComputerCraftAPI implements Plat
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean interactWithEntity(ServerPlayer player, Entity entity, Vec3 hitPos) {
|
||||
public boolean interactWithEntity(ServerPlayer player, EntityHitResult hit) {
|
||||
throw new UnsupportedOperationException("Cannot interact with the world inside tests");
|
||||
}
|
||||
|
||||
|
||||
+2
@@ -69,7 +69,9 @@ object ManagedComputers : ILuaMachine.Factory {
|
||||
val label = os.computerLabel
|
||||
return when {
|
||||
id != 1 -> CobaltLuaMachine(environment, bios)
|
||||
|
||||
label != null && label[0] != null -> KotlinMachine(environment, label[0] as String)
|
||||
|
||||
else -> {
|
||||
LOGGER.error("Kotlin Lua machine must have a label")
|
||||
CobaltLuaMachine(environment, bios)
|
||||
|
||||
@@ -21,6 +21,19 @@ import static dan200.computercraft.api.lua.LuaValues.*;
|
||||
* @see ObjectArguments
|
||||
*/
|
||||
public interface LuaTable<K, V> extends Map<K, V> {
|
||||
/**
|
||||
* Return the value to which a specific integer key is mapped, or {@code null} if there is no mapping for the key.
|
||||
* <p>
|
||||
* This should be used when accessing integer keys, as numeric keys within the table are typically normalised to
|
||||
* doubles.
|
||||
*
|
||||
* @param index The key to look up.
|
||||
* @return The corresponding value, or {@code null} if not present.
|
||||
*/
|
||||
default @Nullable Object get(int index) {
|
||||
return get((double) index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the length of the array part of this table.
|
||||
*
|
||||
@@ -42,7 +55,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
|
||||
* @since 1.116
|
||||
*/
|
||||
default double getDouble(int index) throws LuaException {
|
||||
Object value = get((double) index);
|
||||
var value = get(index);
|
||||
if (!(value instanceof Number number)) throw badTableItem(index, "number", getType(value));
|
||||
return number.doubleValue();
|
||||
}
|
||||
@@ -70,7 +83,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
|
||||
* @throws LuaException If the value is not an integer.
|
||||
*/
|
||||
default long getLong(int index) throws LuaException {
|
||||
Object value = get((double) index);
|
||||
var value = get(index);
|
||||
if (!(value instanceof Number number)) throw badTableItem(index, "number", getType(value));
|
||||
checkFiniteIndex(index, number.doubleValue());
|
||||
return number.longValue();
|
||||
@@ -145,7 +158,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
|
||||
* @since 1.116
|
||||
*/
|
||||
default boolean getBoolean(int index) throws LuaException {
|
||||
Object value = get((double) index);
|
||||
var value = get(index);
|
||||
if (!(value instanceof Boolean bool)) throw badTableItem(index, "boolean", getType(value));
|
||||
return bool;
|
||||
}
|
||||
@@ -173,7 +186,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
|
||||
* @since 1.116
|
||||
*/
|
||||
default String getString(int index) throws LuaException {
|
||||
Object value = get((double) index);
|
||||
var value = get(index);
|
||||
if (!(value instanceof String string)) throw badTableItem(index, "string", getType(value));
|
||||
return string;
|
||||
}
|
||||
@@ -204,7 +217,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
|
||||
* @since 1.116
|
||||
*/
|
||||
default Map<?, ?> getTable(int index) throws LuaException {
|
||||
Object value = get((double) index);
|
||||
var value = get(index);
|
||||
if (!(value instanceof Map<?, ?> table)) throw badTableItem(index, "table", getType(value));
|
||||
return table;
|
||||
}
|
||||
@@ -236,7 +249,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
|
||||
* @since 1.116
|
||||
*/
|
||||
default Optional<Double> optDouble(int index) throws LuaException {
|
||||
Object value = get((double) index);
|
||||
var value = get(index);
|
||||
if (value == null) return Optional.empty();
|
||||
if (!(value instanceof Number number)) throw badTableItem(index, "number", getType(value));
|
||||
return Optional.of(number.doubleValue());
|
||||
@@ -267,7 +280,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
|
||||
* @since 1.116
|
||||
*/
|
||||
default Optional<Long> optLong(int index) throws LuaException {
|
||||
Object value = get((double) index);
|
||||
var value = get(index);
|
||||
if (value == null) return Optional.empty();
|
||||
if (!(value instanceof Number number)) throw badTableItem(index, "number", getType(value));
|
||||
checkFiniteIndex(index, number.doubleValue());
|
||||
@@ -351,7 +364,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
|
||||
* @since 1.116
|
||||
*/
|
||||
default Optional<Boolean> optBoolean(int index) throws LuaException {
|
||||
Object value = get((double) index);
|
||||
var value = get(index);
|
||||
if (value == null) return Optional.empty();
|
||||
if (!(value instanceof Boolean bool)) throw badTableItem(index, "boolean", getType(value));
|
||||
return Optional.of(bool);
|
||||
@@ -381,7 +394,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
|
||||
* @since 1.116
|
||||
*/
|
||||
default Optional<String> optString(int index) throws LuaException {
|
||||
Object value = get((double) index);
|
||||
var value = get(index);
|
||||
if (value == null) return Optional.empty();
|
||||
if (!(value instanceof String string)) throw badTableItem(index, "string", getType(value));
|
||||
return Optional.of(string);
|
||||
@@ -414,7 +427,7 @@ public interface LuaTable<K, V> extends Map<K, V> {
|
||||
* @since 1.116
|
||||
*/
|
||||
default Optional<Map<?, ?>> optTable(int index) throws LuaException {
|
||||
Object value = get((double) index);
|
||||
var value = get(index);
|
||||
if (value == null) return Optional.empty();
|
||||
if (!(value instanceof Map<?, ?> table)) throw badTableItem(index, "table", getType(value));
|
||||
return Optional.of(table);
|
||||
|
||||
@@ -77,8 +77,8 @@ final class LuaDateTime {
|
||||
var month = getField(table, "month", -1);
|
||||
var day = getField(table, "day", -1);
|
||||
var hour = getField(table, "hour", 12);
|
||||
var minute = getField(table, "min", 12);
|
||||
var second = getField(table, "sec", 12);
|
||||
var minute = getField(table, "min", 0);
|
||||
var second = getField(table, "sec", 0);
|
||||
var time = LocalDateTime.of(year, month, day, hour, minute, second);
|
||||
|
||||
var isDst = getBoolField(table, "isdst");
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
@@ -124,6 +125,10 @@ public final class NetworkUtils {
|
||||
if (port < 0) port = ssl ? 443 : 80;
|
||||
var socketAddress = new InetSocketAddress(host, port);
|
||||
if (socketAddress.isUnresolved()) throw new HTTPRequestException("Unknown host");
|
||||
if (socketAddress.getAddress() instanceof Inet6Address inet6 && (inet6.getScopedInterface() != null || inet6.getScopeId() != 0)) {
|
||||
throw new HTTPRequestException("Scoped address not permitted");
|
||||
}
|
||||
|
||||
return socketAddress;
|
||||
}
|
||||
|
||||
|
||||
+12
-1
@@ -72,6 +72,10 @@ interface AddressPredicate {
|
||||
));
|
||||
}
|
||||
|
||||
return parse(address, prefixSize);
|
||||
}
|
||||
|
||||
public static HostRange parse(InetAddress address, int prefixSize) {
|
||||
// Mask the bytes of the IP address.
|
||||
byte[] minBytes = address.getAddress(), maxBytes = address.getAddress();
|
||||
var size = prefixSize;
|
||||
@@ -126,6 +130,7 @@ interface AddressPredicate {
|
||||
|| socketAddress.isMulticastAddress() // 224.0.0.0/4, ff00::/8
|
||||
|| isUniqueLocalAddress(socketAddress) // fd00::/8
|
||||
|| isCarrierGradeNatAddress(socketAddress) // 100.64.0.0/10
|
||||
|| NAT64_RANGE.matches(socketAddress) // 64:ff9b::/96
|
||||
|| additionalAddresses.contains(socketAddress);
|
||||
}
|
||||
|
||||
@@ -154,6 +159,12 @@ interface AddressPredicate {
|
||||
var bytes = address.getAddress();
|
||||
return bytes[0] == 100 && ((bytes[1] & 0xFF) >= 64 && (bytes[1] & 0xFF) <= 127);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The NAT64 address range (64:ff9b::/96).
|
||||
*
|
||||
* @see <a href="https://en.wikipedia.org/wiki/NAT64">NAT64 on Wikipedia</a>
|
||||
*/
|
||||
private static final HostRange NAT64_RANGE = HostRange.parse(InetAddresses.forString("64:ff9b::"), 96);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,9 +6,11 @@ package dan200.computercraft.core.lua;
|
||||
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.LuaValues;
|
||||
import org.jetbrains.annotations.VisibleForTesting;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
import org.squiddev.cobalt.*;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.*;
|
||||
|
||||
import static dan200.computercraft.api.lua.LuaValues.badTableItem;
|
||||
@@ -37,6 +39,7 @@ class TableImpl implements dan200.computercraft.api.lua.LuaTable<Object, Object>
|
||||
|
||||
@Override
|
||||
public long getLong(int index) throws LuaException {
|
||||
checkValid();
|
||||
var value = table.rawget(index);
|
||||
if (!(value instanceof LuaNumber)) throw LuaValues.badTableItem(index, "number", value.typeName());
|
||||
if (value instanceof LuaInteger) return value.toInteger();
|
||||
@@ -58,9 +61,24 @@ class TableImpl implements dan200.computercraft.api.lua.LuaTable<Object, Object>
|
||||
|
||||
private LuaValue getImpl(Object o) {
|
||||
checkValid();
|
||||
if (o instanceof String s) return table.rawget(s);
|
||||
if (o instanceof Integer i) return table.rawget(i);
|
||||
return Constants.NIL;
|
||||
var value = convertValue(o);
|
||||
return value == null ? Constants.NIL : table.rawget(value);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static @Nullable LuaValue convertValue(@Nullable Object object) {
|
||||
if (object == null) return Constants.NIL;
|
||||
if (object instanceof Boolean bool) return ValueFactory.valueOf(bool);
|
||||
if (object instanceof Double num) return ValueFactory.valueOf(num);
|
||||
if (object instanceof String str) return ValueFactory.valueOf(str);
|
||||
if (object instanceof byte[] b) return ValueFactory.valueOf(Arrays.copyOf(b, b.length));
|
||||
if (object instanceof ByteBuffer b) {
|
||||
var bytes = new byte[b.remaining()];
|
||||
b.get(bytes);
|
||||
return ValueFactory.valueOf(bytes);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,6 +92,12 @@ class TableImpl implements dan200.computercraft.api.lua.LuaTable<Object, Object>
|
||||
return CobaltLuaMachine.toObject(getImpl(o), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable Object get(int index) {
|
||||
checkValid();
|
||||
return CobaltLuaMachine.toObject(table.rawget(index), null);
|
||||
}
|
||||
|
||||
private Map<Object, Object> getBackingMap() {
|
||||
checkValid();
|
||||
if (backingMap != null) return backingMap;
|
||||
|
||||
@@ -1,3 +1,17 @@
|
||||
# New features in CC: Tweaked 1.119.0
|
||||
|
||||
* Add `commands.getDimension()`.
|
||||
* Add `cc.base64` module.
|
||||
* Update Cobalt to 0.9.9, bringing in several Lua 5.5 changes:
|
||||
* Floats are now printed with enough digits to round trip correctly.
|
||||
* Add `table.create`.
|
||||
* `utf8.offset` now returns the final position of the codepoint.
|
||||
|
||||
Several bug fixes:
|
||||
* Fix handling of integer indexes in `LuaTable`.
|
||||
* Correct `min` and `sec` defaults in `os.time`. (sircfenner)
|
||||
* Make HTTP IP filtering stricter.
|
||||
|
||||
# New features in CC: Tweaked 1.118.1
|
||||
|
||||
Several bug fixes:
|
||||
|
||||
@@ -1,8 +1,15 @@
|
||||
New features in CC: Tweaked 1.118.1
|
||||
New features in CC: Tweaked 1.119.0
|
||||
|
||||
* Add `commands.getDimension()`.
|
||||
* Add `cc.base64` module.
|
||||
* Update Cobalt to 0.9.9, bringing in several Lua 5.5 changes:
|
||||
* Floats are now printed with enough digits to round trip correctly.
|
||||
* Add `table.create`.
|
||||
* `utf8.offset` now returns the final position of the codepoint.
|
||||
|
||||
Several bug fixes:
|
||||
* Fix crash in recipe serialisers.
|
||||
* Fix breaking progress overlay not matching turtle's rotation.
|
||||
* Fix several recipes not displaying correctly with JEI.
|
||||
* Fix handling of integer indexes in `LuaTable`.
|
||||
* Correct `min` and `sec` defaults in `os.time`. (sircfenner)
|
||||
* Make HTTP IP filtering stricter.
|
||||
|
||||
Type "help changelog" to see the full version history.
|
||||
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
-- SPDX-FileCopyrightText: 2026 The CC: Tweaked Developers
|
||||
--
|
||||
-- SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
--[[- The [`cc.base64`] module provides functions for converting binary data to
|
||||
and from [Base64](https://en.wikipedia.org/wiki/Base64).
|
||||
|
||||
@usage Encode and decode a string from Base64.
|
||||
|
||||
local base64 = require "cc.base64"
|
||||
print(base64.encode("Hello, world"))
|
||||
print(base64.decode("SGVsbG8sIHdvcmxk"))
|
||||
|
||||
@since 1.119.0
|
||||
]]
|
||||
|
||||
local expect = require "cc.expect".expect
|
||||
|
||||
local rshift, byte, char, sub = bit32.rshift, string.byte, string.char, string.sub
|
||||
|
||||
local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
|
||||
|
||||
--[[-
|
||||
Encode a binary string to Base64.
|
||||
|
||||
@tparam string str The binary data to encode.
|
||||
@tparam[opt="+/"] string alt_chars A string of length 2, used to encode the 62nd
|
||||
and 63rd bit.
|
||||
@treturn string The Base64 encoded data.
|
||||
|
||||
@usage Convert a string to Base64
|
||||
|
||||
local base64 = require "cc.base64"
|
||||
print(base64.encode("Hello, world!"))
|
||||
|
||||
@usage Convert a string to [base64url]. This is an alternative form of Base64,
|
||||
where the string is encoded with `"-_"` instead of `"+/"`. This allows the string
|
||||
to be more easily used in URLs, though the padding `=` will still need escaping
|
||||
with [`textutils.urlEncode`].
|
||||
|
||||
local base64 = require "cc.base64"
|
||||
print(base64.encode("Test: \255\230", "-_"))
|
||||
|
||||
[base64url]: https://datatracker.ietf.org/doc/html/rfc4648#section-5 "Base 64 Encoding with URL and Filename Safe Alphabet"
|
||||
]]
|
||||
local function encode(str, alt_chars)
|
||||
expect(1, str, "string")
|
||||
expect(2, alt_chars, "string", "nil")
|
||||
|
||||
if alt_chars and #alt_chars ~= 2 then
|
||||
error("alt_chars must be exactly two characters", 2)
|
||||
end
|
||||
|
||||
--[[
|
||||
The below code is optimised to run against Cobalt, so the code is not
|
||||
entirely idiomatic.
|
||||
- It's quicker to build use a table lookup and do `lookup[x]` than call
|
||||
`sub(alphabet, x, x)`.
|
||||
- As we don't have bit operations, it's quicker to do `x % y`, rather than
|
||||
`band(x, y - 1)`
|
||||
- Naive concatenation is quicker than appending to a table.
|
||||
]]
|
||||
|
||||
local alphabet = alphabet .. (alt_chars or "+/")
|
||||
local lookup = {}
|
||||
for i = 1, #alphabet do lookup[i] = sub(alphabet, i, i) end
|
||||
|
||||
local len = #str
|
||||
local remainder = len % 3
|
||||
local out = ""
|
||||
for i = 1, len - remainder, 3 do
|
||||
local c1, c2, c3 = byte(str, i, i + 2)
|
||||
out = out ..
|
||||
lookup[rshift(c1, 2) + 1] ..
|
||||
lookup[c1 % 4 * 16 + rshift(c2, 4) + 1] ..
|
||||
lookup[c2 % 16 * 4 + rshift(c3, 6) + 1] ..
|
||||
lookup[c3 % 64 + 1]
|
||||
end
|
||||
|
||||
if remainder == 2 then
|
||||
local c1, c2 = byte(str, len - 1, len)
|
||||
out = out ..
|
||||
lookup[rshift(c1, 2) + 1] ..
|
||||
lookup[c1 % 4 * 16 + rshift(c2, 4) + 1] ..
|
||||
lookup[c2 % 16 * 4 + 1] ..
|
||||
"="
|
||||
elseif remainder == 1 then
|
||||
local c1 = byte(str, len)
|
||||
out = out .. lookup[rshift(c1, 2) + 1] .. lookup[c1 % 4 * 16 + 1] .. "=="
|
||||
end
|
||||
|
||||
return out
|
||||
end
|
||||
|
||||
--[[-
|
||||
Decode a Base64-encoded string back to its original data.
|
||||
|
||||
This function requires the data to be valid Base64 with the trailing padding
|
||||
bytes.
|
||||
|
||||
@tparam string str The Base64-encoded data to decode.
|
||||
@tparam[opt="+/"] string alt_chars A string of length 2, used to encode the 62nd
|
||||
and 63rd bit.
|
||||
@treturn[1] string The decoded data.
|
||||
@treturn[2] nil If the data is not valid Base64, or is missing the trailing padding.
|
||||
@treturn[2] string The reason the data failed to decode.
|
||||
|
||||
@usage Decode a string from Base64
|
||||
|
||||
local base64 = require "cc.base64"
|
||||
print(base64.decode("SGVsbG8sIHdvcmxk"))
|
||||
|
||||
@usage Decode [base64url]-encoded data.
|
||||
|
||||
local base64 = require "cc.base64"
|
||||
print(base64.decode("VGVzdDog_-Y=", "-_"))
|
||||
|
||||
[base64url]: https://datatracker.ietf.org/doc/html/rfc4648#section-5 "Base 64 Encoding with URL and Filename Safe Alphabet"
|
||||
]]
|
||||
local function decode(str, alt_chars)
|
||||
expect(1, str, "string")
|
||||
expect(2, alt_chars, "string", "nil")
|
||||
|
||||
if alt_chars and #alt_chars ~= 2 then
|
||||
error("alt_chars must be exactly two characters", 2)
|
||||
end
|
||||
|
||||
if not alt_chars then alt_chars = "+/" end
|
||||
|
||||
local len = #str
|
||||
|
||||
if (len % 4) ~= 0 or not str:find("^[%w%" .. alt_chars:sub(1, 1) .. "%" .. alt_chars:sub(2, 2) .. "]*=?=?$") then
|
||||
return nil, "input is not valid base64"
|
||||
end
|
||||
|
||||
local alphabet = alphabet .. alt_chars
|
||||
local lookup = {}
|
||||
for i = 1, #alphabet do lookup[byte(alphabet, i)] = i - 1 end
|
||||
|
||||
local padding
|
||||
if sub(str, -2) == "==" then
|
||||
padding = 2
|
||||
elseif sub(str, -1) == "=" then
|
||||
padding = 1
|
||||
else
|
||||
padding = 0
|
||||
end
|
||||
|
||||
local out = ""
|
||||
for i = 1, padding == 0 and len or len - 4, 4 do
|
||||
local e1, e2, e3, e4 = byte(str, i, i + 3)
|
||||
e1 = lookup[e1]
|
||||
e2 = lookup[e2]
|
||||
e3 = lookup[e3]
|
||||
e4 = lookup[e4]
|
||||
out = out .. char(
|
||||
e1 * 4 + rshift(e2, 4),
|
||||
e2 % 16 * 16 + rshift(e3, 2),
|
||||
e3 % 4 * 64 + e4
|
||||
)
|
||||
end
|
||||
|
||||
if padding == 2 then
|
||||
local e1, e2 = byte(str, len - 3, len - 2)
|
||||
e1 = lookup[e1]
|
||||
e2 = lookup[e2]
|
||||
out = out .. char(e1 * 4 + rshift(e2, 4))
|
||||
elseif padding == 1 then
|
||||
local e1, e2, e3 = byte(str, len - 3, len - 1)
|
||||
e1 = lookup[e1]
|
||||
e2 = lookup[e2]
|
||||
e3 = lookup[e3]
|
||||
out = out .. char(
|
||||
e1 * 4 + rshift(e2, 4),
|
||||
e2 % 16 * 16 + rshift(e3, 2)
|
||||
)
|
||||
end
|
||||
|
||||
return out
|
||||
end
|
||||
|
||||
return { encode = encode, decode = decode }
|
||||
@@ -350,16 +350,6 @@ function shell.resolve(path)
|
||||
end
|
||||
end
|
||||
|
||||
local function pathWithExtension(_sPath, _sExt)
|
||||
local nLen = #sPath
|
||||
local sEndChar = string.sub(_sPath, nLen, nLen)
|
||||
-- Remove any trailing slashes so we can add an extension to the path safely
|
||||
if sEndChar == "/" or sEndChar == "\\" then
|
||||
_sPath = string.sub(_sPath, 1, nLen - 1)
|
||||
end
|
||||
return _sPath .. "." .. _sExt
|
||||
end
|
||||
|
||||
--- Resolve a program, using the [program path][`path`] and list of [aliases][`aliases`].
|
||||
--
|
||||
-- @tparam string command The name of the program
|
||||
@@ -384,7 +374,7 @@ function shell.resolveProgram(command)
|
||||
if fs.exists(sPath) and not fs.isDir(sPath) then
|
||||
return sPath
|
||||
else
|
||||
local sPathLua = pathWithExtension(sPath, "lua")
|
||||
local sPathLua = sPath .. ".lua"
|
||||
if fs.exists(sPathLua) and not fs.isDir(sPathLua) then
|
||||
return sPathLua
|
||||
end
|
||||
@@ -398,7 +388,7 @@ function shell.resolveProgram(command)
|
||||
if fs.exists(sPath) and not fs.isDir(sPath) then
|
||||
return sPath
|
||||
else
|
||||
local sPathLua = pathWithExtension(sPath, "lua")
|
||||
local sPathLua = sPath .. ".lua"
|
||||
if fs.exists(sPathLua) and not fs.isDir(sPathLua) then
|
||||
return sPathLua
|
||||
end
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
// SPDX-FileCopyrightText: 2026 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.core.apis.http;
|
||||
|
||||
import dan200.computercraft.test.core.ReplaceUnderscoresDisplayNameGenerator;
|
||||
import org.junit.jupiter.api.DisplayNameGeneration;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
@DisplayNameGeneration(ReplaceUnderscoresDisplayNameGenerator.class)
|
||||
class NetworkUtilsTest {
|
||||
@Test
|
||||
public void test_getAddress_with_scoped_address() {
|
||||
var err = assertThrows(HTTPRequestException.class, () -> NetworkUtils.getAddress("[::1%1]", 80, false));
|
||||
assertEquals("Scoped address not permitted", err.getMessage());
|
||||
}
|
||||
}
|
||||
+2
@@ -36,6 +36,8 @@ public class AddressRuleTest {
|
||||
"224.0.0.1", "ff02::1",
|
||||
// CGNAT
|
||||
"100.64.0.0", "100.127.255.255",
|
||||
// NAT64
|
||||
"64:ff9b::c0a8:0101",
|
||||
// Cloud metadata providers
|
||||
"100.100.100.200", // Alibaba
|
||||
"192.0.0.192", // Oracle
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
// SPDX-FileCopyrightText: 2026 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.core.lua;
|
||||
|
||||
import org.squiddev.cobalt.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
class CobaltLuaTableTest implements LuaTableContract<TableImpl> {
|
||||
@Override
|
||||
public TableImpl create(Map<?, ?> map) {
|
||||
try {
|
||||
return new TableImpl(VarargArguments.of(Constants.NONE), convertMap(map));
|
||||
} catch (LuaError e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static LuaValue convert(Object object) throws LuaError {
|
||||
var value = TableImpl.convertValue(object);
|
||||
if (value != null) return value;
|
||||
|
||||
if (object instanceof Map<?, ?> x) return convertMap(x);
|
||||
if (object instanceof Integer x) return ValueFactory.valueOf(x);
|
||||
throw new IllegalArgumentException("Unknown value " + object);
|
||||
}
|
||||
|
||||
private static LuaTable convertMap(Map<?, ?> map) throws LuaError {
|
||||
var out = new LuaTable();
|
||||
for (var entry : map.entrySet()) out.rawset(convert(entry.getKey()), convert(entry.getValue()));
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// SPDX-FileCopyrightText: 2026 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.core.lua;
|
||||
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.LuaTable;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
|
||||
/**
|
||||
* Test Interface defining the behaviour of a {@link LuaTable} implementation.
|
||||
*
|
||||
* @param <T> The implementation of {@link LuaTable} we are testing.
|
||||
*/
|
||||
public interface LuaTableContract<T extends LuaTable<?, ?>> {
|
||||
T create(Map<?, ?> map);
|
||||
|
||||
default T createList(List<?> list) {
|
||||
var out = new HashMap<>();
|
||||
var i = 0;
|
||||
for (var elem : list) {
|
||||
var idx = ++i;
|
||||
// We normalise our index to be a double, to match the behaviour of CobaltLuaMachine.toValue, which converts
|
||||
// all numbers to doubles.
|
||||
if (elem != null) out.put((double) idx, elem);
|
||||
}
|
||||
return create(out);
|
||||
}
|
||||
|
||||
@Test
|
||||
default void testLength() {
|
||||
assertEquals(0, createList(List.of()).length());
|
||||
assertEquals(1, createList(List.of("a")).length());
|
||||
assertEquals(2, createList(List.of("a", "a")).length());
|
||||
assertEquals(1, createList(Arrays.asList("a", null, "a")).length());
|
||||
}
|
||||
|
||||
@Test
|
||||
default void testGetIntLikeKey() {
|
||||
assertEquals("a", createList(List.of("a", "b", "c")).get(1));
|
||||
assertEquals("a", createList(List.of("a", "b", "c")).get(1.0));
|
||||
// This is a little dubious, but ensures we have consistent behaviour between implementations (doubles are
|
||||
// the only number) and we don't need to handle double/int normalisation within ObjectLuaTable.
|
||||
assertNull(createList(List.of("a", "b", "c")).get((Object) 1));
|
||||
assertNull(createList(List.of("a", "b", "c")).get(1.0f));
|
||||
assertNull(createList(List.of("a", "b", "c")).get((Object) (short) 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
default void testGetInt() throws LuaException {
|
||||
assertEquals("a", createList(List.of("a")).get(1));
|
||||
assertEquals(true, createList(List.of(true)).getBoolean(1));
|
||||
assertEquals(12345, createList(List.of(12345.0)).getInt(1));
|
||||
assertEquals(12345L, createList(List.of(12345.0)).getLong(1));
|
||||
assertEquals("abc", createList(List.of("abc")).getString(1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// SPDX-FileCopyrightText: 2026 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.core.lua;
|
||||
|
||||
import dan200.computercraft.api.lua.ObjectLuaTable;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
class ObjectLuaTableTest implements LuaTableContract<ObjectLuaTable> {
|
||||
@Override
|
||||
public ObjectLuaTable create(Map<?, ?> map) {
|
||||
return new ObjectLuaTable(map);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,11 @@ describe("The http library", function()
|
||||
-- to ensure the general control flow works.
|
||||
expect({ http.checkURL("http://localhost") }):same({ false, "Domain not permitted" })
|
||||
expect({ http.checkURL("http://127.0.0.1") }):same({ false, "Domain not permitted" })
|
||||
expect({ http.checkURL("http://[::1]") }):same({ false, "Domain not permitted" })
|
||||
end)
|
||||
|
||||
expect("rejects scoped addresses", function()
|
||||
expect({ http.checkURL("http://[::1%1]") }):same({ false, "Scoped address not permitted" })
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
@@ -143,6 +143,24 @@ describe("The os library", function()
|
||||
local t2 = os.time { year = 2000, month = 10, day = 1, hour = 23, min = 10, sec = 19 }
|
||||
expect(t1 - t2):eq(60 * 2 - 2)
|
||||
end)
|
||||
|
||||
it("uses correct date table default for hour", function()
|
||||
local t1 = os.time { year = 1970, month = 1, day = 1, hour = nil, min = 0, sec = 0 }
|
||||
local t2 = os.time { year = 1970, month = 1, day = 1, hour = 12, min = 0, sec = 0 }
|
||||
expect(t1):eq(t2)
|
||||
end)
|
||||
|
||||
it("uses correct date table default for min", function()
|
||||
local t1 = os.time { year = 1970, month = 1, day = 1, hour = 0, min = nil, sec = 0 }
|
||||
local t2 = os.time { year = 1970, month = 1, day = 1, hour = 0, min = 0, sec = 0 }
|
||||
expect(t1):eq(t2)
|
||||
end)
|
||||
|
||||
it("uses correct date table default for sec", function()
|
||||
local t1 = os.time { year = 1970, month = 1, day = 1, hour = 0, min = 0, sec = nil }
|
||||
local t2 = os.time { year = 1970, month = 1, day = 1, hour = 0, min = 0, sec = 0 }
|
||||
expect(t1):eq(t2)
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("os.day", function()
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
-- SPDX-FileCopyrightText: 2026 The CC: Tweaked Developers
|
||||
--
|
||||
-- SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
describe("cc.base64", function()
|
||||
local base64 = require "cc.base64"
|
||||
|
||||
it("random strings roundtrip", function()
|
||||
for _ = 1, 1000 do
|
||||
local len = math.random(1000)
|
||||
local str = ""
|
||||
for _ = 1, len do str = str .. string.char(math.random(0, 255)) end
|
||||
|
||||
expect(base64.decode(base64.encode(str))):eq(str)
|
||||
end
|
||||
end)
|
||||
|
||||
describe("encode", function()
|
||||
it("validates arguments", function()
|
||||
expect.error(base64.encode, 2):eq("bad argument #1 (string expected, got number)")
|
||||
expect.error(base64.encode, "", 2):eq("bad argument #2 (string expected, got number)")
|
||||
expect.error(base64.encode, "", ""):eq("alt_chars must be exactly two characters")
|
||||
end)
|
||||
|
||||
it("encodes as expected", function()
|
||||
expect(base64.encode("")):eq("")
|
||||
expect(base64.encode("light w")):eq("bGlnaHQgdw==")
|
||||
expect(base64.encode("light wo")):eq("bGlnaHQgd28=")
|
||||
expect(base64.encode("light wor")):eq("bGlnaHQgd29y")
|
||||
expect(base64.encode("Many hands make light work.")):eq("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu")
|
||||
end)
|
||||
|
||||
it("encodes using alternative alphabet", function()
|
||||
expect(base64.encode("Test: \255\230")):eq("VGVzdDog/+Y=")
|
||||
expect(base64.encode("Test: \255\230", "-_")):eq("VGVzdDog_-Y=")
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("decode", function()
|
||||
it("validates arguments", function()
|
||||
expect.error(base64.decode, 2):eq("bad argument #1 (string expected, got number)")
|
||||
expect.error(base64.decode, "", 2):eq("bad argument #2 (string expected, got number)")
|
||||
expect.error(base64.decode, "", ""):eq("alt_chars must be exactly two characters")
|
||||
end)
|
||||
|
||||
it("decodes as expected", function()
|
||||
expect(base64.decode("")):eq("")
|
||||
expect(base64.decode("bGlnaHQgdw==")):eq("light w")
|
||||
expect(base64.decode("bGlnaHQgd28=")):eq("light wo")
|
||||
expect(base64.decode("bGlnaHQgd29y")):eq("light wor")
|
||||
expect(base64.decode("TWFueSBoYW5kcyBtYWtlIGxpZ2h0IHdvcmsu")):eq("Many hands make light work.")
|
||||
end)
|
||||
|
||||
it("decodes using alternative alphabet", function()
|
||||
expect(base64.decode("VGVzdDog/+Y=")):eq("Test: \255\230")
|
||||
expect(base64.decode("VGVzdDog_-Y=", "-_")):eq("Test: \255\230")
|
||||
end)
|
||||
|
||||
it("validates the input string", function()
|
||||
expect { base64.decode("VGVzdDog/+Y") }:same { nil, "input is not valid base64" }
|
||||
expect { base64.decode("VGVzdDog/+Y==") }:same { nil, "input is not valid base64" }
|
||||
expect { base64.decode("VGVzdDog/=Y=") }:same { nil, "input is not valid base64" }
|
||||
expect { base64.decode("VGVzdDog/===") }:same { nil, "input is not valid base64" }
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
@@ -152,6 +152,18 @@ describe("The shell", function()
|
||||
shell.resolveProgram("ls")
|
||||
expect.error(shell.resolveProgram, nil):eq("bad argument #1 (string expected, got nil)")
|
||||
end)
|
||||
|
||||
it("finds files on the shell path", function()
|
||||
expect(shell.resolveProgram("edit")):eq("rom/programs/edit.lua")
|
||||
expect(shell.resolveProgram("edit.lua")):eq("rom/programs/edit.lua")
|
||||
end)
|
||||
|
||||
it("finds programs even with a trailing slash", function()
|
||||
-- This feels silly: "edit/" is a directory, not the name of a file. However,
|
||||
-- fs.combine (and CC's other path normalisation code) strips trailing slashes,
|
||||
-- so this should still resolve the program.
|
||||
expect(shell.resolveProgram("/rom/programs/edit/")):eq("rom/programs/edit.lua")
|
||||
end)
|
||||
end)
|
||||
|
||||
describe("shell.complete", function()
|
||||
|
||||
@@ -65,8 +65,6 @@ dependencies {
|
||||
exclude("net.fabricmc", "fabric-loader")
|
||||
exclude("net.fabricmc.fabric-api")
|
||||
}
|
||||
// FIXME: A lie, but Fabric Create uses the wrong mappings
|
||||
compileOnly(libs.create.forge) { isTransitive = false }
|
||||
|
||||
clientRuntimeOnly(libs.bundles.externalMods.fabric.runtime) {
|
||||
exclude("net.fabricmc", "fabric-loader")
|
||||
|
||||
@@ -17,7 +17,6 @@ import dan200.computercraft.impl.TurtleUpgrades;
|
||||
import dan200.computercraft.shared.command.CommandComputerCraft;
|
||||
import dan200.computercraft.shared.config.ConfigSpec;
|
||||
import dan200.computercraft.shared.details.FluidDetails;
|
||||
import dan200.computercraft.shared.integration.CreateIntegration;
|
||||
import dan200.computercraft.shared.network.NetworkMessages;
|
||||
import dan200.computercraft.shared.peripheral.generic.methods.InventoryMethods;
|
||||
import dan200.computercraft.shared.peripheral.modem.wired.CableBlock;
|
||||
@@ -141,8 +140,6 @@ public class ComputerCraft {
|
||||
ComputerCraftAPI.registerGenericSource(InventoryMethods::new);
|
||||
|
||||
Peripherals.addGenericLookup(InventoryMethods::extractContainer);
|
||||
|
||||
if (FabricLoader.getInstance().isModLoaded(CreateIntegration.ID)) CreateIntegration.setup();
|
||||
}
|
||||
|
||||
private static <B extends FriendlyByteBuf, T extends CustomPacketPayload> void registerPayloadType(PayloadTypeRegistry<B> registry, CustomPacketPayload.TypeAndCodec<B, T> type) {
|
||||
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.shared.integration;
|
||||
|
||||
import com.simibubi.create.api.contraption.BlockMovementChecks;
|
||||
import com.simibubi.create.api.contraption.BlockMovementChecks.CheckResult;
|
||||
import dan200.computercraft.shared.peripheral.modem.wired.CableBlock;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessModemBlock;
|
||||
|
||||
/**
|
||||
* Integration with Create.
|
||||
*/
|
||||
public final class CreateIntegration {
|
||||
public static final String ID = "create";
|
||||
|
||||
private CreateIntegration() {
|
||||
}
|
||||
|
||||
public static void setup() {
|
||||
// Allow modems to be treated as "attached" to their adjacent block.
|
||||
BlockMovementChecks.registerAttachedCheck((state, world, pos, direction) -> {
|
||||
var block = state.getBlock();
|
||||
if (block instanceof WirelessModemBlock) {
|
||||
return CheckResult.of(state.getValue(WirelessModemBlock.FACING) == direction);
|
||||
} else if (block instanceof CableBlock) {
|
||||
return CheckResult.of(state.getValue(CableBlock.MODEM).getFacing() == direction);
|
||||
} else {
|
||||
return CheckResult.PASS;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
+4
-4
@@ -64,7 +64,6 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.nio.file.Path;
|
||||
@@ -220,9 +219,10 @@ public class PlatformHelperImpl implements PlatformHelper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean interactWithEntity(ServerPlayer player, Entity entity, Vec3 hitPos) {
|
||||
return UseEntityCallback.EVENT.invoker().interact(player, entity.level(), InteractionHand.MAIN_HAND, entity, new EntityHitResult(entity, hitPos)).consumesAction()
|
||||
|| player.interactOn(entity, InteractionHand.MAIN_HAND, hitPos).consumesAction();
|
||||
public boolean interactWithEntity(ServerPlayer player, EntityHitResult hit) {
|
||||
var entity = hit.getEntity();
|
||||
return UseEntityCallback.EVENT.invoker().interact(player, entity.level(), InteractionHand.MAIN_HAND, entity, hit).consumesAction()
|
||||
|| player.interactOn(entity, InteractionHand.MAIN_HAND, hit.getLocation().subtract(entity.position())).consumesAction();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
+4
-2
@@ -52,7 +52,7 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.neoforged.fml.ModList;
|
||||
import net.neoforged.neoforge.capabilities.BlockCapability;
|
||||
import net.neoforged.neoforge.capabilities.BlockCapabilityCache;
|
||||
@@ -216,7 +216,9 @@ public class PlatformHelperImpl implements PlatformHelper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean interactWithEntity(ServerPlayer player, Entity entity, Vec3 hitPos) {
|
||||
public boolean interactWithEntity(ServerPlayer player, EntityHitResult hit) {
|
||||
var entity = hit.getEntity();
|
||||
var hitPos = hit.getLocation().subtract(entity.position());
|
||||
var interactAt = CommonHooks.onInteractEntityAt(player, entity, hitPos, InteractionHand.MAIN_HAND);
|
||||
if (interactAt == null) interactAt = player.interactOn(entity, InteractionHand.MAIN_HAND, hitPos);
|
||||
return interactAt.consumesAction();
|
||||
|
||||
@@ -75,6 +75,7 @@ internal class SideProvider {
|
||||
|
||||
private fun getSideImpl(sym: Symbol): Optional<Side> = when (sym.getKind()) {
|
||||
ElementKind.MODULE -> Optional.empty()
|
||||
|
||||
ElementKind.PACKAGE -> {
|
||||
val pkg = sym.toString()
|
||||
when {
|
||||
|
||||
Reference in New Issue
Block a user