1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-16 06:27:39 +00:00

Compare commits

..

111 Commits

Author SHA1 Message Date
Merith
ed9e823f3f update version number for new release 2021-11-17 13:19:25 -08:00
Merith
2b8fea5b35 Merge pull request #20 from Wiggles1305/Wiggles1305-patch-1
Recipe parity with CC: Tweaked
2021-11-11 18:30:31 -08:00
Zachbutwithak
b3e6b4c29a Recipe parity with CC: Tweaked 2021-11-11 18:08:09 -08:00
Merith
c94ff68e7f Merge pull request #19 from Wiggles1305/1.17.1
Fix en_us.json
2021-11-11 17:19:22 -08:00
Wiggles1305
3fb96a3438 Added to en_us.json
Added "upgrade.minecraft.netherite_pickaxe.adjective": "Netherite Mining", because apparently there is a netherite pickaxe mining turtle
2021-11-11 14:53:17 -08:00
Merith
7a2b7c0701 Merge pull request #13 from 3prm3/1.17.1
Added links to ever instance of Fabric.
2021-10-31 12:47:28 -07:00
Merith
fa7a731ad1 Merge pull request #14 from joecharamut/1.17.1
Fix drag-and-drop file uploading
2021-10-31 12:45:18 -07:00
Joseph Charamut
8be48ebcf0 Fix drag-and-drop file uploading 2021-10-31 10:55:50 -04:00
ƐqɿmƐ
123f3abcaa Added links to ever instance of Fabric.
Also capitalized the word "Forge".
2021-10-30 11:21:58 -07:00
Merith
9f2e43f00a Merge pull request #9 from joecharamut/1.17.1
Force Jitpack to actually use Java 16 instead of Java 8
2021-10-28 10:22:25 -07:00
Merith
9fb35b2799 Merge pull request #11 from ga2mer/1.17.1
Wired Modem/Cable breaking and creative picking of sided modem and cable
2021-10-28 10:10:36 -07:00
Nikita Savyolov
272572dbf2 fix: creative picking sided modem/cable 2021-10-28 01:10:47 +03:00
Nikita Savyolov
702e4fc787 fix: correct (maybe) modem properties
something changed in 1.17 and the modem now slowly breaks with hand or pickaxe, so we set this manually
2021-10-28 01:08:31 +03:00
Merith
511327effe Merge pull request #10 from 3prm3/1.17.1
Fixed grammar errors like your/you're added a link.
2021-10-27 08:44:12 -07:00
ƐqɿmƐ
940e35caea Fixed grammar errors like your/you're added a link. 2021-10-26 19:14:04 -07:00
Joseph Charamut
fca01693dd Update jitpack.yml 2021-10-26 21:21:31 -04:00
Joseph Charamut
8846a3f36f Create jitpack.yml 2021-10-26 21:19:36 -04:00
Merith
8002c9e932 Merge pull request #2 from ga2mer/1.17.1
Mainly WiredModem/Cable fixes
2021-10-26 13:29:33 -07:00
Nikita Savyolov
6fd8331e94 fix: BlockCable removedByPlayer 2021-10-18 21:47:43 +03:00
Nikita Savyolov
7a667b9028 fix: correct cable with wired modem highlight
The right thing would be to fix Mixin, just like it is done in Forge, but I think that's enough for now
2021-10-18 21:45:33 +03:00
Nikita Savyolov
67b7cd7a14 fix: wired modem direction 2021-10-17 21:10:10 +03:00
Nikita Savyolov
960d79803d fix: MixinWorld more correct height check
I think this Mixin need to be revisiting
2021-10-17 21:08:48 +03:00
Merith-TK
43ef36fa15 Update links to repo 2021-10-15 16:08:55 -07:00
Merith
f037d9539e update to beta-1 2021-10-14 06:35:57 +00:00
Merith
a3b2f7b5bd please the linter
fix excess whitespace in readme
2021-10-13 23:25:52 -07:00
Merith
0859145d18 Merge pull request #80 from joecharamut/1.17.1
Fix NPE when activating piston
2021-10-13 23:25:14 -07:00
Joseph Charamut
f6e4122f7f Fix NPE when activating piston 2021-10-14 01:33:12 -04:00
Merith
8e4023fdbc please the linter
pleasing the linter
2021-10-13 17:40:28 -07:00
Merith
f10818ec6b update readme 2021-10-13 19:35:37 +00:00
Merith
bc2358489b Merge pull request #78 from ga2mer/1.17-alpha
fix: more correct mouseReleased event
2021-10-12 09:23:55 -07:00
Nikita Savyolov
6e5e682e3a fix: more correct mouseReleased event
WidgetTerminal still calls mouseReleased on every container click instead of terminal only (like Forge does)
2021-10-12 19:14:03 +03:00
Merith
02c63ce7e8 update version number 2021-10-12 16:10:27 +00:00
Jacob Farley
fd24d89f89 my bad 2021-10-11 19:12:07 -05:00
Jacob Farley
685d33a2dd fix github actions 2021-10-11 19:09:41 -05:00
Jacob Farley
ca40c9cf19 needs further testing, but presumably fixes #55 2021-10-11 18:26:20 -05:00
Merith
8985ea9560 Merge pull request #75 from ga2mer/1.17-alpha
1.17.1 some fixes
2021-10-11 14:13:26 -07:00
Nikita Savyolov
1832028dfd fix: remove generated recipes and fix pocket upgrades nbt 2021-10-11 22:50:31 +03:00
Nikita Savyolov
316889dab7 fix: recipe util set nbt correct nbt parsing 2021-10-11 22:49:37 +03:00
Nikita Savyolov
96c80a6549 fix: play sounds using Identifier rather than SoundEvent
6dd33f7099
2021-10-11 22:49:05 +03:00
Nikita Savyolov
fb274e2ed6 fix: recipes with nbt
it looks like the recipes need to be regenerated
2021-10-11 10:06:15 +03:00
Nikita Savyolov
ebe847c04b fix: mouseUp (mouseReleased) event
mouseReleased doesn't work at ClickableWidget, why?
2021-10-10 23:28:07 +03:00
Nikita Savyolov
fdbf41b3c4 fix: MixinLanguage remove keys if they exists in vanilla 2021-10-10 17:26:25 +03:00
Nikita Savyolov
9dcb9f9537 fix: ModelTransformer return old code, it was wrong get offset length 2021-10-10 08:41:23 +03:00
Merith
1395c877af update version number 2021-10-10 00:37:35 +00:00
Merith
969451f18c Merge pull request #74 from ga2mer/1.17-alpha
1.17.1 port
2021-10-09 11:32:11 -07:00
Nikita Savyolov
259c8d57f5 fix: removed some imports 2021-10-09 21:08:59 +03:00
Nikita Savyolov
2ee07283fa Merge branch 'fabric' into 1.17-alpha 2021-10-09 21:02:41 +03:00
Nikita Savyolov
c85a80617a fix: some tile write nbt returns 2021-10-09 20:52:45 +03:00
Nikita Savyolov
5aa8611e43 fix: return cc:r textures except advanced gui corners 2021-10-09 20:30:33 +03:00
Nikita Savyolov
86aecd945e fix: mixins 2021-10-08 23:08:03 +03:00
Nikita Savyolov
a7a9f4fa13 license: imatrix4f 2021-10-08 18:42:29 +03:00
Nikita Savyolov
22e4c0603b fix: remove unused imports 2021-10-08 18:35:01 +03:00
Nikita Savyolov
f3b731460e fix: turtle upgrades item render 2021-10-08 18:31:07 +03:00
Nikita Savyolov
d787c6e6c1 fix: mod name localization 2021-10-08 18:29:55 +03:00
Nikita Savyolov
11272b8d00 style: some spaces and imports 2021-10-07 00:25:18 +03:00
Nikita Savyolov
1c254e3bb0 style: some spaces 2021-10-06 19:13:49 +03:00
Nikita Savyolov
7ade380fad ci: update java to 16 2021-10-06 18:42:47 +03:00
Nikita Savyolov
2a377a37ee fix: and another part of syncing with Tweaked codebase and resources 2021-10-03 23:37:43 +03:00
Nikita Savyolov
861a9e199d fix: another part of syncing with Tweaked codebase 2021-10-03 22:54:13 +03:00
Nikita Savyolov
d4f1e34023 fix: first part of syncing with Tweaked codebase
includes: file drag'n'drop (now doesn't work in Tweaked) and no inventory mode for left hand pocket computer
2021-10-03 18:21:42 +03:00
coolsa
6d25278a5c fixed println, removed .launch configurations. 2021-10-01 23:22:31 -06:00
coolsa
abfb05f04c fix: Clicking in terminal will now work (tested with paint) 2021-10-01 16:08:08 -06:00
Cloud Chagnon
9d8e76c5b4 Merge pull request #3 from ga2mer/fabric
fix: sidebar, textures and lang from Tweaked
2021-10-01 16:07:14 -06:00
Nikita Savyolov
89662bf54a fix: sidebar, textures and lang from tweaked 2021-10-02 00:24:41 +03:00
Cloud Chagnon
520635dfec Merge pull request #2 from ga2mer/fabric
Pocket, speaker, printer, modems, cable
2021-10-01 14:58:25 -06:00
Nikita Savyolov
ee82a8d75f fix: pocket, speaker, printer, modems, cable and some mixins 2021-10-01 18:34:42 +03:00
Cloud Chagnon
967f00cd1b Merge branch 'fabric' into fabric 2021-09-30 16:26:35 -06:00
coolsa
dda5236d84 opening a terminal works, placing blocks does not. 2021-09-30 15:59:20 -06:00
Nikita Savyolov
427ca2f108 fix: turtle read write nbt 2021-10-01 00:53:32 +03:00
Nikita Savyolov
e30f2a86f0 fix: advanced turtle gui interactive and correct turtles tick calling 2021-10-01 00:02:52 +03:00
Nikita Savyolov
121ef6e976 fix: computer, monitor, disk drive and some turtle are works 2021-09-30 14:46:33 +03:00
coolsa
e4271ff6f7 IT COMPILES! but crashes when placing a block. 2021-09-30 04:06:47 -06:00
coolsa
8d3b94734d Now only need to mess with rendering... 2021-09-30 02:43:57 -06:00
coolsa
9e57150384 Merge in from upstream 2021-09-23 23:33:48 -06:00
coolsa
0dc34a7dbe Attempting to update to 1.17.
Todo: refactor rendering to avoid using direct GL calls, instead I've
read that you could use a `BufferBuilder` but need to do more looking
into that.
Also need to update some block entity things, since some calls are also
gone.
2021-09-23 23:32:06 -06:00
Merith
fbe28dc51a update dep versions, actual compile errors yay! 2021-07-11 02:09:43 +00:00
Merith
14e013d075 move remappedSrc to src/main/java 2021-07-11 01:40:01 +00:00
Merith
9bc4e9530c gradle=7.1.1, gradle migrateMappings 2021-07-11 01:33:21 +00:00
Merith
cbff505297 Merge pull request #67 from 3prm3-Org/readme
Fix the badge with a different method using camo.githubusercontent.com
Closes #68
2021-07-10 08:04:07 -07:00
ƐqɿmƐ
c4aef2d4c7 Merge branch 'Merith-TK:fabric' into readme 2021-06-23 14:24:40 -07:00
ƐqɿmƐ
2ed6692f76 Fix the curseforge badge via githubusercontent
Replace the svg with https://camo.githubusercontent.com/07622e6662ef5ead080c4840ef6514a34e079d63015f7e51c977a55b1881dfb9/687474703a2f2f63662e776179326d7563686e6f6973652e65752f7469746c652f63632d726573746974636865642e737667
2021-06-23 14:22:24 -07:00
Merith
f075eabc32 Merge pull request #66 from 3prm3-Org/readme
Fix curseforge svg, use new cc: restitched url
2021-06-22 19:44:41 -07:00
ƐqɿmƐ
3d1c9d1667 Fix curseforge svg, use new cc: restitched url
Make the curseforge svg visible rather than being a broken svg by switching to id
2021-06-22 19:33:03 -07:00
Merith
0028ad8f54 Merge pull request #64 from Toad-Dev/server-lang-fix
Fix getItemDetail() showing raw translation keys.
2021-06-17 09:37:44 -07:00
Merith
4c805f1c27 Make Edits proposed by SquidDev-CC (#65)
* Use toolchains as proposed by SquidDev-CC

* Removed jcenter() repo (where bad mercury dep was coming from)

Co-authored-by: ToadDev <748280+Toad-Dev@users.noreply.github.com>
2021-06-16 13:55:21 -07:00
hugeblank
505543ad94 Merge pull request #63 from hugeblank/fabric
Update InventoryMethods to handle Inventories explicitly, sent with the joint approval of toad-dev
2021-06-16 00:41:26 -07:00
ToadDev
644471c6bf Fix getItemDetail showing raw translation keys.
The dedicated server always uses the default Language instance, as it's
setter method is stripped from the server jar. So if we mixin to this
instance's creation and load it with mods' en_us lang files, we will be
able to "translate" text on the server. Translate in quotes as we're
only loading en_us files, but mojang was the one who left out
translations on the dedicated server we shouldn't feel too bad.
2021-06-16 00:25:46 -07:00
hugeblank
bf87d7faa1 Update InventoryMethods to handle Inventories explicitly 2021-06-16 00:20:35 -07:00
Merith
be95b65488 Merge pull request #62 from 3prm3-Org/readme
Some readme tweaks and fixes
2021-06-13 13:21:55 -07:00
ƐqɿmƐ
7e9f3bd61a Some readme tweaks
1. "What is CC: Restiched" section now says  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.
2. Remove Bullet points next to images in "Conflicts" section
3.Add periods
4:Make CC: R/CC: T spacing more consistent
2021-06-13 13:14:17 -07:00
Merith
4a74aa8166 Change gitpod button, move banner to the top 2021-06-12 17:29:05 -07:00
ToadDev
b4ce4361ce Merge pull request #60 from Toad-Dev/linter-fix
Linter fix and removing unnecessary this's
2021-06-12 16:11:04 -07:00
ToadDev
42a3dd24ad Put some braces back
These blocks were not strictly needed but helped readability. I didn't
mean for the reformatter to change them while dealing with the "this"
problem. It also removed some braces in switch statements but who cares.
2021-06-12 15:51:47 -07:00
ToadDev
9129da2e3d What is this?
This's -> gone
2021-06-12 15:51:45 -07:00
ToadDev
668cdcdd39 Fix linter.. maybe 2021-06-12 15:48:09 -07:00
ToadDev
2543ebee10 Fix checkstyle 2021-06-12 15:46:33 -07:00
hugeblank
104a317163 Gui fixes
- Makes GuiTurtle extend from GuiComputer
- Fixes #51
- Fixes grayed background surrounding interface not rendering for computers
2021-06-12 13:42:28 -07:00
Merith
921802e6c9 Merge pull request #59 from 3prm3-Org/readme
Make images function on readme and make the logo a monitor (again)
2021-06-11 11:24:35 -07:00
ƐqɿmƐ
56cfc1a452 Fix the logo
Makes the logo look like a monitor (again)
2021-06-11 09:15:46 -07:00
ƐqɿmƐ
a14b98be22 Fix images on readme.md
Make the #Conficts images visible without having to click on a link to see them
2021-06-11 09:14:37 -07:00
Merith-TK
76b5c05acc update changelog and whats new 2021-06-11 09:06:14 -07:00
Merith-TK
8b3f1a448f Add Mod Conflicts
litterally just canvas and iris
2021-06-11 08:42:41 -07:00
Merith
3de515c617 Merge pull request #56 from Toad-Dev/monitor-fix
Some things that might improve the monitor rendering situation.
2021-06-11 07:41:36 -07:00
Merith
ab199cd9b0 Merge pull request #58 from Toad-Dev/tag-filler-fix
Fix #57
2021-06-11 06:45:57 -07:00
ToadDev
fc4bc9aa05 Fix #57 2021-06-10 20:11:38 -07:00
ToadDev
9662a106f0 Mark optifabric as incompatible with MonitorRenderer.TBO
Anyone using the default BEST option will automatically have VBOs
enabled when optifabric is detected.
2021-06-10 12:00:11 -07:00
ToadDev
06b0538b76 Reverted change to blocker layer, with tweaks.
Without the blocker layer even VBOs didn't work with shaders. So instead
I put the blocker back and made it mask both color and depth buffers,
which fixes the bug with chests and water drawing over monitors. Since
it now masks color I hoisted it up to be drawn before the terminal, and
made the terminal slightly offset to solve z-fighting with VBO renderer.
2021-06-10 11:55:29 -07:00
ToadDev
fb128152a5 Fix checkstyle :P 2021-06-10 11:55:29 -07:00
ToadDev
f596af059d Add a button to change monitor renderer in mod menu.
Probably useful for now.
2021-06-10 11:55:29 -07:00
ToadDev
52bb06d250 Add a shader mod compatibility check to the MonitorRenderer.BEST option.
Will need to fill in the shader mod ids after some testing.
2021-06-10 11:55:29 -07:00
ToadDev
f3d22444d3 Fix: Stop water and chests being drawn over monitors
Somewhere along the line the gl state was being mangled and I'm still
not sure where! I moved the monitor blocks from the cutout render layer
to the default solid layer, which obviates the depth blocker. I don't
think the transparent front of the monitor blocks was ever visible so
this should be fine. Then the terminal quads are moved slightly outward
to prevent z-fighting with the now present block front.

Finally I noticed some chests were not rendering correctly around
monitors, so I paired an endDrawing() call with our sneaky hack of
calling startDrawing() to force the rendering state. This fixed the
chests. Hopefully we haven't messed up the render state in more ways :)
2021-06-10 00:59:21 -07:00
428 changed files with 8166 additions and 6112 deletions

View File

@@ -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
View File

@@ -21,3 +21,4 @@
.gradle
*.DS_Store
.project
*.launch

2
.gitpod.Dockerfile vendored
View File

@@ -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

View File

@@ -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%"/>
[![Current build status](https://github.com/Merith-TK/cc-restitched/workflows/Build/badge.svg)](https://github.com/Merith-TK/cc-restitched/actions "Current build status") [![Download CC: Restitched on CurseForge](http://cf.way2muchnoise.eu/title/cc-restitched.svg)](https://www.curseforge.com/minecraft/mc-mods/cc-restitched-updated "Download CC: Restitched on CurseForge")
[![Current build status](https://github.com/cc-tweaked/cc-restitched/workflows/Build/badge.svg)](https://github.com/cc-tweaked/cc-restitched/actions "Current build status")
[![Download CC: Restitched on CurseForge](https://camo.githubusercontent.com/07622e6662ef5ead080c4840ef6514a34e079d63015f7e51c977a55b1881dfb9/687474703a2f2f63662e776179326d7563686e6f6973652e65752f7469746c652f63632d726573746974636865642e737667)](https://www.curseforge.com/minecraft/mc-mods/cc-restitched "Download CC: Restitched on CurseForge")
[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/cc-tweaked/cc-restitched/tree/1.17-alpha)
[![Open in Gitpod](https://gitpod.io/button/open-in-gitpod.svg)](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
- ![](https://user-images.githubusercontent.com/10422110/136869483-91824c5f-841f-4316-bfb1-2412477a29ee.png)
- ![](https://user-images.githubusercontent.com/10422110/136869535-a16581a3-5e0a-4632-923f-c8de8cc8a6ea.png)
</details>
* [ YES ] Canvas
* Works with TBO Rendering (Default)
* Scuffed with VBO Rendering
* <details>
<summary>VBO is broken</summary>
Monitors are just... scuffed beyond belief.
- ![](https://i.imgur.com/JVNZ2Pn.png)
- ![](https://i.imgur.com/SXXpr54.png)
* 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?
- ![](https://i.imgur.com/OEmZXsx.png)
</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!
* ![icon](https://raw.githubusercontent.com/Toad-Dev/cc-peripheral-test/master/src/main/resources/assets/cc_test/textures/block/test_peripheral.png) [CC Peripheral Test](https://github.com/Toad-Dev/cc-peripheral-test)
* ![icon](https://raw.githubusercontent.com/Toad-Dev/cc-peripheral-test/master/src/main/resources/assets/cc_test/textures/block/test_peripheral.png) [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!

View File

@@ -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

View File

@@ -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" />

View File

@@ -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>

View File

@@ -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

View File

@@ -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
View File

@@ -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
View 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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@@ -1,6 +1,5 @@
pluginManagement {
repositories {
jcenter()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'

View File

@@ -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;

View File

@@ -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()

View File

@@ -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();

View File

@@ -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() );
}
}

View File

@@ -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

View File

@@ -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;
}
}

View File

@@ -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 ) );
}
/**

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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 );
}
}

View File

@@ -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 );
}
}

View File

@@ -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 );
}
}

View File

@@ -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 );
}
}

View File

@@ -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() );
}
/**

View File

@@ -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;

View File

@@ -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 );
}
}
}

View File

@@ -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.

View File

@@ -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 );
}
}
}

View File

@@ -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 )
{
}
}
}

View File

@@ -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() );
}
/**

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 );
}
}
}

View File

@@ -46,7 +46,7 @@ public abstract class TurtleEvent
@Nonnull
public ITurtleAccess getTurtle()
{
return this.turtle;
return turtle;
}
}

View File

@@ -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 );
}
}

View File

@@ -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;
}
}
}

View File

@@ -39,6 +39,6 @@ public abstract class TurtlePlayerEvent extends TurtleActionEvent
@Nonnull
public FakePlayer getPlayer()
{
return this.player;
return player;
}
}

View File

@@ -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;
}
/**

View File

@@ -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 );

View File

@@ -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;

View 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()
{
}
}
}

View File

@@ -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 )
);
}
}

View File

@@ -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() );
}
}

View File

@@ -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 );
}
}

View File

@@ -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 );
}
}

View File

@@ -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 );
}
}
}

View File

@@ -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;
}

View File

@@ -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 );
}
}

View File

@@ -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;
}
}
}

View 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;
}
}

View File

@@ -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();
}
}
}

View File

@@ -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 );
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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 );
}
}
}

View File

@@ -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();
} );

View File

@@ -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();
}
}

View File

@@ -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 );
}

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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 );
}
}
}

View File

@@ -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;
}
}

View File

@@ -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 );
}
}
}

View File

@@ -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 ) );

View File

@@ -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

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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 );

View File

@@ -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" );
}

View File

@@ -62,6 +62,7 @@ public interface IAPIEnvironment
@Nullable
IPeripheral getPeripheral( ComputerSide side );
@Nullable
String getLabel();
void setLabel( @Nullable String label );

View File

@@ -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 )

View File

@@ -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() );

View File

@@ -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";
}

View File

@@ -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 )

View File

@@ -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() ) );

View File

@@ -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.

View File

@@ -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 )
);
}

View File

@@ -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 )
);
}
}

View File

@@ -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 )

View File

@@ -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;" );

View File

@@ -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() )

View File

@@ -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 );

View File

@@ -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() );
}

View File

@@ -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 );
}
}

View File

@@ -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 ) );

View File

@@ -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 );
}
}

View File

@@ -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();
}
}

View File

@@ -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 );

View File

@@ -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();
}

View File

@@ -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