mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-02 14:43:00 +00:00
Compare commits
173 Commits
v1.15.2-1.
...
v1.16.5-1.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
efa2be2821 | ||
|
|
670db97fc7 | ||
|
|
1650b72edb | ||
|
|
a5bca3f0df | ||
|
|
88f41314c7 | ||
|
|
5ef8d52c13 | ||
|
|
0b65d56ab0 | ||
|
|
a256b70685 | ||
|
|
f16d1499fe | ||
|
|
79ca851e4f | ||
|
|
d5c54d64a6 | ||
|
|
5cfdd2339f | ||
|
|
3ab3213290 | ||
|
|
46c9840d00 | ||
|
|
b3f2f14e96 | ||
|
|
3ace49d27f | ||
|
|
9bd662d8dc | ||
|
|
df7a40354e | ||
|
|
c489d4bc4f | ||
|
|
2b029bd506 | ||
|
|
2227845658 | ||
|
|
2d3e88ef59 | ||
|
|
0bfe960cbd | ||
|
|
a735f23e1f | ||
|
|
de6f27ceaf | ||
|
|
2fab1a3054 | ||
|
|
d4745ae47e | ||
|
|
dc21e2dbc9 | ||
|
|
75dfa71275 | ||
|
|
d71bf225cc | ||
|
|
8644c4ebf6 | ||
|
|
b323db30ee | ||
|
|
53efd6b303 | ||
|
|
97faa1b3bc | ||
|
|
7404133d40 | ||
|
|
e18e24407e | ||
|
|
026afa7f73 | ||
|
|
29cc5bb86b | ||
|
|
aa9d3c8269 | ||
|
|
f8074636bc | ||
|
|
db2cde4a4c | ||
|
|
5eec7d9172 | ||
|
|
8b9735d72e | ||
|
|
1866916cb8 | ||
|
|
f38a6a9d43 | ||
|
|
0f6db63020 | ||
|
|
51fcd83b87 | ||
|
|
c2190e1318 | ||
|
|
c40a13558c | ||
|
|
02695aea51 | ||
|
|
d5be1aca0e | ||
|
|
8ff8b78ed8 | ||
|
|
7fc55aa9a0 | ||
|
|
38335ca187 | ||
|
|
e0e194099c | ||
|
|
8063059764 | ||
|
|
f96d923b2a | ||
|
|
9142ccfc93 | ||
|
|
9f7cc00fcb | ||
|
|
b129ae627b | ||
|
|
f9fb0619fa | ||
|
|
7f9b86a78e | ||
|
|
58ea7a275e | ||
|
|
8487a13764 | ||
|
|
f0ba1108d5 | ||
|
|
5d0daf9b2d | ||
|
|
8b8692ba53 | ||
|
|
1f385f5b35 | ||
|
|
34baa09b6c | ||
|
|
b21866fbff | ||
|
|
e0a288bcb9 | ||
|
|
4592534a18 | ||
|
|
28165bfcd6 | ||
|
|
953b94fd08 | ||
|
|
e10e30f82b | ||
|
|
aeb1fa0e7e | ||
|
|
349a7543b0 | ||
|
|
3d589eda4a | ||
|
|
de646b66b6 | ||
|
|
4f0d311df7 | ||
|
|
d6e3c9a7fa | ||
|
|
a7a724f134 | ||
|
|
b0e30fdce1 | ||
|
|
4e15afa254 | ||
|
|
84bac06178 | ||
|
|
1fecb995c9 | ||
|
|
99b719299c | ||
|
|
fb9590467d | ||
|
|
bc8e090873 | ||
|
|
cf0f67265f | ||
|
|
53dd15a213 | ||
|
|
eb2d617ed8 | ||
|
|
74dae4ec17 | ||
|
|
abbc46877b | ||
|
|
3cb25b3525 | ||
|
|
f387730b88 | ||
|
|
92b45b1868 | ||
|
|
003c7ec2e8 | ||
|
|
c45221a2d0 | ||
|
|
8494ba8ce2 | ||
|
|
058d63e77f | ||
|
|
17b5bca443 | ||
|
|
c3f5700494 | ||
|
|
b17ff6daf0 | ||
|
|
e8f5531a8c | ||
|
|
51d3b091da | ||
|
|
9708dd6786 | ||
|
|
e48427dbbc | ||
|
|
669b6d2d56 | ||
|
|
32d956bbe7 | ||
|
|
3a147c78a8 | ||
|
|
8c56b6a7be | ||
|
|
66e42e0817 | ||
|
|
0ee3d10fda | ||
|
|
ed0afc4068 | ||
|
|
1f70ed6985 | ||
|
|
8f3ea60c74 | ||
|
|
eb722a74cd | ||
|
|
1825f67eee | ||
|
|
975a994581 | ||
|
|
061514549d | ||
|
|
5e52429c23 | ||
|
|
396cf15a1f | ||
|
|
7514cf7320 | ||
|
|
1316d6a3c9 | ||
|
|
e1cbbe3628 | ||
|
|
6d367e08a3 | ||
|
|
eaa7359c8c | ||
|
|
657ceda3af | ||
|
|
a934e42219 | ||
|
|
1544749282 | ||
|
|
763bab80fa | ||
|
|
417fda3019 | ||
|
|
444830cf2d | ||
|
|
23bf33c454 | ||
|
|
0be030c497 | ||
|
|
a3a9684505 | ||
|
|
c5694ea966 | ||
|
|
7b476cb24b | ||
|
|
7ca261d763 | ||
|
|
1edb7288b9 | ||
|
|
4af5bcc0b0 | ||
|
|
96c577482d | ||
|
|
61f8e97f6b | ||
|
|
c92f06cfd9 | ||
|
|
c9f3d315c0 | ||
|
|
83df64e520 | ||
|
|
ab232bd689 | ||
|
|
5bf367af9f | ||
|
|
4766833cf2 | ||
|
|
71563a52ff | ||
|
|
0c6e7b5db5 | ||
|
|
72c1d451fe | ||
|
|
8b4a01df27 | ||
|
|
d0a973fa46 | ||
|
|
26c12ac1a9 | ||
|
|
2c67849b35 | ||
|
|
7809a2eddd | ||
|
|
e8e9294fdf | ||
|
|
99581e1f40 | ||
|
|
29646a7f61 | ||
|
|
50d2712581 | ||
|
|
3093f882d8 | ||
|
|
e5cf0d1c61 | ||
|
|
6b102a8142 | ||
|
|
c8a6888a2f | ||
|
|
9ce33f8a3f | ||
|
|
a1dcd59d95 | ||
|
|
2a17585702 | ||
|
|
087c305b0d | ||
|
|
31764f6d65 | ||
|
|
4efde2b294 | ||
|
|
46595e73df |
@@ -16,6 +16,3 @@ indent_size = 2
|
||||
|
||||
[*.yml]
|
||||
indent_size = 2
|
||||
|
||||
[*.properties]
|
||||
insert_final_newline = false
|
||||
|
||||
12
.gitattributes
vendored
12
.gitattributes
vendored
@@ -1,3 +1,15 @@
|
||||
# Ignore changes in generated files
|
||||
src/generated/resources/data/** linguist-generated
|
||||
src/test/server-files/structures linguist-generated
|
||||
|
||||
* text=auto
|
||||
|
||||
*.gradle eol=lf diff=java
|
||||
*.java eol=lf diff=java
|
||||
*.kt eol=lf diff=java
|
||||
*.lua eol=lf
|
||||
*.md eol=lf diff=markdown
|
||||
*.txt eol=lf
|
||||
|
||||
*.png binary
|
||||
*.jar binary
|
||||
|
||||
16
.github/ISSUE_TEMPLATE/bug_report.md
vendored
16
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,16 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Report some misbehaviour in the mod
|
||||
labels: bug
|
||||
---
|
||||
|
||||
<!--
|
||||
## Before reporting
|
||||
- Search for the bug on the issue tracker. Make sure to look at closed issues too!
|
||||
-->
|
||||
|
||||
## Useful information to include:
|
||||
- Minecraft version
|
||||
- CC: Tweaked version
|
||||
- Logs: These will be located in the `logs/` directory of your Minecraft instance. Please upload them as a gist or directly into this editor.
|
||||
- Detailed reproduction steps: sometimes I can spot a bug pretty easily, but often it's much more obscure. The more information I have to help reproduce it, the quicker it'll get fixed.
|
||||
33
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
33
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
name: Bug report
|
||||
description: Report some misbehaviour in the mod
|
||||
labels: [ bug ]
|
||||
body:
|
||||
- type: dropdown
|
||||
id: mc-version
|
||||
attributes:
|
||||
label: Minecraft Version
|
||||
description: What version of Minecraft are you using?
|
||||
options:
|
||||
- 1.15.x
|
||||
- 1.16.x
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Version
|
||||
description: "What version of CC: Tweaked are you using?"
|
||||
placeholder: "e.g. 1.96.0"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: details
|
||||
attributes:
|
||||
label: Details
|
||||
description: |
|
||||
Description of the bug. Please include the following:
|
||||
- Logs: These will be located in the `logs/` directory of your Minecraft
|
||||
instance. Please upload them as a gist or directly into this editor.
|
||||
- Detailed reproduction steps: sometimes I can spot a bug pretty easily,
|
||||
but often it's much more obscure. The more information I have to help
|
||||
reproduce it, the quicker it'll get fixed.
|
||||
17
.github/matchers/checkstyle.json
vendored
Normal file
17
.github/matchers/checkstyle.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "checkstyle",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^([a-z]+) ([\\w./-]+):(\\d+):(\\d+): (.*)$",
|
||||
"severity": 1,
|
||||
"file": 2,
|
||||
"line": 3,
|
||||
"column": 4,
|
||||
"message": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
18
.github/matchers/illuaminate.json
vendored
Normal file
18
.github/matchers/illuaminate.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "illuaminate",
|
||||
"severity": "warning",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^([\\w./-]+):\\[(\\d+):(\\d+)\\-(?:\\d+):(?:\\d+)\\]: (.*) \\[([a-z:-]+)\\]$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"column": 3,
|
||||
"message": 4,
|
||||
"code": 5
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
15
.github/matchers/junit.json
vendored
Normal file
15
.github/matchers/junit.json
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"problemMatcher": [
|
||||
{
|
||||
"owner": "junit",
|
||||
"pattern": [
|
||||
{
|
||||
"regexp": "^## ([\\w./-]+):(\\d+): (.*)$",
|
||||
"file": 1,
|
||||
"line": 2,
|
||||
"message": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
36
.github/workflows/main-ci.yml
vendored
36
.github/workflows/main-ci.yml
vendored
@@ -23,10 +23,15 @@ jobs:
|
||||
restore-keys: |
|
||||
${{ runner.os }}-gradle-
|
||||
|
||||
- name: Disable Gradle daemon
|
||||
run: |
|
||||
mkdir -p ~/.gradle
|
||||
echo "org.gradle.daemon=false" >> ~/.gradle/gradle.properties
|
||||
|
||||
- name: Build with Gradle
|
||||
run: |
|
||||
./gradlew assemble --no-daemon || ./gradlew assemble --no-daemon
|
||||
./gradlew downloadAssets --no-daemon || ./gradlew downloadAssets --no-daemon
|
||||
./gradlew assemble || ./gradlew assemble
|
||||
./gradlew downloadAssets || ./gradlew downloadAssets
|
||||
./gradlew build
|
||||
|
||||
- name: Upload Jar
|
||||
@@ -36,18 +41,21 @@ jobs:
|
||||
path: build/libs
|
||||
|
||||
- name: Upload Coverage
|
||||
run: bash <(curl -s https://codecov.io/bash)
|
||||
continue-on-error: true
|
||||
uses: codecov/codecov-action@v1
|
||||
|
||||
- name: Generate Java documentation stubs
|
||||
run: ./gradlew luaJavadoc --no-daemon
|
||||
- name: Parse test reports
|
||||
run: ./tools/parse-reports.py
|
||||
if: ${{ failure() }}
|
||||
|
||||
- name: Lint Lua code
|
||||
- name: Cache pre-commit
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pre-commit
|
||||
key: ${{ runner.os }}-pre-commit-${{ hashFiles('config/pre-commit/config.yml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pre-commit-
|
||||
|
||||
- name: Run linters
|
||||
run: |
|
||||
test -d bin || mkdir bin
|
||||
test -f bin/illuaminate || wget -q -Obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate
|
||||
chmod +x bin/illuaminate
|
||||
bin/illuaminate lint
|
||||
|
||||
- name: Check whitespace
|
||||
run: python3 tools/check-lines.py
|
||||
pip install pre-commit
|
||||
pre-commit run --config config/pre-commit/config.yml --show-diff-on-failure --all --color=always
|
||||
|
||||
22
.gitpod.yml
Normal file
22
.gitpod.yml
Normal file
@@ -0,0 +1,22 @@
|
||||
image:
|
||||
file: config/gitpod/Dockerfile
|
||||
|
||||
ports:
|
||||
- port: 25565
|
||||
onOpen: notify
|
||||
|
||||
vscode:
|
||||
extensions:
|
||||
- eamodio.gitlens
|
||||
- github.vscode-pull-request-github
|
||||
- ms-azuretools.vscode-docker
|
||||
- redhat.java
|
||||
- richardwillis.vscode-gradle
|
||||
- vscjava.vscode-java-debug
|
||||
- vscode.github
|
||||
|
||||
tasks:
|
||||
- name: Setup pre-commit hool
|
||||
init: pre-commit install --config config/pre-commit/config.yml --allow-missing-config
|
||||
- name: Install npm packages
|
||||
init: npm ci
|
||||
@@ -19,6 +19,10 @@ process. When building on Windows, Use `gradlew.bat` instead of `./gradlew`.
|
||||
- **Clone the repository:** `git clone https://github.com/SquidDev-CC/CC-Tweaked.git && cd CC-Tweaked`
|
||||
- **Setup Forge:** `./gradlew build`
|
||||
- **Run Minecraft:** `./gradlew runClient` (or run the `GradleStart` class from your IDE).
|
||||
- **Optionally:** For small PRs (especially those only touching Lua code), it may be easier to use GitPod, which
|
||||
provides a pre-configured environment: [](https://gitpod.io/#https://github.com/SquidDev-CC/CC-Tweaked/)
|
||||
|
||||
Do note you will need to download the mod after compiling to test.
|
||||
|
||||
If you want to run CC:T in a normal Minecraft instance, run `./gradlew build` and copy the `.jar` from `build/libs`.
|
||||
These commands may take a few minutes to run the first time, as the environment is set up, but should be much faster
|
||||
@@ -51,18 +55,10 @@ illuaminate, which spits out our HTML.
|
||||
For various reasons, getting the environment set up to build documentation can be pretty complex. I'd quite like to
|
||||
automate this via Docker and/or nix in the future, but this needs to be done manually for now.
|
||||
|
||||
First, you will need JDK 9+ (in addition to JDK 8 which is required to build Minecraft itself). Sadly our version of
|
||||
Gradle doesn't support multiple toolchains, and so you need to install this yourself.
|
||||
|
||||
Gradle needs to be told about this JDK via the `JAVA_HOME_11_X64` environment variable or adding `java11Home` to
|
||||
`~/.gradle/gradle.properties`. On my system this looks like:
|
||||
|
||||
```properties
|
||||
java11Home=/usr/lib/jvm/java-11-openjdk/
|
||||
```
|
||||
|
||||
If you just want to build the documentation stubs for linting, this is enough. However, if you want to build the full
|
||||
website, you will also need to install a few Node packages by running `npm ci`.
|
||||
This tooling is only needed if you need to build the whole website. If you just want to generate the Lua stubs, you can
|
||||
skp this section.
|
||||
- Install Node/npm and install our Node packages with `npm ci`.
|
||||
- Install [illuaminate][illuaminate-usage] as described above.
|
||||
|
||||
#### Building documentation
|
||||
Gradle should be your entrypoint to building most documentation. There's two tasks which are of interest:
|
||||
@@ -73,7 +69,7 @@ Gradle should be your entrypoint to building most documentation. There's two tas
|
||||
|
||||
#### Writing documentation
|
||||
illuaminate's documentation system is not currently documented (somewhat ironic), but is _largely_ the same as
|
||||
[ldoc][ldoc]. Documentation comments are written in Markdown,
|
||||
[ldoc][ldoc]. Documentation comments are written in Markdown,
|
||||
|
||||
Our markdown engine does _not_ support GitHub flavoured markdown, and so does not support all the features one might
|
||||
expect (such as tables). It is very much recommended that you build and preview the docs locally first.
|
||||
@@ -85,18 +81,18 @@ entire test suite (and some additional bits of verification).
|
||||
Before we get into writing tests, it's worth mentioning the various test suites that CC: Tweaked has:
|
||||
- "Core" Java (`./src/test/java`): These test core bits of the mod which don't require any Minecraft interaction.
|
||||
This includes the `@LuaFunction` system, file system code, etc...
|
||||
|
||||
|
||||
These tests are run by `./gradlew test`.
|
||||
|
||||
- CraftOS (`./src/test/resources/test-rom/`): These tests are written in Lua, and ensure the Lua environment, libraries
|
||||
and programs work as expected. These are (generally) written to be able to be run on emulators too, to provide some
|
||||
sort of compliance test.
|
||||
|
||||
|
||||
These tests are run by the '"Core" Java' test suite, and so are also run with `./gradlew test`.
|
||||
|
||||
- In-game (`./src/test/java/dan200/computercraft/ingame/`): These tests are run on an actual Minecraft server, using
|
||||
[the same system Mojang do][mc-test]. The aim of these is to test in-game behaviour of blocks and peripherals.
|
||||
|
||||
|
||||
These are run by `./gradlew testInGame`.
|
||||
|
||||
## CraftOS tests
|
||||
|
||||
14
LICENSE
14
LICENSE
@@ -19,14 +19,14 @@ Mod: The mod code designated by the present license, in source form, binary
|
||||
form, as obtained standalone, as part of a wider distribution or resulting from
|
||||
the compilation of the original or modified sources.
|
||||
|
||||
Dependency: Code required for the mod to work properly. This includes
|
||||
Dependency: Code required for the mod to work properly. This includes
|
||||
dependencies required to compile the code as well as any file or modification
|
||||
that is explicitly or implicitly required for the mod to be working.
|
||||
|
||||
1. Scope
|
||||
--------
|
||||
|
||||
The present license is granted to any user of the mod. As a prerequisite,
|
||||
The present license is granted to any user of the mod. As a prerequisite,
|
||||
a user must own a legally acquired copy of Minecraft
|
||||
|
||||
2. Liability
|
||||
@@ -41,13 +41,13 @@ or misuse of this mod fall on the user.
|
||||
3. Play rights
|
||||
--------------
|
||||
|
||||
The user is allowed to install this mod on a Minecraft client or server and to play
|
||||
The user is allowed to install this mod on a Minecraft client or server and to play
|
||||
without restriction.
|
||||
|
||||
4. Modification rights
|
||||
----------------------
|
||||
|
||||
The user has the right to decompile the source code, look at either the
|
||||
The user has the right to decompile the source code, look at either the
|
||||
decompiled version or the original source code, and to modify it.
|
||||
|
||||
5. Distribution of original or modified copy rights
|
||||
@@ -61,10 +61,10 @@ include:
|
||||
- patch to its source or binary files
|
||||
- any copy of a portion of its binary source files
|
||||
|
||||
The user is allowed to redistribute this mod partially, in totality, or
|
||||
The user is allowed to redistribute this mod partially, in totality, or
|
||||
included in a distribution.
|
||||
|
||||
When distributing binary files, the user must provide means to obtain its
|
||||
When distributing binary files, the user must provide means to obtain its
|
||||
entire set of sources or modified sources at no cost.
|
||||
|
||||
All distributions of this mod must remain licensed under the CCPL.
|
||||
@@ -92,7 +92,7 @@ must be made available at no cost and remain licensed under the CCPL.
|
||||
---------------
|
||||
|
||||
If you choose to contribute code or assets to be included in this mod, you
|
||||
agree that, if added to to the main repository at
|
||||
agree that, if added to to the main repository at
|
||||
https://github.com/dan200/ComputerCraft, your contributions will be covered by
|
||||
this license, and that Daniel Ratcliffe will retain the right to re-license the
|
||||
mod, including your contributions, in part or in whole, under other licenses.
|
||||
|
||||
353
build.gradle
353
build.gradle
@@ -1,40 +1,58 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
maven {
|
||||
name = "forge"
|
||||
url = "https://files.minecraftforge.net/maven"
|
||||
url = "https://maven.minecraftforge.net"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.google.code.gson:gson:2.8.1'
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:3.0.190'
|
||||
classpath 'net.sf.proguard:proguard-gradle:6.1.0beta2'
|
||||
classpath 'org.ajoberstar.grgit:grgit-gradle:3.0.0'
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:5.0.12'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "checkstyle"
|
||||
id "jacoco"
|
||||
id "com.github.hierynomus.license" version "0.15.0"
|
||||
id "com.matthewprenger.cursegradle" version "1.3.0"
|
||||
id "com.github.breadmoirai.github-release" version "2.2.4"
|
||||
id "maven-publish"
|
||||
id "com.github.hierynomus.license" version "0.16.1"
|
||||
id "com.matthewprenger.cursegradle" version "1.4.0"
|
||||
id "com.github.breadmoirai.github-release" version "2.2.12"
|
||||
id "org.jetbrains.kotlin.jvm" version "1.3.72"
|
||||
id "com.modrinth.minotaur" version "1.2.1"
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle'
|
||||
apply plugin: 'org.ajoberstar.grgit'
|
||||
apply plugin: 'maven-publish'
|
||||
apply plugin: 'maven'
|
||||
|
||||
version = mod_version
|
||||
|
||||
group = "org.squiddev"
|
||||
archivesBaseName = "cc-tweaked-${mc_version}"
|
||||
|
||||
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8'
|
||||
def javaVersion = JavaLanguageVersion.of(8)
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = javaVersion
|
||||
}
|
||||
|
||||
withSourcesJar()
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
// Tragically java.toolchain.languageVersion doesn't apply to ForgeGradle's
|
||||
// tasks, so we force all launchers to use the right Java version.
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
javaCompiler = javaToolchains.compilerFor {
|
||||
languageVersion = javaVersion
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaExec).configureEach {
|
||||
javaLauncher = javaToolchains.launcherFor {
|
||||
languageVersion = javaVersion
|
||||
}
|
||||
}
|
||||
|
||||
minecraft {
|
||||
runs {
|
||||
@@ -79,6 +97,7 @@ minecraft {
|
||||
testServer {
|
||||
workingDirectory project.file('test-files/server')
|
||||
parent runs.server
|
||||
arg "--nogui"
|
||||
|
||||
mods {
|
||||
cctest {
|
||||
@@ -88,9 +107,10 @@ minecraft {
|
||||
}
|
||||
}
|
||||
|
||||
mappings channel: 'official', version: project.mc_version
|
||||
mappings channel: 'official', version: mc_version
|
||||
|
||||
accessTransformer file('src/main/resources/META-INF/accesstransformer.cfg')
|
||||
accessTransformer file('src/test/resources/META-INF/accesstransformer.cfg')
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
@@ -110,7 +130,6 @@ repositories {
|
||||
configurations {
|
||||
shade
|
||||
compile.extendsFrom shade
|
||||
deployerJars
|
||||
cctJavadoc
|
||||
}
|
||||
|
||||
@@ -119,15 +138,13 @@ dependencies {
|
||||
|
||||
minecraft "net.minecraftforge:forge:${mc_version}-${forge_version}"
|
||||
|
||||
compileOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.3:api")
|
||||
compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.15.2:6.0.0.9")
|
||||
compileOnly fg.deobf("mezz.jei:jei-1.16.5:7.7.0.104:api")
|
||||
compileOnly fg.deobf("com.blamejared.crafttweaker:CraftTweaker-1.16.5:7.1.0.313")
|
||||
compileOnly fg.deobf("commoble.morered:morered-1.16.5:2.1.1.0")
|
||||
|
||||
runtimeOnly fg.deobf("mezz.jei:jei-1.15.2:6.0.0.3")
|
||||
runtimeOnly fg.deobf("mezz.jei:jei-1.16.5:7.7.0.104")
|
||||
|
||||
compileOnly 'com.google.auto.service:auto-service:1.0-rc7'
|
||||
annotationProcessor 'com.google.auto.service:auto-service:1.0-rc7'
|
||||
|
||||
shade 'org.squiddev:Cobalt:0.5.1-SNAPSHOT'
|
||||
shade 'org.squiddev:Cobalt:0.5.2-SNAPSHOT'
|
||||
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.7.0'
|
||||
@@ -137,9 +154,7 @@ dependencies {
|
||||
testImplementation 'org.jetbrains.kotlin:kotlin-reflect:1.3.72'
|
||||
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.3.8'
|
||||
|
||||
deployerJars "org.apache.maven.wagon:wagon-ssh:3.0.0"
|
||||
|
||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.3.0'
|
||||
cctJavadoc 'cc.tweaked:cct-javadoc:1.4.0'
|
||||
}
|
||||
|
||||
// Compile tasks
|
||||
@@ -158,31 +173,24 @@ task luaJavadoc(type: Javadoc) {
|
||||
|
||||
options.docletpath = configurations.cctJavadoc.files as List
|
||||
options.doclet = "cc.tweaked.javadoc.LuaDoclet"
|
||||
options.noTimestamp = false
|
||||
|
||||
// Attempt to run under Java 11 (any Java >= 9 will work though).
|
||||
if(System.getProperty("java.version").startsWith("1.")
|
||||
&& (System.getenv("JAVA_HOME_11_X64") != null || project.hasProperty("java11Home"))) {
|
||||
executable = "${System.getenv("JAVA_HOME_11_X64") ?: project.property("java11Home")}/bin/javadoc"
|
||||
javadocTool = javaToolchains.javadocToolFor {
|
||||
languageVersion = JavaLanguageVersion.of(11)
|
||||
}
|
||||
}
|
||||
|
||||
jar {
|
||||
dependsOn javadoc
|
||||
|
||||
manifest {
|
||||
attributes(["Specification-Title": "computercraft",
|
||||
"Specification-Vendor": "SquidDev",
|
||||
"Specification-Version": "1",
|
||||
"Implementation-Title": "CC: Tweaked",
|
||||
"Implementation-Version": "${mod_version}",
|
||||
"Implementation-Vendor" :"SquidDev",
|
||||
attributes(["Specification-Title" : "computercraft",
|
||||
"Specification-Vendor" : "SquidDev",
|
||||
"Specification-Version" : "1",
|
||||
"Implementation-Title" : "CC: Tweaked",
|
||||
"Implementation-Version" : "${mod_version}",
|
||||
"Implementation-Vendor" : "SquidDev",
|
||||
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")])
|
||||
}
|
||||
|
||||
from (sourceSets.main.allSource) {
|
||||
include "dan200/computercraft/api/**/*.java"
|
||||
}
|
||||
|
||||
from configurations.shade.collect { it.isDirectory() ? it : zipTree(it) }
|
||||
}
|
||||
|
||||
@@ -192,60 +200,6 @@ jar {
|
||||
}
|
||||
}
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
import java.nio.file.*
|
||||
import java.util.zip.*
|
||||
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.JsonElement
|
||||
import com.hierynomus.gradle.license.tasks.LicenseCheck
|
||||
import com.hierynomus.gradle.license.tasks.LicenseFormat
|
||||
import org.ajoberstar.grgit.Grgit
|
||||
import proguard.gradle.ProGuardTask
|
||||
|
||||
task proguard(type: ProGuardTask, dependsOn: jar) {
|
||||
description "Removes unused shadowed classes from the jar"
|
||||
group "compact"
|
||||
|
||||
injars jar.archivePath
|
||||
outjars "${jar.archivePath.absolutePath.replace(".jar", "")}-min.jar"
|
||||
|
||||
// Add the main runtime jar and all non-shadowed dependencies
|
||||
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
|
||||
libraryjars "${System.getProperty('java.home')}/lib/jce.jar"
|
||||
doFirst {
|
||||
sourceSets.main.compileClasspath
|
||||
.filter { !it.name.contains("Cobalt") }
|
||||
.each { libraryjars it }
|
||||
}
|
||||
|
||||
// We want to avoid as much obfuscation as possible. We're only doing this to shrink code size.
|
||||
dontobfuscate; dontoptimize; keepattributes; keepparameternames
|
||||
|
||||
// Proguard will remove directories by default, but that breaks JarMount.
|
||||
keepdirectories 'data/computercraft/lua**'
|
||||
|
||||
// Preserve ComputerCraft classes - we only want to strip shadowed files.
|
||||
keep 'class dan200.computercraft.** { *; }'
|
||||
|
||||
// LWJGL and Apache bundle Java 9 versions, which is great, but rather breaks Proguard
|
||||
dontwarn 'module-info'
|
||||
dontwarn 'org.apache.**,org.lwjgl.**'
|
||||
}
|
||||
|
||||
task proguardMove(dependsOn: proguard) {
|
||||
description "Replace the original jar with the minified version"
|
||||
group "compact"
|
||||
|
||||
doLast {
|
||||
Files.move(
|
||||
file("${jar.archivePath.absolutePath.replace(".jar", "")}-min.jar").toPath(),
|
||||
file(jar.archivePath).toPath(),
|
||||
StandardCopyOption.REPLACE_EXISTING
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property "version", mod_version
|
||||
inputs.property "mcversion", mc_version
|
||||
@@ -253,25 +207,25 @@ processResources {
|
||||
def hash = 'none'
|
||||
Set<String> contributors = []
|
||||
try {
|
||||
def grgit = Grgit.open(dir: '.')
|
||||
hash = grgit.head().id
|
||||
hash = ["git", "-C", projectDir, "rev-parse", "HEAD"].execute().text.trim()
|
||||
|
||||
def blacklist = ['GitHub', 'dan200', 'Daniel Ratcliffe']
|
||||
grgit.log().each {
|
||||
if (!blacklist.contains(it.author.name)) contributors.add(it.author.name)
|
||||
if (!blacklist.contains(it.committer.name)) contributors.add(it.committer.name)
|
||||
["git", "-C", projectDir, "log", "--format=tformat:%an%n%cn"].execute().text.split('\n').each {
|
||||
if (!blacklist.contains(it)) contributors.add(it)
|
||||
}
|
||||
} catch(Exception ignored) { }
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
inputs.property "commithash", hash
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include 'META-INF/mods.toml'
|
||||
include 'data/computercraft/lua/rom/help/credits.txt'
|
||||
|
||||
expand 'version': mod_version,
|
||||
'mcversion': mc_version,
|
||||
'gitcontributors': contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
|
||||
'mcversion': mc_version,
|
||||
'gitcontributors': contributors.sort(false, String.CASE_INSENSITIVE_ORDER).join('\n')
|
||||
}
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
@@ -280,51 +234,15 @@ processResources {
|
||||
}
|
||||
}
|
||||
|
||||
task compressJson(dependsOn: jar) {
|
||||
group "compact"
|
||||
description "Minifies all JSON files, stripping whitespace"
|
||||
|
||||
def jarPath = file(jar.archivePath)
|
||||
|
||||
def tempPath = File.createTempFile("input", ".jar", temporaryDir)
|
||||
tempPath.deleteOnExit()
|
||||
|
||||
def gson = new GsonBuilder().create()
|
||||
|
||||
doLast {
|
||||
// Copy over all files in the current jar to the new one, running json files from GSON. As pretty printing
|
||||
// is turned off, they should be minified.
|
||||
new ZipFile(jarPath).withCloseable { inJar ->
|
||||
tempPath.getParentFile().mkdirs()
|
||||
new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(tempPath))).withCloseable { outJar ->
|
||||
inJar.entries().each { entry ->
|
||||
if(entry.directory) {
|
||||
outJar.putNextEntry(entry)
|
||||
} else if(!entry.name.endsWith(".json")) {
|
||||
outJar.putNextEntry(entry)
|
||||
inJar.getInputStream(entry).withCloseable { outJar << it }
|
||||
} else {
|
||||
ZipEntry newEntry = new ZipEntry(entry.name)
|
||||
newEntry.setTime(entry.time)
|
||||
outJar.putNextEntry(newEntry)
|
||||
|
||||
def element = inJar.getInputStream(entry).withCloseable { gson.fromJson(it.newReader("UTF8"), JsonElement.class) }
|
||||
outJar.write(gson.toJson(element).getBytes(StandardCharsets.UTF_8))
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// And replace the original jar again
|
||||
Files.move(tempPath.toPath(), jarPath.toPath(), StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
sourcesJar {
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
}
|
||||
|
||||
assemble.dependsOn compressJson
|
||||
|
||||
// Web tasks
|
||||
|
||||
|
||||
import com.hierynomus.gradle.license.tasks.LicenseCheck
|
||||
import com.hierynomus.gradle.license.tasks.LicenseFormat
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
|
||||
List<String> mkCommand(String command) {
|
||||
@@ -423,8 +341,8 @@ gradle.projectsEvaluated {
|
||||
}
|
||||
|
||||
|
||||
task licenseAPI(type: LicenseCheck);
|
||||
task licenseFormatAPI(type: LicenseFormat);
|
||||
task licenseAPI(type: LicenseCheck)
|
||||
task licenseFormatAPI(type: LicenseFormat)
|
||||
[licenseAPI, licenseFormatAPI].forEach {
|
||||
it.configure {
|
||||
source = sourceSets.main.java
|
||||
@@ -447,7 +365,7 @@ task setupServer(type: Copy) {
|
||||
tasks.register('testInGame', JavaExec.class).configure {
|
||||
it.group('test server')
|
||||
it.description("Runs tests on a temporary Minecraft server.")
|
||||
it.dependsOn(setupServer, 'prepareRunTestServer')
|
||||
it.dependsOn(setupServer, 'prepareRunTestServer', 'cleanTestInGame')
|
||||
|
||||
// Copy from runTestServer. We do it in this slightly odd way as runTestServer
|
||||
// isn't created until the task is configured (which is no good for us).
|
||||
@@ -483,8 +401,8 @@ tasks.register('jacocoTestInGameReport', JacocoReport.class).configure {
|
||||
it.dependsOn('testInGame')
|
||||
|
||||
it.executionData(new File(buildDir, 'jacoco/testInGame.exec'))
|
||||
it.setSourceDirectories(project.files(sourceSets.main.allJava.srcDirs))
|
||||
it.setClassDirectories(project.files(new File(buildDir, 'jacocoClassDump/testInGame')))
|
||||
it.sourceDirectories.from(sourceSets.main.allJava.srcDirs)
|
||||
it.classDirectories.from(new File(buildDir, 'jacocoClassDump/testInGame'))
|
||||
|
||||
it.reports {
|
||||
xml.enabled true
|
||||
@@ -501,31 +419,31 @@ task checkRelease {
|
||||
description "Verifies that everything is ready for a release"
|
||||
|
||||
inputs.property "version", mod_version
|
||||
inputs.file("src/main/resources/data/computercraft/lua/rom/help/changelog.txt")
|
||||
inputs.file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.txt")
|
||||
inputs.file("src/main/resources/data/computercraft/lua/rom/help/changelog.md")
|
||||
inputs.file("src/main/resources/data/computercraft/lua/rom/help/whatsnew.md")
|
||||
|
||||
doLast {
|
||||
def ok = true
|
||||
|
||||
// Check we're targetting the current version
|
||||
def whatsnew = new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/whatsnew.txt").readLines()
|
||||
def whatsnew = new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/whatsnew.md").readLines()
|
||||
if (whatsnew[0] != "New features in CC: Tweaked $mod_version") {
|
||||
ok = false
|
||||
project.logger.error("Expected `whatsnew.txt' to target $mod_version.")
|
||||
project.logger.error("Expected `whatsnew.md' to target $mod_version.")
|
||||
}
|
||||
|
||||
// Check "read more" exists and trim it
|
||||
def idx = whatsnew.findIndexOf { it == 'Type "help changelog" to see the full version history.' }
|
||||
if (idx == -1) {
|
||||
ok = false
|
||||
project.logger.error("Must mention the changelog in whatsnew.txt")
|
||||
project.logger.error("Must mention the changelog in whatsnew.md")
|
||||
} else {
|
||||
whatsnew = whatsnew.getAt(0 ..< idx)
|
||||
whatsnew = whatsnew.getAt(0..<idx)
|
||||
}
|
||||
|
||||
// Check whatsnew and changelog match.
|
||||
def versionChangelog = "# " + whatsnew.join("\n")
|
||||
def changelog = new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/changelog.txt").getText()
|
||||
def changelog = new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/changelog.md").getText()
|
||||
if (!changelog.startsWith(versionChangelog)) {
|
||||
ok = false
|
||||
project.logger.error("whatsnew and changelog are not in sync")
|
||||
@@ -549,53 +467,65 @@ curseforge {
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
from components.java
|
||||
// artifact sourceJar
|
||||
}
|
||||
import com.modrinth.minotaur.TaskModrinthUpload
|
||||
tasks.register('publishModrinth', TaskModrinthUpload.class).configure {
|
||||
dependsOn('assemble', 'reobfJar')
|
||||
onlyIf {
|
||||
project.hasProperty('modrinthApiKey')
|
||||
}
|
||||
|
||||
token = project.hasProperty('curseForgeApiKey')
|
||||
projectId = 'gu7yAYhd'
|
||||
versionNumber = project.mod_version
|
||||
uploadFile = jar
|
||||
addGameVersion(project.mc_version)
|
||||
addLoader('forge')
|
||||
}
|
||||
|
||||
uploadArchives {
|
||||
tasks.withType(GenerateModuleMetadata) {
|
||||
// We can't generate metadata as that includes Forge as a dependency.
|
||||
enabled = false
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
maven(MavenPublication) {
|
||||
from components.java
|
||||
|
||||
pom {
|
||||
name = 'CC: Tweaked'
|
||||
description = 'CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.'
|
||||
url = 'https://github.com/SquidDev-CC/CC-Tweaked'
|
||||
|
||||
scm {
|
||||
url = 'https://github.com/SquidDev-CC/CC-Tweaked.git'
|
||||
}
|
||||
|
||||
issueManagement {
|
||||
system = 'github'
|
||||
url = 'https://github.com/SquidDev-CC/CC-Tweaked/issues'
|
||||
}
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name = 'ComputerCraft Public License, Version 1.0'
|
||||
url = 'https://github.com/SquidDev-CC/CC-Tweaked/blob/mc-1.15.x/LICENSE'
|
||||
}
|
||||
}
|
||||
|
||||
withXml { asNode().remove(asNode().get("dependencies")) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
if(project.hasProperty('mavenUploadUrl')) {
|
||||
mavenDeployer {
|
||||
configuration = configurations.deployerJars
|
||||
|
||||
repository(url: project.property('mavenUploadUrl')) {
|
||||
authentication(
|
||||
userName: project.property('mavenUploadUser'),
|
||||
privateKey: project.property('mavenUploadKey'))
|
||||
}
|
||||
|
||||
pom.project {
|
||||
name 'CC: Tweaked'
|
||||
packaging 'jar'
|
||||
description 'CC: Tweaked is a fork of ComputerCraft, adding programmable computers, turtles and more to Minecraft.'
|
||||
url 'https://github.com/SquidDev-CC/CC-Tweaked'
|
||||
|
||||
scm {
|
||||
url 'https://github.com/SquidDev-CC/CC-Tweaked.git'
|
||||
}
|
||||
|
||||
issueManagement {
|
||||
system 'github'
|
||||
url 'https://github.com/SquidDev-CC/CC-Tweaked/issues'
|
||||
}
|
||||
|
||||
licenses {
|
||||
license {
|
||||
name 'ComputerCraft Public License, Version 1.0'
|
||||
url 'https://github.com/SquidDev-CC/CC-Tweaked/blob/master/LICENSE'
|
||||
distribution 'repo'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pom.whenConfigured { pom ->
|
||||
pom.dependencies.clear()
|
||||
if (project.hasProperty("mavenUser")) {
|
||||
maven {
|
||||
name = "SquidDev"
|
||||
url = "https://squiddev.cc/maven"
|
||||
credentials {
|
||||
username = project.property("mavenUser") as String
|
||||
password = project.property("mavenPass") as String
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -606,25 +536,30 @@ githubRelease {
|
||||
token project.hasProperty('githubApiKey') ? project.githubApiKey : ''
|
||||
owner 'SquidDev-CC'
|
||||
repo 'CC-Tweaked'
|
||||
try {
|
||||
targetCommitish = Grgit.open(dir: '.').branch.current().name
|
||||
} catch(Exception ignored) { }
|
||||
targetCommitish.set(project.provider({
|
||||
try {
|
||||
return ["git", "-C", projectDir, "rev-parse", "--abbrev-ref", "HEAD"].execute().text.trim()
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
return "master"
|
||||
}))
|
||||
|
||||
tagName "v${mc_version}-${mod_version}"
|
||||
releaseName "[${mc_version}] ${mod_version}"
|
||||
body {
|
||||
body.set(project.provider({
|
||||
"## " + new File(projectDir, "src/main/resources/data/computercraft/lua/rom/help/whatsnew.txt")
|
||||
.readLines()
|
||||
.takeWhile { it != 'Type "help changelog" to see the full version history.' }
|
||||
.join("\n").trim()
|
||||
}
|
||||
.readLines()
|
||||
.takeWhile { it != 'Type "help changelog" to see the full version history.' }
|
||||
.join("\n").trim()
|
||||
}))
|
||||
prerelease false
|
||||
}
|
||||
|
||||
def uploadTasks = ["uploadArchives", "curseforge", "githubRelease"]
|
||||
def uploadTasks = ["publish", "curseforge", "publishModrinth", "githubRelease"]
|
||||
uploadTasks.forEach { tasks.getByName(it).dependsOn checkRelease }
|
||||
|
||||
task uploadAll(dependsOn: uploadTasks) {
|
||||
group "upload"
|
||||
description "Uploads to all repositories (Maven, Curse, GitHub release)"
|
||||
description "Uploads to all repositories (Maven, Curse, Modrinth, GitHub release)"
|
||||
}
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
<suppress checks="StaticVariableName" files=".*[\\/]ComputerCraft.java" />
|
||||
<suppress checks="StaticVariableName" files=".*[\\/]ComputerCraftAPI.java" />
|
||||
|
||||
<!-- Do not check for missing package Javadoc. -->
|
||||
<suppress checks="JavadocStyle" files=".*[\\/]package-info.java" />
|
||||
|
||||
<!-- The commands API is documented in Lua. -->
|
||||
<suppress checks="SummaryJavadocCheck" files=".*[\\/]CommandAPI.java" />
|
||||
</suppressions>
|
||||
|
||||
8
config/gitpod/Dockerfile
Normal file
8
config/gitpod/Dockerfile
Normal file
@@ -0,0 +1,8 @@
|
||||
FROM gitpod/workspace-base
|
||||
|
||||
USER gitpod
|
||||
|
||||
RUN sudo apt-get -q update \
|
||||
&& sudo apt-get install -yq openjdk-8-jdk openjdk-16-jdk python3-pip npm \
|
||||
&& sudo pip3 install pre-commit \
|
||||
&& sudo update-java-alternatives --set java-1.8.0-openjdk-amd64
|
||||
@@ -2488,4 +2488,4 @@
|
||||
</option>
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
</component>
|
||||
|
||||
@@ -58,4 +58,4 @@
|
||||
<option name="CONTINUATION_INDENT_SIZE" value="4" />
|
||||
</indentOptions>
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</code_scheme>
|
||||
|
||||
55
config/pre-commit/config.yml
Normal file
55
config/pre-commit/config.yml
Normal file
@@ -0,0 +1,55 @@
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.2.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-merge-conflict
|
||||
|
||||
# Quick syntax checkers
|
||||
- id: check-xml
|
||||
- id: check-yaml
|
||||
- id: check-toml
|
||||
- id: check-json
|
||||
exclude: "tsconfig\\.json$"
|
||||
|
||||
- repo: https://github.com/editorconfig-checker/editorconfig-checker.python
|
||||
rev: 2.3.5
|
||||
hooks:
|
||||
- id: editorconfig-checker
|
||||
args: ['-disable-indentation']
|
||||
exclude: "^(.*\\.(bat)|LICENSE)$"
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: checkstyle
|
||||
name: Check Java codestyle
|
||||
files: ".*\\.java$"
|
||||
language: system
|
||||
entry: ./gradlew checkstyleMain checkstyleTest
|
||||
pass_filenames: false
|
||||
require_serial: true
|
||||
- id: license
|
||||
name: Check Java license headers
|
||||
files: ".*\\.java$"
|
||||
language: system
|
||||
entry: ./gradlew licenseFormat
|
||||
pass_filenames: false
|
||||
require_serial: true
|
||||
- id: illuaminate
|
||||
name: Check Lua code
|
||||
files: ".*\\.(lua|java|md)"
|
||||
language: script
|
||||
entry: config/pre-commit/illuaminate-lint.sh
|
||||
pass_filenames: false
|
||||
require_serial: true
|
||||
|
||||
exclude: |
|
||||
(?x)^(
|
||||
src/generated|
|
||||
src/test/resources/test-rom/data/json-parsing/|
|
||||
src/test/server-files/|
|
||||
config/idea/
|
||||
)
|
||||
16
config/pre-commit/illuaminate-lint.sh
Executable file
16
config/pre-commit/illuaminate-lint.sh
Executable file
@@ -0,0 +1,16 @@
|
||||
#!/usr/bin/env sh
|
||||
set -e
|
||||
|
||||
test -d bin || mkdir bin
|
||||
test -f bin/illuaminate || curl -s -obin/illuaminate https://squiddev.cc/illuaminate/linux-x86-64/illuaminate
|
||||
chmod +x bin/illuaminate
|
||||
|
||||
if [ -n ${GITHUB_ACTIONS+x} ]; then
|
||||
# Register a problem matcher (see https://github.com/actions/toolkit/blob/master/docs/problem-matchers.md)
|
||||
# for illuaminate.
|
||||
echo "::add-matcher::.github/matchers/illuaminate.json"
|
||||
trap 'echo "::remove-matcher owner=illuaminate::"' EXIT
|
||||
fi
|
||||
|
||||
./gradlew luaJavadoc
|
||||
bin/illuaminate lint
|
||||
21
doc/events/alarm.md
Normal file
21
doc/events/alarm.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
module: [kind=event] alarm
|
||||
see: os.setAlarm To start an alarm.
|
||||
---
|
||||
|
||||
The @{timer} event is fired when an alarm started with @{os.setAlarm} completes.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{number}: The ID of the alarm that finished.
|
||||
|
||||
## Example
|
||||
Starts a timer and then prints its ID:
|
||||
```lua
|
||||
local alarmID = os.setAlarm(os.time() + 0.05)
|
||||
local event, id
|
||||
repeat
|
||||
event, id = os.pullEvent("alarm")
|
||||
until id == alarmID
|
||||
print("Alarm with ID " .. id .. " was fired")
|
||||
```
|
||||
18
doc/events/computer_command.md
Normal file
18
doc/events/computer_command.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
module: [kind=event] computer_command
|
||||
---
|
||||
|
||||
The @{computer_command} event is fired when the `/computercraft queue` command is run for the current computer.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
... @{string}: The arguments passed to the command.
|
||||
|
||||
## Example
|
||||
Prints the contents of messages sent:
|
||||
```lua
|
||||
while true do
|
||||
local event = {os.pullEvent("computer_command")}
|
||||
print("Received message:", table.unpack(event, 2))
|
||||
end
|
||||
```
|
||||
19
doc/events/disk.md
Normal file
19
doc/events/disk.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
module: [kind=event] disk
|
||||
see: disk_eject For the event sent when a disk is removed.
|
||||
---
|
||||
|
||||
The @{disk} event is fired when a disk is inserted into an adjacent or networked disk drive.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The side of the disk drive that had a disk inserted.
|
||||
|
||||
## Example
|
||||
Prints a message when a disk is inserted:
|
||||
```lua
|
||||
while true do
|
||||
local event, side = os.pullEvent("disk")
|
||||
print("Inserted a disk on side " .. side)
|
||||
end
|
||||
```
|
||||
19
doc/events/disk_eject.md
Normal file
19
doc/events/disk_eject.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
module: [kind=event] disk_eject
|
||||
see: disk For the event sent when a disk is inserted.
|
||||
---
|
||||
|
||||
The @{disk_eject} event is fired when a disk is removed from an adjacent or networked disk drive.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The side of the disk drive that had a disk removed.
|
||||
|
||||
## Example
|
||||
Prints a message when a disk is removed:
|
||||
```lua
|
||||
while true do
|
||||
local event, side = os.pullEvent("disk_eject")
|
||||
print("Removed a disk on side " .. side)
|
||||
end
|
||||
```
|
||||
14
doc/events/http_check.md
Normal file
14
doc/events/http_check.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
module: [kind=event] http_check
|
||||
see: http.checkURLAsync To check a URL asynchronously.
|
||||
---
|
||||
|
||||
The @{http_check} event is fired when a URL check finishes.
|
||||
|
||||
This event is normally handled inside @{http.checkURL}, but it can still be seen when using @{http.checkURLAsync}.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The URL requested to be checked.
|
||||
3. @{boolean}: Whether the check succeeded.
|
||||
4. @{string|nil}: If the check failed, a reason explaining why the check failed.
|
||||
39
doc/events/http_failure.md
Normal file
39
doc/events/http_failure.md
Normal file
@@ -0,0 +1,39 @@
|
||||
---
|
||||
module: [kind=event] http_failure
|
||||
see: http.request To send an HTTP request.
|
||||
---
|
||||
|
||||
The @{http_failure} event is fired when an HTTP request fails.
|
||||
|
||||
This event is normally handled inside @{http.get} and @{http.post}, but it can still be seen when using @{http.request}.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The URL of the site requested.
|
||||
3. @{string}: An error describing the failure.
|
||||
4. @{http.Response|nil}: A response handle if the connection succeeded, but the server's response indicated failure.
|
||||
|
||||
## Example
|
||||
Prints an error why the website cannot be contacted:
|
||||
```lua
|
||||
local myURL = "https://does.not.exist.tweaked.cc"
|
||||
http.request(myURL)
|
||||
local event, url, err
|
||||
repeat
|
||||
event, url, err = os.pullEvent("http_failure")
|
||||
until url == myURL
|
||||
print("The URL " .. url .. " could not be reached: " .. err)
|
||||
```
|
||||
|
||||
Prints the contents of a webpage that does not exist:
|
||||
```lua
|
||||
local myURL = "https://tweaked.cc/this/does/not/exist"
|
||||
http.request(myURL)
|
||||
local event, url, err, handle
|
||||
repeat
|
||||
event, url, err, handle = os.pullEvent("http_failure")
|
||||
until url == myURL
|
||||
print("The URL " .. url .. " could not be reached: " .. err)
|
||||
print(handle.getResponseCode())
|
||||
handle.close()
|
||||
```
|
||||
27
doc/events/http_success.md
Normal file
27
doc/events/http_success.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
module: [kind=event] http_success
|
||||
see: http.request To make an HTTP request.
|
||||
---
|
||||
|
||||
The @{http_success} event is fired when an HTTP request returns successfully.
|
||||
|
||||
This event is normally handled inside @{http.get} and @{http.post}, but it can still be seen when using @{http.request}.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The URL of the site requested.
|
||||
3. @{http.Response}: The handle for the response text.
|
||||
|
||||
## Example
|
||||
Prints the content of a website (this may fail if the request fails):
|
||||
```lua
|
||||
local myURL = "https://tweaked.cc/"
|
||||
http.request(myURL)
|
||||
local event, url, handle
|
||||
repeat
|
||||
event, url, handle = os.pullEvent("http_success")
|
||||
until url == myURL
|
||||
print("Contents of " .. url .. ":")
|
||||
print(handle.readAll())
|
||||
handle.close()
|
||||
```
|
||||
@@ -11,16 +11,16 @@ If the button pressed represented a printable character, then the @{key} event w
|
||||
event. If you are consuming text input, use a @{char} event instead!
|
||||
|
||||
## Return values
|
||||
1. [`string`]: The event name.
|
||||
2. [`number`]: The numerical key value of the key pressed.
|
||||
3. [`boolean`]: Whether the key event was generated while holding the key (@{true}), rather than pressing it the first time (@{false}).
|
||||
1. @{string}: The event name.
|
||||
2. @{number}: The numerical key value of the key pressed.
|
||||
3. @{boolean}: Whether the key event was generated while holding the key (@{true}), rather than pressing it the first time (@{false}).
|
||||
|
||||
## Example
|
||||
Prints each key when the user presses it, and if the key is being held.
|
||||
|
||||
```lua
|
||||
while true do
|
||||
local event, key, is_held = os.pullEvent("key")
|
||||
local event, key, is_held = os.pullEvent("key")
|
||||
print(("%s held=%s"):format(keys.getName(key), is_held))
|
||||
end
|
||||
```
|
||||
|
||||
22
doc/events/modem_message.md
Normal file
22
doc/events/modem_message.md
Normal file
@@ -0,0 +1,22 @@
|
||||
---
|
||||
module: [kind=event] modem_message
|
||||
---
|
||||
|
||||
The @{modem_message} event is fired when a message is received on an open channel on any modem.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The side of the modem that received the message.
|
||||
3. @{number}: The channel that the message was sent on.
|
||||
4. @{number}: The reply channel set by the sender.
|
||||
5. @{any}: The message as sent by the sender.
|
||||
6. @{number}: The distance between the sender and the receiver, in blocks (decimal).
|
||||
|
||||
## Example
|
||||
Prints a message when one is sent:
|
||||
```lua
|
||||
while true do
|
||||
local event, side, channel, replyChannel, message, distance = os.pullEvent("modem_message")
|
||||
print(("Message received on side %s on channel %d (reply to %d) from %f blocks away with message %s"):format(side, channel, replyChannel, distance, tostring(message)))
|
||||
end
|
||||
```
|
||||
18
doc/events/monitor_resize.md
Normal file
18
doc/events/monitor_resize.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
module: [kind=event] monitor_resize
|
||||
---
|
||||
|
||||
The @{monitor_resize} event is fired when an adjacent or networked monitor's size is changed.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The side or network ID of the monitor that resized.
|
||||
|
||||
## Example
|
||||
Prints a message when a monitor is resized:
|
||||
```lua
|
||||
while true do
|
||||
local event, side = os.pullEvent("monitor_resize")
|
||||
print("The monitor on side " .. side .. " was resized.")
|
||||
end
|
||||
```
|
||||
20
doc/events/monitor_touch.md
Normal file
20
doc/events/monitor_touch.md
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
module: [kind=event] monitor_touch
|
||||
---
|
||||
|
||||
The @{monitor_touch} event is fired when an adjacent or networked Advanced Monitor is right-clicked.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The side or network ID of the monitor that was touched.
|
||||
3. @{number}: The X coordinate of the touch, in characters.
|
||||
4. @{number}: The Y coordinate of the touch, in characters.
|
||||
|
||||
## Example
|
||||
Prints a message when a monitor is touched:
|
||||
```lua
|
||||
while true do
|
||||
local event, side, x, y = os.pullEvent("monitor_touch")
|
||||
print("The monitor on side " .. side .. " was touched at (" .. x .. ", " .. y .. ")")
|
||||
end
|
||||
```
|
||||
@@ -20,5 +20,3 @@ while true do
|
||||
print(("The mouse button %s was dragged at %d, %d"):format(button, x, y))
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -19,6 +19,3 @@ while true do
|
||||
print(("The mouse button %s was released at %d, %d"):format(button, x, y))
|
||||
end
|
||||
```
|
||||
|
||||
[`string`]: string
|
||||
[`number`]: number
|
||||
|
||||
18
doc/events/paste.md
Normal file
18
doc/events/paste.md
Normal file
@@ -0,0 +1,18 @@
|
||||
---
|
||||
module: [kind=event] paste
|
||||
---
|
||||
|
||||
The @{paste} event is fired when text is pasted into the computer through Ctrl-V (or ⌘V on Mac).
|
||||
|
||||
## Return values
|
||||
1. @{string}: The event name.
|
||||
2. @{string} The text that was pasted.
|
||||
|
||||
## Example
|
||||
Prints pasted text:
|
||||
```lua
|
||||
while true do
|
||||
local event, text = os.pullEvent("paste")
|
||||
print('"' .. text .. '" was pasted')
|
||||
end
|
||||
```
|
||||
19
doc/events/peripheral.md
Normal file
19
doc/events/peripheral.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
module: [kind=event] peripheral
|
||||
see: peripheral_detach For the event fired when a peripheral is detached.
|
||||
---
|
||||
|
||||
The @{peripheral} event is fired when a peripheral is attached on a side or to a modem.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The side the peripheral was attached to.
|
||||
|
||||
## Example
|
||||
Prints a message when a peripheral is attached:
|
||||
```lua
|
||||
while true do
|
||||
local event, side = os.pullEvent("peripheral")
|
||||
print("A peripheral was attached on side " .. side)
|
||||
end
|
||||
```
|
||||
19
doc/events/peripheral_detach.md
Normal file
19
doc/events/peripheral_detach.md
Normal file
@@ -0,0 +1,19 @@
|
||||
---
|
||||
module: [kind=event] peripheral_detach
|
||||
see: peripheral For the event fired when a peripheral is attached.
|
||||
---
|
||||
|
||||
The @{peripheral_detach} event is fired when a peripheral is detached from a side or from a modem.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The side the peripheral was detached from.
|
||||
|
||||
## Example
|
||||
Prints a message when a peripheral is detached:
|
||||
```lua
|
||||
while true do
|
||||
local event, side = os.pullEvent("peripheral_detach")
|
||||
print("A peripheral was detached on side " .. side)
|
||||
end
|
||||
```
|
||||
30
doc/events/rednet_message.md
Normal file
30
doc/events/rednet_message.md
Normal file
@@ -0,0 +1,30 @@
|
||||
---
|
||||
module: [kind=event] rednet_message
|
||||
see: modem_message For raw modem messages sent outside of Rednet.
|
||||
see: rednet.receive To wait for a Rednet message with an optional timeout and protocol filter.
|
||||
---
|
||||
|
||||
The @{rednet_message} event is fired when a message is sent over Rednet.
|
||||
|
||||
This event is usually handled by @{rednet.receive}, but it can also be pulled manually.
|
||||
|
||||
@{rednet_message} events are sent by @{rednet.run} in the top-level coroutine in response to @{modem_message} events. A @{rednet_message} event is always preceded by a @{modem_message} event. They are generated inside CraftOS rather than being sent by the ComputerCraft machine.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{number}: The ID of the sending computer.
|
||||
3. @{any}: The message sent.
|
||||
4. @{string|nil}: The protocol of the message, if provided.
|
||||
|
||||
## Example
|
||||
Prints a message when one is sent:
|
||||
```lua
|
||||
while true do
|
||||
local event, sender, message, protocol = os.pullEvent("rednet_message")
|
||||
if protocol ~= nil then
|
||||
print("Received message from " .. sender .. " with protocol " .. protocol .. " and message " .. tostring(message))
|
||||
else
|
||||
print("Received message from " .. sender .. " with message " .. tostring(message))
|
||||
end
|
||||
end
|
||||
```
|
||||
14
doc/events/redstone.md
Normal file
14
doc/events/redstone.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
module: [kind=event] redstone
|
||||
---
|
||||
|
||||
The @{redstone} event is fired whenever any redstone inputs on the computer change.
|
||||
|
||||
## Example
|
||||
Prints a message when a redstone input changes:
|
||||
```lua
|
||||
while true do
|
||||
os.pullEvent("redstone")
|
||||
print("A redstone input has changed!")
|
||||
end
|
||||
```
|
||||
28
doc/events/task_complete.md
Normal file
28
doc/events/task_complete.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
module: [kind=event] task_complete
|
||||
see: commands.execAsync To run a command which fires a task_complete event.
|
||||
---
|
||||
|
||||
The @{task_complete} event is fired when an asynchronous task completes. This is usually handled inside the function call that queued the task; however, functions such as @{commands.execAsync} return immediately so the user can wait for completion.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{number}: The ID of the task that completed.
|
||||
3. @{boolean}: Whether the command succeeded.
|
||||
4. @{string}: If the command failed, an error message explaining the failure. (This is not present if the command succeeded.)
|
||||
...: Any parameters returned from the command.
|
||||
|
||||
## Example
|
||||
Prints the results of an asynchronous command:
|
||||
```lua
|
||||
local taskID = commands.execAsync("say Hello")
|
||||
local event
|
||||
repeat
|
||||
event = {os.pullEvent("task_complete")}
|
||||
until event[2] == taskID
|
||||
if event[3] == true then
|
||||
print("Task " .. event[2] .. " succeeded:", table.unpack(event, 4))
|
||||
else
|
||||
print("Task " .. event[2] .. " failed: " .. event[4])
|
||||
end
|
||||
```
|
||||
15
doc/events/term_resize.md
Normal file
15
doc/events/term_resize.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
module: [kind=event] term_resize
|
||||
---
|
||||
|
||||
The @{term_resize} event is fired when the main terminal is resized, mainly when a new tab is opened or closed in @{multishell}.
|
||||
|
||||
## Example
|
||||
Prints :
|
||||
```lua
|
||||
while true do
|
||||
os.pullEvent("term_resize")
|
||||
local w, h = term.getSize()
|
||||
print("The term was resized to (" .. w .. ", " .. h .. ")")
|
||||
end
|
||||
```
|
||||
25
doc/events/terminate.md
Normal file
25
doc/events/terminate.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
module: [kind=event] terminate
|
||||
---
|
||||
|
||||
The @{terminate} event is fired when <kbd>Ctrl-T</kbd> is held down.
|
||||
|
||||
This event is normally handled by @{os.pullEvent}, and will not be returned. However, @{os.pullEventRaw} will return this event when fired.
|
||||
|
||||
@{terminate} will be sent even when a filter is provided to @{os.pullEventRaw}. When using @{os.pullEventRaw} with a filter, make sure to check that the event is not @{terminate}.
|
||||
|
||||
## Example
|
||||
Prints a message when Ctrl-T is held:
|
||||
```lua
|
||||
while true do
|
||||
local event = os.pullEventRaw("terminate")
|
||||
if event == "terminate" then print("Terminate requested!") end
|
||||
end
|
||||
```
|
||||
|
||||
Exits when Ctrl-T is held:
|
||||
```lua
|
||||
while true do
|
||||
os.pullEvent()
|
||||
end
|
||||
```
|
||||
21
doc/events/timer.md
Normal file
21
doc/events/timer.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
module: [kind=event] timer
|
||||
see: os.startTimer To start a timer.
|
||||
---
|
||||
|
||||
The @{timer} event is fired when a timer started with @{os.startTimer} completes.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{number}: The ID of the timer that finished.
|
||||
|
||||
## Example
|
||||
Starts a timer and then prints its ID:
|
||||
```lua
|
||||
local timerID = os.startTimer(2)
|
||||
local event, id
|
||||
repeat
|
||||
event, id = os.pullEvent("timer")
|
||||
until id == timerID
|
||||
print("Timer with ID " .. id .. " was fired")
|
||||
```
|
||||
14
doc/events/turtle_inventory.md
Normal file
14
doc/events/turtle_inventory.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
module: [kind=event] turtle_inventory
|
||||
---
|
||||
|
||||
The @{turtle_inventory} event is fired when a turtle's inventory is changed.
|
||||
|
||||
## Example
|
||||
Prints a message when the inventory is changed:
|
||||
```lua
|
||||
while true do
|
||||
os.pullEvent("turtle_inventory")
|
||||
print("The inventory was changed.")
|
||||
end
|
||||
```
|
||||
21
doc/events/websocket_closed.md
Normal file
21
doc/events/websocket_closed.md
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
module: [kind=event] websocket_closed
|
||||
---
|
||||
|
||||
The @{websocket_closed} event is fired when an open WebSocket connection is closed.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The URL of the WebSocket that was closed.
|
||||
|
||||
## Example
|
||||
Prints a message when a WebSocket is closed (this may take a minute):
|
||||
```lua
|
||||
local myURL = "wss://example.tweaked.cc/echo"
|
||||
local ws = http.websocket(myURL)
|
||||
local event, url
|
||||
repeat
|
||||
event, url = os.pullEvent("websocket_closed")
|
||||
until url == myURL
|
||||
print("The WebSocket at " .. url .. " was closed.")
|
||||
```
|
||||
25
doc/events/websocket_failure.md
Normal file
25
doc/events/websocket_failure.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
module: [kind=event] websocket_failure
|
||||
see: http.websocketAsync To send an HTTP request.
|
||||
---
|
||||
|
||||
The @{websocket_failure} event is fired when a WebSocket connection request fails.
|
||||
|
||||
This event is normally handled inside @{http.websocket}, but it can still be seen when using @{http.websocketAsync}.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The URL of the site requested.
|
||||
3. @{string}: An error describing the failure.
|
||||
|
||||
## Example
|
||||
Prints an error why the website cannot be contacted:
|
||||
```lua
|
||||
local myURL = "wss://example.tweaked.cc/not-a-websocket"
|
||||
http.websocketAsync(myURL)
|
||||
local event, url, err
|
||||
repeat
|
||||
event, url, err = os.pullEvent("websocket_failure")
|
||||
until url == myURL
|
||||
print("The URL " .. url .. " could not be reached: " .. err)
|
||||
```
|
||||
26
doc/events/websocket_message.md
Normal file
26
doc/events/websocket_message.md
Normal file
@@ -0,0 +1,26 @@
|
||||
---
|
||||
module: [kind=event] websocket_message
|
||||
---
|
||||
|
||||
The @{websocket_message} event is fired when a message is received on an open WebSocket connection.
|
||||
|
||||
This event is normally handled by @{http.Websocket.receive}, but it can also be pulled manually.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The URL of the WebSocket.
|
||||
3. @{string}: The contents of the message.
|
||||
|
||||
## Example
|
||||
Prints a message sent by a WebSocket:
|
||||
```lua
|
||||
local myURL = "wss://example.tweaked.cc/echo"
|
||||
local ws = http.websocket(myURL)
|
||||
ws.send("Hello!")
|
||||
local event, url, message
|
||||
repeat
|
||||
event, url, message = os.pullEvent("websocket_message")
|
||||
until url == myURL
|
||||
print("Received message from " .. url .. " with contents " .. message)
|
||||
ws.close()
|
||||
```
|
||||
28
doc/events/websocket_success.md
Normal file
28
doc/events/websocket_success.md
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
module: [kind=event] websocket_success
|
||||
see: http.websocketAsync To open a WebSocket asynchronously.
|
||||
---
|
||||
|
||||
The @{websocket_success} event is fired when a WebSocket connection request returns successfully.
|
||||
|
||||
This event is normally handled inside @{http.websocket}, but it can still be seen when using @{http.websocketAsync}.
|
||||
|
||||
## Return Values
|
||||
1. @{string}: The event name.
|
||||
2. @{string}: The URL of the site.
|
||||
3. @{http.Websocket}: The handle for the WebSocket.
|
||||
|
||||
## Example
|
||||
Prints the content of a website (this may fail if the request fails):
|
||||
```lua
|
||||
local myURL = "wss://example.tweaked.cc/echo"
|
||||
http.websocketAsync(myURL)
|
||||
local event, url, handle
|
||||
repeat
|
||||
event, url, handle = os.pullEvent("websocket_success")
|
||||
until url == myURL
|
||||
print("Connected to " .. url)
|
||||
handle.send("Hello!")
|
||||
print(handle.receive())
|
||||
handle.close()
|
||||
```
|
||||
@@ -58,10 +58,10 @@ function request(...) end
|
||||
-- @treturn string A message detailing why the request failed.
|
||||
-- @treturn Response|nil The failing http response, if available.
|
||||
--
|
||||
-- @usage Make a request to [example.computercraft.cc](https://example.computercraft.cc),
|
||||
-- @usage Make a request to [example.tweaked.cc](https://example.tweaked.cc),
|
||||
-- and print the returned page.
|
||||
-- ```lua
|
||||
-- local request = http.get("https://example.computercraft.cc")
|
||||
-- local request = http.get("https://example.tweaked.cc")
|
||||
-- print(request.readAll())
|
||||
-- -- => HTTP is working!
|
||||
-- request.close()
|
||||
@@ -123,7 +123,7 @@ function checkURLAsync(url) end
|
||||
--
|
||||
-- @usage
|
||||
-- ```lua
|
||||
-- print(http.checkURL("https://example.computercraft.cc/"))
|
||||
-- print(http.checkURL("https://example.tweaked.cc/"))
|
||||
-- -- => true
|
||||
-- print(http.checkURL("http://localhost/"))
|
||||
-- -- => false Domain not permitted
|
||||
|
||||
@@ -1 +1,13 @@
|
||||
--[[- Craft a recipe based on the turtle's inventory.
|
||||
|
||||
The turtle's inventory should set up like a crafting grid. For instance, to
|
||||
craft sticks, slots 1 and 5 should contain sticks. _All_ other slots should be
|
||||
empty, including those outside the crafting "grid".
|
||||
|
||||
@tparam[opt=64] number limit The maximum number of crafting steps to run.
|
||||
@throws When limit is less than 1 or greater than 64.
|
||||
@treturn[1] true If crafting succeeds.
|
||||
@treturn[2] false If crafting fails.
|
||||
@treturn string A string describing why crafting failed.
|
||||
]]
|
||||
function craft(limit) end
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Mod properties
|
||||
mod_version=1.95.2
|
||||
mod_version=1.97.0
|
||||
|
||||
# Minecraft properties (update mods.toml when changing)
|
||||
mc_version=1.15.2
|
||||
forge_version=31.1.41
|
||||
mc_version=1.16.5
|
||||
forge_version=36.1.0
|
||||
# NO SERIOUSLY, UPDATE mods.toml WHEN CHANGING
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
53
gradlew
vendored
53
gradlew
vendored
@@ -1,5 +1,21 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
@@ -66,6 +82,7 @@ esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
@@ -109,10 +126,11 @@ if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
@@ -138,19 +156,19 @@ if $cygwin ; then
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
@@ -159,14 +177,9 @@ save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
43
gradlew.bat
vendored
43
gradlew.bat
vendored
@@ -1,3 +1,19 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -35,7 +54,7 @@ goto fail
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
@@ -45,28 +64,14 @@ echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
@@ -88,27 +88,16 @@
|
||||
|
||||
;; Suppress warnings for currently undocumented modules.
|
||||
(at
|
||||
(; Java APIs
|
||||
/doc/stub/http.lua
|
||||
/doc/stub/os.lua
|
||||
/doc/stub/turtle.lua
|
||||
/doc/stub/global.lua
|
||||
; Java generated APIs
|
||||
/build/docs/luaJavadoc/turtle.lua
|
||||
; Peripherals
|
||||
/build/docs/luaJavadoc/drive.lua
|
||||
/build/docs/luaJavadoc/speaker.lua
|
||||
/build/docs/luaJavadoc/printer.lua
|
||||
; Generic peripherals
|
||||
/build/docs/luaJavadoc/fluid_storage.lua
|
||||
; Lua APIs
|
||||
(; Lua APIs
|
||||
/src/main/resources/*/computercraft/lua/rom/apis/io.lua
|
||||
/src/main/resources/*/computercraft/lua/rom/apis/window.lua)
|
||||
|
||||
(linters -doc:undocumented -doc:undocumented-arg -doc:undocumented-return))
|
||||
|
||||
;; Suppress warnings for the BIOS using its own deprecated members for now.
|
||||
(at /src/main/resources/*/computercraft/lua/bios.lua
|
||||
;; Suppress warnings for various APIs using its own deprecated members.
|
||||
(at
|
||||
(/src/main/resources/*/computercraft/lua/bios.lua
|
||||
/src/main/resources/*/computercraft/lua/rom/apis/turtle/turtle.lua)
|
||||
(linters -var:deprecated))
|
||||
|
||||
(at /src/test/resources/test-rom
|
||||
|
||||
10
src/generated/resources/data/minecraft/tags/items/piglin_loved.json
generated
Normal file
10
src/generated/resources/data/minecraft/tags/items/piglin_loved.json
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"replace": false,
|
||||
"values": [
|
||||
"computercraft:computer_advanced",
|
||||
"computercraft:turtle_advanced",
|
||||
"computercraft:wireless_modem_advanced",
|
||||
"computercraft:pocket_computer_advanced",
|
||||
"computercraft:monitor_advanced"
|
||||
]
|
||||
}
|
||||
@@ -8,7 +8,6 @@ package dan200.computercraft;
|
||||
import dan200.computercraft.api.turtle.event.TurtleAction;
|
||||
import dan200.computercraft.core.apis.http.options.Action;
|
||||
import dan200.computercraft.core.apis.http.options.AddressRule;
|
||||
import dan200.computercraft.core.asm.GenericSource;
|
||||
import dan200.computercraft.shared.Config;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
||||
@@ -17,7 +16,6 @@ import dan200.computercraft.shared.peripheral.monitor.MonitorRenderer;
|
||||
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
|
||||
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
|
||||
import dan200.computercraft.shared.turtle.upgrades.*;
|
||||
import dan200.computercraft.shared.util.ServiceUtil;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -38,7 +36,6 @@ public final class ComputerCraft
|
||||
public static int maximumFilesOpen = 128;
|
||||
public static boolean disableLua51Features = false;
|
||||
public static String defaultComputerSettings = "";
|
||||
public static boolean debugEnable = true;
|
||||
public static boolean logComputerErrors = true;
|
||||
public static boolean commandRequireCreative = true;
|
||||
|
||||
@@ -117,6 +114,5 @@ public final class ComputerCraft
|
||||
{
|
||||
Config.setup();
|
||||
Registry.setup();
|
||||
GenericSource.setup( () -> ServiceUtil.loadServicesForge( GenericSource.class ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ package dan200.computercraft;
|
||||
import dan200.computercraft.api.ComputerCraftAPI.IComputerCraftAPI;
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
import dan200.computercraft.api.lua.GenericSource;
|
||||
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
||||
import dan200.computercraft.api.media.IMediaProvider;
|
||||
import dan200.computercraft.api.network.IPacketNetwork;
|
||||
@@ -18,9 +19,11 @@ import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.redstone.IBundledRedstoneProvider;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import dan200.computercraft.core.apis.ApiFactories;
|
||||
import dan200.computercraft.core.asm.GenericMethod;
|
||||
import dan200.computercraft.core.filesystem.FileMount;
|
||||
import dan200.computercraft.core.filesystem.ResourceMount;
|
||||
import dan200.computercraft.shared.*;
|
||||
import dan200.computercraft.shared.peripheral.generic.GenericPeripheralProvider;
|
||||
import dan200.computercraft.shared.peripheral.modem.wireless.WirelessNetwork;
|
||||
import dan200.computercraft.shared.util.IDAssigner;
|
||||
import dan200.computercraft.shared.wired.WiredNode;
|
||||
@@ -31,6 +34,7 @@ import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.server.ServerLifecycleHooks;
|
||||
@@ -54,7 +58,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
|
||||
public static InputStream getResourceFile( String domain, String subPath )
|
||||
{
|
||||
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResources();
|
||||
IReloadableResourceManager manager = (IReloadableResourceManager) ServerLifecycleHooks.getCurrentServer().getDataPackRegistries().getResourceManager();
|
||||
try
|
||||
{
|
||||
return manager.getResource( new ResourceLocation( domain, subPath ) ).getInputStream();
|
||||
@@ -97,7 +101,7 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
@Override
|
||||
public IMount createResourceMount( @Nonnull String domain, @Nonnull String subPath )
|
||||
{
|
||||
IReloadableResourceManager manager = ServerLifecycleHooks.getCurrentServer().getResources();
|
||||
IReloadableResourceManager manager = (IReloadableResourceManager) ServerLifecycleHooks.getCurrentServer().getDataPackRegistries().getResourceManager();
|
||||
ResourceMount mount = ResourceMount.get( domain, subPath, manager );
|
||||
return mount.exists( "" ) ? mount : null;
|
||||
}
|
||||
@@ -108,6 +112,18 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
Peripherals.register( provider );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGenericSource( @Nonnull GenericSource source )
|
||||
{
|
||||
GenericMethod.register( source );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerGenericCapability( @Nonnull Capability<?> capability )
|
||||
{
|
||||
GenericPeripheralProvider.addCapability( capability );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade )
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ package dan200.computercraft.api;
|
||||
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
import dan200.computercraft.api.lua.GenericSource;
|
||||
import dan200.computercraft.api.lua.ILuaAPIFactory;
|
||||
import dan200.computercraft.api.media.IMedia;
|
||||
import dan200.computercraft.api.media.IMediaProvider;
|
||||
@@ -23,6 +24,7 @@ import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.common.util.LazyOptional;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -98,7 +100,9 @@ public final class ComputerCraftAPI
|
||||
* resource folder onto a computer's file system.
|
||||
*
|
||||
* The files in this mount will be a combination of files in all mod jar, and data packs that contain
|
||||
* resources with the same domain and path.
|
||||
* resources with the same domain and path. For instance, ComputerCraft's resources are stored in
|
||||
* "/data/computercraft/lua/rom". We construct a mount for that with
|
||||
* {@code createResourceMount("computercraft", "lua/rom")}.
|
||||
*
|
||||
* @param domain The domain under which to look for resources. eg: "mymod".
|
||||
* @param subPath The subPath under which to look for resources. eg: "lua/myfiles".
|
||||
@@ -114,7 +118,7 @@ public final class ComputerCraftAPI
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
|
||||
* rers a peripheral provider to convert blocks into {@link IPeripheral} implementations.
|
||||
*
|
||||
* @param provider The peripheral provider to register.
|
||||
* @see IPeripheral
|
||||
@@ -125,6 +129,28 @@ public final class ComputerCraftAPI
|
||||
getInstance().registerPeripheralProvider( provider );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a method source for generic peripherals.
|
||||
*
|
||||
* @param source The method source to register.
|
||||
* @see GenericSource
|
||||
*/
|
||||
public static void registerGenericSource( @Nonnull GenericSource source )
|
||||
{
|
||||
getInstance().registerGenericSource( source );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a capability that can be used by generic peripherals.
|
||||
*
|
||||
* @param capability The capability to register.
|
||||
* @see GenericSource
|
||||
*/
|
||||
public static void registerGenericCapability( @Nonnull Capability<?> capability )
|
||||
{
|
||||
getInstance().registerGenericCapability( capability );
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new turtle turtle for use in ComputerCraft. After calling this,
|
||||
* users should be able to craft Turtles with your new turtle. It is recommended to call
|
||||
@@ -256,6 +282,10 @@ public final class ComputerCraftAPI
|
||||
|
||||
void registerPeripheralProvider( @Nonnull IPeripheralProvider provider );
|
||||
|
||||
void registerGenericSource( @Nonnull GenericSource source );
|
||||
|
||||
void registerGenericCapability( @Nonnull Capability<?> capability );
|
||||
|
||||
void registerTurtleUpgrade( @Nonnull ITurtleUpgrade upgrade );
|
||||
|
||||
void registerBundledRedstoneProvider( @Nonnull IBundledRedstoneProvider provider );
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
package dan200.computercraft.api.client;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.TransformationMatrix;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.ModelManager;
|
||||
import net.minecraft.client.renderer.model.ModelResourceLocation;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.vector.TransformationMatrix;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Objects;
|
||||
@@ -32,7 +32,7 @@ public final class TransformedModel
|
||||
public TransformedModel( @Nonnull IBakedModel model )
|
||||
{
|
||||
this.model = Objects.requireNonNull( model );
|
||||
this.matrix = TransformationMatrix.identity();
|
||||
matrix = TransformationMatrix.identity();
|
||||
}
|
||||
|
||||
public static TransformedModel of( @Nonnull ModelResourceLocation location )
|
||||
|
||||
@@ -30,7 +30,7 @@ public class FileOperationException extends IOException
|
||||
public FileOperationException( @Nonnull String message )
|
||||
{
|
||||
super( Objects.requireNonNull( message, "message cannot be null" ) );
|
||||
this.filename = null;
|
||||
filename = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of the public ComputerCraft API - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. This API may be redistributed unmodified and in full only.
|
||||
* For help using the API, and posting your mods, visit the forums at computercraft.info.
|
||||
*/
|
||||
package dan200.computercraft.api.lua;
|
||||
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.api.peripheral.IPeripheralProvider;
|
||||
import dan200.computercraft.core.asm.LuaMethod;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.common.capabilities.Capability;
|
||||
import net.minecraftforge.items.IItemHandler;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* A generic source of {@link LuaMethod} functions.
|
||||
*
|
||||
* Unlike normal objects ({@link IDynamicLuaObject} or {@link IPeripheral}), methods do not target this object but
|
||||
* instead are defined as {@code static} and accept their target as the first parameter. This allows you to inject
|
||||
* methods onto objects you do not own, as well as declaring methods for a specific "trait" (for instance, a
|
||||
* {@link Capability}).
|
||||
*
|
||||
* Currently the "generic peripheral" system is incompatible with normal peripherals. Normal {@link IPeripheralProvider}
|
||||
* or {@link IPeripheral} implementations take priority. Tile entities which use this system are given a peripheral name
|
||||
* determined by their id, rather than any peripheral provider. This will hopefully change in the future, once a suitable
|
||||
* design has been established.
|
||||
*
|
||||
* For example, the main CC: Tweaked mod defines a generic source for inventories, which works on {@link IItemHandler}s:
|
||||
*
|
||||
* <pre>{@code
|
||||
* public class InventoryMethods implements GenericSource {
|
||||
* \@LuaFunction( mainThread = true )
|
||||
* public static int size(IItemHandler inventory) {
|
||||
* return inventory.getSlots();
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
* }</pre>
|
||||
*
|
||||
* @see ComputerCraftAPI#registerGenericSource(GenericSource)
|
||||
* @see ComputerCraftAPI#registerGenericCapability(Capability) New capabilities (those not built into Forge) must be
|
||||
* explicitly given to the generic peripheral system, as there is no way to enumerate all capabilities.
|
||||
*/
|
||||
public interface GenericSource
|
||||
{
|
||||
/**
|
||||
* A unique identifier for this generic source.
|
||||
*
|
||||
* This is currently unused, but may be used in the future to allow disabling specific sources. It is recommended
|
||||
* to return an identifier using your mod's ID.
|
||||
*
|
||||
* @return This source's identifier.
|
||||
*/
|
||||
@Nonnull
|
||||
ResourceLocation id();
|
||||
}
|
||||
@@ -19,14 +19,14 @@ public class LuaException extends Exception
|
||||
public LuaException( @Nullable String message )
|
||||
{
|
||||
super( message );
|
||||
this.hasLevel = false;
|
||||
this.level = 1;
|
||||
hasLevel = false;
|
||||
level = 1;
|
||||
}
|
||||
|
||||
public LuaException( @Nullable String message, int level )
|
||||
{
|
||||
super( message );
|
||||
this.hasLevel = true;
|
||||
hasLevel = true;
|
||||
this.level = level;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,14 +30,14 @@ public final class MethodResult
|
||||
|
||||
private MethodResult( Object[] arguments, ILuaCallback callback )
|
||||
{
|
||||
this.result = arguments;
|
||||
result = arguments;
|
||||
this.callback = callback;
|
||||
this.adjust = 0;
|
||||
adjust = 0;
|
||||
}
|
||||
|
||||
private MethodResult( Object[] arguments, ILuaCallback callback, int adjust )
|
||||
{
|
||||
this.result = arguments;
|
||||
result = arguments;
|
||||
this.callback = callback;
|
||||
this.adjust = adjust;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.api.network;
|
||||
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -29,7 +29,7 @@ public interface IPacketReceiver
|
||||
* @return The receiver's position.
|
||||
*/
|
||||
@Nonnull
|
||||
Vec3d getPosition();
|
||||
Vector3d getPosition();
|
||||
|
||||
/**
|
||||
* Get the maximum distance this receiver can send and receive messages.
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.api.network;
|
||||
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -29,7 +29,7 @@ public interface IPacketSender
|
||||
* @return The sender's position.
|
||||
*/
|
||||
@Nonnull
|
||||
Vec3d getPosition();
|
||||
Vector3d getPosition();
|
||||
|
||||
/**
|
||||
* Get some sort of identification string for this sender. This does not strictly need to be unique, but you
|
||||
|
||||
@@ -13,7 +13,7 @@ import net.minecraft.inventory.IInventory;
|
||||
import net.minecraft.nbt.CompoundNBT;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.items.IItemHandlerModifiable;
|
||||
|
||||
@@ -67,7 +67,7 @@ public interface ITurtleAccess
|
||||
* @see #getVisualYaw(float)
|
||||
*/
|
||||
@Nonnull
|
||||
Vec3d getVisualPosition( float f );
|
||||
Vector3d getVisualPosition( float f );
|
||||
|
||||
/**
|
||||
* Returns the yaw the turtle is facing when it is rendered.
|
||||
|
||||
40
src/main/java/dan200/computercraft/client/ClientHooks.java
Normal file
40
src/main/java/dan200/computercraft/client/ClientHooks.java
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.ClientPlayerNetworkEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
|
||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
|
||||
public class ClientHooks
|
||||
{
|
||||
@SubscribeEvent
|
||||
public static void onWorldUnload( WorldEvent.Unload event )
|
||||
{
|
||||
if( event.getWorld().isClientSide() )
|
||||
{
|
||||
ClientMonitor.destroyAll();
|
||||
SoundManager.reset();
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLogIn( ClientPlayerNetworkEvent.LoggedInEvent event )
|
||||
{
|
||||
ComputerCraft.clientComputerRegistry.reset();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLogOut( ClientPlayerNetworkEvent.LoggedOutEvent event )
|
||||
{
|
||||
ComputerCraft.clientComputerRegistry.reset();
|
||||
}
|
||||
}
|
||||
@@ -6,31 +6,39 @@
|
||||
package dan200.computercraft.client;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.*;
|
||||
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
|
||||
import dan200.computercraft.client.render.TileEntityTurtleRenderer;
|
||||
import dan200.computercraft.client.render.TurtleModelLoader;
|
||||
import dan200.computercraft.client.render.TurtlePlayerRenderer;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.media.items.ItemDisk;
|
||||
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
|
||||
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.IUnbakedModel;
|
||||
import net.minecraft.client.gui.ScreenManager;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.RenderTypeLookup;
|
||||
import net.minecraft.client.renderer.model.ModelResourceLocation;
|
||||
import net.minecraft.inventory.container.PlayerContainer;
|
||||
import net.minecraft.item.IItemPropertyGetter;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemModelsProperties;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.ColorHandlerEvent;
|
||||
import net.minecraftforge.client.event.ModelBakeEvent;
|
||||
import net.minecraftforge.client.event.ModelRegistryEvent;
|
||||
import net.minecraftforge.client.event.TextureStitchEvent;
|
||||
import net.minecraftforge.client.model.ModelLoader;
|
||||
import net.minecraftforge.client.model.ModelLoaderRegistry;
|
||||
import net.minecraftforge.client.model.SimpleModelTransform;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.client.registry.RenderingRegistry;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Registers textures and models for items.
|
||||
@@ -39,6 +47,7 @@ import java.util.Map;
|
||||
public final class ClientRegistry
|
||||
{
|
||||
private static final String[] EXTRA_MODELS = new String[] {
|
||||
// Turtle upgrades
|
||||
"turtle_modem_normal_off_left",
|
||||
"turtle_modem_normal_on_left",
|
||||
"turtle_modem_normal_off_right",
|
||||
@@ -54,56 +63,20 @@ public final class ClientRegistry
|
||||
"turtle_speaker_upgrade_left",
|
||||
"turtle_speaker_upgrade_right",
|
||||
|
||||
// Turtle block renderer
|
||||
"turtle_colour",
|
||||
"turtle_elf_overlay",
|
||||
};
|
||||
|
||||
private static final String[] EXTRA_TEXTURES = new String[] {
|
||||
// TODO: Gather these automatically from the model. Sadly the model loader isn't available
|
||||
// when stitching textures.
|
||||
"block/turtle_colour",
|
||||
"block/turtle_elf_overlay",
|
||||
"block/turtle_crafty_face",
|
||||
"block/turtle_speaker_face",
|
||||
};
|
||||
|
||||
private ClientRegistry() {}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void registerModels( ModelRegistryEvent event )
|
||||
{
|
||||
ModelLoaderRegistry.registerLoader( new ResourceLocation( ComputerCraft.MOD_ID, "turtle" ), TurtleModelLoader.INSTANCE );
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onTextureStitchEvent( TextureStitchEvent.Pre event )
|
||||
{
|
||||
if( !event.getMap().location().equals( PlayerContainer.BLOCK_ATLAS ) ) return;
|
||||
|
||||
for( String extra : EXTRA_TEXTURES )
|
||||
for( String model : EXTRA_MODELS )
|
||||
{
|
||||
event.addSprite( new ResourceLocation( ComputerCraft.MOD_ID, extra ) );
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onModelBakeEvent( ModelBakeEvent event )
|
||||
{
|
||||
// Load all extra models
|
||||
ModelLoader loader = event.getModelLoader();
|
||||
Map<ResourceLocation, IBakedModel> registry = event.getModelRegistry();
|
||||
|
||||
for( String modelName : EXTRA_MODELS )
|
||||
{
|
||||
ResourceLocation location = new ResourceLocation( ComputerCraft.MOD_ID, "item/" + modelName );
|
||||
IUnbakedModel model = loader.getModel( location );
|
||||
model.getMaterials( loader::getModel, new HashSet<>() );
|
||||
|
||||
IBakedModel baked = model.bake( loader, ModelLoader.defaultTextureGetter(), SimpleModelTransform.IDENTITY, location );
|
||||
if( baked != null )
|
||||
{
|
||||
registry.put( new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, modelName ), "inventory" ), baked );
|
||||
}
|
||||
ModelLoader.addSpecialModel( new ModelResourceLocation( new ResourceLocation( ComputerCraft.MOD_ID, model ), "inventory" ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,4 +121,61 @@ public final class ClientRegistry
|
||||
Registry.ModBlocks.TURTLE_NORMAL.get(), Registry.ModBlocks.TURTLE_ADVANCED.get()
|
||||
);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void setupClient( FMLClientSetupEvent event )
|
||||
{
|
||||
registerContainers();
|
||||
|
||||
// While turtles themselves are not transparent, their upgrades may be.
|
||||
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.TURTLE_NORMAL.get(), RenderType.translucent() );
|
||||
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.TURTLE_ADVANCED.get(), RenderType.translucent() );
|
||||
|
||||
// Monitors' textures have transparent fronts and so count as cutouts.
|
||||
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.MONITOR_NORMAL.get(), RenderType.cutout() );
|
||||
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.MONITOR_ADVANCED.get(), RenderType.cutout() );
|
||||
|
||||
// Setup TESRs
|
||||
net.minecraftforge.fml.client.registry.ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.MONITOR_NORMAL.get(), TileEntityMonitorRenderer::new );
|
||||
net.minecraftforge.fml.client.registry.ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.MONITOR_ADVANCED.get(), TileEntityMonitorRenderer::new );
|
||||
net.minecraftforge.fml.client.registry.ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.TURTLE_NORMAL.get(), TileEntityTurtleRenderer::new );
|
||||
net.minecraftforge.fml.client.registry.ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.TURTLE_ADVANCED.get(), TileEntityTurtleRenderer::new );
|
||||
|
||||
RenderingRegistry.registerEntityRenderingHandler( Registry.ModEntities.TURTLE_PLAYER.get(), TurtlePlayerRenderer::new );
|
||||
|
||||
registerItemProperty( "state",
|
||||
( stack, world, player ) -> ItemPocketComputer.getState( stack ).ordinal(),
|
||||
Registry.ModItems.POCKET_COMPUTER_NORMAL, Registry.ModItems.POCKET_COMPUTER_ADVANCED
|
||||
);
|
||||
registerItemProperty( "coloured",
|
||||
( stack, world, player ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0,
|
||||
Registry.ModItems.POCKET_COMPUTER_NORMAL, Registry.ModItems.POCKET_COMPUTER_ADVANCED
|
||||
);
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private static void registerItemProperty( String name, IItemPropertyGetter getter, Supplier<? extends Item>... items )
|
||||
{
|
||||
ResourceLocation id = new ResourceLocation( ComputerCraft.MOD_ID, name );
|
||||
for( Supplier<? extends Item> item : items )
|
||||
{
|
||||
ItemModelsProperties.register( item.get(), id, getter );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void registerContainers()
|
||||
{
|
||||
// My IDE doesn't think so, but we do actually need these generics.
|
||||
|
||||
ScreenManager.<ContainerComputer, GuiComputer<ContainerComputer>>register( Registry.ModContainers.COMPUTER.get(), GuiComputer::create );
|
||||
ScreenManager.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>register( Registry.ModContainers.POCKET_COMPUTER.get(), GuiComputer::createPocket );
|
||||
ScreenManager.register( Registry.ModContainers.TURTLE.get(), GuiTurtle::new );
|
||||
|
||||
ScreenManager.register( Registry.ModContainers.PRINTER.get(), GuiPrinter::new );
|
||||
ScreenManager.register( Registry.ModContainers.DISK_DRIVE.get(), GuiDiskDrive::new );
|
||||
ScreenManager.register( Registry.ModContainers.PRINTOUT.get(), GuiPrintout::new );
|
||||
|
||||
ScreenManager.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>register( Registry.ModContainers.VIEW_COMPUTER.get(), GuiComputer::createView );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,14 +12,12 @@ import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.gui.NewChatGui;
|
||||
import net.minecraft.client.gui.RenderComponentsUtil;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
public class ClientTableFormatter implements TableFormatter
|
||||
{
|
||||
@@ -57,7 +55,7 @@ public class ClientTableFormatter implements TableFormatter
|
||||
@Override
|
||||
public int getWidth( ITextComponent component )
|
||||
{
|
||||
return renderer().width( component.getColoredString() );
|
||||
return renderer().width( component );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,10 +64,11 @@ public class ClientTableFormatter implements TableFormatter
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
NewChatGui chat = mc.gui.getChat();
|
||||
|
||||
// Trim the text if it goes over the allowed length
|
||||
int maxWidth = MathHelper.floor( chat.getWidth() / chat.getScale() );
|
||||
List<ITextComponent> list = RenderComponentsUtil.wrapComponents( component, maxWidth, mc.font, false, false );
|
||||
if( !list.isEmpty() ) chat.addMessage( list.get( 0 ), id );
|
||||
// TODO: Trim the text if it goes over the allowed length
|
||||
// int maxWidth = MathHelper.floor( chat.getChatWidth() / chat.getScale() );
|
||||
// List<ITextProperties> list = RenderComponentsUtil.wrapComponents( component, maxWidth, mc.fontRenderer );
|
||||
// if( !list.isEmpty() ) chat.printChatMessageWithOptionalDeletion( list.get( 0 ), id );
|
||||
chat.addMessage( component, id );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
84
src/main/java/dan200/computercraft/client/SoundManager.java
Normal file
84
src/main/java/dan200/computercraft/client/SoundManager.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.audio.ISound;
|
||||
import net.minecraft.client.audio.ITickableSound;
|
||||
import net.minecraft.client.audio.LocatableSound;
|
||||
import net.minecraft.client.audio.SoundHandler;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class SoundManager
|
||||
{
|
||||
private static final Map<UUID, MoveableSound> sounds = new HashMap<>();
|
||||
|
||||
public static void playSound( UUID source, Vector3d position, SoundEvent event, float volume, float pitch )
|
||||
{
|
||||
SoundHandler soundManager = Minecraft.getInstance().getSoundManager();
|
||||
|
||||
MoveableSound oldSound = sounds.get( source );
|
||||
if( oldSound != null ) soundManager.stop( oldSound );
|
||||
|
||||
MoveableSound newSound = new MoveableSound( event, position, volume, pitch );
|
||||
sounds.put( source, newSound );
|
||||
soundManager.play( newSound );
|
||||
}
|
||||
|
||||
public static void stopSound( UUID source )
|
||||
{
|
||||
ISound sound = sounds.remove( source );
|
||||
if( sound == null ) return;
|
||||
|
||||
Minecraft.getInstance().getSoundManager().stop( sound );
|
||||
}
|
||||
|
||||
public static void moveSound( UUID source, Vector3d position )
|
||||
{
|
||||
MoveableSound sound = sounds.get( source );
|
||||
if( sound != null ) sound.setPosition( position );
|
||||
}
|
||||
|
||||
public static void reset()
|
||||
{
|
||||
sounds.clear();
|
||||
}
|
||||
|
||||
private static class MoveableSound extends LocatableSound implements ITickableSound
|
||||
{
|
||||
protected MoveableSound( SoundEvent sound, Vector3d position, float volume, float pitch )
|
||||
{
|
||||
super( sound, SoundCategory.RECORDS );
|
||||
setPosition( position );
|
||||
this.volume = volume;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
void setPosition( Vector3d position )
|
||||
{
|
||||
x = (float) position.x();
|
||||
y = (float) position.y();
|
||||
z = (float) position.z();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isStopped()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.upload.FileUpload;
|
||||
import dan200.computercraft.shared.computer.upload.UploadResult;
|
||||
import dan200.computercraft.shared.network.NetworkHandler;
|
||||
import dan200.computercraft.shared.network.server.ContinueUploadMessage;
|
||||
import dan200.computercraft.shared.network.server.UploadFileMessage;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SeekableByteChannel;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ComputerScreenBase<T extends ContainerComputerBase> extends ContainerScreen<T>
|
||||
{
|
||||
private static final ITextComponent OK = new TranslationTextComponent( "gui.ok" );
|
||||
private static final ITextComponent CANCEL = new TranslationTextComponent( "gui.cancel" );
|
||||
private static final ITextComponent OVERWRITE = new TranslationTextComponent( "gui.computercraft.upload.overwrite_button" );
|
||||
|
||||
protected WidgetTerminal terminal;
|
||||
protected final ClientComputer computer;
|
||||
protected final ComputerFamily family;
|
||||
|
||||
protected final int sidebarYOffset;
|
||||
|
||||
public ComputerScreenBase( T container, PlayerInventory player, ITextComponent title, int sidebarYOffset )
|
||||
{
|
||||
super( container, player, title );
|
||||
computer = (ClientComputer) container.getComputer();
|
||||
family = container.getFamily();
|
||||
this.sidebarYOffset = sidebarYOffset;
|
||||
}
|
||||
|
||||
protected abstract WidgetTerminal createTerminal();
|
||||
|
||||
@Override
|
||||
protected final void init()
|
||||
{
|
||||
super.init();
|
||||
minecraft.keyboardHandler.setSendRepeatsToGui( true );
|
||||
|
||||
terminal = addButton( createTerminal() );
|
||||
ComputerSidebar.addButtons( this, computer, this::addButton, leftPos, topPos + sidebarYOffset );
|
||||
setFocused( terminal );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void removed()
|
||||
{
|
||||
super.removed();
|
||||
minecraft.keyboardHandler.setSendRepeatsToGui( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void tick()
|
||||
{
|
||||
super.tick();
|
||||
terminal.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean keyPressed( int key, int scancode, int modifiers )
|
||||
{
|
||||
// Forward the tab key to the terminal, rather than moving between controls.
|
||||
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminal )
|
||||
{
|
||||
return getFocused().keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
return super.keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public final void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
renderBackground( stack );
|
||||
super.render( stack, mouseX, mouseY, partialTicks );
|
||||
renderTooltip( stack, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
|
||||
{
|
||||
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|
||||
|| super.mouseDragged( x, y, button, deltaX, deltaY );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void renderLabels( @Nonnull MatrixStack transform, int mouseX, int mouseY )
|
||||
{
|
||||
// Skip rendering labels.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFilesDrop( @Nonnull List<Path> files )
|
||||
{
|
||||
if( files.isEmpty() ) return;
|
||||
|
||||
if( computer == null || !computer.isOn() )
|
||||
{
|
||||
alert( UploadResult.FAILED_TITLE, UploadResult.COMPUTER_OFF_MSG );
|
||||
return;
|
||||
}
|
||||
|
||||
long size = 0;
|
||||
|
||||
List<FileUpload> toUpload = new ArrayList<>();
|
||||
for( Path file : files )
|
||||
{
|
||||
// TODO: Recurse directories? If so, we probably want to shunt this off-thread.
|
||||
if( !Files.isRegularFile( file ) ) continue;
|
||||
|
||||
try( SeekableByteChannel sbc = Files.newByteChannel( file ) )
|
||||
{
|
||||
long fileSize = sbc.size();
|
||||
if( fileSize > UploadFileMessage.MAX_SIZE || (size += fileSize) >= UploadFileMessage.MAX_SIZE )
|
||||
{
|
||||
alert( UploadResult.FAILED_TITLE, UploadResult.TOO_MUCH_MSG );
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect( (int) fileSize );
|
||||
sbc.read( buffer );
|
||||
buffer.flip();
|
||||
|
||||
toUpload.add( new FileUpload( file.getFileName().toString(), buffer ) );
|
||||
}
|
||||
catch( IOException e )
|
||||
{
|
||||
ComputerCraft.log.error( "Failed uploading files", e );
|
||||
alert( UploadResult.FAILED_TITLE, new TranslationTextComponent( "computercraft.gui.upload.failed.generic", e.getMessage() ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( toUpload.size() > 0 )
|
||||
{
|
||||
NetworkHandler.sendToServer( new UploadFileMessage( computer.getInstanceID(), toUpload ) );
|
||||
}
|
||||
}
|
||||
|
||||
public void uploadResult( UploadResult result, ITextComponent message )
|
||||
{
|
||||
switch( result )
|
||||
{
|
||||
case SUCCESS:
|
||||
alert( UploadResult.SUCCESS_TITLE, message );
|
||||
break;
|
||||
case ERROR:
|
||||
alert( UploadResult.FAILED_TITLE, message );
|
||||
break;
|
||||
case CONFIRM_OVERWRITE:
|
||||
OptionScreen.show(
|
||||
minecraft, UploadResult.UPLOAD_OVERWRITE, message,
|
||||
Arrays.asList(
|
||||
OptionScreen.newButton( CANCEL, b -> cancelUpload() ),
|
||||
OptionScreen.newButton( OVERWRITE, b -> continueUpload() )
|
||||
),
|
||||
this::cancelUpload
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void continueUpload()
|
||||
{
|
||||
if( minecraft.screen instanceof OptionScreen ) ((OptionScreen) minecraft.screen).disable();
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), true ) );
|
||||
}
|
||||
|
||||
private void cancelUpload()
|
||||
{
|
||||
minecraft.setScreen( this );
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), false ) );
|
||||
}
|
||||
|
||||
private void alert( ITextComponent title, ITextComponent message )
|
||||
{
|
||||
OptionScreen.show( minecraft, title, message,
|
||||
Collections.singletonList( OptionScreen.newButton( OK, b -> minecraft.setScreen( this ) ) ),
|
||||
() -> minecraft.setScreen( this )
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -13,10 +13,14 @@ import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.*;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.RenderState;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.math.vector.TransformationMatrix;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@@ -5,45 +5,38 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetWrapper;
|
||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
|
||||
|
||||
public final class GuiComputer<T extends ContainerComputerBase> extends ContainerScreen<T>
|
||||
public final class GuiComputer<T extends ContainerComputerBase> extends ComputerScreenBase<T>
|
||||
{
|
||||
private final ComputerFamily family;
|
||||
private final ClientComputer computer;
|
||||
private final int termWidth;
|
||||
private final int termHeight;
|
||||
|
||||
private WidgetTerminal terminal;
|
||||
private WidgetWrapper terminalWrapper;
|
||||
|
||||
private GuiComputer(
|
||||
T container, PlayerInventory player, ITextComponent title, int termWidth, int termHeight
|
||||
)
|
||||
{
|
||||
super( container, player, title );
|
||||
family = container.getFamily();
|
||||
computer = (ClientComputer) container.getComputer();
|
||||
super( container, player, title, BORDER );
|
||||
this.termWidth = termWidth;
|
||||
this.termHeight = termHeight;
|
||||
terminal = null;
|
||||
|
||||
imageWidth = WidgetTerminal.getWidth( termWidth ) + BORDER * 2 + ComputerSidebar.WIDTH;
|
||||
imageHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2;
|
||||
}
|
||||
|
||||
public static GuiComputer<ContainerComputer> create( ContainerComputer container, PlayerInventory inventory, ITextComponent component )
|
||||
@@ -70,82 +63,21 @@ public final class GuiComputer<T extends ContainerComputerBase> extends Containe
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void init()
|
||||
protected WidgetTerminal createTerminal()
|
||||
{
|
||||
minecraft.keyboardHandler.setSendRepeatsToGui( true );
|
||||
|
||||
int termPxWidth = termWidth * FixedWidthFontRenderer.FONT_WIDTH;
|
||||
int termPxHeight = termHeight * FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
|
||||
imageWidth = termPxWidth + MARGIN * 2 + BORDER * 2;
|
||||
imageHeight = termPxHeight + MARGIN * 2 + BORDER * 2;
|
||||
|
||||
super.init();
|
||||
|
||||
terminal = new WidgetTerminal( minecraft, () -> computer, termWidth, termHeight, MARGIN, MARGIN, MARGIN, MARGIN );
|
||||
terminalWrapper = new WidgetWrapper( terminal, MARGIN + BORDER + leftPos, MARGIN + BORDER + topPos, termPxWidth, termPxHeight );
|
||||
|
||||
children.add( terminalWrapper );
|
||||
setFocused( terminalWrapper );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed()
|
||||
{
|
||||
super.removed();
|
||||
children.remove( terminal );
|
||||
terminal = null;
|
||||
minecraft.keyboardHandler.setSendRepeatsToGui( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
super.tick();
|
||||
terminal.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||
{
|
||||
// Forward the tab key to the terminal, rather than moving between controls.
|
||||
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper )
|
||||
{
|
||||
return getFocused().keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
return super.keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderBg( float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw terminal
|
||||
terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() );
|
||||
|
||||
// Draw a border around the terminal
|
||||
RenderSystem.color4f( 1, 1, 1, 1 );
|
||||
minecraft.getTextureManager().bind( ComputerBorderRenderer.getTexture( family ) );
|
||||
ComputerBorderRenderer.render(
|
||||
terminalWrapper.getX() - MARGIN, terminalWrapper.getY() - MARGIN, getBlitOffset(),
|
||||
terminalWrapper.getWidth() + MARGIN * 2, terminalWrapper.getHeight() + MARGIN * 2
|
||||
return new WidgetTerminal( computer,
|
||||
leftPos + ComputerSidebar.WIDTH + BORDER, topPos + BORDER, termWidth, termHeight
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( int mouseX, int mouseY, float partialTicks )
|
||||
public void renderBg( @Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
renderBackground();
|
||||
super.render( mouseX, mouseY, partialTicks );
|
||||
renderTooltip( mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
|
||||
{
|
||||
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|
||||
|| super.mouseDragged( x, y, button, deltaX, deltaY );
|
||||
// Draw a border around the terminal
|
||||
RenderSystem.color4f( 1, 1, 1, 1 );
|
||||
minecraft.getTextureManager().bind( ComputerBorderRenderer.getTexture( family ) );
|
||||
ComputerBorderRenderer.render( terminal.x, terminal.y, getBlitOffset(), terminal.getWidth(), terminal.getHeight() );
|
||||
ComputerSidebar.renderBackground( stack, leftPos, topPos + sidebarYOffset );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
@@ -12,6 +13,8 @@ import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class GuiDiskDrive extends ContainerScreen<ContainerDiskDrive>
|
||||
{
|
||||
private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/disk_drive.png" );
|
||||
@@ -22,26 +25,18 @@ public class GuiDiskDrive extends ContainerScreen<ContainerDiskDrive>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderLabels( int mouseX, int mouseY )
|
||||
{
|
||||
String title = this.title.getColoredString();
|
||||
font.draw( title, (imageWidth - font.width( title )) / 2.0f, 6, 0x404040 );
|
||||
font.draw( title, 8, imageHeight - 96 + 2, 0x404040 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg( float partialTicks, int mouseX, int mouseY )
|
||||
protected void renderBg( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
minecraft.getTextureManager().bind( BACKGROUND );
|
||||
blit( leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||
blit( transform, leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( int mouseX, int mouseY, float partialTicks )
|
||||
public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
renderBackground();
|
||||
super.render( mouseX, mouseY, partialTicks );
|
||||
renderTooltip( mouseX, mouseY );
|
||||
renderBackground( transform );
|
||||
super.render( transform, mouseX, mouseY, partialTicks );
|
||||
renderTooltip( transform, mouseX, mouseY );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,14 +5,16 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.client.resources.I18n;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class GuiPrinter extends ContainerScreen<ContainerPrinter>
|
||||
{
|
||||
private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/printer.png" );
|
||||
@@ -23,28 +25,20 @@ public class GuiPrinter extends ContainerScreen<ContainerPrinter>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderLabels( int mouseX, int mouseY )
|
||||
{
|
||||
String title = getTitle().getColoredString();
|
||||
font.draw( title, (imageWidth - font.width( title )) / 2.0f, 6, 0x404040 );
|
||||
font.draw( I18n.get( "container.inventory" ), 8, imageHeight - 96 + 2, 0x404040 );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg( float partialTicks, int mouseX, int mouseY )
|
||||
protected void renderBg( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
minecraft.getTextureManager().bind( BACKGROUND );
|
||||
blit( leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||
blit( transform, leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||
|
||||
if( getMenu().isPrinting() ) blit( leftPos + 34, topPos + 21, 176, 0, 25, 45 );
|
||||
if( getMenu().isPrinting() ) blit( transform, leftPos + 34, topPos + 21, 176, 0, 25, 45 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( int mouseX, int mouseY, float partialTicks )
|
||||
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
renderBackground();
|
||||
super.render( mouseX, mouseY, partialTicks );
|
||||
renderTooltip( mouseX, mouseY );
|
||||
renderBackground( stack );
|
||||
super.render( stack, mouseX, mouseY, partialTicks );
|
||||
renderTooltip( stack, mouseX, mouseY );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
@@ -12,18 +13,17 @@ import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.TransformationMatrix;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static dan200.computercraft.client.render.PrintoutRenderer.*;
|
||||
|
||||
public class GuiPrintout extends ContainerScreen<ContainerHeldItem>
|
||||
{
|
||||
private static final Matrix4f IDENTITY = TransformationMatrix.identity().getMatrix();
|
||||
|
||||
private final boolean book;
|
||||
private final int pages;
|
||||
private final TextBuffer[] text;
|
||||
@@ -91,27 +91,33 @@ public class GuiPrintout extends ContainerScreen<ContainerHeldItem>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderBg( float partialTicks, int mouseX, int mouseY )
|
||||
protected void renderBg( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw the printout
|
||||
RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
IRenderTypeBuffer.Impl renderer = Minecraft.getInstance().renderBuffers().bufferSource();
|
||||
drawBorder( IDENTITY, renderer, leftPos, topPos, getBlitOffset(), page, pages, book );
|
||||
drawText( IDENTITY, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, text, colours );
|
||||
Matrix4f matrix = transform.last().pose();
|
||||
drawBorder( matrix, renderer, leftPos, topPos, getBlitOffset(), page, pages, book );
|
||||
drawText( matrix, renderer, leftPos + X_TEXT_MARGIN, topPos + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, text, colours );
|
||||
renderer.endBatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( int mouseX, int mouseY, float partialTicks )
|
||||
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
// We must take the background further back in order to not overlap with our printed pages.
|
||||
setBlitOffset( getBlitOffset() - 1 );
|
||||
renderBackground();
|
||||
renderBackground( stack );
|
||||
setBlitOffset( getBlitOffset() + 1 );
|
||||
|
||||
super.render( mouseX, mouseY, partialTicks );
|
||||
renderTooltip( mouseX, mouseY );
|
||||
super.render( stack, mouseX, mouseY, partialTicks );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderLabels( @Nonnull MatrixStack transform, int mouseX, int mouseY )
|
||||
{
|
||||
// Skip rendering labels.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,134 +5,70 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.ComputerSidebar;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetWrapper;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
||||
import net.minecraft.client.gui.screen.inventory.ContainerScreen;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
public class GuiTurtle extends ContainerScreen<ContainerTurtle>
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static dan200.computercraft.shared.turtle.inventory.ContainerTurtle.*;
|
||||
|
||||
public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
||||
{
|
||||
private static final ResourceLocation BACKGROUND_NORMAL = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/turtle_normal.png" );
|
||||
private static final ResourceLocation BACKGROUND_ADVANCED = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/turtle_advanced.png" );
|
||||
|
||||
private final ContainerTurtle container;
|
||||
private static final int TEX_WIDTH = 254;
|
||||
private static final int TEX_HEIGHT = 217;
|
||||
|
||||
private final ComputerFamily family;
|
||||
private final ClientComputer computer;
|
||||
|
||||
private WidgetTerminal terminal;
|
||||
private WidgetWrapper terminalWrapper;
|
||||
|
||||
public GuiTurtle( ContainerTurtle container, PlayerInventory player, ITextComponent title )
|
||||
{
|
||||
super( container, player, title );
|
||||
|
||||
this.container = container;
|
||||
super( container, player, title, BORDER );
|
||||
family = container.getFamily();
|
||||
computer = (ClientComputer) container.getComputer();
|
||||
|
||||
imageWidth = 254;
|
||||
imageHeight = 217;
|
||||
imageWidth = TEX_WIDTH + ComputerSidebar.WIDTH;
|
||||
imageHeight = TEX_HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init()
|
||||
protected WidgetTerminal createTerminal()
|
||||
{
|
||||
super.init();
|
||||
minecraft.keyboardHandler.setSendRepeatsToGui( true );
|
||||
|
||||
int termPxWidth = ComputerCraft.turtleTermWidth * FixedWidthFontRenderer.FONT_WIDTH;
|
||||
int termPxHeight = ComputerCraft.turtleTermHeight * FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
|
||||
terminal = new WidgetTerminal(
|
||||
minecraft, () -> computer,
|
||||
ComputerCraft.turtleTermWidth,
|
||||
ComputerCraft.turtleTermHeight,
|
||||
2, 2, 2, 2
|
||||
return new WidgetTerminal(
|
||||
computer, leftPos + BORDER + ComputerSidebar.WIDTH, topPos + BORDER,
|
||||
ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight
|
||||
);
|
||||
terminalWrapper = new WidgetWrapper( terminal, 2 + 8 + leftPos, 2 + 8 + topPos, termPxWidth, termPxHeight );
|
||||
|
||||
children.add( terminalWrapper );
|
||||
setFocused( terminalWrapper );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed()
|
||||
protected void renderBg( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
super.removed();
|
||||
children.remove( terminal );
|
||||
terminal = null;
|
||||
minecraft.keyboardHandler.setSendRepeatsToGui( false );
|
||||
}
|
||||
boolean advanced = family == ComputerFamily.ADVANCED;
|
||||
minecraft.getTextureManager().bind( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
|
||||
blit( transform, leftPos + ComputerSidebar.WIDTH, topPos, 0, 0, TEX_WIDTH, TEX_HEIGHT );
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
super.tick();
|
||||
terminal.update();
|
||||
}
|
||||
minecraft.getTextureManager().bind( advanced ? ComputerBorderRenderer.BACKGROUND_ADVANCED : ComputerBorderRenderer.BACKGROUND_NORMAL );
|
||||
ComputerSidebar.renderBackground( transform, leftPos, topPos + sidebarYOffset );
|
||||
|
||||
@Override
|
||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||
{
|
||||
// Forward the tab key to the terminal, rather than moving between controls.
|
||||
if( key == GLFW.GLFW_KEY_TAB && getFocused() != null && getFocused() == terminalWrapper )
|
||||
{
|
||||
return getFocused().keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
return super.keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
private void drawSelectionSlot( boolean advanced )
|
||||
{
|
||||
// Draw selection slot
|
||||
int slot = container.getSelectedSlot();
|
||||
int slot = getMenu().getSelectedSlot();
|
||||
if( slot >= 0 )
|
||||
{
|
||||
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
int slotX = slot % 4;
|
||||
int slotY = slot / 4;
|
||||
minecraft.getTextureManager().bind( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
|
||||
blit( leftPos + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, topPos + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18, 0, 217, 24, 24 );
|
||||
blit( transform,
|
||||
leftPos + TURTLE_START_X - 2 + slotX * 18, topPos + PLAYER_START_Y - 2 + slotY * 18,
|
||||
0, 217, 24, 24
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderBg( float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw term
|
||||
boolean advanced = family == ComputerFamily.ADVANCED;
|
||||
terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() );
|
||||
|
||||
// Draw border/inventory
|
||||
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
minecraft.getTextureManager().bind( advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
|
||||
blit( leftPos, topPos, 0, 0, imageWidth, imageHeight );
|
||||
|
||||
drawSelectionSlot( advanced );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
renderBackground();
|
||||
super.render( mouseX, mouseY, partialTicks );
|
||||
renderTooltip( mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
|
||||
{
|
||||
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY ))
|
||||
|| super.mouseDragged( x, y, button, deltaX, deltaY );
|
||||
}
|
||||
}
|
||||
|
||||
127
src/main/java/dan200/computercraft/client/gui/OptionScreen.java
Normal file
127
src/main/java/dan200/computercraft/client/gui/OptionScreen.java
Normal file
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.IBidiRenderer;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.Widget;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public final class OptionScreen extends Screen
|
||||
{
|
||||
private static final ResourceLocation BACKGROUND = new ResourceLocation( "computercraft", "textures/gui/blank_screen.png" );
|
||||
|
||||
public static final int BUTTON_WIDTH = 100;
|
||||
public static final int BUTTON_HEIGHT = 20;
|
||||
|
||||
private static final int PADDING = 16;
|
||||
private static final int FONT_HEIGHT = 9;
|
||||
|
||||
private int x;
|
||||
private int y;
|
||||
private int innerWidth;
|
||||
private int innerHeight;
|
||||
|
||||
private IBidiRenderer messageRenderer;
|
||||
private final ITextComponent message;
|
||||
private final List<Widget> buttons;
|
||||
private final Runnable exit;
|
||||
|
||||
private final Screen originalScreen;
|
||||
|
||||
private OptionScreen( ITextComponent title, ITextComponent message, List<Widget> buttons, Runnable exit, Screen originalScreen )
|
||||
{
|
||||
super( title );
|
||||
this.message = message;
|
||||
this.buttons = buttons;
|
||||
this.exit = exit;
|
||||
this.originalScreen = originalScreen;
|
||||
}
|
||||
|
||||
public static void show( Minecraft minecraft, ITextComponent title, ITextComponent message, List<Widget> buttons, Runnable exit )
|
||||
{
|
||||
minecraft.setScreen( new OptionScreen( title, message, buttons, exit, unwrap( minecraft.screen ) ) );
|
||||
}
|
||||
|
||||
public static Screen unwrap( Screen screen )
|
||||
{
|
||||
return screen instanceof OptionScreen ? ((OptionScreen) screen).getOriginalScreen() : screen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
super.init();
|
||||
|
||||
int buttonWidth = BUTTON_WIDTH * buttons.size() + PADDING * (buttons.size() - 1);
|
||||
int innerWidth = this.innerWidth = Math.max( 256, buttonWidth + PADDING * 2 );
|
||||
|
||||
messageRenderer = IBidiRenderer.create( font, message, innerWidth - PADDING * 2 );
|
||||
|
||||
int textHeight = messageRenderer.getLineCount() * FONT_HEIGHT + PADDING * 2;
|
||||
innerHeight = textHeight + (buttons.isEmpty() ? 0 : buttons.get( 0 ).getHeight()) + PADDING;
|
||||
|
||||
x = (width - innerWidth) / 2;
|
||||
y = (height - innerHeight) / 2;
|
||||
|
||||
int x = (width - buttonWidth) / 2;
|
||||
for( Widget button : buttons )
|
||||
{
|
||||
button.x = x;
|
||||
button.y = y + textHeight;
|
||||
addButton( button );
|
||||
|
||||
x += BUTTON_WIDTH + PADDING;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
renderBackground( transform );
|
||||
|
||||
// Render the actual texture.
|
||||
minecraft.textureManager.bind( BACKGROUND );
|
||||
blit( transform, x, y, 0, 0, innerWidth, PADDING );
|
||||
blit( transform,
|
||||
x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2,
|
||||
innerWidth, PADDING
|
||||
);
|
||||
blit( transform, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING );
|
||||
|
||||
messageRenderer.renderLeftAlignedNoShadow( transform, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040 );
|
||||
super.render( transform, mouseX, mouseY, partialTicks );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
exit.run();
|
||||
}
|
||||
|
||||
public static Widget newButton( ITextComponent component, Button.IPressable clicked )
|
||||
{
|
||||
return new Button( 0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, component, clicked );
|
||||
}
|
||||
|
||||
public void disable()
|
||||
{
|
||||
for( Widget widget : buttons ) widget.active = false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Screen getOriginalScreen()
|
||||
{
|
||||
return originalScreen;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.gui.widgets;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.Widget;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
import net.minecraft.util.text.TranslationTextComponent;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Registers buttons to interact with a computer.
|
||||
*/
|
||||
public final class ComputerSidebar
|
||||
{
|
||||
private static final ResourceLocation TEXTURE = new ResourceLocation( ComputerCraft.MOD_ID, "textures/gui/buttons.png" );
|
||||
|
||||
private static final int TEX_SIZE = 64;
|
||||
|
||||
private static final int ICON_WIDTH = 12;
|
||||
private static final int ICON_HEIGHT = 12;
|
||||
private static final int ICON_MARGIN = 2;
|
||||
|
||||
private static final int ICON_TEX_Y_DIFF = 14;
|
||||
|
||||
private static final int CORNERS_BORDER = 3;
|
||||
private static final int FULL_BORDER = CORNERS_BORDER + ICON_MARGIN;
|
||||
|
||||
private static final int BUTTONS = 2;
|
||||
private static final int HEIGHT = (ICON_HEIGHT + ICON_MARGIN * 2) * BUTTONS + CORNERS_BORDER * 2;
|
||||
public static final int WIDTH = 17;
|
||||
|
||||
private ComputerSidebar()
|
||||
{
|
||||
}
|
||||
|
||||
public static void addButtons( Screen screen, ClientComputer computer, Consumer<Widget> add, int x, int y )
|
||||
{
|
||||
x += CORNERS_BORDER + 1;
|
||||
y += CORNERS_BORDER + ICON_MARGIN;
|
||||
|
||||
add.accept( new DynamicImageButton(
|
||||
screen, x, y, ICON_WIDTH, ICON_HEIGHT, () -> computer.isOn() ? 15 : 1, 1, ICON_TEX_Y_DIFF,
|
||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> toggleComputer( computer ),
|
||||
() -> computer.isOn() ? Arrays.asList(
|
||||
new TranslationTextComponent( "gui.computercraft.tooltip.turn_off" ),
|
||||
new TranslationTextComponent( "gui.computercraft.tooltip.turn_off.key" ).withStyle( TextFormatting.GRAY )
|
||||
) : Arrays.asList(
|
||||
new TranslationTextComponent( "gui.computercraft.tooltip.turn_on" ),
|
||||
new TranslationTextComponent( "gui.computercraft.tooltip.turn_off.key" ).withStyle( TextFormatting.GRAY )
|
||||
)
|
||||
) );
|
||||
|
||||
y += ICON_HEIGHT + ICON_MARGIN * 2;
|
||||
|
||||
add.accept( new DynamicImageButton(
|
||||
screen, x, y, ICON_WIDTH, ICON_HEIGHT, 29, 1, ICON_TEX_Y_DIFF,
|
||||
TEXTURE, TEX_SIZE, TEX_SIZE, b -> computer.queueEvent( "terminate" ),
|
||||
Arrays.asList(
|
||||
new TranslationTextComponent( "gui.computercraft.tooltip.terminate" ),
|
||||
new TranslationTextComponent( "gui.computercraft.tooltip.terminate.key" ).withStyle( TextFormatting.GRAY )
|
||||
)
|
||||
) );
|
||||
}
|
||||
|
||||
public static void renderBackground( MatrixStack transform, int x, int y )
|
||||
{
|
||||
Screen.blit( transform,
|
||||
x, y, 0, 102, WIDTH, FULL_BORDER,
|
||||
ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
|
||||
);
|
||||
|
||||
Screen.blit( transform,
|
||||
x, y + FULL_BORDER, WIDTH, HEIGHT - FULL_BORDER * 2,
|
||||
0, 107, WIDTH, 4,
|
||||
ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
|
||||
);
|
||||
|
||||
Screen.blit( transform,
|
||||
x, y + HEIGHT - FULL_BORDER, 0, 111, WIDTH, FULL_BORDER,
|
||||
ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
|
||||
);
|
||||
}
|
||||
|
||||
private static void toggleComputer( ClientComputer computer )
|
||||
{
|
||||
if( computer.isOn() )
|
||||
{
|
||||
computer.shutdown();
|
||||
}
|
||||
else
|
||||
{
|
||||
computer.turnOn();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.gui.widgets;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.button.Button;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraftforge.common.util.NonNullSupplier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.function.IntSupplier;
|
||||
|
||||
/**
|
||||
* Version of {@link net.minecraft.client.gui.widget.button.ImageButton} which allows changing some properties
|
||||
* dynamically.
|
||||
*/
|
||||
public class DynamicImageButton extends Button
|
||||
{
|
||||
private final Screen screen;
|
||||
private final ResourceLocation texture;
|
||||
private final IntSupplier xTexStart;
|
||||
private final int yTexStart;
|
||||
private final int yDiffTex;
|
||||
private final int textureWidth;
|
||||
private final int textureHeight;
|
||||
private final NonNullSupplier<List<ITextComponent>> tooltip;
|
||||
|
||||
public DynamicImageButton(
|
||||
Screen screen, int x, int y, int width, int height, int xTexStart, int yTexStart, int yDiffTex,
|
||||
ResourceLocation texture, int textureWidth, int textureHeight,
|
||||
IPressable onPress, List<ITextComponent> tooltip
|
||||
)
|
||||
{
|
||||
this(
|
||||
screen, x, y, width, height, () -> xTexStart, yTexStart, yDiffTex,
|
||||
texture, textureWidth, textureHeight,
|
||||
onPress, () -> tooltip
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public DynamicImageButton(
|
||||
Screen screen, int x, int y, int width, int height, IntSupplier xTexStart, int yTexStart, int yDiffTex,
|
||||
ResourceLocation texture, int textureWidth, int textureHeight,
|
||||
IPressable onPress, NonNullSupplier<List<ITextComponent>> tooltip
|
||||
)
|
||||
{
|
||||
super( x, y, width, height, StringTextComponent.EMPTY, onPress );
|
||||
this.screen = screen;
|
||||
this.textureWidth = textureWidth;
|
||||
this.textureHeight = textureHeight;
|
||||
this.xTexStart = xTexStart;
|
||||
this.yTexStart = yTexStart;
|
||||
this.yDiffTex = yDiffTex;
|
||||
this.texture = texture;
|
||||
this.tooltip = tooltip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderButton( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
Minecraft minecraft = Minecraft.getInstance();
|
||||
minecraft.getTextureManager().bind( texture );
|
||||
RenderSystem.disableDepthTest();
|
||||
|
||||
int yTex = yTexStart;
|
||||
if( isHovered() ) yTex += yDiffTex;
|
||||
|
||||
blit( stack, x, y, xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight );
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
if( isHovered() ) renderToolTip( stack, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ITextComponent getMessage()
|
||||
{
|
||||
List<ITextComponent> tooltip = this.tooltip.get();
|
||||
return tooltip.isEmpty() ? StringTextComponent.EMPTY : tooltip.get( 0 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderToolTip( @Nonnull MatrixStack stack, int mouseX, int mouseY )
|
||||
{
|
||||
List<ITextComponent> tooltip = this.tooltip.get();
|
||||
if( !tooltip.isEmpty() )
|
||||
{
|
||||
screen.renderWrappedToolTip( stack, tooltip, mouseX, mouseY, screen.getMinecraft().font );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,32 +5,35 @@
|
||||
*/
|
||||
package dan200.computercraft.client.gui.widgets;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.core.IComputer;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.IGuiEventListener;
|
||||
import net.minecraft.client.gui.widget.Widget;
|
||||
import net.minecraft.util.SharedConstants;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.BitSet;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
|
||||
|
||||
public class WidgetTerminal implements IGuiEventListener
|
||||
public class WidgetTerminal extends Widget
|
||||
{
|
||||
private static final float TERMINATE_TIME = 0.5f;
|
||||
|
||||
private final Minecraft client;
|
||||
private final ClientComputer computer;
|
||||
|
||||
private boolean focused;
|
||||
|
||||
private final Supplier<ClientComputer> computer;
|
||||
private final int termWidth;
|
||||
private final int termHeight;
|
||||
// The positions of the actual terminal
|
||||
private final int innerX;
|
||||
private final int innerY;
|
||||
private final int innerWidth;
|
||||
private final int innerHeight;
|
||||
|
||||
private float terminateTimer = -1;
|
||||
private float rebootTimer = -1;
|
||||
@@ -40,23 +43,18 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
private int lastMouseX = -1;
|
||||
private int lastMouseY = -1;
|
||||
|
||||
private final int leftMargin;
|
||||
private final int rightMargin;
|
||||
private final int topMargin;
|
||||
private final int bottomMargin;
|
||||
|
||||
private final BitSet keysDown = new BitSet( 256 );
|
||||
|
||||
public WidgetTerminal( Minecraft client, Supplier<ClientComputer> computer, int termWidth, int termHeight, int leftMargin, int rightMargin, int topMargin, int bottomMargin )
|
||||
public WidgetTerminal( @Nonnull ClientComputer computer, int x, int y, int termWidth, int termHeight )
|
||||
{
|
||||
this.client = client;
|
||||
super( x, y, termWidth * FONT_WIDTH + MARGIN * 2, termHeight * FONT_HEIGHT + MARGIN * 2, StringTextComponent.EMPTY );
|
||||
|
||||
this.computer = computer;
|
||||
this.termWidth = termWidth;
|
||||
this.termHeight = termHeight;
|
||||
this.leftMargin = leftMargin;
|
||||
this.rightMargin = rightMargin;
|
||||
this.topMargin = topMargin;
|
||||
this.bottomMargin = bottomMargin;
|
||||
|
||||
innerX = x + MARGIN;
|
||||
innerY = y + MARGIN;
|
||||
innerWidth = termWidth * FONT_WIDTH;
|
||||
innerHeight = termHeight * FONT_HEIGHT;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -65,7 +63,7 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range
|
||||
{
|
||||
// Queue the "char" event
|
||||
queueEvent( "char", Character.toString( ch ) );
|
||||
computer.queueEvent( "char", new Object[] { Character.toString( ch ) } );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -91,7 +89,7 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
|
||||
case GLFW.GLFW_KEY_V:
|
||||
// Ctrl+V for paste
|
||||
String clipboard = client.keyboardHandler.getClipboard();
|
||||
String clipboard = Minecraft.getInstance().keyboardHandler.getClipboard();
|
||||
if( clipboard != null )
|
||||
{
|
||||
// Clip to the first occurrence of \r or \n
|
||||
@@ -116,7 +114,7 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
{
|
||||
// Clip to 512 characters and queue the event
|
||||
if( clipboard.length() > 512 ) clipboard = clipboard.substring( 0, 512 );
|
||||
queueEvent( "paste", clipboard );
|
||||
computer.queueEvent( "paste", new Object[] { clipboard } );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -129,8 +127,7 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
// Queue the "key" event and add to the down set
|
||||
boolean repeat = keysDown.get( key );
|
||||
keysDown.set( key );
|
||||
IComputer computer = this.computer.get();
|
||||
if( computer != null ) computer.keyDown( key, repeat );
|
||||
computer.keyDown( key, repeat );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -143,8 +140,7 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
if( key >= 0 && keysDown.get( key ) )
|
||||
{
|
||||
keysDown.set( key, false );
|
||||
IComputer computer = this.computer.get();
|
||||
if( computer != null ) computer.keyUp( key );
|
||||
computer.keyUp( key );
|
||||
}
|
||||
|
||||
switch( key )
|
||||
@@ -170,14 +166,14 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
@Override
|
||||
public boolean mouseClicked( double mouseX, double mouseY, int button )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer == null || !computer.isColour() || button < 0 || button > 2 ) return false;
|
||||
if( !inTermRegion( mouseX, mouseY ) ) return false;
|
||||
if( !computer.isColour() || button < 0 || button > 2 ) return false;
|
||||
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@@ -194,14 +190,14 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
@Override
|
||||
public boolean mouseReleased( double mouseX, double mouseY, int button )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer == null || !computer.isColour() || button < 0 || button > 2 ) return false;
|
||||
if( !inTermRegion( mouseX, mouseY ) ) return false;
|
||||
if( !computer.isColour() || button < 0 || button > 2 ) return false;
|
||||
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@@ -221,14 +217,14 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
@Override
|
||||
public boolean mouseDragged( double mouseX, double mouseY, int button, double v2, double v3 )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer == null || !computer.isColour() || button < 0 || button > 2 ) return false;
|
||||
if( !inTermRegion( mouseX, mouseY ) ) return false;
|
||||
if( !computer.isColour() || button < 0 || button > 2 ) return false;
|
||||
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@@ -246,14 +242,14 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
@Override
|
||||
public boolean mouseScrolled( double mouseX, double mouseY, double delta )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer == null || !computer.isColour() || delta == 0 ) return false;
|
||||
if( !inTermRegion( mouseX, mouseY ) ) return false;
|
||||
if( !computer.isColour() || delta == 0 ) return false;
|
||||
|
||||
Terminal term = computer.getTerminal();
|
||||
if( term != null )
|
||||
{
|
||||
int charX = (int) (mouseX / FONT_WIDTH);
|
||||
int charY = (int) (mouseY / FONT_HEIGHT);
|
||||
int charX = (int) ((mouseX - innerX) / FONT_WIDTH);
|
||||
int charY = (int) ((mouseY - innerY) / FONT_HEIGHT);
|
||||
charX = Math.min( Math.max( charX, 0 ), term.getWidth() - 1 );
|
||||
charY = Math.min( Math.max( charY, 0 ), term.getHeight() - 1 );
|
||||
|
||||
@@ -266,89 +262,74 @@ public class WidgetTerminal implements IGuiEventListener
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean inTermRegion( double mouseX, double mouseY )
|
||||
{
|
||||
return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
if( terminateTimer >= 0 && terminateTimer < TERMINATE_TIME && (terminateTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
queueEvent( "terminate" );
|
||||
computer.queueEvent( "terminate" );
|
||||
}
|
||||
|
||||
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer != null ) computer.shutdown();
|
||||
computer.shutdown();
|
||||
}
|
||||
|
||||
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer != null ) computer.reboot();
|
||||
computer.reboot();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeFocus( boolean reversed )
|
||||
public void onFocusedChanged( boolean focused )
|
||||
{
|
||||
if( focused )
|
||||
if( !focused )
|
||||
{
|
||||
// When blurring, we should make all keys go up
|
||||
for( int key = 0; key < keysDown.size(); key++ )
|
||||
{
|
||||
if( keysDown.get( key ) ) queueEvent( "key_up", key );
|
||||
if( keysDown.get( key ) ) computer.keyUp( key );
|
||||
}
|
||||
keysDown.clear();
|
||||
|
||||
// When blurring, we should make the last mouse button go up
|
||||
if( lastMouseButton > 0 )
|
||||
{
|
||||
IComputer computer = this.computer.get();
|
||||
if( computer != null ) computer.mouseUp( lastMouseButton + 1, lastMouseX + 1, lastMouseY + 1 );
|
||||
computer.mouseUp( lastMouseButton + 1, lastMouseX + 1, lastMouseY + 1 );
|
||||
lastMouseButton = -1;
|
||||
}
|
||||
|
||||
shutdownTimer = terminateTimer = rebootTimer = -1;
|
||||
}
|
||||
focused = !focused;
|
||||
return true;
|
||||
}
|
||||
|
||||
public void draw( int originX, int originY )
|
||||
{
|
||||
synchronized( computer )
|
||||
{
|
||||
// Draw the screen contents
|
||||
ClientComputer computer = this.computer.get();
|
||||
Terminal terminal = computer != null ? computer.getTerminal() : null;
|
||||
if( terminal != null )
|
||||
{
|
||||
FixedWidthFontRenderer.drawTerminal( originX, originY, terminal, !computer.isColour(), topMargin, bottomMargin, leftMargin, rightMargin );
|
||||
}
|
||||
else
|
||||
{
|
||||
FixedWidthFontRenderer.drawEmptyTerminal(
|
||||
originX - leftMargin, originY - rightMargin,
|
||||
termWidth * FONT_WIDTH + leftMargin + rightMargin,
|
||||
termHeight * FONT_HEIGHT + topMargin + bottomMargin
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void queueEvent( String event )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer != null ) computer.queueEvent( event );
|
||||
}
|
||||
|
||||
private void queueEvent( String event, Object... args )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer != null ) computer.queueEvent( event, args );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver( double x, double y )
|
||||
public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
return true;
|
||||
Matrix4f matrix = transform.last().pose();
|
||||
Terminal terminal = computer.getTerminal();
|
||||
if( terminal != null )
|
||||
{
|
||||
FixedWidthFontRenderer.drawTerminal( matrix, innerX, innerY, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN );
|
||||
}
|
||||
else
|
||||
{
|
||||
FixedWidthFontRenderer.drawEmptyTerminal( matrix, x, y, width, height );
|
||||
}
|
||||
}
|
||||
|
||||
public static int getWidth( int termWidth )
|
||||
{
|
||||
return termWidth * FONT_WIDTH + MARGIN * 2;
|
||||
}
|
||||
|
||||
public static int getHeight( int termHeight )
|
||||
{
|
||||
return termHeight * FONT_HEIGHT + MARGIN * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.gui.widgets;
|
||||
|
||||
import net.minecraft.client.gui.IGuiEventListener;
|
||||
|
||||
public class WidgetWrapper implements IGuiEventListener
|
||||
{
|
||||
private final IGuiEventListener listener;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
public WidgetWrapper( IGuiEventListener listener, int x, int y, int width, int height )
|
||||
{
|
||||
this.listener = listener;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeFocus( boolean b )
|
||||
{
|
||||
return listener.changeFocus( b );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseClicked( double x, double y, int button )
|
||||
{
|
||||
double dx = x - this.x, dy = y - this.y;
|
||||
return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseClicked( dx, dy, button );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased( double x, double y, int button )
|
||||
{
|
||||
double dx = x - this.x, dy = y - this.y;
|
||||
return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseReleased( dx, dy, button );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
|
||||
{
|
||||
double dx = x - this.x, dy = y - this.y;
|
||||
return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseDragged( dx, dy, button, deltaX, deltaY );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled( double x, double y, double delta )
|
||||
{
|
||||
double dx = x - this.x, dy = y - this.y;
|
||||
return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseScrolled( dx, dy, delta );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||
{
|
||||
return listener.keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyReleased( int key, int scancode, int modifiers )
|
||||
{
|
||||
return listener.keyReleased( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped( char character, int modifiers )
|
||||
{
|
||||
return listener.charTyped( character, modifiers );
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return x;
|
||||
}
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver( double x, double y )
|
||||
{
|
||||
double dx = x - this.x, dy = y - this.y;
|
||||
return dx >= 0 && dx < width && dy >= 0 && dy < height;
|
||||
}
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
/*
|
||||
* This file is part of ComputerCraft - http://www.computercraft.info
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
package dan200.computercraft.client.proxy;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.*;
|
||||
import dan200.computercraft.client.render.TileEntityMonitorRenderer;
|
||||
import dan200.computercraft.client.render.TileEntityTurtleRenderer;
|
||||
import dan200.computercraft.client.render.TurtlePlayerRenderer;
|
||||
import dan200.computercraft.shared.Registry;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
|
||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
|
||||
import net.minecraft.client.gui.ScreenManager;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.RenderTypeLookup;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.client.registry.ClientRegistry;
|
||||
import net.minecraftforge.fml.client.registry.RenderingRegistry;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
|
||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD )
|
||||
public final class ComputerCraftProxyClient
|
||||
{
|
||||
@SubscribeEvent
|
||||
public static void setupClient( FMLClientSetupEvent event )
|
||||
{
|
||||
registerContainers();
|
||||
|
||||
// While turtles themselves are not transparent, their upgrades may be.
|
||||
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.TURTLE_NORMAL.get(), RenderType.translucent() );
|
||||
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.TURTLE_ADVANCED.get(), RenderType.translucent() );
|
||||
|
||||
// Monitors' textures have transparent fronts and so count as cutouts.
|
||||
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.MONITOR_NORMAL.get(), RenderType.cutout() );
|
||||
RenderTypeLookup.setRenderLayer( Registry.ModBlocks.MONITOR_ADVANCED.get(), RenderType.cutout() );
|
||||
|
||||
// Setup TESRs
|
||||
ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.MONITOR_NORMAL.get(), TileEntityMonitorRenderer::new );
|
||||
ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.MONITOR_ADVANCED.get(), TileEntityMonitorRenderer::new );
|
||||
ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.TURTLE_NORMAL.get(), TileEntityTurtleRenderer::new );
|
||||
ClientRegistry.bindTileEntityRenderer( Registry.ModTiles.TURTLE_ADVANCED.get(), TileEntityTurtleRenderer::new );
|
||||
|
||||
RenderingRegistry.registerEntityRenderingHandler( Registry.ModEntities.TURTLE_PLAYER.get(), TurtlePlayerRenderer::new );
|
||||
}
|
||||
|
||||
private static void registerContainers()
|
||||
{
|
||||
// My IDE doesn't think so, but we do actually need these generics.
|
||||
|
||||
ScreenManager.<ContainerComputer, GuiComputer<ContainerComputer>>register( Registry.ModContainers.COMPUTER.get(), GuiComputer::create );
|
||||
ScreenManager.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>register( Registry.ModContainers.POCKET_COMPUTER.get(), GuiComputer::createPocket );
|
||||
ScreenManager.register( Registry.ModContainers.TURTLE.get(), GuiTurtle::new );
|
||||
|
||||
ScreenManager.register( Registry.ModContainers.PRINTER.get(), GuiPrinter::new );
|
||||
ScreenManager.register( Registry.ModContainers.DISK_DRIVE.get(), GuiDiskDrive::new );
|
||||
ScreenManager.register( Registry.ModContainers.PRINTOUT.get(), GuiPrintout::new );
|
||||
|
||||
ScreenManager.<ContainerViewComputer, GuiComputer<ContainerViewComputer>>register( Registry.ModContainers.VIEW_COMPUTER.get(), GuiComputer::createView );
|
||||
}
|
||||
|
||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
|
||||
public static final class ForgeHandlers
|
||||
{
|
||||
@SubscribeEvent
|
||||
public static void onWorldUnload( WorldEvent.Unload event )
|
||||
{
|
||||
if( event.getWorld().isClientSide() )
|
||||
{
|
||||
ClientMonitor.destroyAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,14 +14,14 @@ import dan200.computercraft.shared.peripheral.modem.wired.CableShapes;
|
||||
import dan200.computercraft.shared.util.WorldUtil;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.DrawHighlightEvent;
|
||||
@@ -63,7 +63,7 @@ public final class CableHighlightRenderer
|
||||
? CableShapes.getModemShape( state )
|
||||
: CableShapes.getCableShape( state );
|
||||
|
||||
Vec3d cameraPos = info.getPosition();
|
||||
Vector3d cameraPos = info.getPosition();
|
||||
double xOffset = pos.getX() - cameraPos.x();
|
||||
double yOffset = pos.getY() - cameraPos.y();
|
||||
double zOffset = pos.getZ() - cameraPos.z();
|
||||
|
||||
@@ -10,10 +10,10 @@ import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -47,9 +47,13 @@ public class ComputerBorderRenderer
|
||||
private static final int CORNER_LEFT_X = BORDER;
|
||||
private static final int CORNER_RIGHT_X = CORNER_LEFT_X + BORDER;
|
||||
private static final int BORDER_RIGHT_X = 36;
|
||||
private static final int GAP = 4;
|
||||
private static final int LIGHT_BORDER_Y = 56;
|
||||
private static final int LIGHT_CORNER_Y = 80;
|
||||
|
||||
private static final float TEX_SCALE = 1 / 256.0f;
|
||||
public static final int LIGHT_HEIGHT = 8;
|
||||
|
||||
public static final int TEX_SIZE = 256;
|
||||
private static final float TEX_SCALE = 1 / (float) TEX_SIZE;
|
||||
|
||||
private final Matrix4f transform;
|
||||
private final IVertexBuilder builder;
|
||||
@@ -101,15 +105,15 @@ public class ComputerBorderRenderer
|
||||
|
||||
public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int width, int height, float r, float g, float b )
|
||||
{
|
||||
render( transform, buffer, x, y, z, width, height, 0, r, g, b );
|
||||
render( transform, buffer, x, y, z, width, height, false, r, g, b );
|
||||
}
|
||||
|
||||
public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int width, int height, int borderHeight, float r, float g, float b )
|
||||
public static void render( Matrix4f transform, IVertexBuilder buffer, int x, int y, int z, int width, int height, boolean withLight, float r, float g, float b )
|
||||
{
|
||||
new ComputerBorderRenderer( transform, buffer, z, r, g, b ).doRender( x, y, width, height, borderHeight );
|
||||
new ComputerBorderRenderer( transform, buffer, z, r, g, b ).doRender( x, y, width, height, withLight );
|
||||
}
|
||||
|
||||
public void doRender( int x, int y, int width, int height, int bottomHeight )
|
||||
public void doRender( int x, int y, int width, int height, boolean withLight )
|
||||
{
|
||||
int endX = x + width;
|
||||
int endY = y + height;
|
||||
@@ -125,28 +129,18 @@ public class ComputerBorderRenderer
|
||||
|
||||
// Bottom bar. We allow for drawing a stretched version, which allows for additional elements (such as the
|
||||
// pocket computer's lights).
|
||||
if( bottomHeight <= 0 )
|
||||
if( withLight )
|
||||
{
|
||||
renderTexture( x, endY, 0, LIGHT_BORDER_Y, endX - x, BORDER + LIGHT_HEIGHT, BORDER, BORDER + LIGHT_HEIGHT );
|
||||
renderTexture( x - BORDER, endY, CORNER_LEFT_X, LIGHT_CORNER_Y, BORDER, BORDER + LIGHT_HEIGHT );
|
||||
renderTexture( endX, endY, CORNER_RIGHT_X, LIGHT_CORNER_Y, BORDER, BORDER + LIGHT_HEIGHT );
|
||||
}
|
||||
else
|
||||
{
|
||||
renderLine( x, endY, 0, BORDER, endX - x, BORDER );
|
||||
renderCorner( x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y );
|
||||
renderCorner( endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Bottom left, middle, right. We do this in three portions: the top inner corners, an extended region for
|
||||
// lights, and then the bottom outer corners.
|
||||
renderTexture( x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y, BORDER, BORDER / 2 );
|
||||
renderTexture( x, endY, 0, BORDER, width, BORDER / 2, BORDER, BORDER / 2 );
|
||||
renderTexture( endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y, BORDER, BORDER / 2 );
|
||||
|
||||
renderTexture( x - BORDER, endY + BORDER / 2, CORNER_LEFT_X, CORNER_BOTTOM_Y + GAP, BORDER, bottomHeight, BORDER, GAP );
|
||||
renderTexture( x, endY + BORDER / 2, 0, BORDER + GAP, width, bottomHeight, BORDER, GAP );
|
||||
renderTexture( endX, endY + BORDER / 2, CORNER_RIGHT_X, CORNER_BOTTOM_Y + GAP, BORDER, bottomHeight, BORDER, GAP );
|
||||
|
||||
renderTexture( x - BORDER, endY + bottomHeight + BORDER / 2, CORNER_LEFT_X, CORNER_BOTTOM_Y + BORDER / 2, BORDER, BORDER / 2 );
|
||||
renderTexture( x, endY + bottomHeight + BORDER / 2, 0, BORDER + BORDER / 2, width, BORDER / 2 );
|
||||
renderTexture( endX, endY + bottomHeight + BORDER / 2, CORNER_RIGHT_X, CORNER_BOTTOM_Y + BORDER / 2, BORDER, BORDER / 2 );
|
||||
}
|
||||
}
|
||||
|
||||
private void renderCorner( int x, int y, int u, int v )
|
||||
|
||||
@@ -10,12 +10,12 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.player.AbstractClientPlayerEntity;
|
||||
import net.minecraft.client.renderer.FirstPersonRenderer;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.HandSide;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
|
||||
public abstract class ItemMapLikeRenderer
|
||||
{
|
||||
|
||||
@@ -15,9 +15,13 @@ import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.*;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RenderHandEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
@@ -26,8 +30,7 @@ import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.BORDER;
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.*;
|
||||
|
||||
/**
|
||||
* Emulates map rendering for pocket computers.
|
||||
@@ -35,8 +38,6 @@ import static dan200.computercraft.client.render.ComputerBorderRenderer.MARGIN;
|
||||
@Mod.EventBusSubscriber( modid = ComputerCraft.MOD_ID, value = Dist.CLIENT )
|
||||
public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
{
|
||||
private static final int LIGHT_HEIGHT = 8;
|
||||
|
||||
private static final ItemPocketRenderer INSTANCE = new ItemPocketRenderer();
|
||||
|
||||
private ItemPocketRenderer()
|
||||
@@ -127,7 +128,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
BufferBuilder buffer = tessellator.getBuilder();
|
||||
buffer.begin( GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR_TEX );
|
||||
|
||||
ComputerBorderRenderer.render( transform, buffer, 0, 0, 0, width, height, LIGHT_HEIGHT, r, g, b );
|
||||
ComputerBorderRenderer.render( transform, buffer, 0, 0, 0, width, height, true, r, g, b );
|
||||
|
||||
tessellator.end();
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.RenderHandEvent;
|
||||
import net.minecraftforge.client.event.RenderItemInFrameEvent;
|
||||
|
||||
@@ -9,12 +9,12 @@ import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.vertex.IVertexBuilder;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.peripheral.monitor.TileMonitor;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.event.DrawHighlightEvent;
|
||||
@@ -61,7 +61,7 @@ public final class MonitorHighlightRenderer
|
||||
if( monitor.getYIndex() != monitor.getHeight() - 1 ) faces.remove( monitor.getDown() );
|
||||
|
||||
MatrixStack transformStack = event.getMatrix();
|
||||
Vec3d cameraPos = event.getInfo().getPosition();
|
||||
Vector3d cameraPos = event.getInfo().getPosition();
|
||||
transformStack.pushPose();
|
||||
transformStack.translate( pos.getX() - cameraPos.x(), pos.getY() - cameraPos.y(), pos.getZ() - cameraPos.z() );
|
||||
|
||||
|
||||
@@ -11,8 +11,8 @@ import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.texture.TextureUtil;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
@@ -10,11 +10,11 @@ import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.RenderState;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
|
||||
@@ -24,6 +24,9 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.math.vector.TransformationMatrix;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
@@ -141,6 +144,10 @@ public class TileEntityMonitorRenderer extends TileEntityRenderer<TileMonitor>
|
||||
(float) (xSize + 2 * TileMonitor.RENDER_MARGIN), (float) -(ySize + TileMonitor.RENDER_MARGIN * 2)
|
||||
);
|
||||
|
||||
// Force a flush of the blocker. WorldRenderer.updateCameraAndRender will "finish" all the built-in
|
||||
// buffers before calling renderer.finish, which means the blocker isn't actually rendered at that point!
|
||||
renderer.getBuffer( RenderType.solid() );
|
||||
|
||||
transform.popPose();
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,6 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.FontRenderer;
|
||||
import net.minecraft.client.renderer.Atlases;
|
||||
import net.minecraft.client.renderer.IRenderTypeBuffer;
|
||||
import net.minecraft.client.renderer.Matrix4f;
|
||||
import net.minecraft.client.renderer.Vector3f;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.ModelManager;
|
||||
@@ -31,7 +29,9 @@ import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockRayTraceResult;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -99,7 +99,7 @@ public class TileEntityTurtleRenderer extends TileEntityRenderer<TileTurtle>
|
||||
transform.pushPose();
|
||||
|
||||
// Setup the transform.
|
||||
Vec3d offset = turtle.getRenderOffset( partialTicks );
|
||||
Vector3d offset = turtle.getRenderOffset( partialTicks );
|
||||
float yaw = turtle.getRenderYaw( partialTicks );
|
||||
transform.translate( offset.x, offset.y, offset.z );
|
||||
|
||||
|
||||
@@ -57,16 +57,16 @@ public final class TurtleModelLoader implements IModelLoader<TurtleModelLoader.T
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getTextures( IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
|
||||
public Collection<RenderMaterial> getTextures( IModelConfiguration owner, Function<ResourceLocation, IUnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors )
|
||||
{
|
||||
Set<Material> materials = new HashSet<>();
|
||||
Set<RenderMaterial> materials = new HashSet<>();
|
||||
materials.addAll( modelGetter.apply( family ).getMaterials( modelGetter, missingTextureErrors ) );
|
||||
materials.addAll( modelGetter.apply( COLOUR_TURTLE_MODEL ).getMaterials( modelGetter, missingTextureErrors ) );
|
||||
return materials;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBakedModel bake( IModelConfiguration owner, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, IModelTransform transform, ItemOverrideList overrides, ResourceLocation modelLocation )
|
||||
public IBakedModel bake( IModelConfiguration owner, ModelBakery bakery, Function<RenderMaterial, TextureAtlasSprite> spriteGetter, IModelTransform transform, ItemOverrideList overrides, ResourceLocation modelLocation )
|
||||
{
|
||||
return new TurtleSmartItemModel(
|
||||
bakery.getBakedModel( family, transform, spriteGetter ),
|
||||
|
||||
@@ -7,12 +7,12 @@ package dan200.computercraft.client.render;
|
||||
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.renderer.TransformationMatrix;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.model.IBakedModel;
|
||||
import net.minecraft.client.renderer.model.ItemOverrideList;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.vector.TransformationMatrix;
|
||||
import net.minecraftforge.client.model.data.EmptyModelData;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
import net.minecraftforge.client.model.pipeline.BakedQuadBuilder;
|
||||
|
||||
@@ -15,14 +15,14 @@ import dan200.computercraft.shared.util.Holiday;
|
||||
import dan200.computercraft.shared.util.HolidayUtil;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.TransformationMatrix;
|
||||
import net.minecraft.client.renderer.model.*;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.util.math.vector.TransformationMatrix;
|
||||
import net.minecraftforge.client.model.data.IModelData;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -109,7 +109,7 @@ public class TurtleSmartItemModel implements IBakedModel
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
public IBakedModel resolve( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable World world, @Nullable LivingEntity entity )
|
||||
public IBakedModel resolve( @Nonnull IBakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity entity )
|
||||
{
|
||||
ItemTurtle turtle = (ItemTurtle) stack.getItem();
|
||||
int colour = turtle.getColour( stack );
|
||||
|
||||
@@ -14,6 +14,7 @@ import dan200.computercraft.core.apis.http.*;
|
||||
import dan200.computercraft.core.apis.http.request.HttpRequest;
|
||||
import dan200.computercraft.core.apis.http.websocket.Websocket;
|
||||
import io.netty.handler.codec.http.DefaultHttpHeaders;
|
||||
import io.netty.handler.codec.http.HttpHeaderNames;
|
||||
import io.netty.handler.codec.http.HttpHeaders;
|
||||
import io.netty.handler.codec.http.HttpMethod;
|
||||
|
||||
@@ -36,7 +37,7 @@ public class HTTPAPI implements ILuaAPI
|
||||
{
|
||||
private final IAPIEnvironment apiEnvironment;
|
||||
|
||||
private final ResourceGroup<CheckUrl> checkUrls = new ResourceGroup<>();
|
||||
private final ResourceGroup<CheckUrl> checkUrls = new ResourceGroup<>( ResourceGroup.DEFAULT );
|
||||
private final ResourceGroup<HttpRequest> requests = new ResourceQueue<>( () -> ComputerCraft.httpMaxRequests );
|
||||
private final ResourceGroup<Websocket> websockets = new ResourceGroup<>( () -> ComputerCraft.httpMaxWebsockets );
|
||||
|
||||
@@ -126,7 +127,10 @@ public class HTTPAPI implements ILuaAPI
|
||||
HttpRequest request = new HttpRequest( requests, apiEnvironment, address, postString, headers, binary, redirect );
|
||||
|
||||
// Make the request
|
||||
request.queue( r -> r.request( uri, httpMethod ) );
|
||||
if( !request.queue( r -> r.request( uri, httpMethod ) ) )
|
||||
{
|
||||
throw new LuaException( "Too many ongoing HTTP requests" );
|
||||
}
|
||||
|
||||
return new Object[] { true };
|
||||
}
|
||||
@@ -137,12 +141,15 @@ public class HTTPAPI implements ILuaAPI
|
||||
}
|
||||
|
||||
@LuaFunction
|
||||
public final Object[] checkURL( String address )
|
||||
public final Object[] checkURL( String address ) throws LuaException
|
||||
{
|
||||
try
|
||||
{
|
||||
URI uri = HttpRequest.checkUri( address );
|
||||
new CheckUrl( checkUrls, apiEnvironment, address, uri ).queue( CheckUrl::run );
|
||||
if( !new CheckUrl( checkUrls, apiEnvironment, address, uri ).queue( CheckUrl::run ) )
|
||||
{
|
||||
throw new LuaException( "Too many ongoing checkUrl calls" );
|
||||
}
|
||||
|
||||
return new Object[] { true };
|
||||
}
|
||||
@@ -179,7 +186,7 @@ public class HTTPAPI implements ILuaAPI
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private static HttpHeaders getHeaders( @Nonnull Map<?, ?> headerTable ) throws LuaException
|
||||
private HttpHeaders getHeaders( @Nonnull Map<?, ?> headerTable ) throws LuaException
|
||||
{
|
||||
HttpHeaders headers = new DefaultHttpHeaders();
|
||||
for( Map.Entry<?, ?> entry : headerTable.entrySet() )
|
||||
@@ -197,6 +204,11 @@ public class HTTPAPI implements ILuaAPI
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !headers.contains( HttpHeaderNames.USER_AGENT ) )
|
||||
{
|
||||
headers.set( HttpHeaderNames.USER_AGENT, apiEnvironment.getComputerEnvironment().getUserAgent() );
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,7 @@ final class LuaDateTime
|
||||
formatter.appendValue( ChronoField.HOUR_OF_DAY, 2 );
|
||||
break;
|
||||
case 'I':
|
||||
formatter.appendValue( ChronoField.HOUR_OF_AMPM );
|
||||
formatter.appendValue( ChronoField.HOUR_OF_AMPM, 2 );
|
||||
break;
|
||||
case 'j':
|
||||
formatter.appendValue( ChronoField.DAY_OF_YEAR, 3 );
|
||||
|
||||
@@ -191,7 +191,7 @@ public class RedstoneAPI implements ILuaAPI
|
||||
@LuaFunction
|
||||
public final int getBundledInput( ComputerSide side )
|
||||
{
|
||||
return environment.getBundledOutput( side );
|
||||
return environment.getBundledInput( side );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,12 +11,19 @@ import dan200.computercraft.core.apis.http.options.AddressRule;
|
||||
import dan200.computercraft.core.apis.http.options.Options;
|
||||
import dan200.computercraft.shared.util.ThreadUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ConnectTimeoutException;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.handler.codec.DecoderException;
|
||||
import io.netty.handler.codec.TooLongFrameException;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketHandshakeException;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import io.netty.handler.timeout.ReadTimeoutException;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.net.ssl.SSLException;
|
||||
import javax.net.ssl.SSLHandshakeException;
|
||||
import javax.net.ssl.TrustManagerFactory;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
@@ -161,4 +168,29 @@ public final class NetworkUtils
|
||||
buffer.readBytes( bytes );
|
||||
return bytes;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public static String toFriendlyError( @Nonnull Throwable cause )
|
||||
{
|
||||
if( cause instanceof WebSocketHandshakeException || cause instanceof HTTPRequestException )
|
||||
{
|
||||
return cause.getMessage();
|
||||
}
|
||||
else if( cause instanceof TooLongFrameException )
|
||||
{
|
||||
return "Message is too large";
|
||||
}
|
||||
else if( cause instanceof ReadTimeoutException || cause instanceof ConnectTimeoutException )
|
||||
{
|
||||
return "Timed out";
|
||||
}
|
||||
else if( cause instanceof SSLHandshakeException || (cause instanceof DecoderException && cause.getCause() instanceof SSLHandshakeException) )
|
||||
{
|
||||
return "Could not create a secure connection";
|
||||
}
|
||||
else
|
||||
{
|
||||
return "Could not connect";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ public abstract class Resource<T extends Resource<T>> implements Closeable
|
||||
tryClose();
|
||||
}
|
||||
|
||||
public boolean queue( Consumer<T> task )
|
||||
public final boolean queue( Consumer<T> task )
|
||||
{
|
||||
@SuppressWarnings( "unchecked" )
|
||||
T thisT = (T) this;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user