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

Compare commits

...

90 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
331 changed files with 5873 additions and 3814 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

101
README.md
View File

@@ -1,71 +1,74 @@
<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")
[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-908a85?logo=gitpod)](https://gitpod.io/#https://github.com/Merith-TK/cc-restitched)
[![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)
# 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
# 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!
# Conflicts
Currently Iris and Canvas Shaders are Incompatible with this mod,
- Iris has transparent monitors, and when a computer displays something on the monitor, the face becomes black
- Canvas... uhm
- Computer Terminals are 100% unusable and scuffed
- <img src="https://user-images.githubusercontent.com/16393543/120464345-ab619b00-c351-11eb-9dfb-e68ddc93de5e.png">
- Monitors break with either rendering option
- TBO
- Just crashes on world load
- VBO
- <img src="https://user-images.githubusercontent.com/16393543/120475933-d999a780-c35e-11eb-9d94-ef4e5988ad5f.png">
# 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-rc1
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

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

@@ -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;
@@ -73,22 +73,14 @@ public final class TransformedModel
{
matrixStack.push();
AffineTransformationAccess access = (AffineTransformationAccess) (Object) 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( 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

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

@@ -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,27 +25,49 @@ 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;
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
@@ -62,6 +87,32 @@ public abstract class AbstractPocketUpgrade implements IPocketUpgrade
@Override
public final ItemStack getCraftingItem()
{
return 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,16 +36,40 @@ 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
@@ -74,6 +96,32 @@ public abstract class AbstractTurtleUpgrade implements ITurtleUpgrade
@Override
public final ItemStack getCraftingItem()
{
return 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,7 +49,7 @@ public class FakePlayer extends ServerPlayerEntity
{
public FakePlayer( ServerWorld world, GameProfile gameProfile )
{
super( world.getServer(), world, gameProfile, new ServerPlayerInteractionManager( world ) );
super( world.getServer(), world, gameProfile );
networkHandler = new FakeNetHandler( this );
}
@@ -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.

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

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

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( ALL_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 class GuiComputer<T extends ContainerComputerBase> extends HandledScreen<T>
public final class GuiComputer<T extends ContainerComputerBase> extends ComputerScreenBase<T>
{
protected final ComputerFamily family;
protected final ClientComputer computer;
private final int termWidth;
private final int termHeight;
protected WidgetTerminal terminal;
protected WidgetWrapper terminalWrapper;
protected GuiComputer( T container, PlayerInventory player, Text title, int termWidth, int termHeight )
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,96 +52,19 @@ public class GuiComputer<T extends ContainerComputerBase> extends HandledScreen<
return new GuiComputer<>( container, inventory, component, container.getWidth(), container.getHeight() );
}
protected void initTerminal( int border, int widthExtra, int heightExtra )
{
client.keyboard.setRepeatEvents( true );
int termPxWidth = termWidth * FixedWidthFontRenderer.FONT_WIDTH;
int termPxHeight = termHeight * FixedWidthFontRenderer.FONT_HEIGHT;
backgroundWidth = termPxWidth + MARGIN * 2 + border * 2 + widthExtra;
backgroundHeight = termPxHeight + MARGIN * 2 + border * 2 + heightExtra;
super.init();
terminal = new WidgetTerminal( client, () -> computer, termWidth, termHeight, MARGIN, MARGIN, MARGIN, MARGIN );
terminalWrapper = new WidgetWrapper( terminal, MARGIN + border + x, MARGIN + border + y, termPxWidth, termPxHeight );
children.add( terminalWrapper );
setFocused( terminalWrapper );
}
@Override
protected void init()
protected WidgetTerminal createTerminal()
{
initTerminal( BORDER, 0, 0 );
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 )
{
this.renderBackground( stack );
super.render( stack, mouseX, mouseY, partialTicks );
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
terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() );
// Draw a border around the terminal
RenderSystem.color4f( 1, 1, 1, 1 );
client.getTextureManager()
.bindTexture( ComputerBorderRenderer.getTexture( family ) );
ComputerBorderRenderer.render( terminalWrapper.getX() - MARGIN, terminalWrapper.getY() - MARGIN,
getZOffset(), terminalWrapper.getWidth() + MARGIN * 2, terminalWrapper.getHeight() + MARGIN * 2 );
}
@Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{
return (getFocused() != null && getFocused().mouseDragged( x, y, button, deltaX, deltaY )) || super.mouseDragged( x, y, button, deltaX, deltaY );
}
@Override
public boolean mouseReleased( double mouseX, double mouseY, int button )
{
return (getFocused() != null && 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 && getFocused() != null && getFocused() == terminalWrapper )
{
return getFocused().keyPressed( key, scancode, modifiers );
}
return super.keyPressed( key, scancode, modifiers );
}
@Override
public void removed()
{
super.removed();
children.remove( terminal );
terminal = null;
client.keyboard.setRepeatEvents( false );
}
@Override
public void tick()
{
super.tick();
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;
@@ -36,9 +37,9 @@ public class GuiDiskDrive extends HandledScreen<ContainerDiskDrive>
@Override
protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
{
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
client.getTextureManager()
.bindTexture( BACKGROUND );
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,14 +25,6 @@ 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 )
{
@@ -44,9 +36,8 @@ public class GuiPrinter extends HandledScreen<ContainerPrinter>
@Override
protected void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
{
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
client.getTextureManager()
.bindTexture( BACKGROUND );
RenderSystem.setShaderColor( 1.0F, 1.0F, 1.0F, 1.0F );
RenderSystem.setShaderTexture( 0, BACKGROUND );
drawTexture( transform, x, y, 0, 0, backgroundWidth, backgroundHeight );
if( getScreenHandler().isPrinting() )

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>
{
@@ -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, x, y, getZOffset(), page, pages, book );
drawText( matrix, renderer, x + X_TEXT_MARGIN, y + Y_TEXT_MARGIN, ItemPrintout.LINES_PER_PAGE * page, text, 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();
}

View File

@@ -8,6 +8,9 @@ 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.render.ComputerBorderRenderer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import net.minecraft.client.util.math.MatrixStack;
@@ -17,40 +20,46 @@ import net.minecraft.util.Identifier;
import javax.annotation.Nonnull;
public class GuiTurtle extends GuiComputer<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 final ContainerTurtle container;
private static final int TEX_WIDTH = 254;
private static final int TEX_HEIGHT = 217;
private final ComputerFamily family;
public GuiTurtle( ContainerTurtle container, PlayerInventory player, Text title )
{
super( container, player, title, ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight );
super( container, player, title, BORDER );
family = container.getFamily();
backgroundWidth = TEX_WIDTH + ComputerSidebar.WIDTH;
backgroundHeight = TEX_HEIGHT;
this.container = container;
}
@Override
protected void init()
protected WidgetTerminal createTerminal()
{
initTerminal( 8, 0, 80 );
return new WidgetTerminal(
computer, x + BORDER + ComputerSidebar.WIDTH, y + BORDER,
ComputerCraft.turtleTermWidth, ComputerCraft.turtleTermHeight
);
}
@Override
public void drawBackground( @Nonnull MatrixStack transform, float partialTicks, int mouseX, int mouseY )
{
// Draw term
Identifier texture = family == ComputerFamily.ADVANCED ? BACKGROUND_ADVANCED : BACKGROUND_NORMAL;
terminal.draw( terminalWrapper.getX(), terminalWrapper.getY() );
// Draw border/inventory
RenderSystem.color4f( 1.0F, 1.0F, 1.0F, 1.0F );
client.getTextureManager()
.bindTexture( texture );
drawTexture( transform, x, y, 0, 0, backgroundWidth, 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 = container.getSelectedSlot();
int slot = getScreenHandler().getSelectedSlot();
if( slot >= 0 )
{
int slotX = slot % 4;
@@ -61,5 +70,8 @@ public class GuiTurtle extends GuiComputer<ContainerTurtle>
24,
24 );
}
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,66 +9,84 @@ 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 );
@@ -85,17 +103,14 @@ 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 );
@@ -115,17 +130,14 @@ 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 );
@@ -143,17 +155,14 @@ 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 );
@@ -198,7 +207,7 @@ public class WidgetTerminal implements Element
case GLFW.GLFW_KEY_V:
// Ctrl+V for paste
String clipboard = client.keyboard.getClipboard();
String clipboard = MinecraftClient.getInstance().keyboard.getClipboard();
if( clipboard != null )
{
// Clip to the first occurrence of \r or \n
@@ -239,11 +248,7 @@ public class WidgetTerminal implements Element
// Queue the "key" event and add to the down set
boolean repeat = keysDown.get( key );
keysDown.set( key );
IComputer computer = this.computer.get();
if( computer != null )
{
computer.keyDown( key, repeat );
}
computer.keyDown( key, repeat );
}
return true;
@@ -256,11 +261,7 @@ public class WidgetTerminal implements Element
if( key >= 0 && keysDown.get( key ) )
{
keysDown.set( key, false );
IComputer computer = this.computer.get();
if( computer != null )
{
computer.keyUp( key );
}
computer.keyUp( key );
}
switch( key )
@@ -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
queueEvent( "char", Character.toString( ch ) );
}
return true;
}
@Override
public boolean changeFocus( boolean reversed )
{
if( focused )
if( !focused )
{
// When blurring, we should make all keys go up
for( int key = 0; key < keysDown.size(); key++ )
{
if( keysDown.get( key ) )
{
queueEvent( "key_up", key );
}
if( keysDown.get( key ) ) computer.keyUp( key );
}
keysDown.clear();
// When blurring, we should make the last mouse button go up
if( lastMouseButton > 0 )
{
IComputer computer = this.computer.get();
if( computer != null )
{
computer.mouseUp( lastMouseButton + 1, lastMouseX + 1, lastMouseY + 1 );
}
computer.mouseUp( lastMouseButton + 1, lastMouseX + 1, lastMouseY + 1 );
lastMouseButton = -1;
}
shutdownTimer = terminateTimer = rebootTimer = -1;
}
focused = !focused;
return true;
}
@Override
@@ -335,11 +315,7 @@ 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()
@@ -351,50 +327,53 @@ public class WidgetTerminal implements Element
if( shutdownTimer >= 0 && shutdownTimer < TERMINATE_TIME && (shutdownTimer += 0.05f) > TERMINATE_TIME )
{
ClientComputer computer = this.computer.get();
if( computer != null )
{
computer.shutdown();
}
computer.shutdown();
}
if( rebootTimer >= 0 && rebootTimer < TERMINATE_TIME && (rebootTimer += 0.05f) > TERMINATE_TIME )
{
ClientComputer computer = this.computer.get();
if( computer != null )
{
computer.reboot();
}
computer.reboot();
}
}
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( 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(), topMargin, bottomMargin, leftMargin,
rightMargin );
}
else
{
FixedWidthFontRenderer.drawEmptyTerminal( originX - leftMargin,
originY - rightMargin, termWidth * FONT_WIDTH + leftMargin + rightMargin,
termHeight * FONT_HEIGHT + topMargin + 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 < width && dy >= 0 && dy < height && listener.mouseClicked( dx, dy, button );
}
@Override
public boolean mouseReleased( double x, double y, int button )
{
double dx = x - this.x, dy = y - this.y;
return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseReleased( dx, dy, button );
}
@Override
public boolean mouseDragged( double x, double y, int button, double deltaX, double deltaY )
{
double dx = x - this.x, dy = y - this.y;
return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseDragged( dx, dy, button, deltaX, deltaY );
}
@Override
public boolean mouseScrolled( double x, double y, double delta )
{
double dx = x - this.x, dy = y - this.y;
return dx >= 0 && dx < width && dy >= 0 && dy < height && listener.mouseScrolled( dx, dy, delta );
}
@Override
public boolean keyPressed( int key, int scancode, int modifiers )
{
return listener.keyPressed( key, scancode, modifiers );
}
@Override
public boolean keyReleased( int key, int scancode, int modifiers )
{
return listener.keyReleased( key, scancode, modifiers );
}
@Override
public boolean charTyped( char character, int modifiers )
{
return listener.charTyped( character, modifiers );
}
@Override
public boolean changeFocus( boolean b )
{
return listener.changeFocus( b );
}
@Override
public boolean isMouseOver( double x, double y )
{
double dx = x - this.x, dy = y - this.y;
return dx >= 0 && dx < width && dy >= 0 && dy < height;
}
public int getX()
{
return x;
}
public int getY()
{
return y;
}
public int getWidth()
{
return width;
}
public int getHeight()
{
return 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 )
@@ -157,18 +145,22 @@ public class ComputerBorderRenderer
builder.vertex( transform, x, y + height, z )
.color( r, g, b, 1.0f )
.texture( u * TEX_SCALE, (v + textureHeight) * TEX_SCALE )
.light( light )
.next();
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();
builder.vertex( transform, x + width, y, z )
.color( r, g, b, 1.0f )
.texture( (u + textureWidth) * TEX_SCALE, v * TEX_SCALE )
.light( light )
.next();
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
@@ -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 );
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 ) );
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 )
@@ -89,25 +85,14 @@ 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.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);
// Draw the background blocker
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) );
// Set the contents slightly off the surface to prevent z-fighting
transform.translate( 0.0, 0.0, 0.001 );
// Draw the contents
Terminal terminal = originTerminal.getTerminal();
if( terminal != null )
@@ -122,23 +107,22 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
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() );
// To go along with sneaky hack above: make sure state changes are undone. I would have thought this would
// happen automatically after these buffers are drawn, but chests will render weird around monitors without this.
FixedWidthFontRenderer.TYPE.endDrawing();
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
{
@@ -154,7 +138,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
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();
@@ -169,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;
@@ -182,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;
@@ -199,32 +179,27 @@ 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;
}
@@ -234,7 +209,7 @@ public class TileEntityMonitorRenderer extends BlockEntityRenderer<TileMonitor>
{
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,
@@ -250,14 +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 = 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

@@ -15,7 +15,7 @@ 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;
@@ -30,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 )
@@ -120,9 +120,9 @@ public class TurtleMultiModel implements BakedModel
@Nonnull
@Override
@Deprecated
public Sprite getSprite()
public Sprite getParticleSprite()
{
return baseModel.getSprite();
return baseModel.getParticleSprite();
}
@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,8 +54,60 @@ public class TurtleSmartItemModel implements BakedModel
.getModel() );
}
private static class TurtleModelCombination
{
final boolean colour;
final ITurtleUpgrade leftUpgrade;
final ITurtleUpgrade rightUpgrade;
final Identifier overlay;
final boolean christmas;
final boolean flip;
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas,
boolean flip )
{
this.colour = colour;
this.leftUpgrade = leftUpgrade;
this.rightUpgrade = rightUpgrade;
this.overlay = overlay;
this.christmas = christmas;
this.flip = flip;
}
@Override
public boolean equals( Object other )
{
if( other == this )
{
return true;
}
if( !(other instanceof TurtleModelCombination otherCombo) )
{
return false;
}
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;
@@ -70,8 +121,7 @@ public class TurtleSmartItemModel implements BakedModel
{
@Nonnull
@Override
public BakedModel apply( @Nonnull BakedModel originalModel, @Nonnull ItemStack stack, @Nullable ClientWorld world,
@Nullable LivingEntity entity )
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 );
@@ -80,9 +130,7 @@ public class TurtleSmartItemModel implements BakedModel
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;
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 );
@@ -143,12 +191,18 @@ public class TurtleSmartItemModel implements BakedModel
return familyModel.isBuiltin();
}
@Nonnull
@Override
@Deprecated
public Sprite getSprite()
public Sprite getParticleSprite()
{
return familyModel.getSprite();
return familyModel.getParticleSprite();
}
@Nonnull
@Override
public ModelOverrideList getOverrides()
{
return overrides;
}
@Nonnull
@@ -159,63 +213,4 @@ public class TurtleSmartItemModel implements BakedModel
return familyModel.getTransformation();
}
@Nonnull
@Override
public ModelOverrideList getOverrides()
{
return overrides;
}
private static class TurtleModelCombination
{
final boolean colour;
final ITurtleUpgrade leftUpgrade;
final ITurtleUpgrade rightUpgrade;
final Identifier overlay;
final boolean christmas;
final boolean flip;
TurtleModelCombination( boolean colour, ITurtleUpgrade leftUpgrade, ITurtleUpgrade rightUpgrade, Identifier overlay, boolean christmas,
boolean flip )
{
this.colour = colour;
this.leftUpgrade = leftUpgrade;
this.rightUpgrade = rightUpgrade;
this.overlay = overlay;
this.christmas = christmas;
this.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;
}
@Override
public boolean equals( Object other )
{
if( other == this )
{
return true;
}
if( !(other instanceof TurtleModelCombination) )
{
return false;
}
TurtleModelCombination otherCombo = (TurtleModelCombination) other;
return otherCombo.colour == colour && otherCombo.leftUpgrade == leftUpgrade && otherCombo.rightUpgrade == rightUpgrade && Objects.equal(
otherCombo.overlay, overlay ) && otherCombo.christmas == christmas && otherCombo.flip == flip;
}
}
}

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

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

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,8 +114,18 @@ 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 URI}.
* Create a {@link InetSocketAddress} from a {@link java.net.URI}.
*
* Note, this may require a DNS lookup, and so should not be executed on the main CC thread.
*
@@ -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

@@ -18,7 +18,7 @@ import static org.objectweb.asm.Opcodes.ICONST_0;
final class Reflect
{
static final Type OPTIONAL_IN = Optional.class.getTypeParameters()[0];
static final java.lang.reflect.Type OPTIONAL_IN = Optional.class.getTypeParameters()[0];
private Reflect()
{
@@ -52,12 +52,11 @@ 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( Type arg : type.getActualTypeArguments() )
for( java.lang.reflect.Type arg : type.getActualTypeArguments() )
{
if( arg instanceof WildcardType ) continue;
if( arg instanceof TypeVariable && ((TypeVariable<?>) arg).getName().startsWith( "capture#" ) )

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

@@ -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 ) );
@@ -367,6 +363,7 @@ public class CobaltLuaMachine implements ILuaMachine
case Constants.TSTRING:
return value.toString();
case Constants.TTABLE:
{
// Table:
// Start remembering stuff
if( objects == null )
@@ -408,6 +405,7 @@ public class CobaltLuaMachine implements ILuaMachine
}
}
return table;
}
default:
return null;
}

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

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

View File

@@ -7,13 +7,18 @@ package dan200.computercraft.fabric.mixin;
import dan200.computercraft.shared.util.DropConsumer;
import net.minecraft.block.Block;
import net.minecraft.entity.ItemEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import java.util.function.Supplier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
/**
* Captures block drops.
@@ -23,12 +28,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin( Block.class )
public class MixinBlock
{
@Inject( method = "dropStack",
at = @At( value = "INVOKE", target = "Lnet/minecraft/world/World;spawnEntity(Lnet/minecraft/entity/Entity;)Z" ),
@Inject( method = "dropStack(Lnet/minecraft/world/World;Ljava/util/function/Supplier;Lnet/minecraft/item/ItemStack;)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/entity/ItemEntity;setToDefaultPickupDelay()V"
),
locals = LocalCapture.CAPTURE_FAILSOFT,
cancellable = true )
private static void dropStack( World world, BlockPos pos, ItemStack stack, CallbackInfo callbackInfo )
private static void dropStack( World world, Supplier<ItemEntity> itemEntitySupplier, ItemStack stack, CallbackInfo callbackInfo, ItemEntity itemEntity )
{
if( DropConsumer.onHarvestDrops( world, pos, stack ) )
if( DropConsumer.onHarvestDrops( world, itemEntity.getBlockPos(), stack ) )
{
callbackInfo.cancel();
}

View File

@@ -0,0 +1,43 @@
/*
* 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 com.mojang.datafixers.util.Pair;
import dan200.computercraft.client.render.MonitorTextureBufferShader;
import dan200.computercraft.client.render.RenderTypes;
import net.minecraft.client.gl.Program;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.render.Shader;
import net.minecraft.resource.ResourceManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.io.IOException;
import java.util.List;
import java.util.function.Consumer;
@Mixin( GameRenderer.class )
public class MixinGameRenderer
{
@Inject( method = "loadShaders", at = @At( value = "INVOKE_ASSIGN", target = "Ljava/util/List;add(Ljava/lang/Object;)Z", ordinal = 53 ), locals = LocalCapture.CAPTURE_FAILSOFT )
private void loadShaders( ResourceManager manager, CallbackInfo info, List<Program> list, List<Pair<Shader, Consumer<Shader>>> list2 ) throws IOException
{
list2.add( Pair.of( new Shader(
manager,
"terminal",
RenderTypes.TERMINAL_WITHOUT_DEPTH.getVertexFormat()
), shader -> RenderTypes.terminalShader = shader ) );
list2.add( Pair.of( new MonitorTextureBufferShader(
manager,
"monitor_tbo",
RenderTypes.MONITOR_TBO.getVertexFormat()
), shader -> RenderTypes.monitorTboShader = (MonitorTextureBufferShader) shader ) );
}
}

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.fabric.mixin;
import dan200.computercraft.client.gui.widgets.WidgetTerminal;
import net.minecraft.client.gui.Element;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.text.Text;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin( HandledScreen.class )
public class MixinHandledScreen<T extends ScreenHandler> extends Screen
{
protected MixinHandledScreen( Text title )
{
super( title );
}
@Inject( method = "mouseReleased", at = @At ( "HEAD" ) )
public void mouseReleased( double mouseX, double mouseY, int button, CallbackInfoReturnable<Boolean> cir )
{
for ( Element child : this.children() )
{
if ( child instanceof WidgetTerminal )
{
child.mouseReleased( mouseX, mouseY, button );
}
}
}
}

View File

@@ -12,6 +12,7 @@ import net.fabricmc.api.Environment;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.render.entity.ItemFrameEntityRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.decoration.ItemFrameEntity;
import net.minecraft.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
@@ -23,16 +24,27 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Environment( EnvType.CLIENT )
public class MixinItemFrameEntityRenderer
{
@Inject( method = "render", at = @At( "HEAD" ), cancellable = true )
@Inject(
method = "render",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/util/math/MatrixStack;multiply(Lnet/minecraft/util/math/Quaternion;)V",
ordinal = 2,
shift = At.Shift.AFTER
),
cancellable = true )
private void renderItem(
ItemFrameEntity itemFrameEntity, float f, float g, MatrixStack matrixStack,
VertexConsumerProvider vertexConsumerProvider, int i, CallbackInfo info
VertexConsumerProvider vertexConsumerProvider, int itemFrameEntityLight, CallbackInfo info
)
{
ItemStack stack = itemFrameEntity.getHeldItemStack();
if( stack.getItem() instanceof ItemPrintout )
{
ItemPrintoutRenderer.INSTANCE.renderInFrame( matrixStack, vertexConsumerProvider, stack );
int light = itemFrameEntity.getType() == EntityType.GLOW_ITEM_FRAME ? 0xf000d2 : itemFrameEntityLight; // See getLightVal.
ItemPrintoutRenderer.INSTANCE.renderInFrame( matrixStack, vertexConsumerProvider, stack, light );
// TODO: need to find how to make if statement instead return, like it doing Forge
matrixStack.pop();
info.cancel();
}
}

View File

@@ -0,0 +1,80 @@
/*
* 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 com.google.common.collect.ImmutableMap;
import com.google.gson.JsonParseException;
import dan200.computercraft.shared.peripheral.generic.data.ItemData;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.util.Language;
import org.apache.logging.log4j.Logger;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
/**
* Loads all mods en_us lang file into the default Language instance on the dedicated server.
* Needed so that lua code running on the server can access the display name of items.
*
* @see ItemData#fill
*/
@Mixin( Language.class )
public class MixinLanguage
{
@Shadow
private static Logger LOGGER;
@Shadow
public static void load( InputStream inputStream, BiConsumer<String, String> entryConsumer )
{
}
private static void loadModLangFile( String modId, BiConsumer<String, String> biConsumer )
{
String path = "/assets/" + modId + "/lang/en_us.json";
try ( InputStream inputStream = Language.class.getResourceAsStream( path ) )
{
if ( inputStream == null ) return;
load( inputStream, biConsumer );
}
catch ( JsonParseException | IOException e )
{
LOGGER.error( "Couldn't read strings from " + path, e );
}
}
@Inject( method = "create", locals = LocalCapture.CAPTURE_FAILSOFT, at = @At( value = "INVOKE", remap = false, target = "Lcom/google/common/collect/ImmutableMap$Builder;build()Lcom/google/common/collect/ImmutableMap;" ) )
private static void create( CallbackInfoReturnable<Language> cir, ImmutableMap.Builder<String, String> builder )
{
final Map<String, String> originalTranslation = builder.build();
/* We must ensure that the keys are de-duplicated because we can't catch the error that might otherwise
* occur when the injected function calls build() on the ImmutableMap builder. So we use our own hash map and
* exclude "minecraft", as the injected function has already loaded those keys at this point.
*/
HashMap<String, String> translations = new HashMap<>();
FabricLoader.getInstance().getAllMods().stream().map( modContainer -> modContainer.getMetadata().getId() )
.filter( id -> !id.equals( "minecraft" ) ).forEach( id -> {
loadModLangFile( id, translations::put );
} );
// This is needed to remove keys that exist in vanilla Minecraft (Consistency+ does this)
translations.keySet().removeIf( originalTranslation::containsKey );
builder.putAll( translations );
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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 dan200.computercraft.fabric.mixininterface.IMatrix4f;
import net.minecraft.util.math.Matrix4f;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin( Matrix4f.class )
public class MixinMatrix4f implements IMatrix4f
{
@Shadow protected float a00;
@Shadow protected float a01;
@Shadow protected float a02;
@Shadow protected float a03;
@Shadow protected float a10;
@Shadow protected float a11;
@Shadow protected float a12;
@Shadow protected float a13;
@Shadow protected float a20;
@Shadow protected float a21;
@Shadow protected float a22;
@Shadow protected float a23;
@Shadow protected float a30;
@Shadow protected float a31;
@Shadow protected float a32;
@Shadow protected float a33;
public void setFloatArray( float[] values )
{
a00 = values[0];
a01 = values[1];
a02 = values[2];
a03 = values[3];
a10 = values[4];
a11 = values[5];
a12 = values[6];
a13 = values[7];
a20 = values[8];
a21 = values[9];
a22 = values[10];
a23 = values[11];
a30 = values[12];
a31 = values[13];
a32 = values[14];
a33 = values[15];
}
}

View File

@@ -34,7 +34,7 @@ public class MixinServerPlayerInteractionManager
ActionResult actionResult = state.onUse( world, player, hand, hitResult );
if( actionResult.isAccepted() )
{
Criteria.ITEM_USED_ON_BLOCK.test( player, pos, stack );
Criteria.ITEM_USED_ON_BLOCK.trigger( player, pos, stack );
cir.setReturnValue( actionResult );
}
}

View File

@@ -27,12 +27,18 @@ import java.util.Collection;
public class MixinWorld
{
@Shadow
protected boolean iteratingTickingBlockEntities;
private boolean iteratingTickingBlockEntities;
@Inject( method = "setBlockEntity", at = @At( "HEAD" ) )
public void setBlockEntity( BlockPos pos, @Nullable BlockEntity entity, CallbackInfo info )
@Shadow
public boolean isInBuildLimit( BlockPos pos )
{
if( !World.isOutOfBuildLimitVertically( pos ) && entity != null && !entity.isRemoved() && iteratingTickingBlockEntities )
return false;
}
@Inject( method = "addBlockEntity", at = @At( "HEAD" ) )
public void addBlockEntity( @Nullable BlockEntity entity, CallbackInfo info )
{
if( entity != null && !entity.isRemoved() && this.isInBuildLimit( entity.getPos() ) && iteratingTickingBlockEntities )
{
setWorld( entity, this );
}
@@ -42,11 +48,11 @@ public class MixinWorld
{
if( entity.getWorld() != world && entity instanceof TileGeneric )
{
entity.setLocation( (World) world, entity.getPos() );
entity.setWorld( (World) world );
}
}
@Inject( method = "addBlockEntities", at = @At( "HEAD" ) )
// @Inject( method = "addBlockEntities", at = @At( "HEAD" ) )
public void addBlockEntities( Collection<BlockEntity> entities, CallbackInfo info )
{
if( iteratingTickingBlockEntities )

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.item.MusicDiscItem;
import net.minecraft.sound.SoundEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin( MusicDiscItem.class )
public interface MusicDiscItemAccessor
{
@Accessor
SoundEvent getSound();
}

View File

@@ -14,5 +14,5 @@ import org.spongepowered.asm.mixin.gen.Accessor;
public interface SignBlockEntityAccess
{
@Accessor
Text[] getText();
Text[] getTexts();
}

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.sound.SoundEvent;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin( SoundEvent.class )
public interface SoundEventAccess
{
@Accessor
Identifier getId();
}

View File

@@ -0,0 +1,11 @@
/*
* 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.mixininterface;
public interface IMatrix4f
{
void setFloatArray( float[] values );
}

View File

@@ -14,25 +14,24 @@ import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.util.LinkedHashSet;
import java.util.ArrayList;
import java.util.Objects;
import java.util.Set;
public final class BundledRedstone
{
private static final Set<IBundledRedstoneProvider> providers = new LinkedHashSet<>();
private static final ArrayList<IBundledRedstoneProvider> providers = new ArrayList<>();
private BundledRedstone() {}
public static synchronized void register( @Nonnull IBundledRedstoneProvider provider )
{
Objects.requireNonNull( provider, "provider cannot be null" );
providers.add( provider );
if( !providers.contains( provider ) ) providers.add( provider );
}
public static int getDefaultOutput( @Nonnull World world, @Nonnull BlockPos pos, @Nonnull Direction side )
{
return World.isInBuildLimit( pos ) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ) : -1;
return world.isInBuildLimit( pos ) ? DefaultBundledRedstoneProvider.getDefaultBundledRedstoneOutput( world, pos, side ) : -1;
}
public static int getOutput( World world, BlockPos pos, Direction side )
@@ -43,7 +42,7 @@ public final class BundledRedstone
private static int getUnmaskedOutput( World world, BlockPos pos, Direction side )
{
if( !World.isInBuildLimit( pos ) )
if( !world.isInBuildLimit( pos ) )
{
return -1;
}

View File

@@ -13,12 +13,17 @@ import dan200.computercraft.shared.computer.blocks.BlockComputer;
import dan200.computercraft.shared.computer.blocks.TileCommandComputer;
import dan200.computercraft.shared.computer.blocks.TileComputer;
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.inventory.ContainerComputer;
import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory;
import dan200.computercraft.shared.computer.inventory.ContainerComputerBase;
import dan200.computercraft.shared.computer.inventory.ContainerViewComputer;
import dan200.computercraft.shared.computer.items.ItemComputer;
import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.media.items.ItemPrintout;
import dan200.computercraft.shared.media.items.ItemTreasureDisk;
import dan200.computercraft.shared.network.container.ComputerContainerData;
import dan200.computercraft.shared.network.container.ContainerData;
import dan200.computercraft.shared.network.container.HeldItemContainerData;
import dan200.computercraft.shared.network.container.ViewComputerContainerData;
import dan200.computercraft.shared.peripheral.diskdrive.BlockDiskDrive;
import dan200.computercraft.shared.peripheral.diskdrive.ContainerDiskDrive;
import dan200.computercraft.shared.peripheral.diskdrive.TileDiskDrive;
@@ -32,7 +37,6 @@ import dan200.computercraft.shared.peripheral.printer.ContainerPrinter;
import dan200.computercraft.shared.peripheral.printer.TilePrinter;
import dan200.computercraft.shared.peripheral.speaker.BlockSpeaker;
import dan200.computercraft.shared.peripheral.speaker.TileSpeaker;
import dan200.computercraft.shared.pocket.inventory.ContainerPocketComputer;
import dan200.computercraft.shared.pocket.items.ItemPocketComputer;
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
@@ -42,13 +46,11 @@ import dan200.computercraft.shared.turtle.core.TurtlePlayer;
import dan200.computercraft.shared.turtle.inventory.ContainerTurtle;
import dan200.computercraft.shared.turtle.items.ItemTurtle;
import dan200.computercraft.shared.turtle.upgrades.*;
import dan200.computercraft.shared.util.FixedPointTileEntityType;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
import net.fabricmc.fabric.api.screenhandler.v1.ScreenHandlerRegistry;
import net.minecraft.block.AbstractBlock;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.Material;
import net.fabricmc.fabric.api.tool.attribute.v1.FabricToolTags;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.EntityType;
@@ -61,12 +63,10 @@ import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.ScreenHandlerType;
import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.registry.Registry;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import static net.minecraft.util.registry.Registry.BLOCK_ENTITY_TYPE;
@@ -91,32 +91,32 @@ public final class ComputerCraftRegistry
public static final class ModBlocks
{
public static final BlockComputer COMPUTER_NORMAL = register( "computer_normal",
new BlockComputer( properties(), ComputerFamily.NORMAL, ModTiles.COMPUTER_NORMAL ) );
new BlockComputer( properties(), ComputerFamily.NORMAL, ComputerCraftRegistry.ModTiles.COMPUTER_NORMAL ) );
public static final BlockComputer COMPUTER_ADVANCED = register( "computer_advanced",
new BlockComputer( properties(),
ComputerFamily.ADVANCED,
ModTiles.COMPUTER_ADVANCED ) );
ComputerCraftRegistry.ModTiles.COMPUTER_ADVANCED ) );
public static final BlockComputer COMPUTER_COMMAND = register( "computer_command",
new BlockComputer( FabricBlockSettings.copyOf( Blocks.STONE )
.strength( -1, 6000000.0F ),
ComputerFamily.COMMAND,
ModTiles.COMPUTER_COMMAND ) );
ComputerCraftRegistry.ModTiles.COMPUTER_COMMAND ) );
public static final BlockTurtle TURTLE_NORMAL = register( "turtle_normal",
new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, ModTiles.TURTLE_NORMAL ) );
new BlockTurtle( turtleProperties(), ComputerFamily.NORMAL, ComputerCraftRegistry.ModTiles.TURTLE_NORMAL ) );
public static final BlockTurtle TURTLE_ADVANCED = register( "turtle_advanced",
new BlockTurtle( turtleProperties(), ComputerFamily.ADVANCED, ModTiles.TURTLE_ADVANCED ) );
new BlockTurtle( turtleProperties(), ComputerFamily.ADVANCED, ComputerCraftRegistry.ModTiles.TURTLE_ADVANCED ) );
public static final BlockSpeaker SPEAKER = register( "speaker", new BlockSpeaker( properties() ) );
public static final BlockDiskDrive DISK_DRIVE = register( "disk_drive", new BlockDiskDrive( properties() ) );
public static final BlockPrinter PRINTER = register( "printer", new BlockPrinter( properties() ) );
public static final BlockMonitor MONITOR_NORMAL = register( "monitor_normal", new BlockMonitor( properties(), ModTiles.MONITOR_NORMAL ) );
public static final BlockMonitor MONITOR_ADVANCED = register( "monitor_advanced", new BlockMonitor( properties(), ModTiles.MONITOR_ADVANCED ) );
public static final BlockMonitor MONITOR_NORMAL = register( "monitor_normal", new BlockMonitor( properties(), ModTiles.MONITOR_NORMAL, false ) );
public static final BlockMonitor MONITOR_ADVANCED = register( "monitor_advanced", new BlockMonitor( properties(), ModTiles.MONITOR_ADVANCED, true ) );
public static final BlockWirelessModem WIRELESS_MODEM_NORMAL = register( "wireless_modem_normal",
new BlockWirelessModem( properties(), ModTiles.WIRELESS_MODEM_NORMAL ) );
new BlockWirelessModem( properties(), ComputerCraftRegistry.ModTiles.WIRELESS_MODEM_NORMAL, ComputerFamily.NORMAL ) );
public static final BlockWirelessModem WIRELESS_MODEM_ADVANCED = register( "wireless_modem_advanced",
new BlockWirelessModem( properties(), ModTiles.WIRELESS_MODEM_ADVANCED ) );
new BlockWirelessModem( properties(), ComputerCraftRegistry.ModTiles.WIRELESS_MODEM_ADVANCED, ComputerFamily.ADVANCED ) );
public static final BlockWiredModemFull WIRED_MODEM_FULL = register( "wired_modem_full",
new BlockWiredModemFull( emProperties(), ModTiles.WIRED_MODEM_FULL ) );
public static final BlockCable CABLE = register( "cable", new BlockCable( emProperties() ) );
new BlockWiredModemFull( modemProperties(), ComputerCraftRegistry.ModTiles.WIRED_MODEM_FULL ) );
public static final BlockCable CABLE = register( "cable", new BlockCable( modemProperties() ) );
private static Block.Settings properties()
{
@@ -134,9 +134,11 @@ public final class ComputerCraftRegistry
.strength( 2.5f );
}
private static Block.Settings emProperties()
private static Block.Settings modemProperties()
{
return FabricBlockSettings.copyOf( Blocks.STONE )
.breakByHand( true )
.breakByTool( FabricToolTags.PICKAXES )
.strength( 1.5f );
}
@@ -149,46 +151,52 @@ public final class ComputerCraftRegistry
public static class ModTiles
{
public static final BlockEntityType<TileMonitor> MONITOR_NORMAL = ofBlock( () -> ModBlocks.MONITOR_NORMAL,
public static final BlockEntityType<TileMonitor> MONITOR_NORMAL = ofBlock( ModBlocks.MONITOR_NORMAL,
"monitor_normal",
f -> new TileMonitor( f, false ) );
public static final BlockEntityType<TileMonitor> MONITOR_ADVANCED = ofBlock( () -> ModBlocks.MONITOR_ADVANCED,
( blockPos, blockState ) -> new TileMonitor( ModTiles.MONITOR_NORMAL, false, blockPos, blockState ) );
public static final BlockEntityType<TileMonitor> MONITOR_ADVANCED = ofBlock( ModBlocks.MONITOR_ADVANCED,
"monitor_advanced",
f -> new TileMonitor( f, true ) );
public static final BlockEntityType<TileComputer> COMPUTER_NORMAL = ofBlock( () -> ModBlocks.COMPUTER_NORMAL,
( blockPos, blockState ) -> new TileMonitor( ModTiles.MONITOR_ADVANCED, true, blockPos, blockState ) );
public static final BlockEntityType<TileComputer> COMPUTER_NORMAL = ofBlock( ModBlocks.COMPUTER_NORMAL,
"computer_normal",
f -> new TileComputer( ComputerFamily.NORMAL, f ) );
public static final BlockEntityType<TileComputer> COMPUTER_ADVANCED = ofBlock( () -> ModBlocks.COMPUTER_ADVANCED,
( blockPos, blockState ) -> new TileComputer( ComputerFamily.NORMAL, ModTiles.COMPUTER_NORMAL, blockPos, blockState ) );
public static final BlockEntityType<TileComputer> COMPUTER_ADVANCED = ofBlock( ModBlocks.COMPUTER_ADVANCED,
"computer_advanced",
f -> new TileComputer( ComputerFamily.ADVANCED, f ) );
public static final BlockEntityType<TileCommandComputer> COMPUTER_COMMAND = ofBlock( () -> ModBlocks.COMPUTER_COMMAND,
( blockPos, blockState ) -> new TileComputer( ComputerFamily.ADVANCED, ModTiles.COMPUTER_ADVANCED, blockPos, blockState ) );
public static final BlockEntityType<TileCommandComputer> COMPUTER_COMMAND = ofBlock( ModBlocks.COMPUTER_COMMAND,
"computer_command",
f -> new TileCommandComputer( ComputerFamily.COMMAND, f ) );
public static final BlockEntityType<TileTurtle> TURTLE_NORMAL = ofBlock( () -> ModBlocks.TURTLE_NORMAL,
( blockPos, blockState ) -> new TileCommandComputer( ComputerFamily.COMMAND, ModTiles.COMPUTER_COMMAND, blockPos, blockState ) );
public static final BlockEntityType<TileTurtle> TURTLE_NORMAL = ofBlock( ModBlocks.TURTLE_NORMAL,
"turtle_normal",
f -> new TileTurtle( f, ComputerFamily.NORMAL ) );
public static final BlockEntityType<TileTurtle> TURTLE_ADVANCED = ofBlock( () -> ModBlocks.TURTLE_ADVANCED,
( blockPos, blockState ) -> new TileTurtle( ModTiles.TURTLE_NORMAL, blockPos, blockState, ComputerFamily.NORMAL ) );
public static final BlockEntityType<TileTurtle> TURTLE_ADVANCED = ofBlock( ModBlocks.TURTLE_ADVANCED,
"turtle_advanced",
f -> new TileTurtle( f, ComputerFamily.ADVANCED ) );
public static final BlockEntityType<TileSpeaker> SPEAKER = ofBlock( () -> ModBlocks.SPEAKER, "speaker", TileSpeaker::new );
public static final BlockEntityType<TileDiskDrive> DISK_DRIVE = ofBlock( () -> ModBlocks.DISK_DRIVE, "disk_drive", TileDiskDrive::new );
public static final BlockEntityType<TilePrinter> PRINTER = ofBlock( () -> ModBlocks.PRINTER, "printer", TilePrinter::new );
public static final BlockEntityType<TileWiredModemFull> WIRED_MODEM_FULL = ofBlock( () -> ModBlocks.WIRED_MODEM_FULL,
( blockPos, blockState ) -> new TileTurtle( ModTiles.TURTLE_ADVANCED, blockPos, blockState, ComputerFamily.ADVANCED ) );
public static final BlockEntityType<TileSpeaker> SPEAKER = ofBlock( ModBlocks.SPEAKER, "speaker",
( blockPos, blockState ) -> new TileSpeaker( ModTiles.SPEAKER, blockPos, blockState ) );
public static final BlockEntityType<TileDiskDrive> DISK_DRIVE = ofBlock( ModBlocks.DISK_DRIVE, "disk_drive",
( blockPos, blockState ) -> new TileDiskDrive( ModTiles.DISK_DRIVE, blockPos, blockState ) );
public static final BlockEntityType<TilePrinter> PRINTER = ofBlock( ModBlocks.PRINTER, "printer",
( blockPos, blockState ) -> new TilePrinter( ModTiles.PRINTER, blockPos, blockState ) );
public static final BlockEntityType<TileWiredModemFull> WIRED_MODEM_FULL = ofBlock( ModBlocks.WIRED_MODEM_FULL,
"wired_modem_full",
TileWiredModemFull::new );
public static final BlockEntityType<TileCable> CABLE = ofBlock( () -> ModBlocks.CABLE, "cable", TileCable::new );
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_NORMAL = ofBlock( () -> ModBlocks.WIRELESS_MODEM_NORMAL,
( blockPos, blockState ) -> new TileWiredModemFull( ModTiles.WIRED_MODEM_FULL, blockPos, blockState ) );
public static final BlockEntityType<TileCable> CABLE = ofBlock( ModBlocks.CABLE, "cable",
( blockPos, blockState ) -> new TileCable( ModTiles.CABLE, blockPos, blockState ) );
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_NORMAL = ofBlock( ModBlocks.WIRELESS_MODEM_NORMAL,
"wireless_modem_normal",
f -> new TileWirelessModem( f, false ) );
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_ADVANCED = ofBlock( () -> ModBlocks.WIRELESS_MODEM_ADVANCED,
( blockPos, blockState ) -> new TileWirelessModem( ModTiles.WIRELESS_MODEM_NORMAL, false, blockPos, blockState ) );
public static final BlockEntityType<TileWirelessModem> WIRELESS_MODEM_ADVANCED = ofBlock( ModBlocks.WIRELESS_MODEM_ADVANCED,
"wireless_modem_advanced",
f -> new TileWirelessModem( f, true ) );
( blockPos, blockState ) -> new TileWirelessModem( ModTiles.WIRELESS_MODEM_ADVANCED, true, blockPos, blockState ) );
private static <T extends BlockEntity> BlockEntityType<T> ofBlock( Supplier<Block> block, String id, Function<BlockEntityType<T>, T> factory )
private static <T extends BlockEntity> BlockEntityType<T> ofBlock( Block block, String id, BiFunction<BlockPos, BlockState, T> factory )
{
BlockEntityType<T> blockEntityType = FabricBlockEntityTypeBuilder.create( factory::apply, block ).build();
return Registry.register( BLOCK_ENTITY_TYPE,
new Identifier( MOD_ID, id ),
FixedPointTileEntityType.create( Objects.requireNonNull( block ), factory ) );
blockEntityType
);
}
}
@@ -252,24 +260,20 @@ public final class ComputerCraftRegistry
public static class ModContainers
{
public static final ScreenHandlerType<ContainerComputer> COMPUTER = registerExtended( "computer", ContainerComputer::new );
public static final ScreenHandlerType<ContainerPocketComputer> POCKET_COMPUTER = registerExtended( "pocket_computer", ContainerPocketComputer::new );
public static final ScreenHandlerType<ContainerTurtle> TURTLE = registerExtended( "turtle", ContainerTurtle::new );
public static final ScreenHandlerType<ContainerComputerBase> COMPUTER = ContainerData.toType( new Identifier( MOD_ID, "computer" ), ModContainers.COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
public static final ScreenHandlerType<ContainerComputerBase> POCKET_COMPUTER = ContainerData.toType( new Identifier( MOD_ID, "pocket_computer" ), ModContainers.POCKET_COMPUTER, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
public static final ScreenHandlerType<ContainerComputerBase> POCKET_COMPUTER_NO_TERM = ContainerData.toType( new Identifier( MOD_ID, "pocket_computer_no_term" ), ModContainers.POCKET_COMPUTER_NO_TERM, ComputerContainerData::new, ComputerMenuWithoutInventory::new );
public static final ScreenHandlerType<ContainerTurtle> TURTLE = ContainerData.toType( new Identifier( MOD_ID, "turtle" ), ComputerContainerData::new, ContainerTurtle::new );
public static final ScreenHandlerType<ContainerDiskDrive> DISK_DRIVE = registerSimple( "disk_drive", ContainerDiskDrive::new );
public static final ScreenHandlerType<ContainerPrinter> PRINTER = registerSimple( "printer", ContainerPrinter::new );
public static final ScreenHandlerType<ContainerHeldItem> PRINTOUT = registerExtended( "printout", ContainerHeldItem::createPrintout );
public static final ScreenHandlerType<ContainerViewComputer> VIEW_COMPUTER = registerExtended( "view_computer", ContainerViewComputer::new );
public static final ScreenHandlerType<ContainerHeldItem> PRINTOUT = ContainerData.toType( new Identifier( MOD_ID, "printout" ), HeldItemContainerData::new, ContainerHeldItem::createPrintout );
public static final ScreenHandlerType<ContainerViewComputer> VIEW_COMPUTER = ContainerData.toType( new Identifier( MOD_ID, "view_computer" ), ViewComputerContainerData::new, ContainerViewComputer::new );
private static <T extends ScreenHandler> ScreenHandlerType<T> registerSimple( String id,
ScreenHandlerRegistry.SimpleClientHandlerFactory<T> function )
{
return ScreenHandlerRegistry.registerSimple( new Identifier( MOD_ID, id ), function );
}
private static <T extends ScreenHandler> ScreenHandlerType<T> registerExtended( String id, ScreenHandlerRegistry.ExtendedClientHandlerFactory<T> function )
{
return ScreenHandlerRegistry.registerExtended( new Identifier( MOD_ID, id ), function );
}
}
public static final class TurtleUpgrades

View File

@@ -35,7 +35,7 @@ public final class Peripherals
@Nullable
public static IPeripheral getPeripheral( World world, BlockPos pos, Direction side )
{
return World.isInBuildLimit( pos ) && !world.isClient ? getPeripheralAt( world, pos, side ) : null;
return world.isInBuildLimit( pos ) && !world.isClient ? getPeripheralAt( world, pos, side ) : null;
}
@Nullable

View File

@@ -3,12 +3,8 @@
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared;
import com.google.common.eventbus.Subscribe;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.turtle.event.TurtleActionEvent;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld;
@@ -17,23 +13,14 @@ import net.minecraft.world.World;
public final class TurtlePermissions
{
public static boolean isBlockEnterable( World world, BlockPos pos, PlayerEntity player )
{
MinecraftServer server = world.getServer();
return server == null || world.isClient || world instanceof ServerWorld && !server.isSpawnProtected( (ServerWorld) world, pos, player );
}
public static boolean isBlockEditable( World world, BlockPos pos, PlayerEntity player )
{
return isBlockEnterable( world, pos, player );
}
public static boolean isBlockEnterable( World world, BlockPos pos, PlayerEntity player )
{
MinecraftServer server = world.getServer();
return server == null || world.isClient || (world instanceof ServerWorld && !server.isSpawnProtected( (ServerWorld) world, pos, player ));
}
@Subscribe
public void onTurtleAction( TurtleActionEvent event )
{
if( ComputerCraft.turtleDisabledActions.contains( event.getAction() ) )
{
event.setCanceled( true, "Action has been disabled" );
}
}
}

View File

@@ -182,7 +182,7 @@ public final class CommandComputerCraft
ServerPlayerEntity player = (ServerPlayerEntity) entity;
if( player.getEntityWorld() == world )
{
player.networkHandler.teleportRequest(
player.networkHandler.requestTeleport(
pos.getX() + 0.5, pos.getY(), pos.getZ() + 0.5, 0, 0,
EnumSet.noneOf( PlayerPositionLookS2CPacket.Flag.class )
);
@@ -245,7 +245,7 @@ public final class CommandComputerCraft
@Override
public ScreenHandler createMenu( int id, @Nonnull PlayerInventory player, @Nonnull PlayerEntity entity )
{
return new ContainerViewComputer( id, computer );
return new ContainerViewComputer( id, player, computer );
}
} );
return 1;

View File

@@ -56,18 +56,17 @@ public enum UserLevel implements Predicate<ServerCommandSource>
public boolean test( ServerCommandSource source )
{
if( this == ANYONE ) return true;
if( this == OWNER || this == OWNER_OP )
{
MinecraftServer server = source.getMinecraftServer();
Entity sender = source.getEntity();
if( server.isSinglePlayer() && sender instanceof PlayerEntity &&
((PlayerEntity) sender).getGameProfile().getName().equalsIgnoreCase( server.getServerModName() ) )
{
return true;
}
}
if( this == OWNER ) return isOwner( source );
if( this == OWNER_OP && isOwner( source ) ) return true;
return source.hasPermissionLevel( toLevel() );
}
private static boolean isOwner( ServerCommandSource source )
{
MinecraftServer server = source.getServer();
Entity sender = source.getEntity();
return server.isDedicated()
? source.getEntity() == null && source.hasPermissionLevel( 4 ) && source.getName().equals( "Server" )
: sender instanceof PlayerEntity && ((PlayerEntity) sender).getGameProfile().getName().equalsIgnoreCase( server.getServerModName() );
}
}

View File

@@ -66,7 +66,7 @@ public final class HelpingArgumentBuilder extends LiteralArgumentBuilder<ServerC
// An ugly hack to extract usage information from the dispatcher. We generate a temporary node, generate
// the shorthand usage, and emit that.
CommandDispatcher<ServerCommandSource> dispatcher = context.getSource()
.getMinecraftServer()
.getServer()
.getCommandManager()
.getDispatcher();
CommandNode<ServerCommandSource> temp = new LiteralCommandNode<>( "_", null, x -> true, null, null, false );

View File

@@ -18,7 +18,6 @@ import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
@@ -35,6 +34,11 @@ public abstract class BlockGeneric extends BlockWithEntity
this.type = type;
}
public BlockEntityType<? extends TileGeneric> getType()
{
return type;
}
@Override
public BlockRenderType getRenderType( BlockState state )
{
@@ -94,8 +98,12 @@ public abstract class BlockGeneric extends BlockWithEntity
@Nullable
@Override
public BlockEntity createBlockEntity( @Nonnull BlockView world )
public BlockEntity createBlockEntity( BlockPos pos, BlockState state )
{
return type.instantiate();
if ( this.type != null )
{
return type.instantiate( pos, state );
}
return null;
}
}

View File

@@ -8,7 +8,7 @@ package dan200.computercraft.shared.common;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.network.client.TerminalState;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtCompound;
public class ClientTerminal implements ITerminal
{
@@ -80,12 +80,12 @@ public class ClientTerminal implements ITerminal
}
}
public void readDescription( CompoundTag nbt )
public void readDescription( NbtCompound nbt )
{
colour = nbt.getBoolean( "colour" );
if( nbt.contains( "terminal" ) )
{
CompoundTag terminal = nbt.getCompound( "terminal" );
NbtCompound terminal = nbt.getCompound( "terminal" );
resizeTerminal( terminal.getInt( "term_width" ), terminal.getInt( "term_height" ) );
this.terminal.readFromNBT( terminal );
}

View File

@@ -36,11 +36,6 @@ public class ContainerHeldItem extends ScreenHandler
.copy();
}
public static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, PacketByteBuf data )
{
return createPrintout( id, inventory, new HeldItemContainerData( data ) );
}
public static ContainerHeldItem createPrintout( int id, PlayerInventory inventory, HeldItemContainerData data )
{
return new ContainerHeldItem( ComputerCraftRegistry.ModContainers.PRINTOUT, id, inventory.player, data.getHand() );

View File

@@ -7,7 +7,7 @@
package dan200.computercraft.shared.common;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtCompound;
public interface IColouredItem
{
@@ -20,7 +20,7 @@ public interface IColouredItem
static int getColourBasic( ItemStack stack )
{
CompoundTag tag = stack.getTag();
NbtCompound tag = stack.getNbt();
return tag != null && tag.contains( NBT_COLOUR ) ? tag.getInt( NBT_COLOUR ) : -1;
}
@@ -35,7 +35,7 @@ public interface IColouredItem
{
if( colour == -1 )
{
CompoundTag tag = stack.getTag();
NbtCompound tag = stack.getNbt();
if( tag != null )
{
tag.remove( NBT_COLOUR );
@@ -43,7 +43,7 @@ public interface IColouredItem
}
else
{
stack.getOrCreateTag()
stack.getOrCreateNbt()
.putInt( NBT_COLOUR, colour );
}
}

View File

@@ -8,7 +8,7 @@ package dan200.computercraft.shared.common;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.network.client.TerminalState;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtCompound;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -85,12 +85,12 @@ public class ServerTerminal implements ITerminal
return new TerminalState( colour, terminal );
}
public void writeDescription( CompoundTag nbt )
public void writeDescription( NbtCompound nbt )
{
nbt.putBoolean( "colour", colour );
if( terminal != null )
{
CompoundTag terminal = new CompoundTag();
NbtCompound terminal = new NbtCompound();
terminal.putInt( "term_width", this.terminal.getWidth() );
terminal.putInt( "term_height", this.terminal.getHeight() );
this.terminal.writeToNBT( terminal );

View File

@@ -11,7 +11,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
@@ -21,9 +21,9 @@ import javax.annotation.Nonnull;
public abstract class TileGeneric extends BlockEntity implements BlockEntityClientSerializable
{
public TileGeneric( BlockEntityType<? extends TileGeneric> type )
public TileGeneric( BlockEntityType<? extends TileGeneric> type, BlockPos pos, BlockState state )
{
super( type );
super( type, pos, state );
}
public void destroy()
@@ -82,23 +82,23 @@ public abstract class TileGeneric extends BlockEntity implements BlockEntityClie
}
@Override
public void fromClientTag( CompoundTag compoundTag )
public void fromClientTag( NbtCompound compoundTag )
{
readDescription( compoundTag );
}
protected void readDescription( @Nonnull CompoundTag nbt )
protected void readDescription( @Nonnull NbtCompound nbt )
{
}
@Override
public CompoundTag toClientTag( CompoundTag compoundTag )
public NbtCompound toClientTag( NbtCompound compoundTag )
{
writeDescription( compoundTag );
return compoundTag;
}
protected void writeDescription( @Nonnull CompoundTag nbt )
protected void writeDescription( @Nonnull NbtCompound nbt )
{
}
}

View File

@@ -16,7 +16,7 @@ import dan200.computercraft.shared.util.NBTUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.command.CommandManager;
import net.minecraft.server.command.ServerCommandSource;
@@ -204,7 +204,7 @@ public class CommandAPI implements ILuaAPI
World world = computer.getWorld();
BlockPos min = new BlockPos( Math.min( minX, maxX ), Math.min( minY, maxY ), Math.min( minZ, maxZ ) );
BlockPos max = new BlockPos( Math.max( minX, maxX ), Math.max( minY, maxY ), Math.max( minZ, maxZ ) );
if( !World.isInBuildLimit( min ) || !World.isInBuildLimit( max ) )
if( !world.isInBuildLimit( min ) || !world.isInBuildLimit( max ) )
{
throw new LuaException( "Co-ordinates out of range" );
}
@@ -252,7 +252,7 @@ public class CommandAPI implements ILuaAPI
BlockEntity tile = world.getBlockEntity( pos );
if( tile != null )
{
table.put( "nbt", NBTUtil.toLua( tile.toTag( new CompoundTag() ) ) );
table.put( "nbt", NBTUtil.toLua( tile.writeNbt( new NbtCompound() ) ) );
}
return table;
@@ -289,7 +289,7 @@ public class CommandAPI implements ILuaAPI
// Get the details of the block
World world = computer.getWorld();
BlockPos position = new BlockPos( x, y, z );
if( World.isInBuildLimit( position ) )
if( world.isInBuildLimit( position ) )
{
return getBlockInfo( world, position );
}

Some files were not shown because too many files have changed in this diff Show More