mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-10-16 06:27:39 +00:00
Compare commits
111 Commits
v1.96.1-be
...
v1.97.2
Author | SHA1 | Date | |
---|---|---|---|
![]() |
ed9e823f3f | ||
![]() |
2b8fea5b35 | ||
![]() |
b3e6b4c29a | ||
![]() |
c94ff68e7f | ||
![]() |
3fb96a3438 | ||
![]() |
7a2b7c0701 | ||
![]() |
fa7a731ad1 | ||
![]() |
8be48ebcf0 | ||
![]() |
123f3abcaa | ||
![]() |
9f2e43f00a | ||
![]() |
9fb35b2799 | ||
![]() |
272572dbf2 | ||
![]() |
702e4fc787 | ||
![]() |
511327effe | ||
![]() |
940e35caea | ||
![]() |
fca01693dd | ||
![]() |
8846a3f36f | ||
![]() |
8002c9e932 | ||
![]() |
6fd8331e94 | ||
![]() |
7a667b9028 | ||
![]() |
67b7cd7a14 | ||
![]() |
960d79803d | ||
![]() |
43ef36fa15 | ||
![]() |
f037d9539e | ||
![]() |
a3b2f7b5bd | ||
![]() |
0859145d18 | ||
![]() |
f6e4122f7f | ||
![]() |
8e4023fdbc | ||
![]() |
f10818ec6b | ||
![]() |
bc2358489b | ||
![]() |
6e5e682e3a | ||
![]() |
02c63ce7e8 | ||
![]() |
fd24d89f89 | ||
![]() |
685d33a2dd | ||
![]() |
ca40c9cf19 | ||
![]() |
8985ea9560 | ||
![]() |
1832028dfd | ||
![]() |
316889dab7 | ||
![]() |
96c80a6549 | ||
![]() |
fb274e2ed6 | ||
![]() |
ebe847c04b | ||
![]() |
fdbf41b3c4 | ||
![]() |
9dcb9f9537 | ||
![]() |
1395c877af | ||
![]() |
969451f18c | ||
![]() |
259c8d57f5 | ||
![]() |
2ee07283fa | ||
![]() |
c85a80617a | ||
![]() |
5aa8611e43 | ||
![]() |
86aecd945e | ||
![]() |
a7a9f4fa13 | ||
![]() |
22e4c0603b | ||
![]() |
f3b731460e | ||
![]() |
d787c6e6c1 | ||
![]() |
11272b8d00 | ||
![]() |
1c254e3bb0 | ||
![]() |
7ade380fad | ||
![]() |
2a377a37ee | ||
![]() |
861a9e199d | ||
![]() |
d4f1e34023 | ||
![]() |
6d25278a5c | ||
![]() |
abfb05f04c | ||
![]() |
9d8e76c5b4 | ||
![]() |
89662bf54a | ||
![]() |
520635dfec | ||
![]() |
ee82a8d75f | ||
![]() |
967f00cd1b | ||
![]() |
dda5236d84 | ||
![]() |
427ca2f108 | ||
![]() |
e30f2a86f0 | ||
![]() |
121ef6e976 | ||
![]() |
e4271ff6f7 | ||
![]() |
8d3b94734d | ||
![]() |
9e57150384 | ||
![]() |
0dc34a7dbe | ||
![]() |
fbe28dc51a | ||
![]() |
14e013d075 | ||
![]() |
9bc4e9530c | ||
![]() |
cbff505297 | ||
![]() |
c4aef2d4c7 | ||
![]() |
2ed6692f76 | ||
![]() |
f075eabc32 | ||
![]() |
3d1c9d1667 | ||
![]() |
0028ad8f54 | ||
![]() |
4c805f1c27 | ||
![]() |
505543ad94 | ||
![]() |
644471c6bf | ||
![]() |
bf87d7faa1 | ||
![]() |
be95b65488 | ||
![]() |
7e9f3bd61a | ||
![]() |
4a74aa8166 | ||
![]() |
b4ce4361ce | ||
![]() |
42a3dd24ad | ||
![]() |
9129da2e3d | ||
![]() |
668cdcdd39 | ||
![]() |
2543ebee10 | ||
![]() |
104a317163 | ||
![]() |
921802e6c9 | ||
![]() |
56cfc1a452 | ||
![]() |
a14b98be22 | ||
![]() |
76b5c05acc | ||
![]() |
8b3f1a448f | ||
![]() |
3de515c617 | ||
![]() |
ab199cd9b0 | ||
![]() |
fc4bc9aa05 | ||
![]() |
9662a106f0 | ||
![]() |
06b0538b76 | ||
![]() |
fb128152a5 | ||
![]() |
f596af059d | ||
![]() |
52bb06d250 | ||
![]() |
f3d22444d3 |
5
.github/workflows/main-ci.yml
vendored
5
.github/workflows/main-ci.yml
vendored
@@ -12,11 +12,10 @@ jobs:
|
||||
- name: Checkout submodules
|
||||
run: git submodule update --init --recursive
|
||||
|
||||
|
||||
- name: Set up Java 8
|
||||
- name: Set up Java 16
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 8
|
||||
java-version: 16
|
||||
|
||||
- name: Cache gradle dependencies
|
||||
uses: actions/cache@v2
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,3 +21,4 @@
|
||||
.gradle
|
||||
*.DS_Store
|
||||
.project
|
||||
*.launch
|
||||
|
2
.gitpod.Dockerfile
vendored
2
.gitpod.Dockerfile
vendored
@@ -16,4 +16,4 @@ RUN sudo apt-get -q update && \
|
||||
sudo apt install -yq openjdk-8-jdk openjdk-16-jdk
|
||||
|
||||
# This is so that you can use java 8 until such a time as you switch to java 16
|
||||
RUN sudo update-java-alternatives --set java-1.8.0-openjdk-amd64
|
||||
RUN sudo update-java-alternatives --set java-1.16.0-openjdk-amd64
|
||||
|
94
README.md
94
README.md
@@ -1,66 +1,74 @@
|
||||
# CC:Restitched
|
||||
# CC:R Version VS CC:T Version
|
||||
CC:R Strives to maintain perfect pairity with CC:T, however in some cases this is not possible, so CC:R might have a "newer" version than what CC:T has, these newer versions will be primarily bugfixes and the like because fabric is "weird" when porting a forge mod
|
||||
|
||||
<img src="logo.png" alt="CC: Restitched" width="100%"/>
|
||||
|
||||
[](https://github.com/Merith-TK/cc-restitched/actions "Current build status") [](https://www.curseforge.com/minecraft/mc-mods/cc-restitched-updated "Download CC: Restitched on CurseForge")
|
||||
[](https://github.com/cc-tweaked/cc-restitched/actions "Current build status")
|
||||
[](https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched on CurseForge")
|
||||
[](https://gitpod.io/#https://github.com/cc-tweaked/cc-restitched/tree/1.17-alpha)
|
||||
|
||||
[](https://gitpod.io/#https://github.com/Merith-TK/cc-restitched/)
|
||||
# CC: R Version VS CC: T Version
|
||||
CC: R Strives to maintain perfect pairity with CC: T, however in some cases this is not possible, so CC: R might have a "newer" version than what CC: T has, these newer versions will be primarily bugfixes and the like because [Fabric](https://fabricmc.net/) is "weird" when porting a Forge mod.
|
||||
|
||||
## What is CC: Restiched
|
||||
This is an fork of [Zundrel/cc-tweaked-fabric](https://github.com/Zundrel/cc-tweaked-fabric) who's goal was to port [SquidDev-CC/CC-Tweaked](https://github.com/SquidDev-CC/CC-Tweaked) to the [Fabric](https://fabricmc.net/) modloader. I picked up maintaining the mod because the team working on Zundrel's fork, admitted they had gotten lethargic so I picked it up to make it equal with CC:T
|
||||
This is an fork of [Zundrel/cc-tweaked-fabric](https://github.com/Zundrel/cc-tweaked-fabric) who's goal was to port [SquidDev-CC/CC-Tweaked](https://github.com/SquidDev-CC/CC-Tweaked) to the [Fabric](https://fabricmc.net/) modloader. I picked up maintaining the mod because the team working on Zundrel's fork can no longer mantain it so, I picked it up to make it as equal as possible with CC: T.
|
||||
|
||||
## Resource Packs
|
||||
This mod includes textures that are more in-line with the style of Mojang's new texture-artist, Jappa. If you prefer the original textures, enable the "Classic" resource pack provided by the mod.
|
||||
This mod includes textures that are more in-line with the style of Mojang's new texture-artist, Jappa. If you prefer the original textures, enable the "Classic" resource pack.
|
||||
|
||||
<img src="https://raw.githubusercontent.com/3prm3/cc-pack/main/pack.png" alt="CC: Restitched" width="16" height="16"/> [3prm3/cc-pack](https://github.com/3prm3/cc-pack/)
|
||||
We also have a second resourcepack made by [3prm3](https://github.com/3prm3), it features a complete overhaul and can be enabled by enabling the `overhaul` resource pack, go check out his resource pack over here!
|
||||
|
||||
## Major Tasks Planned
|
||||
* Rewrite the config system
|
||||
* **Planned for 1.96.3 release**
|
||||
* it currently sets the values that would normally be read from `config/computercraft.json` to the default values, because it does not read the file at all
|
||||
# Does this work with shaders/[Sodium?](https://github.com/CaffeineMC/sodium-fabric)
|
||||
* [ YES ] Sodium
|
||||
* [ YES ] Optifine
|
||||
* Works with VBO Rendering (automatically set)
|
||||
* No issues
|
||||
* [ EHH ] Iris Shaders
|
||||
* "Works" with TBO Rendering (Default)
|
||||
* Crashes with VBO Rendering
|
||||
* <details>
|
||||
<summary>Shaders are broken</summary>
|
||||
|
||||
* Shaders will cause varrying results ranging from monitors being invisible, to straight up crashing.
|
||||
* Not using shaders will result in odd Z-Fighting of the monitor display and the transparent texture
|
||||
- 
|
||||
- 
|
||||
</details>
|
||||
* [ YES ] Canvas
|
||||
* Works with TBO Rendering (Default)
|
||||
* Scuffed with VBO Rendering
|
||||
* <details>
|
||||
<summary>VBO is broken</summary>
|
||||
|
||||
Monitors are just... scuffed beyond belief.
|
||||
- 
|
||||
- 
|
||||
* The content to the left is supposed to be on the monitors to the right, also the bottom one is supposed to `black/white` not colored.
|
||||
* Turtle Texture for some reason?
|
||||
- 
|
||||
</details>
|
||||
|
||||
## Contributing
|
||||
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. In order to start helping develop CC:R there are a few rules
|
||||
1) Any updates that port commits from CC:T, ***MUST*** follow the format defined in [patchwork.md](patchwork.md) otherwise they will not be accepted,
|
||||
* Commit Message must be the same as it is in CC:T,
|
||||
* patchwork.md must be updated in the following format
|
||||
> Comments, optional but useful if you had to do something differently than in CC:T outside of [Fabric](https://fabricmc.net/)/[Forge](https://mcforge.readthedocs.io/en/1.16.x/) differences
|
||||
>
|
||||
> \`\`\`
|
||||
>
|
||||
>commitID
|
||||
>
|
||||
> commit title
|
||||
>
|
||||
> commit desc
|
||||
>
|
||||
> \`\`\`
|
||||
2) Follow the [Fabric](https://fabricmc.net/) programming guidelines as close as possible. This means you have to use [`loom`](https://fabricmc.net/wiki/tutorial:mappings) mappings,
|
||||
3) You cannot intentionally implement bugs and security vulnerabilities
|
||||
4) Unless the commit is a ["patchwork"](https://github.com/Merith-TK/cc-restitched/blob/fabric/patchwork.md) compliant commit, (IE: taken from CC:T), the lua code is off limits
|
||||
Any contribution is welcome, be that using the mod, reporting bugs or contributing code. In order to start helping develop CC: R there are a few rules;
|
||||
1) Follow the [Fabric](https://fabricmc.net/) programming guidelines as close as possible. This means you have to use [`loom`](https://fabricmc.net/wiki/tutorial:mappings) mappings, if you use anything else, your code will be rejected.
|
||||
2) You cannot intentionally implement bugs and security vulnerabilities.
|
||||
3) Unless the code is taken directly from CC: Tweaked, `lua` code is offlimits from alteration.
|
||||
|
||||
## Bleeding Edge Builds
|
||||
Bleeding edge builds can be found [here](https://github.com/Merith-TK/cc-restitched/actions) at Github Actions.
|
||||
Bleeding edge builds can be found [here](https://github.com/cc-tweaked/cc-restitched/actions) at Github Actions.
|
||||
|
||||
## Community
|
||||
If you need help getting started with CC: Tweaked, want to show off your latest project, or just want to chat about ComputerCraft, here is the [Forum](https://forums.computercraft.cc/) and the [Discord](https://discord.gg/H2UyJXe)
|
||||
If you need help getting started with CC: Restitched, want to show off your latest project, or just want to chat about ComputerCraft, here is the [Forum](https://forums.computercraft.cc/) and the [Discord](https://discord.gg/H2UyJXe).
|
||||
|
||||
## Known Issues
|
||||
## Known Bugs/Issues
|
||||
Main Known issue
|
||||
* Mods that add blocks that can be used as peripherals for CC:T On forge, don't work with CC:R.
|
||||
* This is because of the differences between forge and fabric, and that mod devs, to my knowledge have not agreed upon a standard method in which to implement cross compatibility between mods,
|
||||
* [Fixed (d10f297c): please report if bug persists]</br> ~~Storage Peripherals throw a java "StackOverflowError" when using `pushItems()`,~~
|
||||
* ~~Work around, you are probably using `pushItems(chest, 1)` or similar. please use `pushItems(chest, 1, nil, 1)`.~~
|
||||
* Computers will not run built in commands, saying "File not found"
|
||||
* This is a know bug, dont know what causes it, but just restart the computer (`ctrl+r` for one second) and it will work again
|
||||
* Occurs when server runs `/reload` or a datapack is updated
|
||||
* Mods that add blocks that can be used as peripherals for CC: T on Forge, don't work with CC: R.
|
||||
* This is because of the differences between Forge and [Fabric](https://fabricmc.net/), and that mod devs, to my knowledge have not agreed upon a standard method in which to implement cross compatibility between mods,
|
||||
* Occasionally a computer will say "File not found" when running a built in program, this is normal just hold `crtl+r` to reboot it.
|
||||
* We do not know what causes it directly, however it happens when the world is `/reload`ed, and currently running programs are not affected so nothing *should break*
|
||||
|
||||
## Perpherals
|
||||
Unfortunately, unlike the original CC:Tweaked project, CC:Restitched, does not have any actual peripheral mods, currently the only one we have is an example for mod devs to get started with making/adding the peripheral API to their mods!
|
||||
Unfortunately, unlike the original CC: Tweaked project, CC: Restitched, does not have any actual peripheral mods, currently the only one we have is an example for mod devs to get started with making/adding the peripheral API to their mods!
|
||||
|
||||
If your a mod dev made a mod with CC:R peripheral support, OR if your a player who found a mod with CC:R support, please open an [issue here](https://github.com/Merith-TK/cc-restitched/issues/new?assignees=&labels=peripheralShoutout&template=peripheral_shoutout.md) to let us know so we can add it to the list!
|
||||
If you're a mod dev, made a mod with CC: R peripheral support OR if you're a player who found a mod with CC: R support, please open an [issue here](https://github.com/cc-tweaked/cc-restitched/issues/new?assignees=&labels=peripheralShoutout&template=peripheral_shoutout.md) to let us know so we can add it to the list!
|
||||
|
||||
*  [CC Peripheral Test](https://github.com/Toad-Dev/cc-peripheral-test)
|
||||
*  [CC Peripheral Test [1.16.5]](https://github.com/Toad-Dev/cc-peripheral-test)
|
||||
* This is an example mod for how to make peripherals that work as a block, or as a turtle upgrade!
|
||||
|
37
build.gradle
37
build.gradle
@@ -1,12 +1,16 @@
|
||||
plugins {
|
||||
id 'fabric-loom' version '0.7-SNAPSHOT'
|
||||
id 'fabric-loom' version '0.9-SNAPSHOT'
|
||||
id 'maven-publish'
|
||||
id "checkstyle"
|
||||
id "com.github.hierynomus.license" version "0.15.0"
|
||||
id "com.github.hierynomus.license" version "0.16.1"
|
||||
}
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion = JavaLanguageVersion.of(16)
|
||||
vendor = JvmVendorSpec.ADOPTOPENJDK
|
||||
}
|
||||
}
|
||||
|
||||
version = mod_version
|
||||
|
||||
@@ -16,19 +20,25 @@ archivesBaseName = "cc-restiched"
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url 'https://jitpack.io' }
|
||||
maven { url 'https://api.modrinth.com/maven'}
|
||||
maven { url "https://maven.shedaniel.me/" }
|
||||
maven { url "https://maven.terraformersmc.com/" }
|
||||
maven {
|
||||
name "SquidDev"
|
||||
url "https://squiddev.cc/maven"
|
||||
}
|
||||
}
|
||||
|
||||
loom {
|
||||
accessWidenerPath = file("src/main/resources/cc.accesswidener")
|
||||
}
|
||||
|
||||
configurations {
|
||||
implementation.extendsFrom shade
|
||||
}
|
||||
|
||||
dependencies {
|
||||
checkstyle "com.puppycrawl.tools:checkstyle:8.25"
|
||||
checkstyle 'com.puppycrawl.tools:checkstyle:8.45.1'
|
||||
|
||||
minecraft "com.mojang:minecraft:${mc_version}"
|
||||
mappings "net.fabricmc:yarn:${mc_version}+build.${mappings_version}:v2"
|
||||
@@ -38,7 +48,7 @@ dependencies {
|
||||
modApi("me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}") {
|
||||
exclude(group: "net.fabricmc.fabric-api")
|
||||
}
|
||||
modImplementation "io.github.prospector:modmenu:${modmenu_version}"
|
||||
modImplementation "com.terraformersmc:modmenu:${modmenu_version}"
|
||||
modImplementation "me.shedaniel.cloth.api:cloth-utils-v1:${cloth_api_version}"
|
||||
|
||||
implementation 'com.electronwill.night-config:toml:3.6.3'
|
||||
@@ -51,21 +61,16 @@ dependencies {
|
||||
include 'com.electronwill.night-config:toml:3.6.3'
|
||||
include "me.shedaniel.cloth:cloth-config-fabric:${cloth_config_version}"
|
||||
|
||||
modRuntime "me.shedaniel:RoughlyEnoughItems-api:5.12.248"
|
||||
modRuntime "me.shedaniel:RoughlyEnoughItems:5.12.248"
|
||||
modRuntime "me.shedaniel:RoughlyEnoughItems-api-fabric:6.0.254-alpha"
|
||||
modRuntime "me.shedaniel:RoughlyEnoughItems-fabric:6.0.254-alpha"
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property "version", project.version
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include "fabric.mod.json"
|
||||
expand "version": project.version
|
||||
}
|
||||
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude "fabric.mod.json"
|
||||
}
|
||||
filesMatching("fabric.mod.json") {
|
||||
expand "version": project.version
|
||||
}
|
||||
}
|
||||
|
||||
// ensure that the encoding is set to UTF-8, no matter what the system default is
|
||||
|
@@ -58,13 +58,13 @@
|
||||
<module name="SimplifyBooleanExpression" />
|
||||
<module name="SimplifyBooleanReturn" />
|
||||
<module name="StringLiteralEquality" />
|
||||
<module name="UnnecessaryParentheses" />
|
||||
<!-- <module name="UnnecessaryParentheses" /> -->
|
||||
<module name="UnnecessarySemicolonAfterTypeMemberDeclaration" />
|
||||
<module name="UnnecessarySemicolonInTryWithResources" />
|
||||
<module name="UnnecessarySemicolonInEnumeration" />
|
||||
|
||||
<!-- Imports -->
|
||||
<module name="CustomImportOrder" />
|
||||
<!--<module name="CustomImportOrder" />-->
|
||||
<module name="IllegalImport" />
|
||||
<module name="RedundantImport" />
|
||||
<module name="UnusedImports" />
|
||||
|
@@ -7,6 +7,9 @@
|
||||
<suppress checks="StaticVariableName" files=".*[\\/]ComputerCraft.java" />
|
||||
<suppress checks="StaticVariableName" files=".*[\\/]ComputerCraftAPI.java" />
|
||||
|
||||
<!-- Some shadowed fields in mixins can't be renamed -->
|
||||
<suppress checks="StaticVariableName" files=".*[\\/]mixin[\\/].*" />
|
||||
|
||||
<!-- The commands API is documented in Lua. -->
|
||||
<suppress checks="SummaryJavadocCheck" files=".*[\\/]CommandAPI.java" />
|
||||
</suppressions>
|
||||
|
@@ -2,16 +2,16 @@
|
||||
org.gradle.jvmargs=-Xmx1G
|
||||
|
||||
# Mod properties
|
||||
mod_version=1.96.1-beta
|
||||
mod_version=1.97.2
|
||||
|
||||
# Minecraft properties
|
||||
mc_version=1.16.5
|
||||
mappings_version=9
|
||||
mc_version=1.17.1
|
||||
mappings_version=61
|
||||
|
||||
# Dependencies
|
||||
cloth_config_version=4.11.26
|
||||
fabric_loader_version=0.11.3
|
||||
fabric_api_version=0.32.0+1.16
|
||||
cloth_config_version=5.0.34
|
||||
fabric_loader_version=0.11.7
|
||||
fabric_api_version=0.40.1+1.17
|
||||
jankson_version=1.2.0
|
||||
modmenu_version=1.16.9
|
||||
cloth_api_version=1.4.5
|
||||
modmenu_version=2.0.2
|
||||
cloth_api_version=2.0.54
|
||||
|
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-6.9-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
178
gradlew.bat
vendored
178
gradlew.bat
vendored
@@ -1,89 +1,89 @@
|
||||
@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
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
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="-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 execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
: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 %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
@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
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
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="-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 execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
: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 %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
||||
|
5
jitpack.yml
Normal file
5
jitpack.yml
Normal file
@@ -0,0 +1,5 @@
|
||||
before_install:
|
||||
- wget https://github.com/sormuras/bach/raw/master/install-jdk.sh
|
||||
- source ./install-jdk.sh --feature 16 --license GPL
|
||||
jdk:
|
||||
- openjdk16
|
BIN
logo.png
BIN
logo.png
Binary file not shown.
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 8.1 KiB |
@@ -1,6 +1,5 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = 'Fabric'
|
||||
url = 'https://maven.fabricmc.net/'
|
||||
|
@@ -9,6 +9,7 @@ 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.shared.ComputerCraftRegistry.ModBlocks;
|
||||
import dan200.computercraft.shared.common.ColourableRecipe;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputerRegistry;
|
||||
import dan200.computercraft.shared.computer.core.ServerComputerRegistry;
|
||||
@@ -43,7 +44,6 @@ import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static dan200.computercraft.shared.ComputerCraftRegistry.ModBlocks;
|
||||
import static dan200.computercraft.shared.ComputerCraftRegistry.init;
|
||||
|
||||
public final class ComputerCraft implements ModInitializer
|
||||
@@ -72,6 +72,8 @@ public final class ComputerCraft implements ModInitializer
|
||||
) );
|
||||
public static int httpMaxRequests = 16;
|
||||
public static int httpMaxWebsockets = 4;
|
||||
public static int httpDownloadBandwidth = 32 * 1024 * 1024;
|
||||
public static int httpUploadBandwidth = 32 * 1024 * 1024;
|
||||
|
||||
public static boolean enableCommandBlock = false;
|
||||
public static int modemRange = 64;
|
||||
@@ -81,6 +83,7 @@ public final class ComputerCraft implements ModInitializer
|
||||
public static int maxNotesPerTick = 8;
|
||||
public static MonitorRenderer monitorRenderer = MonitorRenderer.BEST;
|
||||
public static double monitorDistanceSq = 4096;
|
||||
public static int monitorDistance = 65;
|
||||
public static long monitorBandwidth = 1_000_000;
|
||||
|
||||
public static boolean turtlesNeedFuel = true;
|
||||
|
@@ -80,11 +80,11 @@ public final class ComputerCraftAPIImpl implements IComputerCraftAPI
|
||||
@Override
|
||||
public String getInstalledVersion()
|
||||
{
|
||||
if( this.version != null )
|
||||
if( version != null )
|
||||
{
|
||||
return this.version;
|
||||
return version;
|
||||
}
|
||||
return this.version = FabricLoader.getInstance()
|
||||
return version = FabricLoader.getInstance()
|
||||
.getModContainer( ComputerCraft.MOD_ID )
|
||||
.map( x -> x.getMetadata()
|
||||
.getVersion()
|
||||
|
@@ -8,7 +8,7 @@ package dan200.computercraft.api;
|
||||
import dan200.computercraft.api.pocket.IPocketUpgrade;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -76,8 +76,8 @@ public interface IUpgradeBase
|
||||
|
||||
// A more expanded form of ItemStack.areShareTagsEqual, but allowing an empty tag to be equal to a
|
||||
// null one.
|
||||
CompoundTag shareTag = stack.getTag();
|
||||
CompoundTag craftingShareTag = crafting.getTag();
|
||||
NbtCompound shareTag = stack.getNbt();
|
||||
NbtCompound craftingShareTag = crafting.getNbt();
|
||||
if( shareTag == craftingShareTag ) return true;
|
||||
if( shareTag == null ) return craftingShareTag.isEmpty();
|
||||
if( craftingShareTag == null ) return shareTag.isEmpty();
|
||||
|
@@ -6,16 +6,16 @@
|
||||
|
||||
package dan200.computercraft.api.client;
|
||||
|
||||
import dan200.computercraft.fabric.mixin.AffineTransformationAccess;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedModelManager;
|
||||
import net.minecraft.client.util.ModelIdentifier;
|
||||
import net.minecraft.client.util.math.AffineTransformation;
|
||||
import net.minecraft.util.math.AffineTransformation;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.Objects;
|
||||
@@ -38,7 +38,7 @@ public final class TransformedModel
|
||||
public TransformedModel( @Nonnull BakedModel model )
|
||||
{
|
||||
this.model = Objects.requireNonNull( model );
|
||||
this.matrix = AffineTransformation.identity();
|
||||
matrix = AffineTransformation.identity();
|
||||
}
|
||||
|
||||
public static TransformedModel of( @Nonnull ModelIdentifier location )
|
||||
@@ -60,35 +60,27 @@ public final class TransformedModel
|
||||
@Nonnull
|
||||
public BakedModel getModel()
|
||||
{
|
||||
return this.model;
|
||||
return model;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public AffineTransformation getMatrix()
|
||||
{
|
||||
return this.matrix;
|
||||
return matrix;
|
||||
}
|
||||
|
||||
public void push( MatrixStack matrixStack )
|
||||
{
|
||||
matrixStack.push();
|
||||
|
||||
AffineTransformationAccess access = (AffineTransformationAccess) (Object) this.matrix;
|
||||
if( access.getTranslation() != null )
|
||||
{
|
||||
matrixStack.translate( access.getTranslation().getX(), access.getTranslation().getY(), access.getTranslation().getZ() );
|
||||
}
|
||||
Vec3f translation = matrix.getTranslation();
|
||||
matrixStack.translate( translation.getX(), translation.getY(), translation.getZ() );
|
||||
|
||||
matrixStack.multiply( this.matrix.getRotation2() );
|
||||
matrixStack.multiply( matrix.getRotation2() );
|
||||
|
||||
if( access.getScale() != null )
|
||||
{
|
||||
matrixStack.scale( access.getScale().getX(), access.getScale().getY(), access.getScale().getZ() );
|
||||
}
|
||||
Vec3f scale = matrix.getScale();
|
||||
matrixStack.scale( scale.getX(), scale.getY(), scale.getZ() );
|
||||
|
||||
if( access.getRotation1() != null )
|
||||
{
|
||||
matrixStack.multiply( access.getRotation1() );
|
||||
}
|
||||
matrixStack.multiply( matrix.getRotation1() );
|
||||
}
|
||||
}
|
||||
|
@@ -47,13 +47,13 @@ final class FileAttributes implements BasicFileAttributes
|
||||
@Override
|
||||
public boolean isRegularFile()
|
||||
{
|
||||
return !this.isDirectory;
|
||||
return !isDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory()
|
||||
{
|
||||
return this.isDirectory;
|
||||
return isDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,7 +71,7 @@ final class FileAttributes implements BasicFileAttributes
|
||||
@Override
|
||||
public long size()
|
||||
{
|
||||
return this.size;
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -31,12 +31,12 @@ public class FileOperationException extends IOException
|
||||
public FileOperationException( @Nonnull String message )
|
||||
{
|
||||
super( Objects.requireNonNull( message, "message cannot be null" ) );
|
||||
this.filename = null;
|
||||
filename = null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getFilename()
|
||||
{
|
||||
return this.filename;
|
||||
return filename;
|
||||
}
|
||||
}
|
||||
|
@@ -59,11 +59,11 @@ public interface IMount
|
||||
@Nonnull
|
||||
default BasicFileAttributes getAttributes( @Nonnull String path ) throws IOException
|
||||
{
|
||||
if( !this.exists( path ) )
|
||||
if( !exists( path ) )
|
||||
{
|
||||
throw new FileOperationException( path, "No such file" );
|
||||
}
|
||||
return new FileAttributes( this.isDirectory( path ), this.getSize( path ) );
|
||||
return new FileAttributes( isDirectory( path ), getSize( path ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -30,10 +30,10 @@ public interface IArguments
|
||||
|
||||
default Object[] getAll()
|
||||
{
|
||||
Object[] result = new Object[this.count()];
|
||||
Object[] result = new Object[count()];
|
||||
for( int i = 0; i < result.length; i++ )
|
||||
{
|
||||
result[i] = this.get( i );
|
||||
result[i] = get( i );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -71,7 +71,7 @@ public interface IArguments
|
||||
*/
|
||||
default int getInt( int index ) throws LuaException
|
||||
{
|
||||
return (int) this.getLong( index );
|
||||
return (int) getLong( index );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +83,7 @@ public interface IArguments
|
||||
*/
|
||||
default long getLong( int index ) throws LuaException
|
||||
{
|
||||
Object value = this.get( index );
|
||||
Object value = get( index );
|
||||
if( !(value instanceof Number) )
|
||||
{
|
||||
throw LuaValues.badArgumentOf( index, "number", value );
|
||||
@@ -101,7 +101,7 @@ public interface IArguments
|
||||
*/
|
||||
default double getFiniteDouble( int index ) throws LuaException
|
||||
{
|
||||
return checkFinite( index, this.getDouble( index ) );
|
||||
return checkFinite( index, getDouble( index ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,7 +114,7 @@ public interface IArguments
|
||||
*/
|
||||
default double getDouble( int index ) throws LuaException
|
||||
{
|
||||
Object value = this.get( index );
|
||||
Object value = get( index );
|
||||
if( !(value instanceof Number) )
|
||||
{
|
||||
throw LuaValues.badArgumentOf( index, "number", value );
|
||||
@@ -131,7 +131,7 @@ public interface IArguments
|
||||
*/
|
||||
default boolean getBoolean( int index ) throws LuaException
|
||||
{
|
||||
Object value = this.get( index );
|
||||
Object value = get( index );
|
||||
if( !(value instanceof Boolean) )
|
||||
{
|
||||
throw LuaValues.badArgumentOf( index, "boolean", value );
|
||||
@@ -149,7 +149,7 @@ public interface IArguments
|
||||
@Nonnull
|
||||
default ByteBuffer getBytes( int index ) throws LuaException
|
||||
{
|
||||
return LuaValues.encode( this.getString( index ) );
|
||||
return LuaValues.encode( getString( index ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -162,7 +162,7 @@ public interface IArguments
|
||||
@Nonnull
|
||||
default String getString( int index ) throws LuaException
|
||||
{
|
||||
Object value = this.get( index );
|
||||
Object value = get( index );
|
||||
if( !(value instanceof String) )
|
||||
{
|
||||
throw LuaValues.badArgumentOf( index, "string", value );
|
||||
@@ -182,7 +182,7 @@ public interface IArguments
|
||||
@Nonnull
|
||||
default <T extends Enum<T>> T getEnum( int index, Class<T> klass ) throws LuaException
|
||||
{
|
||||
return LuaValues.checkEnum( index, klass, this.getString( index ) );
|
||||
return LuaValues.checkEnum( index, klass, getString( index ) );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +195,7 @@ public interface IArguments
|
||||
@Nonnull
|
||||
default Map<?, ?> getTable( int index ) throws LuaException
|
||||
{
|
||||
Object value = this.get( index );
|
||||
Object value = get( index );
|
||||
if( !(value instanceof Map) )
|
||||
{
|
||||
throw LuaValues.badArgumentOf( index, "table", value );
|
||||
@@ -212,7 +212,7 @@ public interface IArguments
|
||||
*/
|
||||
default Optional<ByteBuffer> optBytes( int index ) throws LuaException
|
||||
{
|
||||
return this.optString( index ).map( LuaValues::encode );
|
||||
return optString( index ).map( LuaValues::encode );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -224,7 +224,7 @@ public interface IArguments
|
||||
*/
|
||||
default Optional<String> optString( int index ) throws LuaException
|
||||
{
|
||||
Object value = this.get( index );
|
||||
Object value = get( index );
|
||||
if( value == null )
|
||||
{
|
||||
return Optional.empty();
|
||||
@@ -248,7 +248,7 @@ public interface IArguments
|
||||
@Nonnull
|
||||
default <T extends Enum<T>> Optional<T> optEnum( int index, Class<T> klass ) throws LuaException
|
||||
{
|
||||
Optional<String> str = this.optString( index );
|
||||
Optional<String> str = optString( index );
|
||||
return str.isPresent() ? Optional.of( LuaValues.checkEnum( index, klass, str.get() ) ) : Optional.empty();
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ public interface IArguments
|
||||
*/
|
||||
default double optDouble( int index, double def ) throws LuaException
|
||||
{
|
||||
return this.optDouble( index ).orElse( def );
|
||||
return optDouble( index ).orElse( def );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,7 +275,7 @@ public interface IArguments
|
||||
@Nonnull
|
||||
default Optional<Double> optDouble( int index ) throws LuaException
|
||||
{
|
||||
Object value = this.get( index );
|
||||
Object value = get( index );
|
||||
if( value == null )
|
||||
{
|
||||
return Optional.empty();
|
||||
@@ -297,7 +297,7 @@ public interface IArguments
|
||||
*/
|
||||
default int optInt( int index, int def ) throws LuaException
|
||||
{
|
||||
return this.optInt( index ).orElse( def );
|
||||
return optInt( index ).orElse( def );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,7 +310,7 @@ public interface IArguments
|
||||
@Nonnull
|
||||
default Optional<Integer> optInt( int index ) throws LuaException
|
||||
{
|
||||
return this.optLong( index ).map( Long::intValue );
|
||||
return optLong( index ).map( Long::intValue );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,7 +322,7 @@ public interface IArguments
|
||||
*/
|
||||
default Optional<Long> optLong( int index ) throws LuaException
|
||||
{
|
||||
Object value = this.get( index );
|
||||
Object value = get( index );
|
||||
if( value == null )
|
||||
{
|
||||
return Optional.empty();
|
||||
@@ -345,7 +345,7 @@ public interface IArguments
|
||||
*/
|
||||
default long optLong( int index, long def ) throws LuaException
|
||||
{
|
||||
return this.optLong( index ).orElse( def );
|
||||
return optLong( index ).orElse( def );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -358,7 +358,7 @@ public interface IArguments
|
||||
*/
|
||||
default double optFiniteDouble( int index, double def ) throws LuaException
|
||||
{
|
||||
return this.optFiniteDouble( index ).orElse( def );
|
||||
return optFiniteDouble( index ).orElse( def );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -370,7 +370,7 @@ public interface IArguments
|
||||
*/
|
||||
default Optional<Double> optFiniteDouble( int index ) throws LuaException
|
||||
{
|
||||
Optional<Double> value = this.optDouble( index );
|
||||
Optional<Double> value = optDouble( index );
|
||||
if( value.isPresent() )
|
||||
{
|
||||
LuaValues.checkFiniteNum( index, value.get() );
|
||||
@@ -388,7 +388,7 @@ public interface IArguments
|
||||
*/
|
||||
default boolean optBoolean( int index, boolean def ) throws LuaException
|
||||
{
|
||||
return this.optBoolean( index ).orElse( def );
|
||||
return optBoolean( index ).orElse( def );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -400,7 +400,7 @@ public interface IArguments
|
||||
*/
|
||||
default Optional<Boolean> optBoolean( int index ) throws LuaException
|
||||
{
|
||||
Object value = this.get( index );
|
||||
Object value = get( index );
|
||||
if( value == null )
|
||||
{
|
||||
return Optional.empty();
|
||||
@@ -422,7 +422,7 @@ public interface IArguments
|
||||
*/
|
||||
default String optString( int index, String def ) throws LuaException
|
||||
{
|
||||
return this.optString( index ).orElse( def );
|
||||
return optString( index ).orElse( def );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,7 +435,7 @@ public interface IArguments
|
||||
*/
|
||||
default Map<?, ?> optTable( int index, Map<Object, Object> def ) throws LuaException
|
||||
{
|
||||
return this.optTable( index ).orElse( def );
|
||||
return optTable( index ).orElse( def );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,7 +447,7 @@ public interface IArguments
|
||||
*/
|
||||
default Optional<Map<?, ?>> optTable( int index ) throws LuaException
|
||||
{
|
||||
Object value = this.get( index );
|
||||
Object value = get( index );
|
||||
if( value == null )
|
||||
{
|
||||
return Optional.empty();
|
||||
|
@@ -9,17 +9,18 @@ package dan200.computercraft.api.lua;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods that allow the peripheral call to interface
|
||||
* with the computer.
|
||||
* An interface passed to peripherals and {@link IDynamicLuaObject}s by computers or turtles, providing methods
|
||||
* that allow the peripheral call to interface with the computer.
|
||||
*/
|
||||
public interface ILuaContext
|
||||
{
|
||||
/**
|
||||
* Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to complete. This should be used when you
|
||||
* need to interact with the world in a thread-safe manner but do not care about the result or you wish to run asynchronously.
|
||||
* Queue a task to be executed on the main server thread at the beginning of next tick, but do not wait for it to
|
||||
* complete. This should be used when you need to interact with the world in a thread-safe manner but do not care
|
||||
* about the result or you wish to run asynchronously.
|
||||
*
|
||||
* When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success value and the return values, or an
|
||||
* error message if it failed.
|
||||
* When the task has finished, it will enqueue a {@code task_completed} event, which takes the task id, a success
|
||||
* value and the return values, or an error message if it failed.
|
||||
*
|
||||
* @param task The task to execute on the main thread.
|
||||
* @return The "id" of the task. This will be the first argument to the {@code task_completed} event.
|
||||
@@ -27,4 +28,18 @@ public interface ILuaContext
|
||||
* @see LuaFunction#mainThread() To run functions on the main thread and return their results synchronously.
|
||||
*/
|
||||
long issueMainThreadTask( @Nonnull ILuaTask task ) throws LuaException;
|
||||
|
||||
/**
|
||||
* Queue a task to be executed on the main server thread at the beginning of next tick, waiting for it to complete.
|
||||
* This should be used when you need to interact with the world in a thread-safe manner.
|
||||
*
|
||||
* Note that the return values of your task are handled as events, meaning more complex objects such as maps or
|
||||
* {@link IDynamicLuaObject} will not preserve their identities.
|
||||
*
|
||||
* @param task The task to execute on the main thread.
|
||||
* @return The objects returned by {@code task}.
|
||||
* @throws LuaException If the task could not be queued, or if the task threw an exception.
|
||||
*/
|
||||
@Nonnull
|
||||
MethodResult executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException;
|
||||
}
|
||||
|
@@ -1,18 +0,0 @@
|
||||
/*
|
||||
* 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 javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public interface ILuaObject
|
||||
{
|
||||
@Nonnull
|
||||
String[] getMethodNames();
|
||||
|
||||
@Nullable
|
||||
Object[] callMethod( @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException;
|
||||
}
|
@@ -20,14 +20,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;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ public class LuaException extends Exception
|
||||
*/
|
||||
public boolean hasLevel()
|
||||
{
|
||||
return this.hasLevel;
|
||||
return hasLevel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,6 +48,6 @@ public class LuaException extends Exception
|
||||
*/
|
||||
public int getLevel()
|
||||
{
|
||||
return this.level;
|
||||
return level;
|
||||
}
|
||||
}
|
||||
|
@@ -31,14 +31,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;
|
||||
}
|
||||
@@ -141,18 +141,18 @@ public final class MethodResult
|
||||
@Nullable
|
||||
public Object[] getResult()
|
||||
{
|
||||
return this.result;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public ILuaCallback getCallback()
|
||||
{
|
||||
return this.callback;
|
||||
return callback;
|
||||
}
|
||||
|
||||
public int getErrorAdjust()
|
||||
{
|
||||
return this.adjust;
|
||||
return adjust;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,10 +168,10 @@ public final class MethodResult
|
||||
{
|
||||
throw new IllegalArgumentException( "cannot adjust by a negative amount" );
|
||||
}
|
||||
if( adjust == 0 || this.callback == null )
|
||||
if( adjust == 0 || callback == null )
|
||||
{
|
||||
return this;
|
||||
}
|
||||
return new MethodResult( this.result, this.callback, this.adjust + adjust );
|
||||
return new MethodResult( result, callback, this.adjust + adjust );
|
||||
}
|
||||
}
|
||||
|
@@ -47,30 +47,30 @@ public final class ObjectArguments implements IArguments
|
||||
{
|
||||
return this;
|
||||
}
|
||||
if( count >= this.args.size() )
|
||||
if( count >= args.size() )
|
||||
{
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
return new ObjectArguments( this.args.subList( count, this.args.size() ) );
|
||||
return new ObjectArguments( args.subList( count, args.size() ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] getAll()
|
||||
{
|
||||
return this.args.toArray();
|
||||
return args.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int count()
|
||||
{
|
||||
return this.args.size();
|
||||
return args.size();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public Object get( int index )
|
||||
{
|
||||
return index >= this.args.size() ? null : this.args.get( index );
|
||||
return index >= args.size() ? null : args.get( index );
|
||||
}
|
||||
}
|
||||
|
@@ -53,7 +53,7 @@ public class Packet
|
||||
*/
|
||||
public int getChannel()
|
||||
{
|
||||
return this.channel;
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -63,7 +63,7 @@ public class Packet
|
||||
*/
|
||||
public int getReplyChannel()
|
||||
{
|
||||
return this.replyChannel;
|
||||
return replyChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +74,7 @@ public class Packet
|
||||
@Nullable
|
||||
public Object getPayload()
|
||||
{
|
||||
return this.payload;
|
||||
return payload;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,17 +85,17 @@ public class Packet
|
||||
@Nonnull
|
||||
public IPacketSender getSender()
|
||||
{
|
||||
return this.sender;
|
||||
return sender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int result;
|
||||
result = this.channel;
|
||||
result = 31 * result + this.replyChannel;
|
||||
result = 31 * result + (this.payload != null ? this.payload.hashCode() : 0);
|
||||
result = 31 * result + this.sender.hashCode();
|
||||
result = channel;
|
||||
result = 31 * result + replyChannel;
|
||||
result = 31 * result + (payload != null ? payload.hashCode() : 0);
|
||||
result = 31 * result + sender.hashCode();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -106,25 +106,25 @@ public class Packet
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if( o == null || this.getClass() != o.getClass() )
|
||||
if( o == null || getClass() != o.getClass() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Packet packet = (Packet) o;
|
||||
|
||||
if( this.channel != packet.channel )
|
||||
if( channel != packet.channel )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( this.replyChannel != packet.replyChannel )
|
||||
if( replyChannel != packet.replyChannel )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if( !Objects.equals( this.payload, packet.payload ) )
|
||||
if( !Objects.equals( payload, packet.payload ) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return this.sender.equals( packet.sender );
|
||||
return sender.equals( packet.sender );
|
||||
}
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ public interface IWiredNode extends IPacketNetwork
|
||||
*/
|
||||
default boolean connectTo( @Nonnull IWiredNode node )
|
||||
{
|
||||
return this.getNetwork().connect( this, node );
|
||||
return getNetwork().connect( this, node );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +72,7 @@ public interface IWiredNode extends IPacketNetwork
|
||||
*/
|
||||
default boolean disconnectFrom( @Nonnull IWiredNode node )
|
||||
{
|
||||
return this.getNetwork().disconnect( this, node );
|
||||
return getNetwork().disconnect( this, node );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,7 +86,7 @@ public interface IWiredNode extends IPacketNetwork
|
||||
*/
|
||||
default boolean remove()
|
||||
{
|
||||
return this.getNetwork().remove( this );
|
||||
return getNetwork().remove( this );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,6 +99,6 @@ public interface IWiredNode extends IPacketNetwork
|
||||
*/
|
||||
default void updatePeripherals( @Nonnull Map<String, IPeripheral> peripherals )
|
||||
{
|
||||
this.getNetwork().updatePeripherals( this, peripherals );
|
||||
getNetwork().updatePeripherals( this, peripherals );
|
||||
}
|
||||
}
|
||||
|
@@ -43,7 +43,7 @@ public interface IComputerAccess
|
||||
@Nullable
|
||||
default String mount( @Nonnull String desiredLocation, @Nonnull IMount mount )
|
||||
{
|
||||
return this.mount( desiredLocation, mount, this.getAttachmentName() );
|
||||
return mount( desiredLocation, mount, getAttachmentName() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,7 +93,7 @@ public interface IComputerAccess
|
||||
@Nullable
|
||||
default String mountWritable( @Nonnull String desiredLocation, @Nonnull IWritableMount mount )
|
||||
{
|
||||
return this.mountWritable( desiredLocation, mount, this.getAttachmentName() );
|
||||
return mountWritable( desiredLocation, mount, getAttachmentName() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -45,7 +45,7 @@ public interface IWorkMonitor
|
||||
default boolean runWork( @Nonnull Runnable runnable )
|
||||
{
|
||||
Objects.requireNonNull( runnable, "runnable should not be null" );
|
||||
if( !this.canWork() )
|
||||
if( !canWork() )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -57,7 +57,7 @@ public interface IWorkMonitor
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.trackWork( System.nanoTime() - start, TimeUnit.NANOSECONDS );
|
||||
trackWork( System.nanoTime() - start, TimeUnit.NANOSECONDS );
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@@ -6,12 +6,15 @@
|
||||
|
||||
package dan200.computercraft.api.pocket;
|
||||
|
||||
import dan200.computercraft.shared.util.NonNullSupplier;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A base class for {@link IPocketUpgrade}s.
|
||||
@@ -22,46 +25,94 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade
|
||||
{
|
||||
private final Identifier id;
|
||||
private final String adjective;
|
||||
private final ItemStack stack;
|
||||
private final NonNullSupplier<ItemStack> stack;
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, ItemConvertible item )
|
||||
{
|
||||
this( id, Util.createTranslationKey( "upgrade", id ) + ".adjective", item );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemConvertible item )
|
||||
{
|
||||
this.id = id;
|
||||
this.adjective = adjective;
|
||||
this.stack = new ItemStack( item );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack )
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, NonNullSupplier<ItemStack> stack )
|
||||
{
|
||||
this.id = id;
|
||||
this.adjective = adjective;
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, NonNullSupplier<ItemStack> item )
|
||||
{
|
||||
this( id, Util.createTranslationKey( "upgrade", id ) + ".adjective", item );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemStack stack )
|
||||
{
|
||||
this( id, adjective, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, ItemStack stack )
|
||||
{
|
||||
this( id, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, ItemConvertible item )
|
||||
{
|
||||
this( id, adjective, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, ItemConvertible item )
|
||||
{
|
||||
this( id, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, String adjective, Supplier<? extends ItemConvertible> item )
|
||||
{
|
||||
this( id, adjective, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractPocketUpgrade( Identifier id, Supplier<? extends ItemConvertible> item )
|
||||
{
|
||||
this( id, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final Identifier getUpgradeID()
|
||||
{
|
||||
return this.id;
|
||||
return id;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final String getUnlocalisedAdjective()
|
||||
{
|
||||
return this.adjective;
|
||||
return adjective;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final ItemStack getCraftingItem()
|
||||
{
|
||||
return this.stack;
|
||||
return stack.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* Caches the construction of an item stack.
|
||||
*
|
||||
* @see dan200.computercraft.api.turtle.AbstractTurtleUpgrade For explanation of this class.
|
||||
*/
|
||||
private static final class CachedStack implements NonNullSupplier<ItemStack>
|
||||
{
|
||||
private final Supplier<? extends ItemConvertible> provider;
|
||||
private Item item;
|
||||
private ItemStack stack;
|
||||
|
||||
CachedStack( Supplier<? extends ItemConvertible> provider )
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemStack get()
|
||||
{
|
||||
Item item = provider.get().asItem();
|
||||
if( item == this.item && stack != null ) return stack;
|
||||
return stack = new ItemStack( this.item = item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ package dan200.computercraft.api.pocket;
|
||||
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -73,7 +73,7 @@ public interface IPocketAccess
|
||||
* @see #updateUpgradeNBTData()
|
||||
*/
|
||||
@Nonnull
|
||||
CompoundTag getUpgradeNBTData();
|
||||
NbtCompound getUpgradeNBTData();
|
||||
|
||||
/**
|
||||
* Mark the upgrade-specific NBT as dirty.
|
||||
|
@@ -6,12 +6,15 @@
|
||||
|
||||
package dan200.computercraft.api.turtle;
|
||||
|
||||
import dan200.computercraft.shared.util.NonNullSupplier;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemConvertible;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.Util;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* A base class for {@link ITurtleUpgrade}s.
|
||||
@@ -23,14 +26,9 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
private final Identifier id;
|
||||
private final TurtleUpgradeType type;
|
||||
private final String adjective;
|
||||
private final ItemStack stack;
|
||||
private final NonNullSupplier<ItemStack> stack;
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item )
|
||||
{
|
||||
this( id, type, adjective, new ItemStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack )
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, NonNullSupplier<ItemStack> stack )
|
||||
{
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
@@ -38,42 +36,92 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
|
||||
this.stack = stack;
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemConvertible item )
|
||||
{
|
||||
this( id, type, new ItemStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack )
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, NonNullSupplier<ItemStack> stack )
|
||||
{
|
||||
this( id, type, Util.createTranslationKey( "upgrade", id ) + ".adjective", stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemStack stack )
|
||||
{
|
||||
this( id, type, adjective, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemStack stack )
|
||||
{
|
||||
this( id, type, () -> stack );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, ItemConvertible item )
|
||||
{
|
||||
this( id, type, adjective, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, ItemConvertible item )
|
||||
{
|
||||
this( id, type, new CachedStack( () -> item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, String adjective, Supplier<? extends ItemConvertible> item )
|
||||
{
|
||||
this( id, type, adjective, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
protected AbstractTurtleUpgrade( Identifier id, TurtleUpgradeType type, Supplier<? extends ItemConvertible> item )
|
||||
{
|
||||
this( id, type, new CachedStack( item ) );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final Identifier getUpgradeID()
|
||||
{
|
||||
return this.id;
|
||||
return id;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final String getUnlocalisedAdjective()
|
||||
{
|
||||
return this.adjective;
|
||||
return adjective;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final TurtleUpgradeType getType()
|
||||
{
|
||||
return this.type;
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public final ItemStack getCraftingItem()
|
||||
{
|
||||
return this.stack;
|
||||
return stack.get();
|
||||
}
|
||||
|
||||
/**
|
||||
* A supplier which converts an item into an item stack.
|
||||
*
|
||||
* Constructing item stacks is somewhat expensive due to attaching capabilities. We cache it if given a consistent item.
|
||||
*/
|
||||
private static final class CachedStack implements NonNullSupplier<ItemStack>
|
||||
{
|
||||
private final Supplier<? extends ItemConvertible> provider;
|
||||
private Item item;
|
||||
private ItemStack stack;
|
||||
|
||||
CachedStack( Supplier<? extends ItemConvertible> provider )
|
||||
{
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ItemStack get()
|
||||
{
|
||||
Item item = provider.get().asItem();
|
||||
if( item == this.item && stack != null ) return stack;
|
||||
return stack = new ItemStack( this.item = item );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -23,20 +23,16 @@ import net.minecraft.network.packet.c2s.play.RequestCommandCompletionsC2SPacket;
|
||||
import net.minecraft.network.packet.c2s.play.VehicleMoveC2SPacket;
|
||||
import net.minecraft.recipe.Recipe;
|
||||
import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||
import net.minecraft.screen.ScreenHandler;
|
||||
import net.minecraft.server.network.ServerPlayNetworkHandler;
|
||||
import net.minecraft.server.network.ServerPlayerEntity;
|
||||
import net.minecraft.server.network.ServerPlayerInteractionManager;
|
||||
import net.minecraft.server.world.ServerWorld;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.sound.SoundEvent;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.collection.DefaultedList;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.village.TradeOfferList;
|
||||
import net.minecraft.world.GameMode;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import javax.crypto.Cipher;
|
||||
@@ -53,8 +49,8 @@ public class FakePlayer extends ServerPlayerEntity
|
||||
{
|
||||
public FakePlayer( ServerWorld world, GameProfile gameProfile )
|
||||
{
|
||||
super( world.getServer(), world, gameProfile, new ServerPlayerInteractionManager( world ) );
|
||||
this.networkHandler = new FakeNetHandler( this );
|
||||
super( world.getServer(), world, gameProfile );
|
||||
networkHandler = new FakeNetHandler( this );
|
||||
}
|
||||
|
||||
// region Direct networkHandler access
|
||||
@@ -128,7 +124,7 @@ public class FakePlayer extends ServerPlayerEntity
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openEditBookScreen( ItemStack stack, Hand hand )
|
||||
public void useBook( ItemStack stack, Hand hand )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -137,30 +133,30 @@ public class FakePlayer extends ServerPlayerEntity
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSlotUpdate( ScreenHandler container, int slot, ItemStack stack )
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onHandlerRegistered( ScreenHandler container, DefaultedList<ItemStack> defaultedList )
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPropertyUpdate( ScreenHandler container, int key, int value )
|
||||
{
|
||||
}
|
||||
// @Override
|
||||
// public void onSlotUpdate( ScreenHandler container, int slot, ItemStack stack )
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onHandlerRegistered( ScreenHandler container, DefaultedList<ItemStack> defaultedList )
|
||||
// {
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onPropertyUpdate( ScreenHandler container, int key, int value )
|
||||
// {
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void closeHandledScreen()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateCursorStack()
|
||||
{
|
||||
}
|
||||
// @Override
|
||||
// public void updateCursorStack()
|
||||
// {
|
||||
// }
|
||||
|
||||
@Override
|
||||
public int unlockRecipes( Collection<Recipe<?>> recipes )
|
||||
@@ -191,17 +187,17 @@ public class FakePlayer extends ServerPlayerEntity
|
||||
}
|
||||
|
||||
@Override
|
||||
public void method_14222( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target )
|
||||
public void lookAtEntity( EntityAnchorArgumentType.EntityAnchor self, Entity entity, EntityAnchorArgumentType.EntityAnchor target )
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStatusEffectApplied( StatusEffectInstance statusEffectInstance )
|
||||
protected void onStatusEffectApplied( StatusEffectInstance statusEffectInstance, @Nullable Entity source )
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStatusEffectUpgraded( StatusEffectInstance statusEffectInstance, boolean particles )
|
||||
protected void onStatusEffectUpgraded( StatusEffectInstance statusEffectInstance, boolean particles, @Nullable Entity source )
|
||||
{
|
||||
}
|
||||
|
||||
@@ -215,10 +211,10 @@ public class FakePlayer extends ServerPlayerEntity
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGameMode( GameMode gameMode )
|
||||
{
|
||||
}
|
||||
// @Override
|
||||
// public void setGameMode( GameMode gameMode )
|
||||
// {
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void sendMessage( Text message, MessageType type, UUID senderUuid )
|
||||
@@ -232,15 +228,15 @@ public class FakePlayer extends ServerPlayerEntity
|
||||
return "[Fake Player]";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendResourcePackUrl( String url, String hash )
|
||||
{
|
||||
}
|
||||
// @Override
|
||||
// public void sendResourcePackUrl( String url, String hash )
|
||||
// {
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void onStoppedTracking( Entity entity )
|
||||
{
|
||||
}
|
||||
// @Override
|
||||
// public void onStoppedTracking( Entity entity )
|
||||
// {
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void setCameraEntity( Entity entity )
|
||||
@@ -347,10 +343,5 @@ public class FakePlayer extends ServerPlayerEntity
|
||||
public void disableAutoRead()
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCompressionThreshold( int size )
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ import dan200.computercraft.api.lua.MethodResult;
|
||||
import dan200.computercraft.api.peripheral.IPeripheral;
|
||||
import dan200.computercraft.shared.util.ItemStorage;
|
||||
import net.minecraft.inventory.Inventory;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
@@ -255,7 +255,7 @@ public interface ITurtleAccess
|
||||
* @see #updateUpgradeNBTData(TurtleSide)
|
||||
*/
|
||||
@Nonnull
|
||||
CompoundTag getUpgradeNBTData( @Nullable TurtleSide side );
|
||||
NbtCompound getUpgradeNBTData( @Nullable TurtleSide side );
|
||||
|
||||
/**
|
||||
* Mark the upgrade-specific data as dirty on a specific side. This is required for the data to be synced to the client and persisted.
|
||||
@@ -267,7 +267,7 @@ public interface ITurtleAccess
|
||||
|
||||
default ItemStorage getItemHandler()
|
||||
{
|
||||
return ItemStorage.wrap( this.getInventory() );
|
||||
return ItemStorage.wrap( getInventory() );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -91,7 +91,7 @@ public final class TurtleCommandResult
|
||||
*/
|
||||
public boolean isSuccess()
|
||||
{
|
||||
return this.success;
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,7 +102,7 @@ public final class TurtleCommandResult
|
||||
@Nullable
|
||||
public String getErrorMessage()
|
||||
{
|
||||
return this.errorMessage;
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,6 +113,6 @@ public final class TurtleCommandResult
|
||||
@Nullable
|
||||
public Object[] getResults()
|
||||
{
|
||||
return this.results;
|
||||
return results;
|
||||
}
|
||||
}
|
||||
|
@@ -32,7 +32,7 @@ public class TurtleActionEvent extends TurtleEvent
|
||||
|
||||
public TurtleAction getAction()
|
||||
{
|
||||
return this.action;
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,7 +47,7 @@ public class TurtleActionEvent extends TurtleEvent
|
||||
@Deprecated
|
||||
public void setCanceled( boolean cancel )
|
||||
{
|
||||
this.setCanceled( cancel, null );
|
||||
setCanceled( cancel, null );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,7 +61,7 @@ public class TurtleActionEvent extends TurtleEvent
|
||||
*/
|
||||
public void setCanceled( boolean cancel, @Nullable String failureMessage )
|
||||
{
|
||||
this.cancelled = true;
|
||||
cancelled = true;
|
||||
this.failureMessage = cancel ? failureMessage : null;
|
||||
}
|
||||
|
||||
@@ -75,11 +75,11 @@ public class TurtleActionEvent extends TurtleEvent
|
||||
@Nullable
|
||||
public String getFailureMessage()
|
||||
{
|
||||
return this.failureMessage;
|
||||
return failureMessage;
|
||||
}
|
||||
|
||||
public boolean isCancelled()
|
||||
{
|
||||
return this.cancelled;
|
||||
return cancelled;
|
||||
}
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ public class TurtleAttackEvent extends TurtlePlayerEvent
|
||||
@Nonnull
|
||||
public Entity getTarget()
|
||||
{
|
||||
return this.target;
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,7 +57,7 @@ public class TurtleAttackEvent extends TurtlePlayerEvent
|
||||
@Nonnull
|
||||
public ITurtleUpgrade getUpgrade()
|
||||
{
|
||||
return this.upgrade;
|
||||
return upgrade;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,6 +68,6 @@ public class TurtleAttackEvent extends TurtlePlayerEvent
|
||||
@Nonnull
|
||||
public TurtleSide getSide()
|
||||
{
|
||||
return this.side;
|
||||
return side;
|
||||
}
|
||||
}
|
||||
|
@@ -52,7 +52,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
|
||||
*/
|
||||
public World getWorld()
|
||||
{
|
||||
return this.world;
|
||||
return world;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,7 +62,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
|
||||
*/
|
||||
public BlockPos getPos()
|
||||
{
|
||||
return this.pos;
|
||||
return pos;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,7 +97,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
|
||||
@Nonnull
|
||||
public BlockState getBlock()
|
||||
{
|
||||
return this.block;
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +108,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
|
||||
@Nonnull
|
||||
public ITurtleUpgrade getUpgrade()
|
||||
{
|
||||
return this.upgrade;
|
||||
return upgrade;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +119,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
|
||||
@Nonnull
|
||||
public TurtleSide getSide()
|
||||
{
|
||||
return this.side;
|
||||
return side;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
|
||||
@Nonnull
|
||||
public ItemStack getStack()
|
||||
{
|
||||
return this.stack;
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
|
||||
@Nonnull
|
||||
public BlockState getState()
|
||||
{
|
||||
return this.state;
|
||||
return state;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,7 +207,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
|
||||
@Nonnull
|
||||
public Map<String, Object> getData()
|
||||
{
|
||||
return this.data;
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,7 +218,7 @@ public abstract class TurtleBlockEvent extends TurtlePlayerEvent
|
||||
public void addData( @Nonnull Map<String, ?> newData )
|
||||
{
|
||||
Objects.requireNonNull( newData, "newData cannot be null" );
|
||||
this.data.putAll( newData );
|
||||
data.putAll( newData );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ public abstract class TurtleEvent
|
||||
@Nonnull
|
||||
public ITurtleAccess getTurtle()
|
||||
{
|
||||
return this.turtle;
|
||||
return turtle;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -53,7 +53,7 @@ public class TurtleInspectItemEvent extends TurtleActionEvent
|
||||
@Nonnull
|
||||
public ItemStack getStack()
|
||||
{
|
||||
return this.stack;
|
||||
return stack;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,7 +64,7 @@ public class TurtleInspectItemEvent extends TurtleActionEvent
|
||||
@Nonnull
|
||||
public Map<String, Object> getData()
|
||||
{
|
||||
return this.data;
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -74,7 +74,7 @@ public class TurtleInspectItemEvent extends TurtleActionEvent
|
||||
*/
|
||||
public boolean onMainThread()
|
||||
{
|
||||
return this.mainThread;
|
||||
return mainThread;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -85,6 +85,6 @@ public class TurtleInspectItemEvent extends TurtleActionEvent
|
||||
public void addData( @Nonnull Map<String, ?> newData )
|
||||
{
|
||||
Objects.requireNonNull( newData, "newData cannot be null" );
|
||||
this.data.putAll( newData );
|
||||
data.putAll( newData );
|
||||
}
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent
|
||||
@Nullable
|
||||
public Inventory getItemHandler()
|
||||
{
|
||||
return this.handler;
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,7 +81,7 @@ public abstract class TurtleInventoryEvent extends TurtleBlockEvent
|
||||
@Nonnull
|
||||
public ItemStack getStack()
|
||||
{
|
||||
return this.stack;
|
||||
return stack;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -39,6 +39,6 @@ public abstract class TurtlePlayerEvent extends TurtleActionEvent
|
||||
@Nonnull
|
||||
public FakePlayer getPlayer()
|
||||
{
|
||||
return this.player;
|
||||
return player;
|
||||
}
|
||||
}
|
||||
|
@@ -41,7 +41,7 @@ public class TurtleRefuelEvent extends TurtleActionEvent
|
||||
*/
|
||||
public ItemStack getStack()
|
||||
{
|
||||
return this.stack;
|
||||
return stack;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,7 +53,7 @@ public class TurtleRefuelEvent extends TurtleActionEvent
|
||||
@Nullable
|
||||
public Handler getHandler()
|
||||
{
|
||||
return this.handler;
|
||||
return handler;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -77,7 +77,7 @@ public final class ClientRegistry
|
||||
}
|
||||
|
||||
@SuppressWarnings( "NewExpressionSideOnly" )
|
||||
public static void onModelBakeEvent( ResourceManager manager, Consumer<ModelIdentifier> out )
|
||||
public static void onModelBakeEvent( ResourceManager manager, Consumer<Identifier> out )
|
||||
{
|
||||
for( String model : EXTRA_MODELS )
|
||||
{
|
||||
@@ -103,10 +103,8 @@ public final class ClientRegistry
|
||||
case 1: // Frame colour
|
||||
return IColouredItem.getColourBasic( stack );
|
||||
case 2: // Light colour
|
||||
{
|
||||
int light = ItemPocketComputer.getLightState( stack );
|
||||
return light == -1 ? Colour.BLACK.getHex() : light;
|
||||
}
|
||||
}
|
||||
}, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL, ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
|
||||
|
@@ -21,10 +21,6 @@ import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@SuppressWarnings( {
|
||||
"MethodCallSideOnly",
|
||||
"LocalVariableDeclarationSideOnly"
|
||||
} )
|
||||
public class ClientTableFormatter implements TableFormatter
|
||||
{
|
||||
public static final ClientTableFormatter INSTANCE = new ClientTableFormatter();
|
||||
@@ -35,7 +31,7 @@ public class ClientTableFormatter implements TableFormatter
|
||||
@Nullable
|
||||
public Text getPadding( Text component, int width )
|
||||
{
|
||||
int extraWidth = width - this.getWidth( component );
|
||||
int extraWidth = width - getWidth( component );
|
||||
if( extraWidth <= 0 )
|
||||
{
|
||||
return null;
|
||||
|
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.MinecraftClient;
|
||||
import net.minecraft.client.sound.AbstractSoundInstance;
|
||||
import net.minecraft.client.sound.SoundInstance;
|
||||
import net.minecraft.client.sound.TickableSoundInstance;
|
||||
import net.minecraft.sound.SoundCategory;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
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, Vec3d position, Identifier event, float volume, float pitch )
|
||||
{
|
||||
var soundManager = MinecraftClient.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 )
|
||||
{
|
||||
SoundInstance sound = sounds.remove( source );
|
||||
if( sound == null ) return;
|
||||
|
||||
MinecraftClient.getInstance().getSoundManager().stop( sound );
|
||||
}
|
||||
|
||||
public static void moveSound( UUID source, Vec3d position )
|
||||
{
|
||||
MoveableSound sound = sounds.get( source );
|
||||
if( sound != null ) sound.setPosition( position );
|
||||
}
|
||||
|
||||
public static void reset()
|
||||
{
|
||||
sounds.clear();
|
||||
}
|
||||
|
||||
private static class MoveableSound extends AbstractSoundInstance implements TickableSoundInstance
|
||||
{
|
||||
protected MoveableSound( Identifier sound, Vec3d position, float volume, float pitch )
|
||||
{
|
||||
super( sound, SoundCategory.RECORDS );
|
||||
setPosition( position );
|
||||
this.volume = volume;
|
||||
this.pitch = pitch;
|
||||
attenuationType = SoundInstance.AttenuationType.LINEAR;
|
||||
}
|
||||
|
||||
void setPosition( Vec3d position )
|
||||
{
|
||||
x = (float) position.getX();
|
||||
y = (float) position.getY();
|
||||
z = (float) position.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDone()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,228 @@
|
||||
/*
|
||||
* 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 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.ingame.HandledScreen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
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 HandledScreen<T>
|
||||
{
|
||||
|
||||
private static final Text OK = new TranslatableText( "gui.ok" );
|
||||
private static final Text CANCEL = new TranslatableText( "gui.cancel" );
|
||||
private static final Text OVERWRITE = new TranslatableText( "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, Text 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();
|
||||
client.keyboard.setRepeatEvents( true );
|
||||
|
||||
terminal = addDrawableChild( createTerminal() );
|
||||
ComputerSidebar.addButtons( this, computer, this::addDrawableChild, x, y + sidebarYOffset );
|
||||
setFocused( terminal );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void removed()
|
||||
{
|
||||
super.removed();
|
||||
client.keyboard.setRepeatEvents( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void handledScreenTick()
|
||||
{
|
||||
super.handledScreenTick();
|
||||
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 );
|
||||
drawMouseoverTooltip( 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 drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY )
|
||||
{
|
||||
// Skip rendering labels.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void filesDragged( @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;
|
||||
}
|
||||
|
||||
String name = file.getFileName().toString();
|
||||
if( name.length() > UploadFileMessage.MAX_FILE_NAME )
|
||||
{
|
||||
alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.name_too_long" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect( (int) fileSize );
|
||||
sbc.read( buffer );
|
||||
buffer.flip();
|
||||
|
||||
byte[] digest = FileUpload.getDigest( buffer );
|
||||
if( digest == null )
|
||||
{
|
||||
alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.corrupted" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
buffer.rewind();
|
||||
toUpload.add( new FileUpload( name, buffer, digest ) );
|
||||
}
|
||||
catch( IOException e )
|
||||
{
|
||||
ComputerCraft.log.error( "Failed uploading files", e );
|
||||
alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.generic", "Cannot compute checksum" ) );
|
||||
}
|
||||
}
|
||||
|
||||
if( toUpload.size() > UploadFileMessage.MAX_FILES )
|
||||
{
|
||||
alert( UploadResult.FAILED_TITLE, new TranslatableText( "gui.computercraft.upload.failed.too_many_files" ) );
|
||||
return;
|
||||
}
|
||||
|
||||
if( toUpload.size() > 0 )
|
||||
{
|
||||
UploadFileMessage.send( computer.getInstanceID(), toUpload );
|
||||
}
|
||||
}
|
||||
|
||||
public void uploadResult( UploadResult result, Text message )
|
||||
{
|
||||
switch( result )
|
||||
{
|
||||
case SUCCESS:
|
||||
alert( UploadResult.SUCCESS_TITLE, message );
|
||||
break;
|
||||
case ERROR:
|
||||
alert( UploadResult.FAILED_TITLE, message );
|
||||
break;
|
||||
case CONFIRM_OVERWRITE:
|
||||
OptionScreen.show(
|
||||
client, UploadResult.UPLOAD_OVERWRITE, message,
|
||||
Arrays.asList(
|
||||
OptionScreen.newButton( CANCEL, b -> cancelUpload() ),
|
||||
OptionScreen.newButton( OVERWRITE, b -> continueUpload() )
|
||||
),
|
||||
this::cancelUpload
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void continueUpload()
|
||||
{
|
||||
if( client.currentScreen instanceof OptionScreen ) ((OptionScreen) client.currentScreen).disable();
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), true ) );
|
||||
}
|
||||
|
||||
private void cancelUpload()
|
||||
{
|
||||
client.setScreen( this );
|
||||
NetworkHandler.sendToServer( new ContinueUploadMessage( computer.getInstanceID(), false ) );
|
||||
}
|
||||
|
||||
private void alert( Text title, Text message )
|
||||
{
|
||||
OptionScreen.show( client, title, message,
|
||||
Collections.singletonList( OptionScreen.newButton( OK, b -> client.setScreen( this ) ) ),
|
||||
() -> client.setScreen( this )
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@@ -6,22 +6,24 @@
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.client.FrameInfo;
|
||||
import dan200.computercraft.client.render.RenderTypes;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.client.util.math.AffineTransformation;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.AffineTransformation;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
|
||||
|
||||
public final class FixedWidthFontRenderer
|
||||
{
|
||||
public static final int FONT_HEIGHT = 9;
|
||||
@@ -31,47 +33,16 @@ public final class FixedWidthFontRenderer
|
||||
public static final float BACKGROUND_END = (WIDTH - 4.0f) / WIDTH;
|
||||
private static final Matrix4f IDENTITY = AffineTransformation.identity()
|
||||
.getMatrix();
|
||||
private static final Identifier FONT = new Identifier( "computercraft", "textures/gui/term_font.png" );
|
||||
public static final RenderLayer TYPE = Type.MAIN;
|
||||
public static final Identifier FONT = new Identifier( "computercraft", "textures/gui/term_font.png" );
|
||||
|
||||
|
||||
private FixedWidthFontRenderer()
|
||||
{
|
||||
}
|
||||
|
||||
public static void drawString( float x, float y, @Nonnull TextBuffer text, @Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour,
|
||||
@Nonnull Palette palette, boolean greyscale, float leftMarginSize, float rightMarginSize )
|
||||
{
|
||||
bindFont();
|
||||
|
||||
VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance()
|
||||
.getBufferBuilders()
|
||||
.getEntityVertexConsumers();
|
||||
drawString( IDENTITY,
|
||||
((VertexConsumerProvider) renderer).getBuffer( TYPE ),
|
||||
x,
|
||||
y,
|
||||
text,
|
||||
textColour,
|
||||
backgroundColour,
|
||||
palette,
|
||||
greyscale,
|
||||
leftMarginSize,
|
||||
rightMarginSize );
|
||||
renderer.draw();
|
||||
}
|
||||
|
||||
private static void bindFont()
|
||||
{
|
||||
MinecraftClient.getInstance()
|
||||
.getTextureManager()
|
||||
.bindTexture( FONT );
|
||||
RenderSystem.texParameter( GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_CLAMP );
|
||||
}
|
||||
|
||||
public static void drawString( @Nonnull Matrix4f transform, @Nonnull VertexConsumer renderer, float x, float y, @Nonnull TextBuffer text,
|
||||
@Nonnull TextBuffer textColour, @Nullable TextBuffer backgroundColour, @Nonnull Palette palette, boolean greyscale,
|
||||
float leftMarginSize, float rightMarginSize )
|
||||
float leftMarginSize, float rightMarginSize, int light )
|
||||
{
|
||||
if( backgroundColour != null )
|
||||
{
|
||||
@@ -99,7 +70,7 @@ public final class FixedWidthFontRenderer
|
||||
{
|
||||
index = '?';
|
||||
}
|
||||
drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b );
|
||||
drawChar( transform, renderer, x + i * FONT_WIDTH, y, index, r, g, b, light );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -170,7 +141,7 @@ public final class FixedWidthFontRenderer
|
||||
return (float) ((rgb[0] + rgb[1] + rgb[2]) / 3);
|
||||
}
|
||||
|
||||
private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b )
|
||||
private static void drawChar( Matrix4f transform, VertexConsumer buffer, float x, float y, int index, float r, float g, float b, int light )
|
||||
{
|
||||
// Short circuit to avoid the common case - the texture should be blank here after all.
|
||||
if( index == '\0' || index == ' ' )
|
||||
@@ -187,26 +158,32 @@ public final class FixedWidthFontRenderer
|
||||
buffer.vertex( transform, x, y, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.texture( xStart / WIDTH, yStart / WIDTH )
|
||||
.light( light )
|
||||
.next();
|
||||
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.texture( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
|
||||
.light( light )
|
||||
.next();
|
||||
buffer.vertex( transform, x + FONT_WIDTH, y, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.texture( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH )
|
||||
.light( light )
|
||||
.next();
|
||||
buffer.vertex( transform, x + FONT_WIDTH, y, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.texture( (xStart + FONT_WIDTH) / WIDTH, yStart / WIDTH )
|
||||
.light( light )
|
||||
.next();
|
||||
buffer.vertex( transform, x, y + FONT_HEIGHT, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.texture( xStart / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
|
||||
.light( light )
|
||||
.next();
|
||||
buffer.vertex( transform, x + FONT_WIDTH, y + FONT_HEIGHT, 0f )
|
||||
.color( r, g, b, 1.0f )
|
||||
.texture( (xStart + FONT_WIDTH) / WIDTH, (yStart + FONT_HEIGHT) / WIDTH )
|
||||
.light( light )
|
||||
.next();
|
||||
}
|
||||
|
||||
@@ -300,7 +277,7 @@ public final class FixedWidthFontRenderer
|
||||
palette,
|
||||
greyscale,
|
||||
leftMarginSize,
|
||||
rightMarginSize );
|
||||
rightMarginSize, FULL_BRIGHT_LIGHTMAP );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,7 +305,7 @@ public final class FixedWidthFontRenderer
|
||||
b = (float) colour[2];
|
||||
}
|
||||
|
||||
drawChar( transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b );
|
||||
drawChar( transform, buffer, x + cursorX * FONT_WIDTH, y + cursorY * FONT_HEIGHT, '_', r, g, b, FULL_BRIGHT_LIGHTMAP );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -342,14 +319,12 @@ public final class FixedWidthFontRenderer
|
||||
public static void drawTerminal( @Nonnull Matrix4f transform, float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize,
|
||||
float bottomMarginSize, float leftMarginSize, float rightMarginSize )
|
||||
{
|
||||
bindFont();
|
||||
|
||||
VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance()
|
||||
.getBufferBuilders()
|
||||
.getEntityVertexConsumers();
|
||||
VertexConsumer buffer = renderer.getBuffer( TYPE );
|
||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH );
|
||||
drawTerminal( transform, buffer, x, y, terminal, greyscale, topMarginSize, bottomMarginSize, leftMarginSize, rightMarginSize );
|
||||
renderer.draw( TYPE );
|
||||
renderer.draw();
|
||||
}
|
||||
|
||||
public static void drawTerminal( float x, float y, @Nonnull Terminal terminal, boolean greyscale, float topMarginSize, float bottomMarginSize,
|
||||
@@ -360,13 +335,12 @@ public final class FixedWidthFontRenderer
|
||||
|
||||
public static void drawEmptyTerminal( float x, float y, float width, float height )
|
||||
{
|
||||
Colour colour = Colour.BLACK;
|
||||
drawEmptyTerminal( IDENTITY, x, y, width, height );
|
||||
}
|
||||
|
||||
public static void drawEmptyTerminal( @Nonnull Matrix4f transform, float x, float y, float width, float height )
|
||||
{
|
||||
bindFont();
|
||||
|
||||
VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance()
|
||||
.getBufferBuilders()
|
||||
.getEntityVertexConsumers();
|
||||
@@ -378,44 +352,12 @@ public final class FixedWidthFontRenderer
|
||||
float height )
|
||||
{
|
||||
Colour colour = Colour.BLACK;
|
||||
drawQuad( transform, renderer.getBuffer( TYPE ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||
drawQuad( transform, renderer.getBuffer( RenderTypes.TERMINAL_WITH_DEPTH ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||
}
|
||||
|
||||
public static void drawBlocker( @Nonnull Matrix4f transform, @Nonnull VertexConsumerProvider renderer, float x, float y, float width, float height )
|
||||
{
|
||||
Colour colour = Colour.BLACK;
|
||||
drawQuad( transform, renderer.getBuffer( Type.BLOCKER ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||
}
|
||||
|
||||
private static final class Type extends RenderPhase
|
||||
{
|
||||
private static final int GL_MODE = GL11.GL_TRIANGLES;
|
||||
|
||||
private static final VertexFormat FORMAT = VertexFormats.POSITION_COLOR_TEXTURE;
|
||||
|
||||
static final RenderLayer MAIN = RenderLayer.of( "terminal_font", FORMAT, GL_MODE, 1024, false, false, // useDelegate, needsSorting
|
||||
RenderLayer.MultiPhaseParameters.builder()
|
||||
.texture( new RenderPhase.Texture( FONT,
|
||||
false,
|
||||
false ) ) // blur, minimap
|
||||
.alpha( ONE_TENTH_ALPHA )
|
||||
.lightmap( DISABLE_LIGHTMAP )
|
||||
.writeMaskState( COLOR_MASK )
|
||||
.build( false ) );
|
||||
|
||||
static final RenderLayer BLOCKER = RenderLayer.of( "terminal_blocker", FORMAT, GL_MODE, 256, false, false, // useDelegate, needsSorting
|
||||
RenderLayer.MultiPhaseParameters.builder()
|
||||
.texture( new RenderPhase.Texture( FONT,
|
||||
false,
|
||||
false ) ) // blur, minimap
|
||||
.alpha( ONE_TENTH_ALPHA )
|
||||
.writeMaskState( DEPTH_MASK )
|
||||
.lightmap( DISABLE_LIGHTMAP )
|
||||
.build( false ) );
|
||||
|
||||
private Type( String name, Runnable setup, Runnable destroy )
|
||||
{
|
||||
super( name, setup, destroy );
|
||||
}
|
||||
drawQuad( transform, renderer.getBuffer( RenderTypes.TERMINAL_BLOCKER ), x, y, width, height, colour.getR(), colour.getG(), colour.getB() );
|
||||
}
|
||||
}
|
||||
|
@@ -6,54 +6,43 @@
|
||||
|
||||
package dan200.computercraft.client.gui;
|
||||
|
||||
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.client.render.RenderTypes;
|
||||
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.ingame.HandledScreen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.Text;
|
||||
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;
|
||||
import static dan200.computercraft.client.render.ComputerBorderRenderer.getTexture;
|
||||
|
||||
public final class GuiComputer<T extends ContainerComputerBase> extends HandledScreen<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, Text title, int termWidth, int termHeight )
|
||||
{
|
||||
super( container, player, title );
|
||||
this.family = container.getFamily();
|
||||
this.computer = (ClientComputer) container.getComputer();
|
||||
super( container, player, title, BORDER );
|
||||
this.termWidth = termWidth;
|
||||
this.termHeight = termHeight;
|
||||
this.terminal = null;
|
||||
|
||||
backgroundWidth = WidgetTerminal.getWidth( termWidth ) + BORDER * 2 + ComputerSidebar.WIDTH;
|
||||
backgroundHeight = WidgetTerminal.getHeight( termHeight ) + BORDER * 2;
|
||||
}
|
||||
|
||||
public static GuiComputer<ContainerComputer> create( ContainerComputer container, PlayerInventory inventory, Text component )
|
||||
public static GuiComputer<ContainerComputerBase> create( ContainerComputerBase container, PlayerInventory inventory, Text component )
|
||||
{
|
||||
return new GuiComputer<>( container, inventory, component, ComputerCraft.computerTermWidth, ComputerCraft.computerTermHeight );
|
||||
}
|
||||
|
||||
public static GuiComputer<ContainerPocketComputer> createPocket( ContainerPocketComputer container, PlayerInventory inventory, Text component )
|
||||
public static GuiComputer<ContainerComputerBase> createPocket( ContainerComputerBase container, PlayerInventory inventory, Text component )
|
||||
{
|
||||
return new GuiComputer<>( container, inventory, component, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight );
|
||||
}
|
||||
@@ -63,91 +52,19 @@ public final class GuiComputer<T extends ContainerComputerBase> extends HandledS
|
||||
return new GuiComputer<>( container, inventory, component, container.getWidth(), container.getHeight() );
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void init()
|
||||
protected WidgetTerminal createTerminal()
|
||||
{
|
||||
this.client.keyboard.setRepeatEvents( true );
|
||||
|
||||
int termPxWidth = this.termWidth * FixedWidthFontRenderer.FONT_WIDTH;
|
||||
int termPxHeight = this.termHeight * FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
|
||||
this.backgroundWidth = termPxWidth + MARGIN * 2 + BORDER * 2;
|
||||
this.backgroundHeight = termPxHeight + MARGIN * 2 + BORDER * 2;
|
||||
|
||||
super.init();
|
||||
|
||||
this.terminal = new WidgetTerminal( this.client, () -> this.computer, this.termWidth, this.termHeight, MARGIN, MARGIN, MARGIN, MARGIN );
|
||||
this.terminalWrapper = new WidgetWrapper( this.terminal, MARGIN + BORDER + this.x, MARGIN + BORDER + this.y, termPxWidth, termPxHeight );
|
||||
|
||||
this.children.add( this.terminalWrapper );
|
||||
this.setFocused( this.terminalWrapper );
|
||||
return new WidgetTerminal( computer,
|
||||
x + ComputerSidebar.WIDTH + BORDER, y + BORDER, termWidth, termHeight
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
super.render( stack, mouseX, mouseY, partialTicks );
|
||||
this.drawMouseoverTooltip( stack, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY )
|
||||
{
|
||||
// Skip rendering labels.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void drawBackground( @Nonnull MatrixStack stack, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw terminal
|
||||
this.terminal.draw( this.terminalWrapper.getX(), this.terminalWrapper.getY() );
|
||||
|
||||
// Draw a border around the terminal
|
||||
RenderSystem.color4f( 1, 1, 1, 1 );
|
||||
this.client.getTextureManager()
|
||||
.bindTexture( ComputerBorderRenderer.getTexture( this.family ) );
|
||||
ComputerBorderRenderer.render( this.terminalWrapper.getX() - MARGIN, this.terminalWrapper.getY() - MARGIN,
|
||||
this.getZOffset(), this.terminalWrapper.getWidth() + MARGIN * 2, this.terminalWrapper.getHeight() + MARGIN * 2 );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
|
||||
{
|
||||
return (this.getFocused() != null && this.getFocused().mouseDragged( x, y, button, deltaX, deltaY )) || super.mouseDragged( x, y, button, deltaX, deltaY );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseReleased( double mouseX, double mouseY, int button )
|
||||
{
|
||||
return (this.getFocused() != null && this.getFocused().mouseReleased( mouseX, mouseY, button )) || super.mouseReleased( x, y, button );
|
||||
}
|
||||
|
||||
@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 && this.getFocused() != null && this.getFocused() == this.terminalWrapper )
|
||||
{
|
||||
return this.getFocused().keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
return super.keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed()
|
||||
{
|
||||
super.removed();
|
||||
this.children.remove( this.terminal );
|
||||
this.terminal = null;
|
||||
this.client.keyboard.setRepeatEvents( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
super.tick();
|
||||
this.terminal.update();
|
||||
ComputerBorderRenderer.render(
|
||||
getTexture( family ), terminal.x, terminal.y, getZOffset(),
|
||||
RenderTypes.FULL_BRIGHT_LIGHTMAP, terminal.getWidth(), terminal.getHeight() );
|
||||
ComputerSidebar.renderBackground( stack, x, y + sidebarYOffset );
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@ package dan200.computercraft.client.gui;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||
import net.minecraft.client.render.GameRenderer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.Text;
|
||||
@@ -28,17 +29,17 @@ public class GuiDiskDrive extends HandledScreen<ContainerDiskDrive>
|
||||
@Override
|
||||
public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
this.renderBackground( transform );
|
||||
renderBackground( transform );
|
||||
super.render( transform, mouseX, mouseY, partialTicks );
|
||||
this.drawMouseoverTooltip( transform, mouseX, mouseY );
|
||||
drawMouseoverTooltip( transform, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
this.client.getTextureManager()
|
||||
.bindTexture( BACKGROUND );
|
||||
this.drawTexture( transform, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight );
|
||||
RenderSystem.setShader( GameRenderer::getPositionTexShader );
|
||||
RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
||||
drawTexture( transform, x, y, 0, 0, backgroundWidth, backgroundHeight );
|
||||
}
|
||||
}
|
||||
|
@@ -25,33 +25,24 @@ public class GuiPrinter extends HandledScreen<ContainerPrinter>
|
||||
super( container, player, title );
|
||||
}
|
||||
|
||||
/*@Override
|
||||
protected void drawGuiContainerForegroundLayer( int mouseX, int mouseY )
|
||||
{
|
||||
String title = getTitle().getFormattedText();
|
||||
font.drawString( title, (xSize - font.getStringWidth( title )) / 2.0f, 6, 0x404040 );
|
||||
font.drawString( I18n.format( "container.inventory" ), 8, ySize - 96 + 2, 0x404040 );
|
||||
}*/
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
this.renderBackground( stack );
|
||||
renderBackground( stack );
|
||||
super.render( stack, mouseX, mouseY, partialTicks );
|
||||
this.drawMouseoverTooltip( stack, mouseX, mouseY );
|
||||
drawMouseoverTooltip( stack, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
this.client.getTextureManager()
|
||||
.bindTexture( BACKGROUND );
|
||||
this.drawTexture( transform, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight );
|
||||
RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
||||
drawTexture( transform, x, y, 0, 0, backgroundWidth, backgroundHeight );
|
||||
|
||||
if( this.getScreenHandler().isPrinting() )
|
||||
if( getScreenHandler().isPrinting() )
|
||||
{
|
||||
this.drawTexture( transform, this.x + 34, this.y + 21, 176, 0, 25, 45 );
|
||||
drawTexture( transform, x + 34, y + 21, 176, 0, 25, 45 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -22,6 +22,7 @@ import org.lwjgl.glfw.GLFW;
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
import static dan200.computercraft.client.render.PrintoutRenderer.*;
|
||||
import static dan200.computercraft.client.render.RenderTypes.FULL_BRIGHT_LIGHTMAP;
|
||||
|
||||
public class GuiPrintout extends HandledScreen<ContainerHeldItem>
|
||||
{
|
||||
@@ -35,7 +36,7 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem>
|
||||
{
|
||||
super( container, player, title );
|
||||
|
||||
this.backgroundHeight = Y_SIZE;
|
||||
backgroundHeight = Y_SIZE;
|
||||
|
||||
String[] text = ItemPrintout.getText( container.getStack() );
|
||||
this.text = new TextBuffer[text.length];
|
||||
@@ -51,9 +52,9 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem>
|
||||
this.colours[i] = new TextBuffer( colours[i] );
|
||||
}
|
||||
|
||||
this.page = 0;
|
||||
this.pages = Math.max( this.text.length / ItemPrintout.LINES_PER_PAGE, 1 );
|
||||
this.book = ((ItemPrintout) container.getStack()
|
||||
page = 0;
|
||||
pages = Math.max( this.text.length / ItemPrintout.LINES_PER_PAGE, 1 );
|
||||
book = ((ItemPrintout) container.getStack()
|
||||
.getItem()).getType() == ItemPrintout.Type.BOOK;
|
||||
}
|
||||
|
||||
@@ -67,9 +68,9 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem>
|
||||
if( delta < 0 )
|
||||
{
|
||||
// Scroll up goes to the next page
|
||||
if( this.page < this.pages - 1 )
|
||||
if( page < pages - 1 )
|
||||
{
|
||||
this.page++;
|
||||
page++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -77,9 +78,9 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem>
|
||||
if( delta > 0 )
|
||||
{
|
||||
// Scroll down goes to the previous page
|
||||
if( this.page > 0 )
|
||||
if( page > 0 )
|
||||
{
|
||||
this.page--;
|
||||
page--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -91,9 +92,9 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem>
|
||||
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.
|
||||
this.setZOffset( this.getZOffset() - 1 );
|
||||
this.renderBackground( stack );
|
||||
this.setZOffset( this.getZOffset() + 1 );
|
||||
setZOffset( getZOffset() - 1 );
|
||||
renderBackground( stack );
|
||||
setZOffset( getZOffset() + 1 );
|
||||
|
||||
super.render( stack, mouseX, mouseY, partialTicks );
|
||||
}
|
||||
@@ -108,7 +109,7 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem>
|
||||
protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw the printout
|
||||
RenderSystem.color4f( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
RenderSystem.setShaderColor( 1.0f, 1.0f, 1.0f, 1.0f );
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
VertexConsumerProvider.Immediate renderer = MinecraftClient.getInstance()
|
||||
@@ -116,8 +117,8 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem>
|
||||
.getEntityVertexConsumers();
|
||||
Matrix4f matrix = transform.peek()
|
||||
.getModel();
|
||||
drawBorder( matrix, renderer, this.x, this.y, this.getZOffset(), this.page, this.pages, this.book );
|
||||
drawText( matrix, renderer, this.x + X_TEXT_MARGIN, this.y + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * this.page, this.text, this.colours );
|
||||
drawBorder( matrix, renderer, x, y, getZOffset(), page, pages, book, FULL_BRIGHT_LIGHTMAP );
|
||||
drawText( matrix, renderer, x + X_TEXT_MARGIN, y + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, FULL_BRIGHT_LIGHTMAP, text, colours );
|
||||
renderer.draw();
|
||||
}
|
||||
|
||||
@@ -131,18 +132,18 @@ public class GuiPrintout extends HandledScreen<ContainerHeldItem>
|
||||
|
||||
if( key == GLFW.GLFW_KEY_RIGHT )
|
||||
{
|
||||
if( this.page < this.pages - 1 )
|
||||
if( page < pages - 1 )
|
||||
{
|
||||
this.page++;
|
||||
page++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if( key == GLFW.GLFW_KEY_LEFT )
|
||||
{
|
||||
if( this.page > 0 )
|
||||
if( page > 0 )
|
||||
{
|
||||
this.page--;
|
||||
page--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -8,130 +8,70 @@ package dan200.computercraft.client.gui;
|
||||
|
||||
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.ingame.HandledScreen;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class GuiTurtle extends HandledScreen<ContainerTurtle>
|
||||
import static dan200.computercraft.shared.turtle.inventory.ContainerTurtle.BORDER;
|
||||
|
||||
public class GuiTurtle extends ComputerScreenBase<ContainerTurtle>
|
||||
{
|
||||
private static final Identifier BACKGROUND_NORMAL = new Identifier( "computercraft", "textures/gui/turtle_normal.png" );
|
||||
private static final Identifier BACKGROUND_ADVANCED = new Identifier( "computercraft", "textures/gui/turtle_advanced.png" );
|
||||
|
||||
private static final int TEX_WIDTH = 254;
|
||||
private static final int TEX_HEIGHT = 217;
|
||||
|
||||
private final ComputerFamily family;
|
||||
private final ClientComputer computer;
|
||||
private final ContainerTurtle container;
|
||||
private WidgetTerminal terminal;
|
||||
private WidgetWrapper terminalWrapper;
|
||||
|
||||
public GuiTurtle( ContainerTurtle container, PlayerInventory player, Text title )
|
||||
{
|
||||
super( container, player, title );
|
||||
super( container, player, title, BORDER );
|
||||
|
||||
this.container = container;
|
||||
this.family = container.getFamily();
|
||||
this.computer = (ClientComputer) container.getComputer();
|
||||
family = container.getFamily();
|
||||
backgroundWidth = TEX_WIDTH + ComputerSidebar.WIDTH;
|
||||
backgroundHeight = TEX_HEIGHT;
|
||||
|
||||
this.backgroundWidth = 254;
|
||||
this.backgroundHeight = 217;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init()
|
||||
protected WidgetTerminal createTerminal()
|
||||
{
|
||||
super.init();
|
||||
this.client.keyboard.setRepeatEvents( true );
|
||||
|
||||
int termPxWidth = ComputerCraft.turtleTermWidth * FixedWidthFontRenderer.FONT_WIDTH;
|
||||
int termPxHeight = ComputerCraft.turtleTermHeight * FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
|
||||
this.terminal = new WidgetTerminal( this.client, () -> this.computer, ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight, 2, 2, 2, 2 );
|
||||
this.terminalWrapper = new WidgetWrapper( this.terminal, 2 + 8 + this.x, 2 + 8 + this.y, termPxWidth, termPxHeight );
|
||||
|
||||
this.children.add( this.terminalWrapper );
|
||||
this.setFocused( this.terminalWrapper );
|
||||
return new WidgetTerminal(
|
||||
computer, x + BORDER + ComputerSidebar.WIDTH, y + BORDER,
|
||||
ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull MatrixStack stack, int mouseX, int mouseY, float partialTicks )
|
||||
public void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
this.renderBackground( stack );
|
||||
super.render( stack, mouseX, mouseY, partialTicks );
|
||||
this.drawMouseoverTooltip( stack, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawForeground( @Nonnull MatrixStack transform, int mouseX, int mouseY )
|
||||
{
|
||||
// Skip rendering labels.
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
|
||||
{
|
||||
// Draw term
|
||||
Identifier texture = this.family == ComputerFamily.ADVANCED ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL;
|
||||
this.terminal.draw( this.terminalWrapper.getX(), this.terminalWrapper.getY() );
|
||||
|
||||
// Draw border/inventory
|
||||
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
|
||||
this.client.getTextureManager()
|
||||
.bindTexture( texture );
|
||||
this.drawTexture( transform, this.x, this.y, 0, 0, this.backgroundWidth, this.backgroundHeight );
|
||||
boolean advanced = family == ComputerFamily.ADVANCED;
|
||||
RenderSystem.setShaderTexture( 0, advanced ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL );
|
||||
drawTexture( transform, x + ComputerSidebar.WIDTH, y, 0, 0, TEX_WIDTH, TEX_HEIGHT );
|
||||
|
||||
// Draw selection slot
|
||||
int slot = this.container.getSelectedSlot();
|
||||
int slot = getScreenHandler().getSelectedSlot();
|
||||
if( slot >= 0 )
|
||||
{
|
||||
int slotX = slot % 4;
|
||||
int slotY = slot / 4;
|
||||
this.drawTexture( transform, this.x + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, this.y + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18,
|
||||
drawTexture( transform, x + ContainerTurtle.TURTLE_START_X - 2 + slotX * 18, y + ContainerTurtle.PLAYER_START_Y - 2 + slotY * 18,
|
||||
0,
|
||||
217,
|
||||
24,
|
||||
24 );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
|
||||
{
|
||||
return (this.getFocused() != null && this.getFocused().mouseDragged( x, y, button, deltaX, deltaY )) || super.mouseDragged( x, y, button, deltaX, deltaY );
|
||||
}
|
||||
|
||||
@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 && this.getFocused() != null && this.getFocused() == this.terminalWrapper )
|
||||
{
|
||||
return this.getFocused().keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
return super.keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removed()
|
||||
{
|
||||
super.removed();
|
||||
this.children.remove( this.terminal );
|
||||
this.terminal = null;
|
||||
this.client.keyboard.setRepeatEvents( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tick()
|
||||
{
|
||||
super.tick();
|
||||
this.terminal.update();
|
||||
RenderSystem.setShaderTexture( 0, advanced ? ComputerBorderRenderer.BACKGROUND_ADVANCED : ComputerBorderRenderer.BACKGROUND_NORMAL );
|
||||
ComputerSidebar.renderBackground( transform, x, y + sidebarYOffset );
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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 dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.player.PlayerInventory;
|
||||
import net.minecraft.text.OrderedText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public class NoTermComputerScreen<T extends ContainerComputerBase> extends Screen implements ScreenHandlerProvider<T>
|
||||
{
|
||||
private final T menu;
|
||||
private WidgetTerminal terminal;
|
||||
|
||||
public NoTermComputerScreen( T menu, PlayerInventory player, Text title )
|
||||
{
|
||||
super( title );
|
||||
this.menu = menu;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public T getScreenHandler()
|
||||
{
|
||||
return menu;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init()
|
||||
{
|
||||
this.passEvents = true;
|
||||
client.mouse.lockCursor();
|
||||
client.currentScreen = this;
|
||||
super.init();
|
||||
client.keyboard.setRepeatEvents( true );
|
||||
|
||||
terminal = addSelectableChild( new WidgetTerminal( (ClientComputer) menu.getComputer(), 0, 0, ComputerCraft.pocketTermWidth, ComputerCraft.pocketTermHeight ) );
|
||||
terminal.visible = false;
|
||||
terminal.active = false;
|
||||
setFocused( terminal );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void removed()
|
||||
{
|
||||
super.removed();
|
||||
client.keyboard.setRepeatEvents( false );
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void tick()
|
||||
{
|
||||
super.tick();
|
||||
terminal.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean mouseScrolled( double pMouseX, double pMouseY, double pDelta )
|
||||
{
|
||||
client.player.getInventory().scrollInHotbar( pDelta );
|
||||
return super.mouseScrolled( pMouseX, pMouseY, pDelta );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
client.player.closeHandledScreen();
|
||||
super.onClose();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPauseScreen()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@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 void render( MatrixStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
super.render( transform, mouseX, mouseY, partialTicks );
|
||||
|
||||
TextRenderer font = client.textRenderer;
|
||||
List<OrderedText> lines = font.wrapLines( new TranslatableText( "gui.computercraft.pocket_computer_overlay" ), (int) (width * 0.8) );
|
||||
float y = 10.0f;
|
||||
for( OrderedText line : lines )
|
||||
{
|
||||
font.drawWithShadow( transform, line, (float) ((width / 2) - (client.textRenderer.getWidth( line ) / 2)), y, 0xFFFFFF );
|
||||
y += 9.0f;
|
||||
}
|
||||
}
|
||||
}
|
128
src/main/java/dan200/computercraft/client/gui/OptionScreen.java
Normal file
128
src/main/java/dan200/computercraft/client/gui/OptionScreen.java
Normal file
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.systems.RenderSystem;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.font.MultilineText;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
|
||||
public final class OptionScreen extends Screen
|
||||
{
|
||||
private static final Identifier BACKGROUND = new Identifier( "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 MultilineText messageRenderer;
|
||||
private final Text message;
|
||||
private final List<ClickableWidget> buttons;
|
||||
private final Runnable exit;
|
||||
|
||||
private final Screen originalScreen;
|
||||
|
||||
private OptionScreen( Text title, Text message, List<ClickableWidget> buttons, Runnable exit, Screen originalScreen )
|
||||
{
|
||||
super( title );
|
||||
this.message = message;
|
||||
this.buttons = buttons;
|
||||
this.exit = exit;
|
||||
this.originalScreen = originalScreen;
|
||||
}
|
||||
|
||||
public static void show( MinecraftClient client, Text title, Text message, List<ClickableWidget> buttons, Runnable exit )
|
||||
{
|
||||
client.setScreen( new OptionScreen( title, message, buttons, exit, unwrap( client.currentScreen ) ) );
|
||||
}
|
||||
|
||||
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 = MultilineText.create( textRenderer, message, innerWidth - PADDING * 2 );
|
||||
|
||||
int textHeight = messageRenderer.count() * 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( ClickableWidget button : buttons )
|
||||
{
|
||||
button.x = x;
|
||||
button.y = y + textHeight;
|
||||
addDrawableChild( button );
|
||||
|
||||
x += BUTTON_WIDTH + PADDING;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
renderBackground( transform );
|
||||
|
||||
// Render the actual texture.
|
||||
RenderSystem.setShaderTexture( 0, BACKGROUND );
|
||||
drawTexture( transform, x, y, 0, 0, innerWidth, PADDING );
|
||||
drawTexture( transform,
|
||||
x, y + PADDING, 0, PADDING, innerWidth, innerHeight - PADDING * 2,
|
||||
innerWidth, PADDING
|
||||
);
|
||||
drawTexture( transform, x, y + innerHeight - PADDING, 0, 256 - PADDING, innerWidth, PADDING );
|
||||
|
||||
messageRenderer.draw( transform, x + PADDING, y + PADDING, FONT_HEIGHT, 0x404040 );
|
||||
super.render( transform, mouseX, mouseY, partialTicks );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose()
|
||||
{
|
||||
exit.run();
|
||||
}
|
||||
|
||||
public static ClickableWidget newButton( Text component, ButtonWidget.PressAction clicked )
|
||||
{
|
||||
return new ButtonWidget( 0, 0, BUTTON_WIDTH, BUTTON_HEIGHT, component, clicked );
|
||||
}
|
||||
|
||||
public void disable()
|
||||
{
|
||||
for( ClickableWidget widget : buttons ) widget.active = false;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
public Screen getOriginalScreen()
|
||||
{
|
||||
return originalScreen;
|
||||
}
|
||||
}
|
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* 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 dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.render.ComputerBorderRenderer;
|
||||
import dan200.computercraft.shared.command.text.ChatHelpers;
|
||||
import dan200.computercraft.shared.computer.core.ClientComputer;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.TranslatableText;
|
||||
import net.minecraft.util.Formatting;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Registers buttons to interact with a computer.
|
||||
*/
|
||||
public final class ComputerSidebar
|
||||
{
|
||||
private static final Identifier TEXTURE = new Identifier( 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<ClickableWidget> 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 TranslatableText( "gui.computercraft.tooltip.turn_off" ),
|
||||
ChatHelpers.coloured( new TranslatableText( "gui.computercraft.tooltip.turn_off.key" ), Formatting.GRAY )
|
||||
) : Arrays.asList(
|
||||
new TranslatableText( "gui.computercraft.tooltip.turn_on" ),
|
||||
ChatHelpers.coloured( new TranslatableText( "gui.computercraft.tooltip.turn_off.key" ), Formatting.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 TranslatableText( "gui.computercraft.tooltip.terminate" ),
|
||||
ChatHelpers.coloured( new TranslatableText( "gui.computercraft.tooltip.terminate.key" ), Formatting.GRAY )
|
||||
)
|
||||
) );
|
||||
}
|
||||
|
||||
public static void renderBackground( MatrixStack transform, int x, int y )
|
||||
{
|
||||
Screen.drawTexture( transform,
|
||||
x, y, 0, 102, WIDTH, FULL_BORDER,
|
||||
ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
|
||||
);
|
||||
|
||||
Screen.drawTexture( transform,
|
||||
x, y + FULL_BORDER, WIDTH, HEIGHT - FULL_BORDER * 2,
|
||||
0, 107, WIDTH, 4,
|
||||
ComputerBorderRenderer.TEX_SIZE, ComputerBorderRenderer.TEX_SIZE
|
||||
);
|
||||
|
||||
Screen.drawTexture( 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,100 @@
|
||||
/*
|
||||
* 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.systems.RenderSystem;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.function.IntSupplier;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
* Version of {@link net.minecraft.client.gui.widget.TexturedButtonWidget} which allows changing some properties
|
||||
* dynamically.
|
||||
*/
|
||||
public class DynamicImageButton extends ButtonWidget
|
||||
{
|
||||
private final Screen screen;
|
||||
private final Identifier texture;
|
||||
private final IntSupplier xTexStart;
|
||||
private final int yTexStart;
|
||||
private final int yDiffTex;
|
||||
private final int textureWidth;
|
||||
private final int textureHeight;
|
||||
private final Supplier<List<Text>> tooltip;
|
||||
|
||||
public DynamicImageButton(
|
||||
Screen screen, int x, int y, int width, int height, int xTexStart, int yTexStart, int yDiffTex,
|
||||
Identifier texture, int textureWidth, int textureHeight,
|
||||
PressAction onPress, List<Text> 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,
|
||||
Identifier texture, int textureWidth, int textureHeight,
|
||||
PressAction onPress, Supplier<List<Text>> tooltip
|
||||
)
|
||||
{
|
||||
super( x, y, width, height, LiteralText.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 )
|
||||
{
|
||||
RenderSystem.setShaderTexture( 0, texture );
|
||||
RenderSystem.disableDepthTest();
|
||||
|
||||
int yTex = yTexStart;
|
||||
if( isHovered() ) yTex += yDiffTex;
|
||||
|
||||
drawTexture( stack, x, y, xTexStart.getAsInt(), yTex, width, height, textureWidth, textureHeight );
|
||||
RenderSystem.enableDepthTest();
|
||||
|
||||
if( isHovered() ) renderToolTip( stack, mouseX, mouseY );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public Text getMessage()
|
||||
{
|
||||
List<Text> tooltip = this.tooltip.get();
|
||||
return tooltip.isEmpty() ? LiteralText.EMPTY : tooltip.get( 0 );
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void renderToolTip( @Nonnull MatrixStack stack, int mouseX, int mouseY )
|
||||
{
|
||||
List<Text> tooltip = this.tooltip.get();
|
||||
|
||||
if( !tooltip.isEmpty() )
|
||||
{
|
||||
screen.renderTooltip( stack, tooltip, mouseX, mouseY );
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,74 +9,92 @@ package dan200.computercraft.client.gui.widgets;
|
||||
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.SharedConstants;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder;
|
||||
import net.minecraft.client.gui.widget.ClickableWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.LiteralText;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
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 Element
|
||||
public class WidgetTerminal extends ClickableWidget
|
||||
{
|
||||
private static final float TERMINATE_TIME = 0.5f;
|
||||
|
||||
private final MinecraftClient client;
|
||||
private final Supplier<ClientComputer> computer;
|
||||
private final int termWidth;
|
||||
private final int termHeight;
|
||||
private final int leftMargin;
|
||||
private final int rightMargin;
|
||||
private final int topMargin;
|
||||
private final int bottomMargin;
|
||||
private final BitSet keysDown = new BitSet( 256 );
|
||||
private boolean focused;
|
||||
private final ClientComputer computer;
|
||||
|
||||
// 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;
|
||||
private float shutdownTimer = -1;
|
||||
|
||||
private int lastMouseButton = -1;
|
||||
private int lastMouseX = -1;
|
||||
private int lastMouseY = -1;
|
||||
|
||||
public WidgetTerminal( MinecraftClient client, Supplier<ClientComputer> computer, int termWidth, int termHeight, int leftMargin, int rightMargin,
|
||||
int topMargin, int bottomMargin )
|
||||
private final BitSet keysDown = new BitSet( 256 );
|
||||
|
||||
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, LiteralText.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
|
||||
public boolean charTyped( char ch, int modifiers )
|
||||
{
|
||||
if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range
|
||||
{
|
||||
// Queue the "char" event
|
||||
queueEvent( "char", Character.toString( ch ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean inTermRegion( double mouseX, double mouseY )
|
||||
{
|
||||
return active && visible && mouseX >= innerX && mouseY >= innerY && mouseX < innerX + innerWidth && mouseY < innerY + innerHeight;
|
||||
}
|
||||
|
||||
@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 );
|
||||
|
||||
computer.mouseClick( button + 1, charX + 1, charY + 1 );
|
||||
|
||||
this.lastMouseButton = button;
|
||||
this.lastMouseX = charX;
|
||||
this.lastMouseY = charY;
|
||||
lastMouseButton = button;
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -85,28 +103,25 @@ public class WidgetTerminal implements Element
|
||||
@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 );
|
||||
|
||||
if( this.lastMouseButton == button )
|
||||
if( lastMouseButton == button )
|
||||
{
|
||||
computer.mouseUp( this.lastMouseButton + 1, charX + 1, charY + 1 );
|
||||
this.lastMouseButton = -1;
|
||||
computer.mouseUp( lastMouseButton + 1, charX + 1, charY + 1 );
|
||||
lastMouseButton = -1;
|
||||
}
|
||||
|
||||
this.lastMouseX = charX;
|
||||
this.lastMouseY = charY;
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -115,25 +130,22 @@ public class WidgetTerminal implements Element
|
||||
@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 );
|
||||
|
||||
if( button == this.lastMouseButton && (charX != this.lastMouseX || charY != this.lastMouseY) )
|
||||
if( button == lastMouseButton && (charX != lastMouseX || charY != lastMouseY) )
|
||||
{
|
||||
computer.mouseDrag( button + 1, charX + 1, charY + 1 );
|
||||
this.lastMouseX = charX;
|
||||
this.lastMouseY = charY;
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,24 +155,21 @@ public class WidgetTerminal implements Element
|
||||
@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 );
|
||||
|
||||
computer.mouseScroll( delta < 0 ? 1 : -1, charX + 1, charY + 1 );
|
||||
|
||||
this.lastMouseX = charX;
|
||||
this.lastMouseY = charY;
|
||||
lastMouseX = charX;
|
||||
lastMouseY = charY;
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -178,27 +187,27 @@ public class WidgetTerminal implements Element
|
||||
switch( key )
|
||||
{
|
||||
case GLFW.GLFW_KEY_T:
|
||||
if( this.terminateTimer < 0 )
|
||||
if( terminateTimer < 0 )
|
||||
{
|
||||
this.terminateTimer = 0;
|
||||
terminateTimer = 0;
|
||||
}
|
||||
return true;
|
||||
case GLFW.GLFW_KEY_S:
|
||||
if( this.shutdownTimer < 0 )
|
||||
if( shutdownTimer < 0 )
|
||||
{
|
||||
this.shutdownTimer = 0;
|
||||
shutdownTimer = 0;
|
||||
}
|
||||
return true;
|
||||
case GLFW.GLFW_KEY_R:
|
||||
if( this.rebootTimer < 0 )
|
||||
if( rebootTimer < 0 )
|
||||
{
|
||||
this.rebootTimer = 0;
|
||||
rebootTimer = 0;
|
||||
}
|
||||
return true;
|
||||
|
||||
case GLFW.GLFW_KEY_V:
|
||||
// Ctrl+V for paste
|
||||
String clipboard = this.client.keyboard.getClipboard();
|
||||
String clipboard = MinecraftClient.getInstance().keyboard.getClipboard();
|
||||
if( clipboard != null )
|
||||
{
|
||||
// Clip to the first occurrence of \r or \n
|
||||
@@ -226,7 +235,7 @@ public class WidgetTerminal implements Element
|
||||
{
|
||||
clipboard = clipboard.substring( 0, 512 );
|
||||
}
|
||||
this.queueEvent( "paste", clipboard );
|
||||
queueEvent( "paste", clipboard );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -234,16 +243,12 @@ public class WidgetTerminal implements Element
|
||||
}
|
||||
}
|
||||
|
||||
if( key >= 0 && this.terminateTimer < 0 && this.rebootTimer < 0 && this.shutdownTimer < 0 )
|
||||
if( key >= 0 && terminateTimer < 0 && rebootTimer < 0 && shutdownTimer < 0 )
|
||||
{
|
||||
// Queue the "key" event and add to the down set
|
||||
boolean repeat = this.keysDown.get( key );
|
||||
this.keysDown.set( key );
|
||||
IComputer computer = this.computer.get();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.keyDown( key, repeat );
|
||||
}
|
||||
boolean repeat = keysDown.get( key );
|
||||
keysDown.set( key );
|
||||
computer.keyDown( key, repeat );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -253,30 +258,26 @@ public class WidgetTerminal implements Element
|
||||
public boolean keyReleased( int key, int scancode, int modifiers )
|
||||
{
|
||||
// Queue the "key_up" event and remove from the down set
|
||||
if( key >= 0 && this.keysDown.get( key ) )
|
||||
if( key >= 0 && keysDown.get( key ) )
|
||||
{
|
||||
this.keysDown.set( key, false );
|
||||
IComputer computer = this.computer.get();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.keyUp( key );
|
||||
}
|
||||
keysDown.set( key, false );
|
||||
computer.keyUp( key );
|
||||
}
|
||||
|
||||
switch( key )
|
||||
{
|
||||
case GLFW.GLFW_KEY_T:
|
||||
this.terminateTimer = -1;
|
||||
terminateTimer = -1;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_R:
|
||||
this.rebootTimer = -1;
|
||||
rebootTimer = -1;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_S:
|
||||
this.shutdownTimer = -1;
|
||||
shutdownTimer = -1;
|
||||
break;
|
||||
case GLFW.GLFW_KEY_LEFT_CONTROL:
|
||||
case GLFW.GLFW_KEY_RIGHT_CONTROL:
|
||||
this.terminateTimer = this.rebootTimer = this.shutdownTimer = -1;
|
||||
terminateTimer = rebootTimer = shutdownTimer = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -284,47 +285,26 @@ public class WidgetTerminal implements Element
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped( char ch, int modifiers )
|
||||
public void onFocusedChanged( boolean focused )
|
||||
{
|
||||
if( ch >= 32 && ch <= 126 || ch >= 160 && ch <= 255 ) // printable chars in byte range
|
||||
{
|
||||
// Queue the "char" event
|
||||
this.queueEvent( "char", Character.toString( ch ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeFocus( boolean reversed )
|
||||
{
|
||||
if( this.focused )
|
||||
if( !focused )
|
||||
{
|
||||
// When blurring, we should make all keys go up
|
||||
for( int key = 0; key < this.keysDown.size(); key++ )
|
||||
for( int key = 0; key < keysDown.size(); key++ )
|
||||
{
|
||||
if( this.keysDown.get( key ) )
|
||||
{
|
||||
this.queueEvent( "key_up", key );
|
||||
}
|
||||
if( keysDown.get( key ) ) computer.keyUp( key );
|
||||
}
|
||||
this.keysDown.clear();
|
||||
keysDown.clear();
|
||||
|
||||
// When blurring, we should make the last mouse button go up
|
||||
if( this.lastMouseButton > 0 )
|
||||
if( lastMouseButton > 0 )
|
||||
{
|
||||
IComputer computer = this.computer.get();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.mouseUp( this.lastMouseButton + 1, this.lastMouseX + 1, this.lastMouseY + 1 );
|
||||
}
|
||||
this.lastMouseButton = -1;
|
||||
computer.mouseUp( lastMouseButton + 1, lastMouseX + 1, lastMouseY + 1 );
|
||||
lastMouseButton = -1;
|
||||
}
|
||||
|
||||
this.shutdownTimer = this.terminateTimer = this.rebootTimer = -1;
|
||||
shutdownTimer = terminateTimer = rebootTimer = -1;
|
||||
}
|
||||
this.focused = !this.focused;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -335,66 +315,65 @@ public class WidgetTerminal implements Element
|
||||
|
||||
private void queueEvent( String event, Object... args )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.queueEvent( event, args );
|
||||
}
|
||||
computer.queueEvent( event, args );
|
||||
}
|
||||
|
||||
public void update()
|
||||
{
|
||||
if( this.terminateTimer >= 0 && this.terminateTimer < TERMINATE_TIME && (this.terminateTimer += 0.05f) > TERMINATE_TIME )
|
||||
if( terminateTimer >= 0 && terminateTimer < TERMINATE_TIME && (terminateTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
this.queueEvent( "terminate" );
|
||||
queueEvent( "terminate" );
|
||||
}
|
||||
|
||||
if( this.shutdownTimer >= 0 && this.shutdownTimer < TERMINATE_TIME && (this.shutdownTimer += 0.05f) > TERMINATE_TIME )
|
||||
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.shutdown();
|
||||
}
|
||||
computer.shutdown();
|
||||
}
|
||||
|
||||
if( this.rebootTimer >= 0 && this.rebootTimer < TERMINATE_TIME && (this.rebootTimer += 0.05f) > TERMINATE_TIME )
|
||||
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
if( computer != null )
|
||||
{
|
||||
computer.reboot();
|
||||
}
|
||||
computer.reboot();
|
||||
}
|
||||
}
|
||||
|
||||
private void queueEvent( String event )
|
||||
{
|
||||
ClientComputer computer = this.computer.get();
|
||||
ClientComputer computer = this.computer;
|
||||
if( computer != null )
|
||||
{
|
||||
computer.queueEvent( event );
|
||||
}
|
||||
}
|
||||
|
||||
public void draw( int originX, int originY )
|
||||
@Override
|
||||
public void render( @Nonnull MatrixStack transform, int mouseX, int mouseY, float partialTicks )
|
||||
{
|
||||
synchronized( this.computer )
|
||||
if( !visible ) return;
|
||||
Matrix4f matrix = transform.peek().getModel();
|
||||
Terminal terminal = computer.getTerminal();
|
||||
if( terminal != null )
|
||||
{
|
||||
// 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(), this.topMargin, this.bottomMargin, this.leftMargin,
|
||||
this.rightMargin );
|
||||
}
|
||||
else
|
||||
{
|
||||
FixedWidthFontRenderer.drawEmptyTerminal( originX - this.leftMargin,
|
||||
originY - this.rightMargin, this.termWidth * FONT_WIDTH + this.leftMargin + this.rightMargin,
|
||||
this.termHeight * FONT_HEIGHT + this.topMargin + this.bottomMargin );
|
||||
}
|
||||
FixedWidthFontRenderer.drawTerminal( matrix, innerX, innerY, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN );
|
||||
}
|
||||
else
|
||||
{
|
||||
FixedWidthFontRenderer.drawEmptyTerminal( matrix, x, y, width, height );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendNarrations( NarrationMessageBuilder builder )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
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,106 +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.Element;
|
||||
|
||||
public class WidgetWrapper implements Element
|
||||
{
|
||||
private final Element listener;
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int width;
|
||||
private final int height;
|
||||
|
||||
public WidgetWrapper( Element 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 mouseClicked( double x, double y, int button )
|
||||
{
|
||||
double dx = x - this.x, dy = y - this.y;
|
||||
return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height && this.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 < this.width && dy >= 0 && dy < this.height && this.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 < this.width && dy >= 0 && dy < this.height && this.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 < this.width && dy >= 0 && dy < this.height && this.listener.mouseScrolled( dx, dy, delta );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyPressed( int key, int scancode, int modifiers )
|
||||
{
|
||||
return this.listener.keyPressed( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean keyReleased( int key, int scancode, int modifiers )
|
||||
{
|
||||
return this.listener.keyReleased( key, scancode, modifiers );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean charTyped( char character, int modifiers )
|
||||
{
|
||||
return this.listener.charTyped( character, modifiers );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean changeFocus( boolean b )
|
||||
{
|
||||
return this.listener.changeFocus( b );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMouseOver( double x, double y )
|
||||
{
|
||||
double dx = x - this.x, dy = y - this.y;
|
||||
return dx >= 0 && dx < this.width && dy >= 0 && dy < this.height;
|
||||
}
|
||||
|
||||
public int getX()
|
||||
{
|
||||
return this.x;
|
||||
}
|
||||
|
||||
public int getY()
|
||||
{
|
||||
return this.y;
|
||||
}
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return this.width;
|
||||
}
|
||||
|
||||
public int getHeight()
|
||||
{
|
||||
return this.height;
|
||||
}
|
||||
}
|
@@ -19,12 +19,11 @@ import dan200.computercraft.shared.ComputerCraftRegistry;
|
||||
import dan200.computercraft.shared.common.ContainerHeldItem;
|
||||
import dan200.computercraft.shared.common.IColouredItem;
|
||||
import dan200.computercraft.shared.common.TileGeneric;
|
||||
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.peripheral.diskdrive.ContainerDiskDrive;
|
||||
import dan200.computercraft.shared.peripheral.monitor.ClientMonitor;
|
||||
import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
|
||||
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
|
||||
import dan200.computercraft.shared.util.Config;
|
||||
@@ -35,12 +34,12 @@ import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientBlockEntityEvents;
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents;
|
||||
import net.fabricmc.fabric.api.client.model.ModelLoadingRegistry;
|
||||
import net.fabricmc.fabric.api.client.rendereregistry.v1.BlockEntityRendererRegistry;
|
||||
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.BlockEntityRendererRegistry;
|
||||
import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry;
|
||||
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
|
||||
import net.fabricmc.fabric.api.event.client.ClientSpriteRegistryCallback;
|
||||
import net.fabricmc.fabric.mixin.object.builder.ModelPredicateProviderRegistrySpecificAccessor;
|
||||
import net.minecraft.client.item.ModelPredicateProvider;
|
||||
import net.fabricmc.fabric.api.object.builder.v1.client.model.FabricModelPredicateProviderRegistry;
|
||||
import net.minecraft.client.item.UnclampedModelPredicateProvider;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.screen.PlayerScreenHandler;
|
||||
@@ -76,33 +75,32 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
// While turtles themselves are not transparent, their upgrades may be.
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_NORMAL, RenderLayer.getTranslucent() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.TURTLE_ADVANCED, RenderLayer.getTranslucent() );
|
||||
|
||||
// Monitors' textures have transparent fronts and so count as cutouts.
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_NORMAL, RenderLayer.getCutout() );
|
||||
BlockRenderLayerMap.INSTANCE.putBlock( ComputerCraftRegistry.ModBlocks.MONITOR_ADVANCED, RenderLayer.getCutout() );
|
||||
|
||||
// Setup TESRs
|
||||
BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new );
|
||||
BlockEntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new );
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.MONITOR_NORMAL, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.MONITOR_ADVANCED, TileEntityMonitorRenderer::new );
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.TURTLE_NORMAL, TileEntityTurtleRenderer::new );
|
||||
BlockEntityRendererRegistry.register( ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED, TileEntityTurtleRenderer::new );
|
||||
|
||||
ClientSpriteRegistryCallback.event( PlayerScreenHandler.BLOCK_ATLAS_TEXTURE )
|
||||
.register( ClientRegistry::onTextureStitchEvent );
|
||||
ModelLoadingRegistry.INSTANCE.registerAppender( ClientRegistry::onModelBakeEvent );
|
||||
ModelLoadingRegistry.INSTANCE.registerModelProvider( ClientRegistry::onModelBakeEvent );
|
||||
ModelLoadingRegistry.INSTANCE.registerResourceProvider( loader -> ( name, context ) -> TurtleModelLoader.INSTANCE.accepts( name ) ?
|
||||
TurtleModelLoader.INSTANCE.loadModel(
|
||||
name ) : null );
|
||||
|
||||
EntityRendererRegistry.INSTANCE.register( ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new );
|
||||
EntityRendererRegistry.register( ComputerCraftRegistry.ModEntities.TURTLE_PLAYER, TurtlePlayerRenderer::new );
|
||||
|
||||
registerItemProperty( "state",
|
||||
( stack, world, player ) -> ItemPocketComputer.getState( stack )
|
||||
( stack, world, player, integer ) -> ItemPocketComputer.getState( stack )
|
||||
.ordinal(),
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
registerItemProperty( "state",
|
||||
( stack, world, player ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0,
|
||||
( stack, world, player, integer ) -> IColouredItem.getColourBasic( stack ) != -1 ? 1 : 0,
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_NORMAL,
|
||||
() -> ComputerCraftRegistry.ModItems.POCKET_COMPUTER_ADVANCED );
|
||||
ClientRegistry.onItemColours();
|
||||
@@ -113,9 +111,11 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
// My IDE doesn't think so, but we do actually need these generics.
|
||||
private static void registerContainers()
|
||||
{
|
||||
ScreenRegistry.<ContainerComputer, GuiComputer<ContainerComputer>>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create );
|
||||
ScreenRegistry.<ContainerPocketComputer, GuiComputer<ContainerPocketComputer>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER,
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.COMPUTER, GuiComputer::create );
|
||||
ScreenRegistry.<ContainerComputerBase, GuiComputer<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER,
|
||||
GuiComputer::createPocket );
|
||||
ScreenRegistry.<ContainerComputerBase, NoTermComputerScreen<ContainerComputerBase>>register( ComputerCraftRegistry.ModContainers.POCKET_COMPUTER_NO_TERM,
|
||||
NoTermComputerScreen::new );
|
||||
ScreenRegistry.<ContainerTurtle, GuiTurtle>register( ComputerCraftRegistry.ModContainers.TURTLE, GuiTurtle::new );
|
||||
|
||||
ScreenRegistry.<ContainerPrinter, GuiPrinter>register( ComputerCraftRegistry.ModContainers.PRINTER, GuiPrinter::new );
|
||||
@@ -127,12 +127,12 @@ public final class ComputerCraftProxyClient implements ClientModInitializer
|
||||
}
|
||||
|
||||
@SafeVarargs
|
||||
private static void registerItemProperty( String name, ModelPredicateProvider getter, Supplier<? extends Item>... items )
|
||||
private static void registerItemProperty( String name, UnclampedModelPredicateProvider getter, Supplier<? extends Item>... items )
|
||||
{
|
||||
Identifier id = new Identifier( ComputerCraft.MOD_ID, name );
|
||||
for( Supplier<? extends Item> item : items )
|
||||
{
|
||||
ModelPredicateProviderRegistrySpecificAccessor.callRegister( item.get(), id, getter );
|
||||
FabricModelPredicateProviderRegistry.register( item.get(), id, getter );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,9 +18,8 @@ import net.minecraft.client.render.Camera;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.util.shape.VoxelShape;
|
||||
|
||||
@Environment( EnvType.CLIENT )
|
||||
@@ -42,24 +41,40 @@ public final class CableHighlightRenderer
|
||||
return false;
|
||||
}
|
||||
|
||||
HitResult hitResult = MinecraftClient.getInstance().crosshairTarget;
|
||||
|
||||
Vec3d hitPos = hitResult != null ? hitResult.getPos() : new Vec3d( d, e, f );
|
||||
|
||||
VoxelShape shape = WorldUtil.isVecInside( CableShapes.getModemShape( state ),
|
||||
new Vec3d( d, e, f ).subtract( pos.getX(),
|
||||
hitPos.subtract( pos.getX(),
|
||||
pos.getY(),
|
||||
pos.getZ() ) ) ? CableShapes.getModemShape( state ) : CableShapes.getCableShape(
|
||||
state );
|
||||
|
||||
Vec3d cameraPos = info.getPos();
|
||||
|
||||
double xOffset = pos.getX() - cameraPos.getX();
|
||||
double yOffset = pos.getY() - cameraPos.getY();
|
||||
double zOffset = pos.getZ() - cameraPos.getZ();
|
||||
Matrix4f matrix4f = stack.peek()
|
||||
.getModel();
|
||||
Matrix3f normal = stack.peek().getNormal();
|
||||
shape.forEachEdge( ( x1, y1, z1, x2, y2, z2 ) -> {
|
||||
float xDelta = (float) (x2 - x1);
|
||||
float yDelta = (float) (y2 - y1);
|
||||
float zDelta = (float) (z2 - z1);
|
||||
float len = MathHelper.sqrt( xDelta * xDelta + yDelta * yDelta + zDelta * zDelta );
|
||||
xDelta = xDelta / len;
|
||||
yDelta = yDelta / len;
|
||||
zDelta = zDelta / len;
|
||||
|
||||
consumer.vertex( matrix4f, (float) (x1 + xOffset), (float) (y1 + yOffset), (float) (z1 + zOffset) )
|
||||
.color( 0, 0, 0, 0.4f )
|
||||
.normal( normal, xDelta, yDelta, zDelta )
|
||||
.next();
|
||||
consumer.vertex( matrix4f, (float) (x2 + xOffset), (float) (y2 + yOffset), (float) (z2 + zOffset) )
|
||||
.color( 0, 0, 0, 0.4f )
|
||||
.normal( normal, xDelta, yDelta, zDelta )
|
||||
.next();
|
||||
} );
|
||||
|
||||
|
@@ -5,16 +5,14 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
import net.minecraft.client.render.Tessellator;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
@@ -42,7 +40,8 @@ public class ComputerBorderRenderer
|
||||
private static final int LIGHT_CORNER_Y = 80;
|
||||
|
||||
public static final int LIGHT_HEIGHT = 8;
|
||||
private static final float TEX_SCALE = 1 / 256.0f;
|
||||
public static final int TEX_SIZE = 256;
|
||||
private static final float TEX_SCALE = 1 / (float) TEX_SIZE;
|
||||
|
||||
static
|
||||
{
|
||||
@@ -54,11 +53,14 @@ public class ComputerBorderRenderer
|
||||
private final int z;
|
||||
private final float r, g, b;
|
||||
|
||||
public ComputerBorderRenderer( Matrix4f transform, VertexConsumer builder, int z, float r, float g, float b )
|
||||
private final int light;
|
||||
|
||||
public ComputerBorderRenderer( Matrix4f transform, VertexConsumer builder, int z, int light, float r, float g, float b )
|
||||
{
|
||||
this.transform = transform;
|
||||
this.builder = builder;
|
||||
this.z = z;
|
||||
this.light = light;
|
||||
this.r = r;
|
||||
this.g = g;
|
||||
this.b = b;
|
||||
@@ -80,31 +82,17 @@ public class ComputerBorderRenderer
|
||||
}
|
||||
}
|
||||
|
||||
public static void render( int x, int y, int z, int width, int height )
|
||||
public static void render( Identifier location, int x, int y, int z, int light, int width, int height )
|
||||
{
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE );
|
||||
|
||||
render( IDENTITY, buffer, x, y, z, width, height );
|
||||
|
||||
RenderSystem.enableAlphaTest();
|
||||
tessellator.draw();
|
||||
VertexConsumerProvider.Immediate source = VertexConsumerProvider.immediate( Tessellator.getInstance().getBuffer() );
|
||||
render( IDENTITY, source.getBuffer( RenderLayer.getText( location ) ), x, y, z, light, width, height, false, 1, 1, 1 );
|
||||
source.draw();
|
||||
}
|
||||
|
||||
public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height )
|
||||
{
|
||||
render( transform, buffer, x, y, z, width, height, 1, 1, 1 );
|
||||
}
|
||||
|
||||
public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int width, int height, float r, float g, float b )
|
||||
public static void render( Matrix4f transform, VertexConsumer buffer, int x, int y, int z, int light, int width, int height, boolean withLight, float r, float g, float b )
|
||||
{
|
||||
render( transform, buffer, x, y, z, width, height, false, r, g, b );
|
||||
}
|
||||
|
||||
public static void render( Matrix4f transform, VertexConsumer 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, withLight );
|
||||
new ComputerBorderRenderer( transform, buffer, z, light, r, g, b ).doRender( x, y, width, height, withLight );
|
||||
}
|
||||
|
||||
public void doRender( int x, int y, int width, int height, boolean withLight )
|
||||
@@ -113,13 +101,13 @@ public class ComputerBorderRenderer
|
||||
int endY = y + height;
|
||||
|
||||
// Vertical bars
|
||||
this.renderLine( x - BORDER, y, 0, CORNER_TOP_Y, BORDER, endY - y );
|
||||
this.renderLine( endX, y, BORDER_RIGHT_X, CORNER_TOP_Y, BORDER, endY - y );
|
||||
renderLine( x - BORDER, y, 0, CORNER_TOP_Y, BORDER, endY - y );
|
||||
renderLine( endX, y, BORDER_RIGHT_X, CORNER_TOP_Y, BORDER, endY - y );
|
||||
|
||||
// Top bar
|
||||
this.renderLine( x, y - BORDER, 0, 0, endX - x, BORDER );
|
||||
this.renderCorner( x - BORDER, y - BORDER, CORNER_LEFT_X, CORNER_TOP_Y );
|
||||
this.renderCorner( endX, y - BORDER, CORNER_RIGHT_X, CORNER_TOP_Y );
|
||||
renderLine( x, y - BORDER, 0, 0, endX - x, BORDER );
|
||||
renderCorner( x - BORDER, y - BORDER, CORNER_LEFT_X, CORNER_TOP_Y );
|
||||
renderCorner( endX, y - BORDER, CORNER_RIGHT_X, CORNER_TOP_Y );
|
||||
|
||||
// Bottom bar. We allow for drawing a stretched version, which allows for additional elements (such as the
|
||||
// pocket computer's lights).
|
||||
@@ -131,44 +119,48 @@ public class ComputerBorderRenderer
|
||||
}
|
||||
else
|
||||
{
|
||||
this.renderLine( x, endY, 0, BORDER, endX - x, BORDER );
|
||||
this.renderCorner( x - BORDER, endY, CORNER_LEFT_X, CORNER_BOTTOM_Y );
|
||||
this.renderCorner( endX, endY, CORNER_RIGHT_X, CORNER_BOTTOM_Y );
|
||||
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 );
|
||||
}
|
||||
}
|
||||
|
||||
private void renderLine( int x, int y, int u, int v, int width, int height )
|
||||
{
|
||||
this.renderTexture( x, y, u, v, width, height, BORDER, BORDER );
|
||||
renderTexture( x, y, u, v, width, height, BORDER, BORDER );
|
||||
}
|
||||
|
||||
private void renderCorner( int x, int y, int u, int v )
|
||||
{
|
||||
this.renderTexture( x, y, u, v, BORDER, BORDER, BORDER, BORDER );
|
||||
renderTexture( x, y, u, v, BORDER, BORDER, BORDER, BORDER );
|
||||
}
|
||||
|
||||
private void renderTexture( int x, int y, int u, int v, int width, int height )
|
||||
{
|
||||
this.renderTexture( x, y, u, v, width, height, width, height );
|
||||
renderTexture( x, y, u, v, width, height, width, height );
|
||||
}
|
||||
|
||||
private void renderTexture( int x, int y, int u, int v, int width, int height, int textureWidth, int textureHeight )
|
||||
{
|
||||
this.builder.vertex( this.transform, x, y + height, this.z )
|
||||
.color( this.r, this.g, this.b, 1.0f )
|
||||
builder.vertex( transform, x, y + height, z )
|
||||
.color( r, g, b, 1.0f )
|
||||
.texture( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE )
|
||||
.light( light )
|
||||
.next();
|
||||
this.builder.vertex( this.transform, x + width, y + height, this.z )
|
||||
.color( this.r, this.g, this.b, 1.0f )
|
||||
builder.vertex( transform, x + width, y + height, z )
|
||||
.color( r, g, b, 1.0f )
|
||||
.texture( (u + textureWidth) * TEX_SCALE, (v + textureHeight) * TEX_SCALE )
|
||||
.light( light )
|
||||
.next();
|
||||
this.builder.vertex( this.transform, x + width, y, this.z )
|
||||
.color( this.r, this.g, this.b, 1.0f )
|
||||
builder.vertex( transform, x + width, y, z )
|
||||
.color( r, g, b, 1.0f )
|
||||
.texture( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE )
|
||||
.light( light )
|
||||
.next();
|
||||
this.builder.vertex( this.transform, x, y, this.z )
|
||||
.color( this.r, this.g, this.b, 1.0f )
|
||||
builder.vertex( transform, x, y, z )
|
||||
.color( r, g, b, 1.0f )
|
||||
.texture( u * TEX_SCALE, v * TEX_SCALE )
|
||||
.light( light )
|
||||
.next();
|
||||
}
|
||||
}
|
||||
|
@@ -13,12 +13,12 @@ import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.item.HeldItemRenderer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Arm;
|
||||
import net.minecraft.util.Hand;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
|
||||
@Environment( EnvType.CLIENT )
|
||||
public abstract class ItemMapLikeRenderer
|
||||
@@ -33,11 +33,11 @@ public abstract class ItemMapLikeRenderer
|
||||
transform.push();
|
||||
if( hand == Hand.MAIN_HAND && player.getOffHandStack().isEmpty() )
|
||||
{
|
||||
this.renderItemFirstPersonCenter( transform, render, lightTexture, pitch, equipProgress, swingProgress, stack );
|
||||
renderItemFirstPersonCenter( transform, render, lightTexture, pitch, equipProgress, swingProgress, stack );
|
||||
}
|
||||
else
|
||||
{
|
||||
this.renderItemFirstPersonSide( transform,
|
||||
renderItemFirstPersonSide( transform,
|
||||
render,
|
||||
lightTexture,
|
||||
hand == Hand.MAIN_HAND ? player.getMainArm() : player.getMainArm().getOpposite(),
|
||||
@@ -75,21 +75,21 @@ public abstract class ItemMapLikeRenderer
|
||||
HeldItemRendererAccess access = (HeldItemRendererAccess) renderer;
|
||||
float pitchAngle = access.callGetMapAngle( pitch );
|
||||
transform.translate( 0, 0.04F + equipProgress * -1.2f + pitchAngle * -0.5f, -0.72f );
|
||||
transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( pitchAngle * -85.0f ) );
|
||||
transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( pitchAngle * -85.0f ) );
|
||||
if( !minecraft.player.isInvisible() )
|
||||
{
|
||||
transform.push();
|
||||
transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( 90.0F ) );
|
||||
transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 90.0F ) );
|
||||
access.callRenderArm( transform, render, combinedLight, Arm.RIGHT );
|
||||
access.callRenderArm( transform, render, combinedLight, Arm.LEFT );
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
float rX = MathHelper.sin( swingRt * (float) Math.PI );
|
||||
transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( rX * 20.0F ) );
|
||||
transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( rX * 20.0F ) );
|
||||
transform.scale( 2.0F, 2.0F, 2.0F );
|
||||
|
||||
this.renderItem( transform, render, stack );
|
||||
renderItem( transform, render, stack, combinedLight );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,7 +114,7 @@ public abstract class ItemMapLikeRenderer
|
||||
if( !minecraft.player.isInvisible() )
|
||||
{
|
||||
transform.push();
|
||||
transform.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( offset * 10f ) );
|
||||
transform.multiply( Vec3f.POSITIVE_Z.getDegreesQuaternion( offset * 10f ) );
|
||||
((HeldItemRendererAccess) minecraft.getHeldItemRenderer())
|
||||
.callRenderArmHoldingItem( transform, render, combinedLight, equipProgress, swingProgress, side );
|
||||
transform.pop();
|
||||
@@ -130,10 +130,10 @@ public abstract class ItemMapLikeRenderer
|
||||
float f4 = 0.4f * MathHelper.sin( f1 * ((float) Math.PI * 2f) );
|
||||
float f5 = -0.3f * MathHelper.sin( swingProgress * (float) Math.PI );
|
||||
transform.translate( offset * f3, f4 - 0.3f * f2, f5 );
|
||||
transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( f2 * -45f ) );
|
||||
transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( offset * f2 * -30f ) );
|
||||
transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( f2 * -45f ) );
|
||||
transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( offset * f2 * -30f ) );
|
||||
|
||||
this.renderItem( transform, render, stack );
|
||||
renderItem( transform, render, stack, combinedLight );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
@@ -144,6 +144,7 @@ public abstract class ItemMapLikeRenderer
|
||||
* @param transform The matrix transformation stack
|
||||
* @param render The buffer to render to
|
||||
* @param stack The stack to render
|
||||
* @param light TODO rebase
|
||||
*/
|
||||
protected abstract void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack );
|
||||
protected abstract void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack, int light );
|
||||
}
|
||||
|
@@ -15,15 +15,12 @@ import dan200.computercraft.shared.computer.core.ComputerFamily;
|
||||
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.BufferBuilder;
|
||||
import net.minecraft.client.render.Tessellator;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
|
||||
@@ -41,7 +38,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack )
|
||||
protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack, int light )
|
||||
{
|
||||
ClientComputer computer = ItemPocketComputer.createClientComputer( stack );
|
||||
Terminal terminal = computer == null ? null : computer.getTerminal();
|
||||
@@ -64,8 +61,8 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
// Setup various transformations. Note that these are partially adapted from the corresponding method
|
||||
// in ItemRenderer
|
||||
transform.push();
|
||||
transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( 180f ) );
|
||||
transform.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( 180f ) );
|
||||
transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 180f ) );
|
||||
transform.multiply( Vec3f.POSITIVE_Z.getDegreesQuaternion( 180f ) );
|
||||
transform.scale( 0.5f, 0.5f, 0.5f );
|
||||
|
||||
float scale = 0.75f / Math.max( width + BORDER * 2, height + BORDER * 2 + LIGHT_HEIGHT );
|
||||
@@ -79,7 +76,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
|
||||
Matrix4f matrix = transform.peek()
|
||||
.getModel();
|
||||
renderFrame( matrix, family, frameColour, width, height );
|
||||
renderFrame( matrix, render, family, frameColour, light, width, height );
|
||||
|
||||
// Render the light
|
||||
int lightColour = ItemPocketComputer.getLightState( stack );
|
||||
@@ -91,7 +88,12 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
|
||||
if( computer != null && terminal != null )
|
||||
{
|
||||
FixedWidthFontRenderer.drawTerminal( matrix, MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN );
|
||||
FixedWidthFontRenderer.drawTerminal(
|
||||
matrix, render.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ),
|
||||
MARGIN, MARGIN, terminal, !computer.isColour(), MARGIN, MARGIN, MARGIN, MARGIN
|
||||
);
|
||||
FixedWidthFontRenderer.drawBlocker( transform.peek().getModel(), render, 0, 0, width, height );
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -101,24 +103,20 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
private static void renderFrame( Matrix4f transform, ComputerFamily family, int colour, int width, int height )
|
||||
private static void renderFrame( Matrix4f transform, VertexConsumerProvider render, ComputerFamily family, int colour, int light, int width, int height )
|
||||
{
|
||||
RenderSystem.enableBlend();
|
||||
MinecraftClient.getInstance()
|
||||
.getTextureManager()
|
||||
.bindTexture( colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family ) );
|
||||
|
||||
Identifier texture = colour != -1 ? ComputerBorderRenderer.BACKGROUND_COLOUR : ComputerBorderRenderer.getTexture( family );
|
||||
|
||||
float r = ((colour >>> 16) & 0xFF) / 255.0f;
|
||||
float g = ((colour >>> 8) & 0xFF) / 255.0f;
|
||||
float b = (colour & 0xFF) / 255.0f;
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR_TEXTURE );
|
||||
|
||||
ComputerBorderRenderer.render( transform, buffer, 0, 0, 0, width, height, true, r, g, b );
|
||||
|
||||
tessellator.draw();
|
||||
ComputerBorderRenderer.render( transform, render.getBuffer( RenderLayer.getText( texture ) ), 0, 0, 0, light, width, height, true, r, g, b );
|
||||
}
|
||||
|
||||
private static void renderLight( Matrix4f transform, int colour, int width, int height )
|
||||
@@ -131,7 +129,7 @@ public final class ItemPocketRenderer extends ItemMapLikeRenderer
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin( GL11.GL_QUADS, VertexFormats.POSITION_COLOR );
|
||||
buffer.begin( VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_COLOR );
|
||||
buffer.vertex( transform, width - LIGHT_HEIGHT * 2, height + LIGHT_HEIGHT + BORDER / 2.0f, 0 )
|
||||
.color( r, g, b, 1.0f )
|
||||
.next();
|
||||
|
@@ -9,9 +9,9 @@ package dan200.computercraft.client.render;
|
||||
import dan200.computercraft.shared.media.items.ItemPrintout;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_WIDTH;
|
||||
@@ -31,16 +31,16 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack )
|
||||
protected void renderItem( MatrixStack transform, VertexConsumerProvider render, ItemStack stack, int light )
|
||||
{
|
||||
transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( 180f ) );
|
||||
transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( 180f ) );
|
||||
transform.scale( 0.42f, 0.42f, -0.42f );
|
||||
transform.translate( -0.5f, -0.48f, 0.0f );
|
||||
|
||||
drawPrintout( transform, render, stack );
|
||||
drawPrintout( transform, render, stack, light );
|
||||
}
|
||||
|
||||
private static void drawPrintout( MatrixStack transform, VertexConsumerProvider render, ItemStack stack )
|
||||
private static void drawPrintout( MatrixStack transform, VertexConsumerProvider render, ItemStack stack, int light )
|
||||
{
|
||||
int pages = ItemPrintout.getPageCount( stack );
|
||||
boolean book = ((ItemPrintout) stack.getItem()).getType() == ItemPrintout.Type.BOOK;
|
||||
@@ -72,11 +72,11 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
||||
|
||||
Matrix4f matrix = transform.peek()
|
||||
.getModel();
|
||||
drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book );
|
||||
drawText( matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) );
|
||||
drawBorder( matrix, render, 0, 0, -0.01f, 0, pages, book, light );
|
||||
drawText( matrix, render, X_TEXT_MARGIN, Y_TEXT_MARGIN, 0, light, ItemPrintout.getText( stack ), ItemPrintout.getColours( stack ) );
|
||||
}
|
||||
|
||||
public boolean renderInFrame( MatrixStack matrixStack, VertexConsumerProvider consumerProvider, ItemStack stack )
|
||||
public boolean renderInFrame( MatrixStack matrixStack, VertexConsumerProvider consumerProvider, ItemStack stack, int light )
|
||||
{
|
||||
if( !(stack.getItem() instanceof ItemPrintout) )
|
||||
{
|
||||
@@ -85,11 +85,11 @@ public final class ItemPrintoutRenderer extends ItemMapLikeRenderer
|
||||
|
||||
// Move a little bit forward to ensure we're not clipping with the frame
|
||||
matrixStack.translate( 0.0f, 0.0f, -0.001f );
|
||||
matrixStack.multiply( Vector3f.POSITIVE_Z.getDegreesQuaternion( 180f ) );
|
||||
matrixStack.multiply( Vec3f.POSITIVE_Z.getDegreesQuaternion( 180f ) );
|
||||
matrixStack.scale( 0.95f, 0.95f, -0.95f );
|
||||
matrixStack.translate( -0.5f, -0.5f, 0.0f );
|
||||
|
||||
drawPrintout( matrixStack, consumerProvider, stack );
|
||||
drawPrintout( matrixStack, consumerProvider, stack, light );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@@ -5,15 +5,14 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import dan200.computercraft.fabric.mixin.BakedQuadAccess;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.render.VertexFormat;
|
||||
import net.minecraft.client.render.VertexFormatElement;
|
||||
import net.minecraft.client.render.VertexFormats;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.util.math.Vector4f;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Vector4f;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -58,7 +57,7 @@ public final class ModelTransformer
|
||||
private static BakedQuad doTransformQuad( VertexFormat format, BakedQuad quad, Matrix4f transform )
|
||||
{
|
||||
int[] vertexData = quad.getVertexData().clone();
|
||||
BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), ((BakedQuadAccess) quad).getSprite(), true );
|
||||
BakedQuad copy = new BakedQuad( vertexData, -1, quad.getFace(), quad.getSprite(), true );
|
||||
|
||||
int offsetBytes = 0;
|
||||
for( int v = 0; v < 4; ++v )
|
||||
@@ -66,7 +65,7 @@ public final class ModelTransformer
|
||||
for( VertexFormatElement element : format.getElements() ) // For each vertex element
|
||||
{
|
||||
int start = offsetBytes / Integer.BYTES;
|
||||
if( element.getType() == VertexFormatElement.Type.POSITION && element.getFormat() == VertexFormatElement.Format.FLOAT ) // When we find a position element
|
||||
if( element.getType() == VertexFormatElement.Type.POSITION && element.getDataType() == VertexFormatElement.DataType.FLOAT ) // When we find a position element
|
||||
{
|
||||
Vector4f pos = new Vector4f( Float.intBitsToFloat( vertexData[start] ),
|
||||
Float.intBitsToFloat( vertexData[start + 1] ),
|
||||
@@ -81,7 +80,7 @@ public final class ModelTransformer
|
||||
vertexData[start + 1] = Float.floatToRawIntBits( pos.getY() );
|
||||
vertexData[start + 2] = Float.floatToRawIntBits( pos.getZ() );
|
||||
}
|
||||
offsetBytes += element.getSize();
|
||||
offsetBytes += element.getByteLength();
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
|
@@ -15,14 +15,10 @@ import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import static net.minecraft.util.math.Direction.*;
|
||||
|
||||
/**
|
||||
@@ -36,9 +32,7 @@ public final class MonitorHighlightRenderer
|
||||
{
|
||||
}
|
||||
|
||||
public static boolean drawHighlight(
|
||||
MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState
|
||||
)
|
||||
public static boolean drawHighlight( MatrixStack matrixStack, VertexConsumer vertexConsumer, Entity entity, double d, double e, double f, BlockPos pos, BlockState blockState )
|
||||
{
|
||||
// Preserve normal behaviour when crouching.
|
||||
if( entity.isInSneakingPose() )
|
||||
@@ -49,13 +43,11 @@ public final class MonitorHighlightRenderer
|
||||
World world = entity.getEntityWorld();
|
||||
|
||||
BlockEntity tile = world.getBlockEntity( pos );
|
||||
if( !(tile instanceof TileMonitor) )
|
||||
if( !(tile instanceof TileMonitor monitor) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TileMonitor monitor = (TileMonitor) tile;
|
||||
|
||||
// Determine which sides are part of the external faces of the monitor, and so which need to be rendered.
|
||||
EnumSet<Direction> faces = EnumSet.allOf( Direction.class );
|
||||
Direction front = monitor.getFront();
|
||||
@@ -87,53 +79,54 @@ public final class MonitorHighlightRenderer
|
||||
// I wish I could think of a better way to do this
|
||||
Matrix4f transform = matrixStack.peek()
|
||||
.getModel();
|
||||
Matrix3f normal = matrixStack.peek().getNormal();
|
||||
if( faces.contains( NORTH ) || faces.contains( WEST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 0, 0, 0, UP );
|
||||
line( vertexConsumer, transform, normal, 0, 0, 0, UP );
|
||||
}
|
||||
if( faces.contains( SOUTH ) || faces.contains( WEST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 0, 0, 1, UP );
|
||||
line( vertexConsumer, transform, normal, 0, 0, 1, UP );
|
||||
}
|
||||
if( faces.contains( NORTH ) || faces.contains( EAST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 1, 0, 0, UP );
|
||||
line( vertexConsumer, transform, normal, 1, 0, 0, UP );
|
||||
}
|
||||
if( faces.contains( SOUTH ) || faces.contains( EAST ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 1, 0, 1, UP );
|
||||
line( vertexConsumer, transform, normal, 1, 0, 1, UP );
|
||||
}
|
||||
if( faces.contains( NORTH ) || faces.contains( DOWN ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 0, 0, 0, EAST );
|
||||
line( vertexConsumer, transform, normal, 0, 0, 0, EAST );
|
||||
}
|
||||
if( faces.contains( SOUTH ) || faces.contains( DOWN ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 0, 0, 1, EAST );
|
||||
line( vertexConsumer, transform, normal, 0, 0, 1, EAST );
|
||||
}
|
||||
if( faces.contains( NORTH ) || faces.contains( UP ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 0, 1, 0, EAST );
|
||||
line( vertexConsumer, transform, normal, 0, 1, 0, EAST );
|
||||
}
|
||||
if( faces.contains( SOUTH ) || faces.contains( UP ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 0, 1, 1, EAST );
|
||||
line( vertexConsumer, transform, normal, 0, 1, 1, EAST );
|
||||
}
|
||||
if( faces.contains( WEST ) || faces.contains( DOWN ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 0, 0, 0, SOUTH );
|
||||
line( vertexConsumer, transform, normal, 0, 0, 0, SOUTH );
|
||||
}
|
||||
if( faces.contains( EAST ) || faces.contains( DOWN ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 1, 0, 0, SOUTH );
|
||||
line( vertexConsumer, transform, normal, 1, 0, 0, SOUTH );
|
||||
}
|
||||
if( faces.contains( WEST ) || faces.contains( UP ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 0, 1, 0, SOUTH );
|
||||
line( vertexConsumer, transform, normal, 0, 1, 0, SOUTH );
|
||||
}
|
||||
if( faces.contains( EAST ) || faces.contains( UP ) )
|
||||
{
|
||||
line( vertexConsumer, transform, 1, 1, 0, SOUTH );
|
||||
line( vertexConsumer, transform, normal, 1, 1, 0, SOUTH );
|
||||
}
|
||||
|
||||
matrixStack.pop();
|
||||
@@ -141,13 +134,15 @@ public final class MonitorHighlightRenderer
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void line( VertexConsumer buffer, Matrix4f transform, float x, float y, float z, Direction direction )
|
||||
private static void line( VertexConsumer buffer, Matrix4f transform, Matrix3f normal, float x, float y, float z, Direction direction )
|
||||
{
|
||||
buffer.vertex( transform, x, y, z )
|
||||
.color( 0, 0, 0, 0.4f )
|
||||
.normal( normal, direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ() )
|
||||
.next();
|
||||
buffer.vertex( transform, x + direction.getOffsetX(), y + direction.getOffsetY(), z + direction.getOffsetZ() )
|
||||
.color( 0, 0, 0, 0.4f )
|
||||
.normal( normal, direction.getOffsetX(), direction.getOffsetY(), direction.getOffsetZ() )
|
||||
.next();
|
||||
}
|
||||
}
|
||||
|
@@ -5,180 +5,107 @@
|
||||
*/
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
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.texture.TextureUtil;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import org.lwjgl.BufferUtils;
|
||||
import net.minecraft.client.gl.GlUniform;
|
||||
import net.minecraft.client.render.Shader;
|
||||
import net.minecraft.client.render.VertexFormat;
|
||||
import net.minecraft.resource.ResourceFactory;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
|
||||
import java.io.InputStream;
|
||||
import javax.annotation.Nullable;
|
||||
import java.io.IOException;
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
class MonitorTextureBufferShader
|
||||
public class MonitorTextureBufferShader extends Shader
|
||||
{
|
||||
static final int TEXTURE_INDEX = GL13.GL_TEXTURE3;
|
||||
|
||||
private static final FloatBuffer MATRIX_BUFFER = BufferUtils.createFloatBuffer( 16 );
|
||||
private static final FloatBuffer PALETTE_BUFFER = BufferUtils.createFloatBuffer( 16 * 3 );
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
private static int uniformMv;
|
||||
private final GlUniform palette;
|
||||
private final GlUniform width;
|
||||
private final GlUniform height;
|
||||
|
||||
private static int uniformFont;
|
||||
private static int uniformWidth;
|
||||
private static int uniformHeight;
|
||||
private static int uniformTbo;
|
||||
private static int uniformPalette;
|
||||
|
||||
private static boolean initialised;
|
||||
private static boolean ok;
|
||||
private static int program;
|
||||
|
||||
static void setupUniform( Matrix4f transform, int width, int height, Palette palette, boolean greyscale )
|
||||
public MonitorTextureBufferShader( ResourceFactory factory, String name, VertexFormat format ) throws IOException
|
||||
{
|
||||
MATRIX_BUFFER.rewind();
|
||||
transform.writeToBuffer( MATRIX_BUFFER );
|
||||
MATRIX_BUFFER.rewind();
|
||||
RenderSystem.glUniformMatrix4( uniformMv, false, MATRIX_BUFFER );
|
||||
super( factory, name, format );
|
||||
|
||||
RenderSystem.glUniform1i( uniformWidth, width );
|
||||
RenderSystem.glUniform1i( uniformHeight, height );
|
||||
width = getUniformChecked( "Width" );
|
||||
height = getUniformChecked( "Height" );
|
||||
palette = new GlUniform( "Palette", GlUniform.field_32044 /* UT_FLOAT3 */, 16 * 3, this );
|
||||
updateUniformLocation( palette );
|
||||
|
||||
PALETTE_BUFFER.rewind();
|
||||
GlUniform tbo = getUniformChecked( "Tbo" );
|
||||
if( tbo != null ) tbo.set( TEXTURE_INDEX - GL13.GL_TEXTURE0 );
|
||||
}
|
||||
|
||||
void setupUniform( int width, int height, Palette palette, boolean greyscale )
|
||||
{
|
||||
if( this.width != null ) this.width.set( width );
|
||||
if( this.height != null ) this.height.set( height );
|
||||
setupPalette( palette, greyscale );
|
||||
}
|
||||
|
||||
private void setupPalette( Palette palette, boolean greyscale )
|
||||
{
|
||||
if( this.palette == null ) return;
|
||||
|
||||
FloatBuffer paletteBuffer = this.palette.getFloatData();
|
||||
paletteBuffer.rewind();
|
||||
for( int i = 0; i < 16; i++ )
|
||||
{
|
||||
double[] colour = palette.getColour( i );
|
||||
if( greyscale )
|
||||
{
|
||||
float f = FixedWidthFontRenderer.toGreyscale( colour );
|
||||
PALETTE_BUFFER.put( f )
|
||||
.put( f )
|
||||
.put( f );
|
||||
paletteBuffer.put( f ).put( f ).put( f );
|
||||
}
|
||||
else
|
||||
{
|
||||
PALETTE_BUFFER.put( (float) colour[0] )
|
||||
.put( (float) colour[1] )
|
||||
.put( (float) colour[2] );
|
||||
paletteBuffer.put( (float) colour[0] ).put( (float) colour[1] ).put( (float) colour[2] );
|
||||
}
|
||||
}
|
||||
PALETTE_BUFFER.flip();
|
||||
RenderSystem.glUniform3( uniformPalette, PALETTE_BUFFER );
|
||||
}
|
||||
|
||||
static boolean use()
|
||||
{
|
||||
if( initialised )
|
||||
{
|
||||
if( ok )
|
||||
{
|
||||
GlStateManager.useProgram( program );
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
if( ok = load() )
|
||||
{
|
||||
GL20.glUseProgram( program );
|
||||
RenderSystem.glUniform1i( uniformFont, 0 );
|
||||
RenderSystem.glUniform1i( uniformTbo, TEXTURE_INDEX - GL13.GL_TEXTURE0 );
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
private static boolean load()
|
||||
{
|
||||
initialised = true;
|
||||
|
||||
try
|
||||
{
|
||||
int vertexShader = loadShader( GL20.GL_VERTEX_SHADER, "assets/computercraft/shaders/monitor.vert" );
|
||||
int fragmentShader = loadShader( GL20.GL_FRAGMENT_SHADER, "assets/computercraft/shaders/monitor.frag" );
|
||||
|
||||
program = GlStateManager.createProgram();
|
||||
GlStateManager.attachShader( program, vertexShader );
|
||||
GlStateManager.attachShader( program, fragmentShader );
|
||||
GL20.glBindAttribLocation( program, 0, "v_pos" );
|
||||
|
||||
GlStateManager.linkProgram( program );
|
||||
boolean ok = GlStateManager.getProgram( program, GL20.GL_LINK_STATUS ) != 0;
|
||||
String log = GlStateManager.getProgramInfoLog( program, Short.MAX_VALUE )
|
||||
.trim();
|
||||
if( !Strings.isNullOrEmpty( log ) )
|
||||
{
|
||||
ComputerCraft.log.warn( "Problems when linking monitor shader: {}", log );
|
||||
}
|
||||
|
||||
GL20.glDetachShader( program, vertexShader );
|
||||
GL20.glDetachShader( program, fragmentShader );
|
||||
GlStateManager.deleteShader( vertexShader );
|
||||
GlStateManager.deleteShader( fragmentShader );
|
||||
|
||||
if( !ok )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
uniformMv = getUniformLocation( program, "u_mv" );
|
||||
uniformFont = getUniformLocation( program, "u_font" );
|
||||
uniformWidth = getUniformLocation( program, "u_width" );
|
||||
uniformHeight = getUniformLocation( program, "u_height" );
|
||||
uniformTbo = getUniformLocation( program, "u_tbo" );
|
||||
uniformPalette = getUniformLocation( program, "u_palette" );
|
||||
|
||||
ComputerCraft.log.info( "Loaded monitor shader." );
|
||||
return true;
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
ComputerCraft.log.error( "Cannot load monitor shaders", e );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static int loadShader( int kind, String path )
|
||||
@Override
|
||||
public void bind()
|
||||
{
|
||||
InputStream stream = TileEntityMonitorRenderer.class.getClassLoader()
|
||||
.getResourceAsStream( path );
|
||||
if( stream == null )
|
||||
{
|
||||
throw new IllegalArgumentException( "Cannot find " + path );
|
||||
}
|
||||
String contents = TextureUtil.readAllToString( stream );
|
||||
|
||||
int shader = GlStateManager.createShader( kind );
|
||||
|
||||
GlStateManager.shaderSource( shader, contents );
|
||||
GlStateManager.compileShader( shader );
|
||||
|
||||
boolean ok = GlStateManager.getShader( shader, GL20.GL_COMPILE_STATUS ) != 0;
|
||||
String log = GlStateManager.getShaderInfoLog( shader, Short.MAX_VALUE )
|
||||
.trim();
|
||||
if( !Strings.isNullOrEmpty( log ) )
|
||||
{
|
||||
ComputerCraft.log.warn( "Problems when loading monitor shader {}: {}", path, log );
|
||||
}
|
||||
|
||||
if( !ok )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot compile shader " + path );
|
||||
}
|
||||
return shader;
|
||||
super.bind();
|
||||
palette.upload();
|
||||
}
|
||||
|
||||
private static int getUniformLocation( int program, String name )
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
int uniform = GlStateManager.getUniformLocation( program, name );
|
||||
if( uniform == -1 )
|
||||
palette.close();
|
||||
super.close();
|
||||
}
|
||||
|
||||
private void updateUniformLocation( GlUniform uniform )
|
||||
{
|
||||
int id = GlUniform.getUniformLocation( getProgramRef(), uniform.getName() );
|
||||
if( id == -1 )
|
||||
{
|
||||
throw new IllegalStateException( "Cannot find uniform " + name );
|
||||
LOGGER.warn( "Shader {} could not find uniform named {} in the specified shader program.", getName(), uniform.getName() );
|
||||
}
|
||||
else
|
||||
{
|
||||
uniform.setLoc( id );
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private GlUniform getUniformChecked( String name )
|
||||
{
|
||||
GlUniform uniform = getUniform( name );
|
||||
if( uniform == null )
|
||||
{
|
||||
LOGGER.warn( "Monitor shader {} should have uniform {}, but it was not present.", getName(), name );
|
||||
}
|
||||
|
||||
return uniform;
|
||||
}
|
||||
}
|
||||
|
@@ -9,10 +9,9 @@ package dan200.computercraft.client.render;
|
||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.TextBuffer;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.FONT_HEIGHT;
|
||||
import static dan200.computercraft.shared.media.items.ItemPrintout.LINES_PER_PAGE;
|
||||
@@ -39,7 +38,6 @@ public final class PrintoutRenderer
|
||||
* Size of the leather cover.
|
||||
*/
|
||||
public static final int COVER_SIZE = 12;
|
||||
private static final Identifier BG = new Identifier( "computercraft", "textures/gui/printout.png" );
|
||||
private static final float BG_SIZE = 256.0f;
|
||||
/**
|
||||
* Width of the extra page texture.
|
||||
@@ -50,9 +48,9 @@ public final class PrintoutRenderer
|
||||
|
||||
private PrintoutRenderer() {}
|
||||
|
||||
public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, TextBuffer[] text, TextBuffer[] colours )
|
||||
public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, int light, TextBuffer[] text, TextBuffer[] colours )
|
||||
{
|
||||
VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE );
|
||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
|
||||
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
||||
{
|
||||
FixedWidthFontRenderer.drawString( transform,
|
||||
@@ -65,13 +63,14 @@ public final class PrintoutRenderer
|
||||
Palette.DEFAULT,
|
||||
false,
|
||||
0,
|
||||
0 );
|
||||
0,
|
||||
light );
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, String[] text, String[] colours )
|
||||
public static void drawText( Matrix4f transform, VertexConsumerProvider renderer, int x, int y, int start, int light, String[] text, String[] colours )
|
||||
{
|
||||
VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE );
|
||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_TEXT );
|
||||
for( int line = 0; line < LINES_PER_PAGE && line < text.length; line++ )
|
||||
{
|
||||
FixedWidthFontRenderer.drawString( transform,
|
||||
@@ -84,16 +83,17 @@ public final class PrintoutRenderer
|
||||
Palette.DEFAULT,
|
||||
false,
|
||||
0,
|
||||
0 );
|
||||
0,
|
||||
light );
|
||||
}
|
||||
}
|
||||
|
||||
public static void drawBorder( Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float z, int page, int pages, boolean isBook )
|
||||
public static void drawBorder( Matrix4f transform, VertexConsumerProvider renderer, float x, float y, float z, int page, int pages, boolean isBook, int light )
|
||||
{
|
||||
int leftPages = page;
|
||||
int rightPages = pages - page - 1;
|
||||
|
||||
VertexConsumer buffer = renderer.getBuffer( Type.TYPE );
|
||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.PRINTOUT_BACKGROUND );
|
||||
|
||||
if( isBook )
|
||||
{
|
||||
@@ -103,8 +103,8 @@ public final class PrintoutRenderer
|
||||
float right = x + X_SIZE + offset - 4;
|
||||
|
||||
// Left and right border
|
||||
drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 );
|
||||
drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2 );
|
||||
drawTexture( transform, buffer, left - 4, y - 8, z - 0.02f, COVER_X, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light );
|
||||
drawTexture( transform, buffer, right, y - 8, z - 0.02f, COVER_X + COVER_SIZE, 0, COVER_SIZE, Y_SIZE + COVER_SIZE * 2, light );
|
||||
|
||||
// Draw centre panel (just stretched texture, sorry).
|
||||
drawTexture( transform,
|
||||
@@ -117,34 +117,35 @@ public final class PrintoutRenderer
|
||||
COVER_X + COVER_SIZE / 2.0f,
|
||||
COVER_SIZE,
|
||||
COVER_SIZE,
|
||||
Y_SIZE );
|
||||
Y_SIZE,
|
||||
light );
|
||||
|
||||
float borderX = left;
|
||||
while( borderX < right )
|
||||
{
|
||||
double thisWidth = Math.min( right - borderX, X_SIZE );
|
||||
drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE );
|
||||
drawTexture( transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE );
|
||||
drawTexture( transform, buffer, borderX, y - 8, z - 0.02f, 0, COVER_Y, (float) thisWidth, COVER_SIZE, light );
|
||||
drawTexture( transform, buffer, borderX, y + Y_SIZE - 4, z - 0.02f, 0, COVER_Y + COVER_SIZE, (float) thisWidth, COVER_SIZE, light );
|
||||
borderX += thisWidth;
|
||||
}
|
||||
}
|
||||
|
||||
// Left half
|
||||
drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE );
|
||||
drawTexture( transform, buffer, x, y, z, X_FOLD_SIZE * 2, 0, X_SIZE / 2.0f, Y_SIZE, light );
|
||||
for( int n = 0; n <= leftPages; n++ )
|
||||
{
|
||||
drawTexture( transform, buffer, x - offsetAt( n ), y, z - 1e-3f * n,
|
||||
// Use the left "bold" fold for the outermost page
|
||||
n == leftPages ? 0 : X_FOLD_SIZE, 0, X_FOLD_SIZE, Y_SIZE );
|
||||
n == leftPages ? 0 : X_FOLD_SIZE, 0, X_FOLD_SIZE, Y_SIZE, light );
|
||||
}
|
||||
|
||||
// Right half
|
||||
drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE );
|
||||
drawTexture( transform, buffer, x + X_SIZE / 2.0f, y, z, X_FOLD_SIZE * 2 + X_SIZE / 2.0f, 0, X_SIZE / 2.0f, Y_SIZE, light );
|
||||
for( int n = 0; n <= rightPages; n++ )
|
||||
{
|
||||
drawTexture( transform, buffer, x + (X_SIZE - X_FOLD_SIZE) + offsetAt( n ), y, z - 1e-3f * n,
|
||||
// Two folds, then the main page. Use the right "bold" fold for the outermost page.
|
||||
X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, X_FOLD_SIZE, Y_SIZE );
|
||||
X_FOLD_SIZE * 2 + X_SIZE + (n == rightPages ? X_FOLD_SIZE : 0), 0, X_FOLD_SIZE, Y_SIZE, light );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,57 +154,25 @@ public final class PrintoutRenderer
|
||||
return (float) (32 * (1 - Math.pow( 1.2, -page )));
|
||||
}
|
||||
|
||||
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height )
|
||||
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float u, float v, float width, float height, int light )
|
||||
{
|
||||
buffer.vertex( matrix, x, y + height, z )
|
||||
.texture( u / BG_SIZE, (v + height) / BG_SIZE )
|
||||
.next();
|
||||
buffer.vertex( matrix, x + width, y + height, z )
|
||||
.texture( (u + width) / BG_SIZE, (v + height) / BG_SIZE )
|
||||
.next();
|
||||
buffer.vertex( matrix, x + width, y, z )
|
||||
.texture( (u + width) / BG_SIZE, v / BG_SIZE )
|
||||
.next();
|
||||
buffer.vertex( matrix, x, y, z )
|
||||
.texture( u / BG_SIZE, v / BG_SIZE )
|
||||
.next();
|
||||
vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + height) / BG_SIZE, light );
|
||||
vertex( buffer, matrix, x + width, y + height, z, (u + width) / BG_SIZE, (v + height) / BG_SIZE, light );
|
||||
vertex( buffer, matrix, x + width, y, z, (u + width) / BG_SIZE, v / BG_SIZE, light );
|
||||
vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light );
|
||||
}
|
||||
|
||||
private static void drawTexture( Matrix4f matrix, VertexConsumer buffer, float x, float y, float z, float width, float height, float u, float v,
|
||||
float tWidth, float tHeight )
|
||||
float tWidth, float tHeight, int light )
|
||||
{
|
||||
buffer.vertex( matrix, x, y + height, z )
|
||||
.texture( u / BG_SIZE, (v + tHeight) / BG_SIZE )
|
||||
.next();
|
||||
buffer.vertex( matrix, x + width, y + height, z )
|
||||
.texture( (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE )
|
||||
.next();
|
||||
buffer.vertex( matrix, x + width, y, z )
|
||||
.texture( (u + tWidth) / BG_SIZE, v / BG_SIZE )
|
||||
.next();
|
||||
buffer.vertex( matrix, x, y, z )
|
||||
.texture( u / BG_SIZE, v / BG_SIZE )
|
||||
.next();
|
||||
vertex( buffer, matrix, x, y + height, z, u / BG_SIZE, (v + tHeight) / BG_SIZE, light );
|
||||
vertex( buffer, matrix, x + width, y + height, z, (u + tWidth) / BG_SIZE, (v + tHeight) / BG_SIZE, light );
|
||||
vertex( buffer, matrix, x + width, y, z, (u + tWidth) / BG_SIZE, v / BG_SIZE, light );
|
||||
vertex( buffer, matrix, x, y, z, u / BG_SIZE, v / BG_SIZE, light );
|
||||
}
|
||||
|
||||
private static final class Type extends RenderPhase
|
||||
private static void vertex( VertexConsumer buffer, Matrix4f matrix, float x, float y, float z, float u, float v, int light )
|
||||
{
|
||||
static final RenderLayer TYPE = RenderLayer.of( "printout_background",
|
||||
VertexFormats.POSITION_TEXTURE,
|
||||
GL11.GL_QUADS,
|
||||
1024,
|
||||
false,
|
||||
false,
|
||||
// useDelegate, needsSorting
|
||||
RenderLayer.MultiPhaseParameters.builder()
|
||||
.texture( new RenderPhase.Texture( BG, false, false ) ) // blur, minimap
|
||||
.alpha( ONE_TENTH_ALPHA )
|
||||
.lightmap( DISABLE_LIGHTMAP )
|
||||
.build( false ) );
|
||||
|
||||
private Type( String name, Runnable setup, Runnable destroy )
|
||||
{
|
||||
super( name, setup, destroy );
|
||||
}
|
||||
buffer.vertex( matrix, x, y, z ).color( 255, 255, 255, 255 ).texture( u, v ).light( light ).next();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* 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.render;
|
||||
|
||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
public class RenderTypes
|
||||
{
|
||||
|
||||
public static final int FULL_BRIGHT_LIGHTMAP = (0xF << 4) | (0xF << 20);
|
||||
|
||||
@Nullable
|
||||
public static MonitorTextureBufferShader monitorTboShader;
|
||||
|
||||
@Nullable
|
||||
public static Shader terminalShader;
|
||||
|
||||
public static final RenderLayer TERMINAL_WITHOUT_DEPTH = Types.TERMINAL_WITHOUT_DEPTH;
|
||||
public static final RenderLayer MONITOR_TBO = Types.MONITOR_TBO;
|
||||
public static final RenderLayer TERMINAL_BLOCKER = Types.BLOCKER;
|
||||
public static final RenderLayer TERMINAL_WITH_DEPTH = Types.TERMINAL_WITH_DEPTH;
|
||||
public static final RenderLayer PRINTOUT_TEXT = Types.PRINTOUT_TEXT;
|
||||
|
||||
public static final RenderLayer PRINTOUT_BACKGROUND = RenderLayer.getText( new Identifier( "computercraft", "textures/gui/printout.png" ) );
|
||||
|
||||
public static final RenderLayer POSITION_COLOR = Types.POSITION_COLOR;
|
||||
|
||||
@Nonnull
|
||||
static MonitorTextureBufferShader getMonitorTextureBufferShader()
|
||||
{
|
||||
if( monitorTboShader == null ) throw new NullPointerException( "MonitorTboShader has not been registered" );
|
||||
return monitorTboShader;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
static Shader getTerminalShader()
|
||||
{
|
||||
if( terminalShader == null ) throw new NullPointerException( "MonitorTboShader has not been registered" );
|
||||
return terminalShader;
|
||||
}
|
||||
|
||||
private static final class Types extends RenderPhase
|
||||
{
|
||||
private static final VertexFormat.DrawMode GL_MODE = VertexFormat.DrawMode.TRIANGLES;
|
||||
private static final VertexFormat FORMAT = VertexFormats.POSITION_COLOR_TEXTURE;
|
||||
private static final Shader TERM_SHADER = new Shader( RenderTypes::getTerminalShader );
|
||||
|
||||
private static final RenderPhase.Texture TERM_FONT_TEXTURE = new RenderPhase.Texture(
|
||||
FixedWidthFontRenderer.FONT,
|
||||
false, false // blur, minimap
|
||||
);
|
||||
|
||||
public static final RenderLayer MONITOR_TBO = RenderLayer.of( "monitor_tbo", VertexFormats.POSITION_TEXTURE, VertexFormat.DrawMode.TRIANGLE_STRIP, 128, false, false, // useDelegate, needsSorting
|
||||
RenderLayer.MultiPhaseParameters.builder()
|
||||
.texture( TERM_FONT_TEXTURE ) // blur, minimap
|
||||
.shader( new RenderPhase.Shader( RenderTypes::getMonitorTextureBufferShader ) )
|
||||
.writeMaskState( RenderLayer.ALL_MASK )
|
||||
.build( false ) );
|
||||
|
||||
static final RenderLayer TERMINAL_WITHOUT_DEPTH = RenderLayer.of(
|
||||
"terminal_without_depth", FORMAT, GL_MODE, 1024,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderLayer.MultiPhaseParameters.builder()
|
||||
.texture( TERM_FONT_TEXTURE )
|
||||
.shader( TERM_SHADER )
|
||||
.writeMaskState( COLOR_MASK )
|
||||
.build( false )
|
||||
);
|
||||
|
||||
static final RenderLayer BLOCKER = RenderLayer.of( "terminal_blocker", FORMAT, GL_MODE, 256, false, false, // useDelegate, needsSorting
|
||||
RenderLayer.MultiPhaseParameters.builder()
|
||||
.texture( TERM_FONT_TEXTURE )
|
||||
.shader( TERM_SHADER )
|
||||
.writeMaskState( DEPTH_MASK )
|
||||
.build( false ) );
|
||||
|
||||
static final RenderLayer TERMINAL_WITH_DEPTH = RenderLayer.of(
|
||||
"terminal_with_depth", FORMAT, GL_MODE, 1024,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderLayer.MultiPhaseParameters.builder()
|
||||
.texture( TERM_FONT_TEXTURE )
|
||||
.shader( TERM_SHADER )
|
||||
.build( false )
|
||||
);
|
||||
|
||||
static final RenderLayer PRINTOUT_TEXT = RenderLayer.of(
|
||||
"printout_text", VertexFormats.POSITION_COLOR_TEXTURE_LIGHT, GL_MODE, 1024,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderLayer.MultiPhaseParameters.builder()
|
||||
.texture( TERM_FONT_TEXTURE )
|
||||
.shader( RenderPhase.TEXT_SHADER )
|
||||
.lightmap( RenderPhase.ENABLE_LIGHTMAP )
|
||||
.build( false )
|
||||
);
|
||||
|
||||
static final RenderLayer POSITION_COLOR = RenderLayer.of(
|
||||
"position_color", VertexFormats.POSITION_COLOR, VertexFormat.DrawMode.QUADS, 128,
|
||||
false, false, // useDelegate, needsSorting
|
||||
RenderLayer.MultiPhaseParameters.builder()
|
||||
.shader( COLOR_SHADER )
|
||||
.build( false )
|
||||
);
|
||||
|
||||
private Types( String name, Runnable setup, Runnable destroy )
|
||||
{
|
||||
super( name, setup, destroy );
|
||||
}
|
||||
}
|
||||
}
|
@@ -7,6 +7,8 @@
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.client.FrameInfo;
|
||||
import dan200.computercraft.client.gui.FixedWidthFontRenderer;
|
||||
import dan200.computercraft.core.terminal.Terminal;
|
||||
@@ -18,17 +20,11 @@ import dan200.computercraft.shared.util.Colour;
|
||||
import dan200.computercraft.shared.util.DirectionUtil;
|
||||
import net.minecraft.client.gl.VertexBuffer;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||
import net.minecraft.client.util.GlAllocationUtils;
|
||||
import net.minecraft.client.util.math.AffineTransformation;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.*;
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.opengl.GL13;
|
||||
import org.lwjgl.opengl.GL20;
|
||||
import org.lwjgl.opengl.GL31;
|
||||
|
||||
@@ -36,8 +32,9 @@ import javax.annotation.Nonnull;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static dan200.computercraft.client.gui.FixedWidthFontRenderer.*;
|
||||
import static net.minecraft.client.util.GlAllocationUtils.allocateByteBuffer;
|
||||
|
||||
public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
|
||||
public class TileEntityMonitorRenderer implements BlockEntityRenderer<TileMonitor>
|
||||
{
|
||||
/**
|
||||
* {@link TileMonitor#RENDER_MARGIN}, but a tiny bit of additional padding to ensure that there is no space between the monitor frame and contents.
|
||||
@@ -47,11 +44,10 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
|
||||
.getMatrix();
|
||||
private static ByteBuffer tboContents;
|
||||
|
||||
public TileEntityMonitorRenderer( BlockEntityRenderDispatcher rendererDispatcher )
|
||||
public TileEntityMonitorRenderer( BlockEntityRendererFactory.Context context )
|
||||
{
|
||||
super( rendererDispatcher );
|
||||
// super( context );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileMonitor monitor, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer,
|
||||
int lightmapCoord, int overlayLight )
|
||||
@@ -59,10 +55,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
|
||||
// Render from the origin monitor
|
||||
ClientMonitor originTerminal = monitor.getClientMonitor();
|
||||
|
||||
if( originTerminal == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( originTerminal == null ) return;
|
||||
TileMonitor origin = originTerminal.getOrigin();
|
||||
BlockPos monitorPos = monitor.getPos();
|
||||
|
||||
@@ -92,11 +85,11 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
|
||||
originPos.getY() - monitorPos.getY() + 0.5,
|
||||
originPos.getZ() - monitorPos.getZ() + 0.5 );
|
||||
|
||||
transform.multiply( Vector3f.NEGATIVE_Y.getDegreesQuaternion( yaw ) );
|
||||
transform.multiply( Vector3f.POSITIVE_X.getDegreesQuaternion( pitch ) );
|
||||
transform.multiply( Vec3f.NEGATIVE_Y.getDegreesQuaternion( yaw ) );
|
||||
transform.multiply( Vec3f.POSITIVE_X.getDegreesQuaternion( pitch ) );
|
||||
transform.translate( -0.5 + TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN,
|
||||
origin.getHeight() - 0.5 - (TileMonitor.RENDER_BORDER + TileMonitor.RENDER_MARGIN) + 0,
|
||||
0.5 );
|
||||
0.50 );
|
||||
double xSize = origin.getWidth() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
||||
double ySize = origin.getHeight() - 2.0 * (TileMonitor.RENDER_MARGIN + TileMonitor.RENDER_BORDER);
|
||||
|
||||
@@ -112,22 +105,24 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
|
||||
transform.push();
|
||||
transform.scale( (float) xScale, (float) -yScale, 1.0f );
|
||||
|
||||
Matrix4f matrix = transform.peek()
|
||||
.getModel();
|
||||
Matrix4f matrix = transform.peek().getModel();
|
||||
|
||||
// Sneaky hack here: we get a buffer now in order to flush existing ones and set up the appropriate
|
||||
// render state. I've no clue how well this'll work in future versions of Minecraft, but it does the trick
|
||||
// for now.
|
||||
VertexConsumer buffer = renderer.getBuffer( FixedWidthFontRenderer.TYPE );
|
||||
FixedWidthFontRenderer.TYPE.startDrawing();
|
||||
|
||||
renderTerminal( matrix, originTerminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale) );
|
||||
renderTerminal( renderer, matrix, originTerminal, (float) (MARGIN / xScale), (float) (MARGIN / yScale) );
|
||||
|
||||
// We don't draw the cursor with the VBO, as it's dynamic and so we'll end up refreshing far more than is
|
||||
// reasonable.
|
||||
FixedWidthFontRenderer.drawCursor( matrix, buffer, 0, 0, terminal, !originTerminal.isColour() );
|
||||
FixedWidthFontRenderer.drawCursor( matrix, renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH ), 0, 0, terminal, !originTerminal.isColour() );
|
||||
|
||||
transform.pop();
|
||||
|
||||
// Draw the background blocker
|
||||
FixedWidthFontRenderer.drawBlocker(
|
||||
transform.peek().getModel(), renderer,
|
||||
-MARGIN, MARGIN,
|
||||
(float) (xSize + 2 * MARGIN), (float) -(ySize + MARGIN * 2)
|
||||
);
|
||||
|
||||
renderer.getBuffer( RenderLayer.getSolid() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -140,18 +135,10 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
|
||||
(float) -(ySize + MARGIN * 2) );
|
||||
}
|
||||
|
||||
FixedWidthFontRenderer.drawBlocker( transform.peek()
|
||||
.getModel(),
|
||||
renderer,
|
||||
(float) -TileMonitor.RENDER_MARGIN,
|
||||
(float) TileMonitor.RENDER_MARGIN,
|
||||
(float) (xSize + 2 * TileMonitor.RENDER_MARGIN),
|
||||
(float) -(ySize + TileMonitor.RENDER_MARGIN * 2) );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
private static void renderTerminal( Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin )
|
||||
private static void renderTerminal( VertexConsumerProvider renderer, Matrix4f matrix, ClientMonitor monitor, float xMargin, float yMargin )
|
||||
{
|
||||
Terminal terminal = monitor.getTerminal();
|
||||
|
||||
@@ -166,10 +153,6 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
|
||||
{
|
||||
case TBO:
|
||||
{
|
||||
if( !MonitorTextureBufferShader.use() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int width = terminal.getWidth(), height = terminal.getHeight();
|
||||
int pixelWidth = width * FONT_WIDTH, pixelHeight = height * FONT_HEIGHT;
|
||||
@@ -179,7 +162,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
|
||||
int size = width * height * 3;
|
||||
if( tboContents == null || tboContents.capacity() < size )
|
||||
{
|
||||
tboContents = GlAllocationUtils.allocateByteBuffer( size );
|
||||
tboContents = allocateByteBuffer( size );
|
||||
}
|
||||
|
||||
ByteBuffer monitorBuffer = tboContents;
|
||||
@@ -196,43 +179,37 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
|
||||
}
|
||||
monitorBuffer.flip();
|
||||
|
||||
GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer );
|
||||
GlStateManager.bufferData( GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL20.GL_STATIC_DRAW );
|
||||
GlStateManager.bindBuffers( GL31.GL_TEXTURE_BUFFER, 0 );
|
||||
GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, monitor.tboBuffer );
|
||||
GlStateManager._glBufferData( GL31.GL_TEXTURE_BUFFER, monitorBuffer, GL20.GL_STATIC_DRAW );
|
||||
GlStateManager._glBindBuffer( GL31.GL_TEXTURE_BUFFER, 0 );
|
||||
}
|
||||
|
||||
// Nobody knows what they're doing!
|
||||
GlStateManager.activeTexture( MonitorTextureBufferShader.TEXTURE_INDEX );
|
||||
int active = GlStateManager._getActiveTexture();
|
||||
RenderSystem.activeTexture( MonitorTextureBufferShader.TEXTURE_INDEX );
|
||||
GL11.glBindTexture( GL31.GL_TEXTURE_BUFFER, monitor.tboTexture );
|
||||
GlStateManager.activeTexture( GL13.GL_TEXTURE0 );
|
||||
RenderSystem.activeTexture( active );
|
||||
|
||||
MonitorTextureBufferShader.setupUniform( matrix, width, height, terminal.getPalette(), !monitor.isColour() );
|
||||
MonitorTextureBufferShader shader = RenderTypes.getMonitorTextureBufferShader();
|
||||
shader.setupUniform( width, height, terminal.getPalette(), !monitor.isColour() );
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
buffer.begin( GL11.GL_TRIANGLE_STRIP, VertexFormats.POSITION );
|
||||
buffer.vertex( -xMargin, -yMargin, 0 )
|
||||
.next();
|
||||
buffer.vertex( -xMargin, pixelHeight + yMargin, 0 )
|
||||
.next();
|
||||
buffer.vertex( pixelWidth + xMargin, -yMargin, 0 )
|
||||
.next();
|
||||
buffer.vertex( pixelWidth + xMargin, pixelHeight + yMargin, 0 )
|
||||
.next();
|
||||
tessellator.draw();
|
||||
VertexConsumer buffer = renderer.getBuffer( RenderTypes.MONITOR_TBO );
|
||||
tboVertex( buffer, matrix, -xMargin, -yMargin );
|
||||
tboVertex( buffer, matrix, -xMargin, pixelHeight + yMargin );
|
||||
tboVertex( buffer, matrix, pixelWidth + xMargin, -yMargin );
|
||||
tboVertex( buffer, matrix, pixelWidth + xMargin, pixelHeight + yMargin );
|
||||
|
||||
GlStateManager.useProgram( 0 );
|
||||
renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
|
||||
break;
|
||||
}
|
||||
|
||||
case VBO:
|
||||
{
|
||||
VertexBuffer vbo = monitor.buffer;
|
||||
if( redraw )
|
||||
{
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder builder = tessellator.getBuffer();
|
||||
builder.begin( FixedWidthFontRenderer.TYPE.getDrawMode(), FixedWidthFontRenderer.TYPE.getVertexFormat() );
|
||||
builder.begin( RenderTypes.TERMINAL_WITHOUT_DEPTH.getDrawMode(), RenderTypes.TERMINAL_WITHOUT_DEPTH.getVertexFormat() );
|
||||
FixedWidthFontRenderer.drawTerminalWithoutCursor( IDENTITY,
|
||||
builder,
|
||||
0,
|
||||
@@ -248,15 +225,23 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
|
||||
vbo.upload( builder );
|
||||
}
|
||||
|
||||
vbo.bind();
|
||||
FixedWidthFontRenderer.TYPE.getVertexFormat()
|
||||
.startDrawing( 0L );
|
||||
vbo.draw( matrix, FixedWidthFontRenderer.TYPE.getDrawMode() );
|
||||
VertexBuffer.unbind();
|
||||
FixedWidthFontRenderer.TYPE.getVertexFormat()
|
||||
.endDrawing();
|
||||
renderer.getBuffer( RenderTypes.TERMINAL_WITHOUT_DEPTH );
|
||||
|
||||
RenderTypes.TERMINAL_WITHOUT_DEPTH.startDrawing();
|
||||
vbo.setShader( matrix, RenderSystem.getProjectionMatrix(), RenderTypes.getTerminalShader() );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void tboVertex( VertexConsumer builder, Matrix4f matrix, float x, float y )
|
||||
{
|
||||
// We encode position in the UV, as that's not transformed by the matrix.
|
||||
builder.vertex( matrix, x, y, 0 ).texture( x, y ).next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRenderDistance()
|
||||
{
|
||||
return ComputerCraft.monitorDistance;
|
||||
}
|
||||
}
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
@@ -21,24 +20,25 @@ import net.minecraft.client.render.VertexConsumer;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderDispatcher;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRenderer;
|
||||
import net.minecraft.client.render.block.entity.BlockEntityRendererFactory;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedModelManager;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.util.ModelIdentifier;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.hit.BlockHitResult;
|
||||
import net.minecraft.util.hit.HitResult;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.Matrix4f;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.Vec3f;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
|
||||
public class TileEntityTurtleRenderer implements BlockEntityRenderer<TileTurtle>
|
||||
{
|
||||
private static final ModelIdentifier NORMAL_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_normal", "inventory" );
|
||||
private static final ModelIdentifier ADVANCED_TURTLE_MODEL = new ModelIdentifier( "computercraft:turtle_advanced", "inventory" );
|
||||
@@ -47,9 +47,11 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
|
||||
|
||||
private final Random random = new Random( 0 );
|
||||
|
||||
public TileEntityTurtleRenderer( BlockEntityRenderDispatcher renderDispatcher )
|
||||
BlockEntityRenderDispatcher renderer;
|
||||
|
||||
public TileEntityTurtleRenderer( BlockEntityRendererFactory.Context context )
|
||||
{
|
||||
super( renderDispatcher );
|
||||
renderer = context.getRenderDispatcher();
|
||||
}
|
||||
|
||||
public static ModelIdentifier getTurtleModel( ComputerFamily family, boolean coloured )
|
||||
@@ -77,6 +79,118 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider buffers,
|
||||
int lightmapCoord, int overlayLight )
|
||||
{
|
||||
// Render the label
|
||||
String label = turtle.createProxy()
|
||||
.getLabel();
|
||||
HitResult hit = renderer.crosshairTarget;
|
||||
if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getPos()
|
||||
.equals( ((BlockHitResult) hit).getBlockPos() ) )
|
||||
{
|
||||
MinecraftClient mc = MinecraftClient.getInstance();
|
||||
TextRenderer font = mc.textRenderer;
|
||||
|
||||
transform.push();
|
||||
transform.translate( 0.5, 1.2, 0.5 );
|
||||
transform.multiply( mc.getEntityRenderDispatcher()
|
||||
.getRotation() );
|
||||
transform.scale( -0.025f, -0.025f, 0.025f );
|
||||
|
||||
Matrix4f matrix = transform.peek()
|
||||
.getModel();
|
||||
int opacity = (int) (mc.options.getTextBackgroundOpacity( 0.25f ) * 255) << 24;
|
||||
float width = -font.getWidth( label ) / 2.0f;
|
||||
font.draw( label, width, (float) 0, 0x20ffffff, false, matrix, buffers, true, opacity, lightmapCoord );
|
||||
font.draw( label, width, (float) 0, 0xffffffff, false, matrix, buffers, false, 0, lightmapCoord );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
transform.push();
|
||||
|
||||
// Setup the transform.
|
||||
Vec3d offset = turtle.getRenderOffset( partialTicks );
|
||||
float yaw = turtle.getRenderYaw( partialTicks );
|
||||
transform.translate( offset.x, offset.y, offset.z );
|
||||
|
||||
transform.translate( 0.5f, 0.5f, 0.5f );
|
||||
transform.multiply( Vec3f.POSITIVE_Y.getDegreesQuaternion( 180.0f - yaw ) );
|
||||
if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) )
|
||||
{
|
||||
// Flip the model
|
||||
transform.scale( 1.0f, -1.0f, 1.0f );
|
||||
}
|
||||
transform.translate( -0.5f, -0.5f, -0.5f );
|
||||
|
||||
// Render the turtle
|
||||
int colour = turtle.getColour();
|
||||
ComputerFamily family = turtle.getFamily();
|
||||
Identifier overlay = turtle.getOverlay();
|
||||
|
||||
VertexConsumer buffer = buffers.getBuffer( TexturedRenderLayers.getEntityTranslucentCull() );
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
|
||||
|
||||
// Render the overlay
|
||||
ModelIdentifier overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS );
|
||||
if( overlayModel != null )
|
||||
{
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null );
|
||||
}
|
||||
|
||||
// Render the upgrades
|
||||
renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks );
|
||||
renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.RIGHT, partialTicks );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
private void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
|
||||
TurtleSide side, float f )
|
||||
{
|
||||
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
|
||||
if( upgrade == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
transform.push();
|
||||
|
||||
float toolAngle = turtle.getToolRenderAngle( side, f );
|
||||
transform.translate( 0.0f, 0.5f, 0.5f );
|
||||
transform.multiply( Vec3f.NEGATIVE_X.getDegreesQuaternion( toolAngle ) );
|
||||
transform.translate( 0.0f, -0.5f, -0.5f );
|
||||
|
||||
TransformedModel model = upgrade.getModel( turtle.getAccess(), side );
|
||||
model.push( transform );
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, model.getModel(), null );
|
||||
transform.pop();
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
private void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
|
||||
ModelIdentifier modelLocation, int[] tints )
|
||||
{
|
||||
BakedModelManager modelManager = MinecraftClient.getInstance()
|
||||
.getItemRenderer()
|
||||
.getModels()
|
||||
.getModelManager();
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
|
||||
}
|
||||
|
||||
private void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
|
||||
int[] tints )
|
||||
{
|
||||
random.setSeed( 0 );
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints );
|
||||
for( Direction facing : DirectionUtil.FACINGS )
|
||||
{
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random ), tints );
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderQuads( @Nonnull MatrixStack transform, @Nonnull VertexConsumer buffer, int lightmapCoord, int overlayLight,
|
||||
List<BakedQuad> quads, int[] tints )
|
||||
{
|
||||
@@ -108,117 +222,4 @@ public class TileEntityTurtleRenderer extends BlockEntityRenderer<TileTurtle>
|
||||
true );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void render( @Nonnull TileTurtle turtle, float partialTicks, @Nonnull MatrixStack transform, @Nonnull VertexConsumerProvider renderer,
|
||||
int lightmapCoord, int overlayLight )
|
||||
{
|
||||
// Render the label
|
||||
String label = turtle.createProxy()
|
||||
.getLabel();
|
||||
HitResult hit = this.dispatcher.crosshairTarget;
|
||||
if( label != null && hit.getType() == HitResult.Type.BLOCK && turtle.getPos()
|
||||
.equals( ((BlockHitResult) hit).getBlockPos() ) )
|
||||
{
|
||||
MinecraftClient mc = MinecraftClient.getInstance();
|
||||
TextRenderer font = mc.textRenderer;
|
||||
|
||||
transform.push();
|
||||
transform.translate( 0.5, 1.2, 0.5 );
|
||||
transform.multiply( mc.getEntityRenderDispatcher()
|
||||
.getRotation() );
|
||||
transform.scale( -0.025f, -0.025f, 0.025f );
|
||||
|
||||
Matrix4f matrix = transform.peek()
|
||||
.getModel();
|
||||
int opacity = (int) (mc.options.getTextBackgroundOpacity( 0.25f ) * 255) << 24;
|
||||
float width = -font.getWidth( label ) / 2.0f;
|
||||
font.draw( label, width, (float) 0, 0x20ffffff, false, matrix, renderer, true, opacity, lightmapCoord );
|
||||
font.draw( label, width, (float) 0, 0xffffffff, false, matrix, renderer, false, 0, lightmapCoord );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
transform.push();
|
||||
|
||||
// Setup the transform.
|
||||
Vec3d offset = turtle.getRenderOffset( partialTicks );
|
||||
float yaw = turtle.getRenderYaw( partialTicks );
|
||||
transform.translate( offset.x, offset.y, offset.z );
|
||||
|
||||
transform.translate( 0.5f, 0.5f, 0.5f );
|
||||
transform.multiply( Vector3f.POSITIVE_Y.getDegreesQuaternion( 180.0f - yaw ) );
|
||||
if( label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" )) )
|
||||
{
|
||||
// Flip the model
|
||||
transform.scale( 1.0f, -1.0f, 1.0f );
|
||||
}
|
||||
transform.translate( -0.5f, -0.5f, -0.5f );
|
||||
|
||||
// Render the turtle
|
||||
int colour = turtle.getColour();
|
||||
ComputerFamily family = turtle.getFamily();
|
||||
Identifier overlay = turtle.getOverlay();
|
||||
|
||||
VertexConsumer buffer = renderer.getBuffer( TexturedRenderLayers.getEntityTranslucentCull() );
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, getTurtleModel( family, colour != -1 ), colour == -1 ? null : new int[] { colour } );
|
||||
|
||||
// Render the overlay
|
||||
ModelIdentifier overlayModel = getTurtleOverlayModel( overlay, HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS );
|
||||
if( overlayModel != null )
|
||||
{
|
||||
renderModel( transform, buffer, lightmapCoord, overlayLight, overlayModel, null );
|
||||
}
|
||||
|
||||
// Render the upgrades
|
||||
renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.LEFT, partialTicks );
|
||||
renderUpgrade( transform, buffer, lightmapCoord, overlayLight, turtle, TurtleSide.RIGHT, partialTicks );
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
public static void renderUpgrade( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, TileTurtle turtle,
|
||||
TurtleSide side, float f )
|
||||
{
|
||||
ITurtleUpgrade upgrade = turtle.getUpgrade( side );
|
||||
if( upgrade == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
transform.push();
|
||||
|
||||
float toolAngle = turtle.getToolRenderAngle( side, f );
|
||||
transform.translate( 0.0f, 0.5f, 0.5f );
|
||||
transform.multiply( Vector3f.NEGATIVE_X.getDegreesQuaternion( toolAngle ) );
|
||||
transform.translate( 0.0f, -0.5f, -0.5f );
|
||||
|
||||
TransformedModel model = upgrade.getModel( turtle.getAccess(), side );
|
||||
model.push( transform );
|
||||
TileEntityTurtleRenderer.renderModel( transform, renderer, lightmapCoord, overlayLight, model.getModel(), null );
|
||||
transform.pop();
|
||||
|
||||
transform.pop();
|
||||
}
|
||||
|
||||
public static void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight,
|
||||
ModelIdentifier modelLocation, int[] tints )
|
||||
{
|
||||
BakedModelManager modelManager = MinecraftClient.getInstance()
|
||||
.getItemRenderer()
|
||||
.getModels()
|
||||
.getModelManager();
|
||||
renderModel( transform, renderer, lightmapCoord, overlayLight, modelManager.getModel( modelLocation ), tints );
|
||||
}
|
||||
|
||||
public static void renderModel( @Nonnull MatrixStack transform, @Nonnull VertexConsumer renderer, int lightmapCoord, int overlayLight, BakedModel model,
|
||||
int[] tints )
|
||||
{
|
||||
Random random = new Random();
|
||||
random.setSeed( 0 );
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, null, random ), tints );
|
||||
for( Direction facing : DirectionUtil.FACINGS )
|
||||
{
|
||||
renderQuads( transform, renderer, lightmapCoord, overlayLight, model.getQuads( null, facing, random ), tints );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -76,7 +76,7 @@ public final class TurtleModelLoader
|
||||
public Collection<SpriteIdentifier> getTextureDependencies( Function<Identifier, UnbakedModel> modelGetter,
|
||||
Set<Pair<String, String>> missingTextureErrors )
|
||||
{
|
||||
return this.getModelDependencies()
|
||||
return getModelDependencies()
|
||||
.stream()
|
||||
.flatMap( x -> modelGetter.apply( x )
|
||||
.getTextureDependencies( modelGetter, missingTextureErrors )
|
||||
@@ -88,14 +88,14 @@ public final class TurtleModelLoader
|
||||
@Override
|
||||
public Collection<Identifier> getModelDependencies()
|
||||
{
|
||||
return Arrays.asList( this.family, COLOUR_TURTLE_MODEL );
|
||||
return Arrays.asList( family, COLOUR_TURTLE_MODEL );
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake( @Nonnull ModelLoader loader, @Nonnull Function<SpriteIdentifier, Sprite> spriteGetter, @Nonnull ModelBakeSettings state,
|
||||
Identifier modelId )
|
||||
{
|
||||
return new TurtleSmartItemModel( loader.getOrLoadModel( this.family )
|
||||
return new TurtleSmartItemModel( loader.getOrLoadModel( family )
|
||||
.bake( loader, spriteGetter, state, modelId ),
|
||||
loader.getOrLoadModel( COLOUR_TURTLE_MODEL )
|
||||
.bake( loader, spriteGetter, state, modelId ) );
|
||||
|
@@ -13,8 +13,9 @@ import net.minecraft.block.BlockState;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.math.AffineTransformation;
|
||||
import net.minecraft.util.math.AffineTransformation;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -29,7 +30,7 @@ public class TurtleMultiModel implements BakedModel
|
||||
private final TransformedModel leftUpgradeModel;
|
||||
private final TransformedModel rightUpgradeModel;
|
||||
private List<BakedQuad> generalQuads = null;
|
||||
private Map<Direction, List<BakedQuad>> faceQuads = new EnumMap<>( Direction.class );
|
||||
private final Map<Direction, List<BakedQuad>> faceQuads = new EnumMap<>( Direction.class );
|
||||
|
||||
public TurtleMultiModel( BakedModel baseModel, BakedModel overlayModel, AffineTransformation generalTransform, TransformedModel leftUpgradeModel,
|
||||
TransformedModel rightUpgradeModel )
|
||||
@@ -48,19 +49,19 @@ public class TurtleMultiModel implements BakedModel
|
||||
{
|
||||
if( side != null )
|
||||
{
|
||||
if( !this.faceQuads.containsKey( side ) )
|
||||
if( !faceQuads.containsKey( side ) )
|
||||
{
|
||||
this.faceQuads.put( side, this.buildQuads( state, side, rand ) );
|
||||
faceQuads.put( side, buildQuads( state, side, rand ) );
|
||||
}
|
||||
return this.faceQuads.get( side );
|
||||
return faceQuads.get( side );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( this.generalQuads == null )
|
||||
if( generalQuads == null )
|
||||
{
|
||||
this.generalQuads = this.buildQuads( state, side, rand );
|
||||
generalQuads = buildQuads( state, side, rand );
|
||||
}
|
||||
return this.generalQuads;
|
||||
return generalQuads;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,22 +70,22 @@ public class TurtleMultiModel implements BakedModel
|
||||
ArrayList<BakedQuad> quads = new ArrayList<>();
|
||||
|
||||
|
||||
ModelTransformer.transformQuadsTo( quads, this.baseModel.getQuads( state, side, rand ), this.generalTransform.getMatrix() );
|
||||
if( this.overlayModel != null )
|
||||
ModelTransformer.transformQuadsTo( quads, baseModel.getQuads( state, side, rand ), generalTransform.getMatrix() );
|
||||
if( overlayModel != null )
|
||||
{
|
||||
ModelTransformer.transformQuadsTo( quads, this.overlayModel.getQuads( state, side, rand ), this.generalTransform.getMatrix() );
|
||||
ModelTransformer.transformQuadsTo( quads, overlayModel.getQuads( state, side, rand ), generalTransform.getMatrix() );
|
||||
}
|
||||
if( this.leftUpgradeModel != null )
|
||||
if( leftUpgradeModel != null )
|
||||
{
|
||||
AffineTransformation upgradeTransform = this.generalTransform.multiply( this.leftUpgradeModel.getMatrix() );
|
||||
ModelTransformer.transformQuadsTo( quads, this.leftUpgradeModel.getModel()
|
||||
AffineTransformation upgradeTransform = generalTransform.multiply( leftUpgradeModel.getMatrix() );
|
||||
ModelTransformer.transformQuadsTo( quads, leftUpgradeModel.getModel()
|
||||
.getQuads( state, side, rand ),
|
||||
upgradeTransform.getMatrix() );
|
||||
}
|
||||
if( this.rightUpgradeModel != null )
|
||||
if( rightUpgradeModel != null )
|
||||
{
|
||||
AffineTransformation upgradeTransform = this.generalTransform.multiply( this.rightUpgradeModel.getMatrix() );
|
||||
ModelTransformer.transformQuadsTo( quads, this.rightUpgradeModel.getModel()
|
||||
AffineTransformation upgradeTransform = generalTransform.multiply( rightUpgradeModel.getMatrix() );
|
||||
ModelTransformer.transformQuadsTo( quads, rightUpgradeModel.getModel()
|
||||
.getQuads( state, side, rand ),
|
||||
upgradeTransform.getMatrix() );
|
||||
}
|
||||
@@ -95,41 +96,41 @@ public class TurtleMultiModel implements BakedModel
|
||||
@Override
|
||||
public boolean useAmbientOcclusion()
|
||||
{
|
||||
return this.baseModel.useAmbientOcclusion();
|
||||
return baseModel.useAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth()
|
||||
{
|
||||
return this.baseModel.hasDepth();
|
||||
return baseModel.hasDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit()
|
||||
{
|
||||
return this.baseModel.isSideLit();
|
||||
return baseModel.isSideLit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin()
|
||||
{
|
||||
return this.baseModel.isBuiltin();
|
||||
return baseModel.isBuiltin();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public Sprite getSprite()
|
||||
public Sprite getParticleSprite()
|
||||
{
|
||||
return this.baseModel.getSprite();
|
||||
return baseModel.getParticleSprite();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public net.minecraft.client.render.model.json.ModelTransformation getTransformation()
|
||||
public ModelTransformation getTransformation()
|
||||
{
|
||||
return this.baseModel.getTransformation();
|
||||
return baseModel.getTransformation();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
@@ -6,25 +6,19 @@
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import dan200.computercraft.shared.turtle.core.TurtlePlayer;
|
||||
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
|
||||
import net.minecraft.client.render.VertexConsumerProvider;
|
||||
import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
||||
import net.minecraft.client.render.entity.EntityRenderer;
|
||||
import net.minecraft.client.render.entity.EntityRendererFactory;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class TurtlePlayerRenderer extends EntityRenderer<TurtlePlayer>
|
||||
{
|
||||
public TurtlePlayerRenderer( EntityRenderDispatcher renderManager )
|
||||
{ //FIXME Make sure this isn't an issue. Context was EntityRenderDispatcher.
|
||||
public TurtlePlayerRenderer( EntityRendererFactory.Context context )
|
||||
{
|
||||
super( renderManager );
|
||||
}
|
||||
|
||||
public TurtlePlayerRenderer( EntityRenderDispatcher entityRenderDispatcher, EntityRendererRegistry.Context context )
|
||||
{
|
||||
super( entityRenderDispatcher );
|
||||
super( context );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -3,7 +3,6 @@
|
||||
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
||||
* Send enquiries to dratcliffe@gmail.com
|
||||
*/
|
||||
|
||||
package dan200.computercraft.client.render;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
@@ -24,12 +23,12 @@ import net.minecraft.client.render.model.json.ModelOverrideList;
|
||||
import net.minecraft.client.render.model.json.ModelTransformation;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import net.minecraft.client.util.ModelIdentifier;
|
||||
import net.minecraft.client.util.math.AffineTransformation;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.AffineTransformation;
|
||||
import net.minecraft.util.math.Direction;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -55,117 +54,6 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
.getModel() );
|
||||
}
|
||||
|
||||
private final BakedModel familyModel;
|
||||
private final BakedModel colourModel;
|
||||
private final HashMap<TurtleModelCombination, BakedModel> cachedModels = new HashMap<>();
|
||||
private final ModelOverrideList overrides;
|
||||
|
||||
public TurtleSmartItemModel( BakedModel familyModel, BakedModel colourModel )
|
||||
{
|
||||
this.familyModel = familyModel;
|
||||
this.colourModel = colourModel;
|
||||
|
||||
// this actually works I think, trust me
|
||||
this.overrides = new ModelOverrideList( null, null, null, Collections.emptyList() )
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
public BakedModel apply( @Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientWorld world,
|
||||
@Nullable LivingEntity entity )
|
||||
{
|
||||
ItemTurtle turtle = (ItemTurtle) stack.getItem();
|
||||
int colour = turtle.getColour( stack );
|
||||
ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.LEFT );
|
||||
ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.RIGHT );
|
||||
Identifier overlay = turtle.getOverlay( stack );
|
||||
boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS;
|
||||
String label = turtle.getLabel( stack );
|
||||
// TODO make upside down turtle items render properly (currently inivisible)
|
||||
//boolean flip = label != null && (label.equals("Dinnerbone") || label.equals("Grumm"));
|
||||
boolean flip = false;
|
||||
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
|
||||
|
||||
BakedModel model = TurtleSmartItemModel.this.cachedModels.get( combo );
|
||||
if( model == null )
|
||||
{
|
||||
TurtleSmartItemModel.this.cachedModels.put( combo, model = TurtleSmartItemModel.this.buildModel( combo ) );
|
||||
}
|
||||
return model;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private BakedModel buildModel( TurtleModelCombination combo )
|
||||
{
|
||||
MinecraftClient mc = MinecraftClient.getInstance();
|
||||
BakedModelManager modelManager = mc.getItemRenderer()
|
||||
.getModels()
|
||||
.getModelManager();
|
||||
ModelIdentifier overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay, combo.christmas );
|
||||
|
||||
BakedModel baseModel = combo.colour ? this.colourModel : this.familyModel;
|
||||
BakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel( overlayModelLocation ) : null;
|
||||
AffineTransformation transform = combo.flip ? flip : identity;
|
||||
TransformedModel leftModel = combo.leftUpgrade != null ? combo.leftUpgrade.getModel( null, TurtleSide.LEFT ) : null;
|
||||
TransformedModel rightModel = combo.rightUpgrade != null ? combo.rightUpgrade.getModel( null, TurtleSide.RIGHT ) : null;
|
||||
return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel, rightModel );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public List<BakedQuad> getQuads( BlockState state, Direction facing, @Nonnull Random rand )
|
||||
{
|
||||
return this.familyModel.getQuads( state, facing, rand );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion()
|
||||
{
|
||||
return this.familyModel.useAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth()
|
||||
{
|
||||
return this.familyModel.hasDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit()
|
||||
{
|
||||
return this.familyModel.isSideLit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin()
|
||||
{
|
||||
return this.familyModel.isBuiltin();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public Sprite getSprite()
|
||||
{
|
||||
return this.familyModel.getSprite();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public ModelTransformation getTransformation()
|
||||
{
|
||||
return this.familyModel.getTransformation();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ModelOverrideList getOverrides()
|
||||
{
|
||||
return this.overrides;
|
||||
}
|
||||
|
||||
private static class TurtleModelCombination
|
||||
{
|
||||
final boolean colour;
|
||||
@@ -186,20 +74,6 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
this.flip = flip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 0;
|
||||
result = prime * result + (this.colour ? 1 : 0);
|
||||
result = prime * result + (this.leftUpgrade != null ? this.leftUpgrade.hashCode() : 0);
|
||||
result = prime * result + (this.rightUpgrade != null ? this.rightUpgrade.hashCode() : 0);
|
||||
result = prime * result + (this.overlay != null ? this.overlay.hashCode() : 0);
|
||||
result = prime * result + (this.christmas ? 1 : 0);
|
||||
result = prime * result + (this.flip ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals( Object other )
|
||||
{
|
||||
@@ -207,15 +81,136 @@ public class TurtleSmartItemModel implements BakedModel
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if( !(other instanceof TurtleModelCombination) )
|
||||
if( !(other instanceof TurtleModelCombination otherCombo) )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
TurtleModelCombination otherCombo = (TurtleModelCombination) other;
|
||||
return otherCombo.colour == this.colour && otherCombo.leftUpgrade == this.leftUpgrade && otherCombo.rightUpgrade == this.rightUpgrade && Objects.equal(
|
||||
otherCombo.overlay, this.overlay ) && otherCombo.christmas == this.christmas && otherCombo.flip == this.flip;
|
||||
return otherCombo.colour == colour && otherCombo.leftUpgrade == leftUpgrade && otherCombo.rightUpgrade == rightUpgrade && Objects.equal(
|
||||
otherCombo.overlay, overlay ) && otherCombo.christmas == christmas && otherCombo.flip == flip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
final int prime = 31;
|
||||
int result = 0;
|
||||
result = prime * result + (colour ? 1 : 0);
|
||||
result = prime * result + (leftUpgrade != null ? leftUpgrade.hashCode() : 0);
|
||||
result = prime * result + (rightUpgrade != null ? rightUpgrade.hashCode() : 0);
|
||||
result = prime * result + (overlay != null ? overlay.hashCode() : 0);
|
||||
result = prime * result + (christmas ? 1 : 0);
|
||||
result = prime * result + (flip ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private final BakedModel familyModel;
|
||||
private final BakedModel colourModel;
|
||||
|
||||
private final HashMap<TurtleModelCombination, BakedModel> cachedModels = new HashMap<>();
|
||||
private final ModelOverrideList overrides;
|
||||
|
||||
public TurtleSmartItemModel( BakedModel familyModel, BakedModel colourModel )
|
||||
{
|
||||
this.familyModel = familyModel;
|
||||
this.colourModel = colourModel;
|
||||
|
||||
// this actually works I think, trust me
|
||||
overrides = new ModelOverrideList( null, null, null, Collections.emptyList() )
|
||||
{
|
||||
@Nonnull
|
||||
@Override
|
||||
public BakedModel apply( BakedModel originalModel, ItemStack stack, @Nullable ClientWorld world, @Nullable LivingEntity entity, int seed )
|
||||
{
|
||||
ItemTurtle turtle = (ItemTurtle) stack.getItem();
|
||||
int colour = turtle.getColour( stack );
|
||||
ITurtleUpgrade leftUpgrade = turtle.getUpgrade( stack, TurtleSide.LEFT );
|
||||
ITurtleUpgrade rightUpgrade = turtle.getUpgrade( stack, TurtleSide.RIGHT );
|
||||
Identifier overlay = turtle.getOverlay( stack );
|
||||
boolean christmas = HolidayUtil.getCurrentHoliday() == Holiday.CHRISTMAS;
|
||||
String label = turtle.getLabel( stack );
|
||||
boolean flip = label != null && (label.equals( "Dinnerbone" ) || label.equals( "Grumm" ));
|
||||
TurtleModelCombination combo = new TurtleModelCombination( colour != -1, leftUpgrade, rightUpgrade, overlay, christmas, flip );
|
||||
|
||||
BakedModel model = cachedModels.get( combo );
|
||||
if( model == null )
|
||||
{
|
||||
cachedModels.put( combo, model = buildModel( combo ) );
|
||||
}
|
||||
return model;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private BakedModel buildModel( TurtleModelCombination combo )
|
||||
{
|
||||
MinecraftClient mc = MinecraftClient.getInstance();
|
||||
BakedModelManager modelManager = mc.getItemRenderer()
|
||||
.getModels()
|
||||
.getModelManager();
|
||||
ModelIdentifier overlayModelLocation = TileEntityTurtleRenderer.getTurtleOverlayModel( combo.overlay, combo.christmas );
|
||||
|
||||
BakedModel baseModel = combo.colour ? colourModel : familyModel;
|
||||
BakedModel overlayModel = overlayModelLocation != null ? modelManager.getModel( overlayModelLocation ) : null;
|
||||
AffineTransformation transform = combo.flip ? flip : identity;
|
||||
TransformedModel leftModel = combo.leftUpgrade != null ? combo.leftUpgrade.getModel( null, TurtleSide.LEFT ) : null;
|
||||
TransformedModel rightModel = combo.rightUpgrade != null ? combo.rightUpgrade.getModel( null, TurtleSide.RIGHT ) : null;
|
||||
return new TurtleMultiModel( baseModel, overlayModel, transform, leftModel, rightModel );
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public List<BakedQuad> getQuads( BlockState state, Direction facing, @Nonnull Random rand )
|
||||
{
|
||||
return familyModel.getQuads( state, facing, rand );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useAmbientOcclusion()
|
||||
{
|
||||
return familyModel.useAmbientOcclusion();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasDepth()
|
||||
{
|
||||
return familyModel.hasDepth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSideLit()
|
||||
{
|
||||
return familyModel.isSideLit();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBuiltin()
|
||||
{
|
||||
return familyModel.isBuiltin();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public Sprite getParticleSprite()
|
||||
{
|
||||
return familyModel.getParticleSprite();
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public ModelOverrideList getOverrides()
|
||||
{
|
||||
return overrides;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
@Deprecated
|
||||
public ModelTransformation getTransformation()
|
||||
{
|
||||
return familyModel.getTransformation();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@
|
||||
*/
|
||||
package dan200.computercraft.core.apis;
|
||||
|
||||
import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.filesystem.IMount;
|
||||
import dan200.computercraft.api.filesystem.IWritableMount;
|
||||
import dan200.computercraft.api.peripheral.IComputerAccess;
|
||||
@@ -30,6 +31,10 @@ public abstract class ComputerAccess implements IComputerAccess
|
||||
public void unmountAll()
|
||||
{
|
||||
FileSystem fileSystem = environment.getFileSystem();
|
||||
if( !mounts.isEmpty() )
|
||||
{
|
||||
ComputerCraft.log.warn( "Peripheral or API called mount but did not call unmount for {}", mounts );
|
||||
}
|
||||
for( String mount : mounts )
|
||||
{
|
||||
fileSystem.unmount( mount );
|
||||
|
@@ -344,11 +344,9 @@ public class FSAPI implements ILuaAPI
|
||||
return new Object[] { new EncodedWritableHandle( writer.get(), writer ) };
|
||||
}
|
||||
case "rb":
|
||||
{
|
||||
// Open the file for binary reading, then create a wrapper around the reader
|
||||
FileSystemWrapper<ReadableByteChannel> reader = fileSystem.openForRead( path, Function.identity() );
|
||||
return new Object[] { BinaryReadableHandle.of( reader.get(), reader ) };
|
||||
}
|
||||
case "wb":
|
||||
{
|
||||
// Open the file for binary writing, then create a wrapper around the writer
|
||||
@@ -356,11 +354,9 @@ public class FSAPI implements ILuaAPI
|
||||
return new Object[] { BinaryWritableHandle.of( writer.get(), writer ) };
|
||||
}
|
||||
case "ab":
|
||||
{
|
||||
// Open the file for binary appending, then create a wrapper around the reader
|
||||
FileSystemWrapper<WritableByteChannel> writer = fileSystem.openForWrite( path, true, Function.identity() );
|
||||
return new Object[] { BinaryWritableHandle.of( writer.get(), writer ) };
|
||||
}
|
||||
default:
|
||||
throw new LuaException( "Unsupported mode" );
|
||||
}
|
||||
|
@@ -62,6 +62,7 @@ public interface IAPIEnvironment
|
||||
@Nullable
|
||||
IPeripheral getPeripheral( ComputerSide side );
|
||||
|
||||
@Nullable
|
||||
String getLabel();
|
||||
|
||||
void setLabel( @Nullable String label );
|
||||
|
@@ -403,11 +403,9 @@ public class OSAPI implements ILuaAPI
|
||||
return getEpochForCalendar( c );
|
||||
}
|
||||
case "local":
|
||||
{
|
||||
// Get local epoch
|
||||
Calendar c = Calendar.getInstance();
|
||||
return getEpochForCalendar( c );
|
||||
}
|
||||
case "ingame":
|
||||
// Get in-game epoch
|
||||
synchronized( alarms )
|
||||
|
@@ -96,9 +96,8 @@ public abstract class HandleGeneric
|
||||
|
||||
protected static SeekableByteChannel asSeekable( Channel channel )
|
||||
{
|
||||
if( !(channel instanceof SeekableByteChannel) ) return null;
|
||||
if( !(channel instanceof SeekableByteChannel seekable) ) return null;
|
||||
|
||||
SeekableByteChannel seekable = (SeekableByteChannel) channel;
|
||||
try
|
||||
{
|
||||
seekable.position( seekable.position() );
|
||||
|
@@ -20,6 +20,8 @@ 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 io.netty.handler.traffic.AbstractTrafficShapingHandler;
|
||||
import io.netty.handler.traffic.GlobalTrafficShapingHandler;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.net.ssl.SSLException;
|
||||
@@ -28,9 +30,7 @@ import javax.net.ssl.TrustManagerFactory;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.security.KeyStore;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -38,10 +38,8 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public final class NetworkUtils
|
||||
{
|
||||
public static final ExecutorService EXECUTOR = new ThreadPoolExecutor(
|
||||
4, Integer.MAX_VALUE,
|
||||
60L, TimeUnit.SECONDS,
|
||||
new SynchronousQueue<>(),
|
||||
public static final ScheduledThreadPoolExecutor EXECUTOR = new ScheduledThreadPoolExecutor(
|
||||
4,
|
||||
ThreadUtils.builder( "Network" )
|
||||
.setPriority( Thread.MIN_PRIORITY + (Thread.NORM_PRIORITY - Thread.MIN_PRIORITY) / 2 )
|
||||
.build()
|
||||
@@ -52,6 +50,15 @@ public final class NetworkUtils
|
||||
.build()
|
||||
);
|
||||
|
||||
public static final AbstractTrafficShapingHandler SHAPING_HANDLER = new GlobalTrafficShapingHandler(
|
||||
EXECUTOR, ComputerCraft.httpUploadBandwidth, ComputerCraft.httpDownloadBandwidth
|
||||
);
|
||||
|
||||
static
|
||||
{
|
||||
EXECUTOR.setKeepAliveTime( 60, TimeUnit.SECONDS );
|
||||
}
|
||||
|
||||
private NetworkUtils()
|
||||
{
|
||||
}
|
||||
@@ -107,6 +114,16 @@ public final class NetworkUtils
|
||||
}
|
||||
}
|
||||
|
||||
public static void reloadConfig()
|
||||
{
|
||||
SHAPING_HANDLER.configure( ComputerCraft.httpUploadBandwidth, ComputerCraft.httpDownloadBandwidth );
|
||||
}
|
||||
|
||||
public static void reset()
|
||||
{
|
||||
SHAPING_HANDLER.trafficCounter().resetCumulativeTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link InetSocketAddress} from a {@link java.net.URI}.
|
||||
*
|
||||
@@ -184,7 +201,7 @@ public final class NetworkUtils
|
||||
{
|
||||
return "Timed out";
|
||||
}
|
||||
else if( cause instanceof SSLHandshakeException || (cause instanceof DecoderException && cause.getCause() instanceof SSLHandshakeException) )
|
||||
else if( cause instanceof SSLHandshakeException || cause instanceof DecoderException && cause.getCause() instanceof SSLHandshakeException )
|
||||
{
|
||||
return "Could not create a secure connection";
|
||||
}
|
||||
|
@@ -75,7 +75,7 @@ public final class AddressRule
|
||||
if( this.port != null && this.port != port ) return false;
|
||||
return predicate.matches( domain )
|
||||
|| predicate.matches( address )
|
||||
|| (ipv4Address != null && predicate.matches( ipv4Address ));
|
||||
|| ipv4Address != null && predicate.matches( ipv4Address );
|
||||
}
|
||||
|
||||
public static Options apply( Iterable<? extends AddressRule> rules, String domain, InetSocketAddress socketAddress )
|
||||
|
@@ -167,6 +167,7 @@ public class HttpRequest extends Resource<HttpRequest>
|
||||
}
|
||||
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
p.addLast( NetworkUtils.SHAPING_HANDLER );
|
||||
if( sslContext != null )
|
||||
{
|
||||
p.addLast( sslContext.newHandler( ch.alloc(), uri.getHost(), socketAddress.getPort() ) );
|
||||
|
@@ -100,9 +100,8 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpOb
|
||||
{
|
||||
if( closed || request.checkClosed() ) return;
|
||||
|
||||
if( message instanceof HttpResponse )
|
||||
if( message instanceof HttpResponse response )
|
||||
{
|
||||
HttpResponse response = (HttpResponse) message;
|
||||
|
||||
if( request.redirects.get() > 0 )
|
||||
{
|
||||
@@ -137,9 +136,8 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpOb
|
||||
responseHeaders.add( response.headers() );
|
||||
}
|
||||
|
||||
if( message instanceof HttpContent )
|
||||
if( message instanceof HttpContent content )
|
||||
{
|
||||
HttpContent content = (HttpContent) message;
|
||||
|
||||
if( responseBody == null )
|
||||
{
|
||||
@@ -162,9 +160,8 @@ public final class HttpRequestHandler extends SimpleChannelInboundHandler<HttpOb
|
||||
responseBody.addComponent( true, partial.retain() );
|
||||
}
|
||||
|
||||
if( message instanceof LastHttpContent )
|
||||
if( message instanceof LastHttpContent last )
|
||||
{
|
||||
LastHttpContent last = (LastHttpContent) message;
|
||||
responseHeaders.add( last.trailingHeaders() );
|
||||
|
||||
// Set the content length, if not already given.
|
||||
|
@@ -22,12 +22,12 @@ import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.HttpClientCodec;
|
||||
import io.netty.handler.codec.http.HttpHeaderNames;
|
||||
import io.netty.handler.codec.http.HttpHeaders;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
@@ -145,20 +145,22 @@ public class Websocket extends Resource<Websocket>
|
||||
protected void initChannel( SocketChannel ch )
|
||||
{
|
||||
ChannelPipeline p = ch.pipeline();
|
||||
p.addLast( NetworkUtils.SHAPING_HANDLER );
|
||||
if( sslContext != null )
|
||||
{
|
||||
p.addLast( sslContext.newHandler( ch.alloc(), uri.getHost(), socketAddress.getPort() ) );
|
||||
}
|
||||
|
||||
String subprotocol = headers.get( HttpHeaderNames.SEC_WEBSOCKET_PROTOCOL );
|
||||
WebSocketClientHandshaker handshaker = WebSocketClientHandshakerFactory.newHandshaker(
|
||||
uri, WebSocketVersion.V13, null, true, headers,
|
||||
uri, WebSocketVersion.V13, subprotocol, true, headers,
|
||||
options.websocketMessage <= 0 ? MAX_MESSAGE_SIZE : options.websocketMessage
|
||||
);
|
||||
|
||||
p.addLast(
|
||||
new HttpClientCodec(),
|
||||
new HttpObjectAggregator( 8192 ),
|
||||
WebSocketClientCompressionHandler.INSTANCE,
|
||||
WebsocketCompressionHandler.INSTANCE,
|
||||
new WebsocketHandler( Websocket.this, handshaker, options )
|
||||
);
|
||||
}
|
||||
|
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.core.apis.http.websocket;
|
||||
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.handler.codec.compression.ZlibCodecFactory;
|
||||
import io.netty.handler.codec.http.websocketx.extensions.WebSocketClientExtensionHandler;
|
||||
import io.netty.handler.codec.http.websocketx.extensions.compression.DeflateFrameClientExtensionHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.extensions.compression.PerMessageDeflateClientExtensionHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.extensions.compression.WebSocketClientCompressionHandler;
|
||||
|
||||
import static io.netty.handler.codec.http.websocketx.extensions.compression.PerMessageDeflateServerExtensionHandshaker.MAX_WINDOW_SIZE;
|
||||
|
||||
/**
|
||||
* An alternative to {@link WebSocketClientCompressionHandler} which supports the {@literal client_no_context_takeover}
|
||||
* extension. Makes CC <em>slightly</em> more flexible.
|
||||
*/
|
||||
@ChannelHandler.Sharable
|
||||
final class WebsocketCompressionHandler extends WebSocketClientExtensionHandler
|
||||
{
|
||||
public static final WebsocketCompressionHandler INSTANCE = new WebsocketCompressionHandler();
|
||||
|
||||
private WebsocketCompressionHandler()
|
||||
{
|
||||
super(
|
||||
new PerMessageDeflateClientExtensionHandshaker(
|
||||
6, ZlibCodecFactory.isSupportingWindowSizeAndMemLevel(), MAX_WINDOW_SIZE,
|
||||
true, false
|
||||
),
|
||||
new DeflateFrameClientExtensionHandshaker( false ),
|
||||
new DeflateFrameClientExtensionHandshaker( true )
|
||||
);
|
||||
|
||||
}
|
||||
}
|
@@ -55,9 +55,8 @@ public class WebsocketHandler extends SimpleChannelInboundHandler<Object>
|
||||
return;
|
||||
}
|
||||
|
||||
if( msg instanceof FullHttpResponse )
|
||||
if( msg instanceof FullHttpResponse response )
|
||||
{
|
||||
FullHttpResponse response = (FullHttpResponse) msg;
|
||||
throw new IllegalStateException( "Unexpected FullHttpResponse (getStatus=" + response.status() + ", content=" + response.content().toString( CharsetUtil.UTF_8 ) + ')' );
|
||||
}
|
||||
|
||||
@@ -76,9 +75,8 @@ public class WebsocketHandler extends SimpleChannelInboundHandler<Object>
|
||||
websocket.environment().addTrackingChange( TrackingField.WEBSOCKET_INCOMING, converted.length );
|
||||
websocket.environment().queueEvent( MESSAGE_EVENT, websocket.address(), converted, true );
|
||||
}
|
||||
else if( frame instanceof CloseWebSocketFrame )
|
||||
else if( frame instanceof CloseWebSocketFrame closeFrame )
|
||||
{
|
||||
CloseWebSocketFrame closeFrame = (CloseWebSocketFrame) frame;
|
||||
websocket.close( closeFrame.statusCode(), closeFrame.reasonText() );
|
||||
}
|
||||
else if( frame instanceof PingWebSocketFrame )
|
||||
|
@@ -66,7 +66,7 @@ public final class Generator<T>
|
||||
{
|
||||
this.base = base;
|
||||
this.context = context;
|
||||
this.interfaces = new String[] { Type.getInternalName( base ) };
|
||||
interfaces = new String[] { Type.getInternalName( base ) };
|
||||
this.wrap = wrap;
|
||||
|
||||
StringBuilder methodDesc = new StringBuilder().append( "(Ljava/lang/Object;" );
|
||||
|
@@ -52,9 +52,8 @@ final class Reflect
|
||||
{
|
||||
if( underlying instanceof Class<?> ) return (Class<?>) underlying;
|
||||
|
||||
if( underlying instanceof ParameterizedType )
|
||||
if( underlying instanceof ParameterizedType type )
|
||||
{
|
||||
ParameterizedType type = (ParameterizedType) underlying;
|
||||
if( !allowParameter )
|
||||
{
|
||||
for( java.lang.reflect.Type arg : type.getActualTypeArguments() )
|
||||
|
@@ -309,9 +309,9 @@ public final class Environment implements IAPIEnvironment
|
||||
{
|
||||
int index = side.ordinal();
|
||||
IPeripheral existing = peripherals[index];
|
||||
if( (existing == null && peripheral != null) ||
|
||||
(existing != null && peripheral == null) ||
|
||||
(existing != null && !existing.equals( peripheral )) )
|
||||
if( existing == null && peripheral != null ||
|
||||
existing != null && peripheral == null ||
|
||||
existing != null && !existing.equals( peripheral ) )
|
||||
{
|
||||
peripherals[index] = peripheral;
|
||||
if( peripheralListener != null ) peripheralListener.onPeripheralChanged( side, peripheral );
|
||||
|
@@ -293,9 +293,8 @@ class MountWrapper
|
||||
|
||||
private FileSystemException localExceptionOf( @Nullable String localPath, @Nonnull IOException e )
|
||||
{
|
||||
if( !location.isEmpty() && e instanceof FileOperationException )
|
||||
if( !location.isEmpty() && e instanceof FileOperationException ex )
|
||||
{
|
||||
FileOperationException ex = (FileOperationException) e;
|
||||
if( ex.getFilename() != null ) return localExceptionOf( ex.getFilename(), ex.getMessage() );
|
||||
}
|
||||
|
||||
|
@@ -16,10 +16,9 @@ import dan200.computercraft.shared.util.IoUtil;
|
||||
import net.minecraft.resource.ReloadableResourceManager;
|
||||
import net.minecraft.resource.Resource;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.resource.ResourceReloadListener;
|
||||
import net.minecraft.resource.SynchronousResourceReloader;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.InvalidIdentifierException;
|
||||
import net.minecraft.util.profiler.Profiler;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
@@ -29,8 +28,6 @@ import java.io.InputStream;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.ReadableByteChannel;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public final class ResourceMount implements IMount
|
||||
@@ -113,6 +110,7 @@ public final class ResourceMount implements IMount
|
||||
existingNamespace = file.getNamespace();
|
||||
|
||||
if( !file.getNamespace().equals( namespace ) ) continue;
|
||||
if( !FileSystem.contains( subPath, file.getPath() ) ) continue; // Some packs seem to include the parent?
|
||||
|
||||
String localPath = FileSystem.toLocal( file.getPath(), subPath );
|
||||
create( newRoot, localPath );
|
||||
@@ -294,12 +292,12 @@ public final class ResourceMount implements IMount
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link ResourceReloadListener} which reloads any associated mounts.
|
||||
* A {@link ResourceReloader} which reloads any associated mounts.
|
||||
*
|
||||
* While people should really be keeping a permanent reference to this, some people construct it every
|
||||
* method call, so let's make this as small as possible.
|
||||
*/
|
||||
static class Listener implements ResourceReloadListener
|
||||
static class Listener implements SynchronousResourceReloader
|
||||
{
|
||||
private static final Listener INSTANCE = new Listener();
|
||||
|
||||
@@ -307,24 +305,14 @@ public final class ResourceMount implements IMount
|
||||
private final Set<ReloadableResourceManager> managers = Collections.newSetFromMap( new WeakHashMap<>() );
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> reload( Synchronizer synchronizer, ResourceManager manager, Profiler prepareProfiler, Profiler applyProfiler, Executor prepareExecutor, Executor applyExecutor )
|
||||
public void reload( @Nonnull ResourceManager manager )
|
||||
{
|
||||
return CompletableFuture.runAsync( () -> {
|
||||
prepareProfiler.push( "Mount reloading" );
|
||||
try
|
||||
{
|
||||
for( ResourceMount mount : this.mounts ) mount.load();
|
||||
}
|
||||
finally
|
||||
{
|
||||
prepareProfiler.pop();
|
||||
}
|
||||
}, prepareExecutor );
|
||||
for( ResourceMount mount : mounts ) mount.load();
|
||||
}
|
||||
|
||||
synchronized void add( ReloadableResourceManager manager, ResourceMount mount )
|
||||
{
|
||||
if( managers.add( manager ) ) manager.registerListener( this );
|
||||
if( managers.add( manager ) ) manager.registerReloader( this );
|
||||
mounts.add( mount );
|
||||
}
|
||||
}
|
||||
|
@@ -64,7 +64,7 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
{
|
||||
this.computer = computer;
|
||||
this.timeout = timeout;
|
||||
this.context = new LuaContext( computer );
|
||||
context = new LuaContext( computer );
|
||||
debug = new TimeoutDebugHandler();
|
||||
|
||||
// Create an environment to run in
|
||||
@@ -97,7 +97,7 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
globals.load( state, new CoroutineLib() );
|
||||
globals.load( state, new Bit32Lib() );
|
||||
globals.load( state, new Utf8Lib() );
|
||||
if( ComputerCraft.debugEnable ) globals.load( state, new DebugLib() );
|
||||
globals.load( state, new DebugLib() );
|
||||
|
||||
// Remove globals we don't want to expose
|
||||
globals.rawset( "collectgarbage", Constants.NIL );
|
||||
@@ -260,14 +260,12 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
if( object instanceof Number ) return valueOf( ((Number) object).doubleValue() );
|
||||
if( object instanceof Boolean ) return valueOf( (Boolean) object );
|
||||
if( object instanceof String ) return valueOf( object.toString() );
|
||||
if( object instanceof byte[] )
|
||||
if( object instanceof byte[] b )
|
||||
{
|
||||
byte[] b = (byte[]) object;
|
||||
return valueOf( Arrays.copyOf( b, b.length ) );
|
||||
}
|
||||
if( object instanceof ByteBuffer )
|
||||
if( object instanceof ByteBuffer b )
|
||||
{
|
||||
ByteBuffer b = (ByteBuffer) object;
|
||||
byte[] bytes = new byte[b.remaining()];
|
||||
b.get( bytes );
|
||||
return valueOf( bytes );
|
||||
@@ -304,9 +302,8 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
return table;
|
||||
}
|
||||
|
||||
if( object instanceof Collection )
|
||||
if( object instanceof Collection<?> objects )
|
||||
{
|
||||
Collection<?> objects = (Collection<?>) object;
|
||||
LuaTable table = new LuaTable( objects.size(), 0 );
|
||||
values.put( object, table );
|
||||
int i = 0;
|
||||
@@ -314,9 +311,8 @@ public class CobaltLuaMachine implements ILuaMachine
|
||||
return table;
|
||||
}
|
||||
|
||||
if( object instanceof Object[] )
|
||||
if( object instanceof Object[] objects )
|
||||
{
|
||||
Object[] objects = (Object[]) object;
|
||||
LuaTable table = new LuaTable( objects.length, 0 );
|
||||
values.put( object, table );
|
||||
for( int i = 0; i < objects.length; i++ ) table.rawset( i + 1, toValue( objects[i], values ) );
|
||||
|
@@ -9,6 +9,8 @@ import dan200.computercraft.ComputerCraft;
|
||||
import dan200.computercraft.api.lua.ILuaContext;
|
||||
import dan200.computercraft.api.lua.ILuaTask;
|
||||
import dan200.computercraft.api.lua.LuaException;
|
||||
import dan200.computercraft.api.lua.MethodResult;
|
||||
import dan200.computercraft.core.asm.TaskCallback;
|
||||
import dan200.computercraft.core.computer.Computer;
|
||||
import dan200.computercraft.core.computer.MainThread;
|
||||
|
||||
@@ -66,4 +68,11 @@ class LuaContext implements ILuaContext
|
||||
throw new LuaException( "Task limit exceeded" );
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
@Override
|
||||
public MethodResult executeMainThreadTask( @Nonnull ILuaTask task ) throws LuaException
|
||||
{
|
||||
return TaskCallback.make( this, task );
|
||||
}
|
||||
}
|
||||
|
@@ -7,7 +7,7 @@ package dan200.computercraft.core.terminal;
|
||||
|
||||
import dan200.computercraft.shared.util.Colour;
|
||||
import dan200.computercraft.shared.util.Palette;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtCompound;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
@@ -44,9 +44,9 @@ public class Terminal
|
||||
this.height = height;
|
||||
onChanged = changedCallback;
|
||||
|
||||
text = new TextBuffer[this.height];
|
||||
textColour = new TextBuffer[this.height];
|
||||
backgroundColour = new TextBuffer[this.height];
|
||||
text = new TextBuffer[height];
|
||||
textColour = new TextBuffer[height];
|
||||
backgroundColour = new TextBuffer[height];
|
||||
for( int i = 0; i < this.height; i++ )
|
||||
{
|
||||
text[i] = new TextBuffer( ' ', this.width );
|
||||
@@ -93,9 +93,9 @@ public class Terminal
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
|
||||
text = new TextBuffer[this.height];
|
||||
textColour = new TextBuffer[this.height];
|
||||
backgroundColour = new TextBuffer[this.height];
|
||||
text = new TextBuffer[height];
|
||||
textColour = new TextBuffer[height];
|
||||
backgroundColour = new TextBuffer[height];
|
||||
for( int i = 0; i < this.height; i++ )
|
||||
{
|
||||
if( i >= oldHeight )
|
||||
@@ -366,7 +366,7 @@ public class Terminal
|
||||
setChanged();
|
||||
}
|
||||
|
||||
public synchronized CompoundTag writeToNBT( CompoundTag nbt )
|
||||
public synchronized NbtCompound writeToNBT( NbtCompound nbt )
|
||||
{
|
||||
nbt.putInt( "term_cursorX", cursorX );
|
||||
nbt.putInt( "term_cursorY", cursorY );
|
||||
@@ -384,7 +384,7 @@ public class Terminal
|
||||
return nbt;
|
||||
}
|
||||
|
||||
public synchronized void readFromNBT( CompoundTag nbt )
|
||||
public synchronized void readFromNBT( NbtCompound nbt )
|
||||
{
|
||||
cursorX = nbt.getInt( "term_cursorX" );
|
||||
cursorY = nbt.getInt( "term_cursorY" );
|
||||
@@ -419,6 +419,7 @@ public class Terminal
|
||||
{
|
||||
if( c >= '0' && c <= '9' ) return c - '0';
|
||||
if( c >= 'a' && c <= 'f' ) return c - 'a' + 10;
|
||||
if( c >= 'A' && c <= 'F' ) return c - 'A' + 10;
|
||||
return 15 - def.ordinal();
|
||||
}
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ public class TextBuffer
|
||||
public TextBuffer( char c, int length )
|
||||
{
|
||||
text = new char[length];
|
||||
this.fill( c );
|
||||
fill( c );
|
||||
}
|
||||
|
||||
public TextBuffer( String text )
|
||||
@@ -79,6 +79,7 @@ public class TextBuffer
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return new String( text );
|
||||
|
@@ -1,25 +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.fabric.mixin;
|
||||
|
||||
import net.minecraft.client.util.math.AffineTransformation;
|
||||
import net.minecraft.client.util.math.Vector3f;
|
||||
import net.minecraft.util.math.Quaternion;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin( AffineTransformation.class )
|
||||
public interface AffineTransformationAccess
|
||||
{
|
||||
@Accessor
|
||||
Vector3f getTranslation();
|
||||
|
||||
@Accessor
|
||||
Vector3f getScale();
|
||||
|
||||
@Accessor
|
||||
Quaternion getRotation1();
|
||||
}
|
@@ -1,18 +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.fabric.mixin;
|
||||
|
||||
import net.minecraft.client.render.model.BakedQuad;
|
||||
import net.minecraft.client.texture.Sprite;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
@Mixin( BakedQuad.class )
|
||||
public interface BakedQuadAccess
|
||||
{
|
||||
@Accessor
|
||||
Sprite getSprite();
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user