Compare commits

...

145 Commits

Author SHA1 Message Date
470b5839a4 尝试修复客户端崩溃问题 2026-05-31 21:52:07 +08:00
GiantLuigi4
594c4decf3 improve keyboard camera 2024-10-21 23:53:07 -04:00
GiantLuigi4
ecb0dcee56 bump version, very start of audio stuff, fix a strange crash where camera is null 2024-10-19 00:53:48 -04:00
GiantLuigi4
cc18c6f793 improve handling of errors in the wd scheme
also config for join message
2024-10-18 00:11:58 -04:00
GiantLuigi4
6e712fc8da fix minisrv 2024-10-17 23:07:02 -04:00
GiantLuigi4
06e722cb7c screens can now be mined with a pickaxe 2024-10-17 12:36:11 -04:00
ds58
2ffe983e12
Merge pull request #17 from OtterCodes101/1.20
Add Modrinth link
2024-08-09 10:14:31 -05:00
OtterDev
5462ec7e93
Update README.md 2023-12-13 08:53:10 -07:00
GiantLuigi4
a603bdc8df - fix issues with minepad cursor lock
- keyboard now enables mouse controls
- fix some issues with the keyboard camera
- helper methods on the screen block entity for dealing with hit results
- update non-english language files to json
2023-11-29 13:54:42 -05:00
GiantLuigi4
21ffc08fcf keyboard camera mode config, fix some bugs with the ElementCenterQuery, fix ownership theif interacting with the wrong side 2023-11-27 18:05:18 -05:00
GiantLuigi4
cc0803de11 screen configurator now uses the correct direction 2023-11-27 15:24:43 -05:00
GiantLuigi4
7e7133e08c tweaks to js handling 2023-11-27 15:18:30 -05:00
GiantLuigi4
2e30446281 fix load distance 2023-11-27 11:18:12 -05:00
GiantLuigi4
9452482254 some refactoring 2023-11-27 10:35:26 -05:00
GiantLuigi4
91557161e0 pointer lock support 2023-11-26 00:46:53 -05:00
GiantLuigi4
85b076d638 ok I can push this too 2023-11-25 16:29:41 -05:00
GiantLuigi4
5292e97a8f start work on pointer lock api 2023-11-25 16:29:04 -05:00
GiantLuigi4
f843376f7a better mouse movement 2023-11-24 18:04:09 -05:00
GiantLuigi4
84d475d61c use a proper inverse of hit2px for the coordinate calculation for the keyboard camera 2023-11-22 23:59:18 -05:00
GiantLuigi4
f3f3cff079 not the best code quality, but it works how I wanted it to work 2023-11-22 22:52:08 -05:00
GiantLuigi4
fe81c18b5b I believe I have messed up... 2023-11-22 21:59:14 -05:00
GiantLuigi4
ec904c199e Merge remote-tracking branch 'origin/1.20' into 1.20
# Conflicts:
#	src/main/java/net/montoyo/wd/block/ScreenBlock.java
#	src/main/java/net/montoyo/wd/client/ClientProxy.java
#	src/main/java/net/montoyo/wd/client/gui/GuiKeyboard.java
#	src/main/java/net/montoyo/wd/client/gui/GuiScreenConfig.java
#	src/main/java/net/montoyo/wd/client/renderers/ScreenRenderer.java
#	src/main/java/net/montoyo/wd/controls/builtin/ManageRightsAndUpdgradesControl.java
#	src/main/java/net/montoyo/wd/data/ScreenConfigData.java
#	src/main/java/net/montoyo/wd/entity/AbstractInterfaceBlockEntity.java
#	src/main/java/net/montoyo/wd/entity/KeyboardBlockEntity.java
#	src/main/java/net/montoyo/wd/entity/RedstoneControlBlockEntity.java
#	src/main/java/net/montoyo/wd/entity/RemoteControlBlockEntity.java
#	src/main/java/net/montoyo/wd/entity/ScreenBlockEntity.java
#	src/main/java/net/montoyo/wd/item/ItemLaserPointer.java
#	src/main/java/net/montoyo/wd/item/ItemLinker.java
#	src/main/java/net/montoyo/wd/item/ItemOwnershipThief.java
#	src/main/java/net/montoyo/wd/item/ItemScreenConfigurator.java
#	src/main/java/net/montoyo/wd/net/client_bound/S2CMessageAddScreen.java
2023-11-22 21:54:43 -05:00
GiantLuigi4
281eb51c0d keyboard camera prototype 2023-11-22 21:48:54 -05:00
GiantLuigi4
3d2f786049 split "Screen" class out of TileEntityScreen 2023-11-22 15:51:38 -05:00
GiantLuigi4
3ca9f6ceb1
Merge pull request #7 from CinemaMod/format
Format
2023-11-11 18:05:22 -05:00
GiantLuigi4
92bd6924b0 undo cleanup of mouse handling, because it did not work 2023-11-11 17:59:15 -05:00
ds58
639fdefcce 2.0.1-1.20.1 2023-11-11 15:44:59 -06:00
ds58
1de20710fe Fix mcef dependency version in mods.toml 2023-11-11 15:44:22 -06:00
ds58
5b37a39dbc
Update README.md 2023-11-10 23:36:42 -06:00
ds58
0bc5b3b67d
Update README.md 2023-11-10 23:36:14 -06:00
ds58
dbd8fba683
Update README.md 2023-11-10 23:31:09 -06:00
ds58
d6da33da63 Merge branch '1.20' of https://github.com/CinemaMod/webdisplays into 1.20 2023-11-10 23:10:01 -06:00
ds58
2969470796 Update mods.toml 2023-11-10 23:09:32 -06:00
GiantLuigi4
074cedc85c some restructuring 2023-11-11 00:06:56 -05:00
GiantLuigi4
a4b4162fa9 modernize naming pt1 2023-11-10 23:58:05 -05:00
GiantLuigi4
a2f81aeeac modernize naming pt0 2023-11-10 23:57:02 -05:00
ds58
c2d6f01991
Add some images to README 2023-11-10 22:50:25 -06:00
GiantLuigi4
a9d9dcfecf format. 2023-11-10 23:50:06 -05:00
ds58
96d7c92c37 MIT License, start new README, gradle.properties cleanup 2023-11-10 22:46:18 -06:00
ds58
6869461124 Update Specification-Title in MANIFEST 2023-11-10 21:55:38 -06:00
ds58
66212d2d16 Make gradlew executable, remove libs dir 2023-11-10 21:54:56 -06:00
GiantLuigi4
aa8c545089 screens now get removed properly, TileEntityScreen has had ctrl+alt+l applied to it, and gradle has been cleaned up 2023-11-10 22:09:39 -05:00
GiantLuigi4
5ac5bada9d vivecraft support's back 2023-10-19 09:52:26 -04:00
GiantLuigi4
2a2d3077f4 update to latest MCEF, fix a potential rendering crash for the event that MCEF doesn't initalize properly 2023-10-19 00:21:03 -04:00
GiantLuigi4
92d5da727e update cursor textures 2023-09-27 23:16:07 -04:00
GiantLuigi4
ce718eeea2 minepad stuff 2023-09-27 22:33:13 -04:00
GiantLuigi4
e0ab3d2495 Merge remote-tracking branch 'origin/1.20' into 1.20
# Conflicts:
#	src/main/java/net/montoyo/wd/WebDisplays.java
2023-09-27 21:44:30 -04:00
GiantLuigi4
a4f8b630ef Packet for turning off a screen, start working on schema stuff 2023-09-27 21:36:35 -04:00
GiantLuigi4
3548b5806c fix some bugs with text fields 2023-09-27 15:04:52 -04:00
GiantLuigi4
95dc94d108 fix gui rendering, fix sounds being null, reimplement crosshair rendering 2023-09-27 14:41:35 -04:00
GiantLuigi4
48a46969ba sounds now work and the minepad now renders properly in hand 2023-09-24 22:52:29 -04:00
GiantLuigi4
42421a031a fix a dumb 2023-09-22 17:37:02 -04:00
GiantLuigi4
583fcc7be8 ack3 2023-09-22 17:30:26 -04:00
GiantLuigi4
2fc7c49977 ack2 2023-09-22 16:51:50 -04:00
GiantLuigi4
260027f12e ack 2023-09-22 16:51:36 -04:00
GiantLuigi4
5281694d6a fix a bunch of stuff that I intentionally broke 2023-09-22 16:25:45 -04:00
GiantLuigi4
2c931928d8 things are just barely able to be considered as working 2023-09-22 15:40:17 -04:00
GiantLuigi4
0867dd68d7 mod compiles, things *really* don't work 2023-09-22 15:26:43 -04:00
GiantLuigi4
f7f92cd19c lot of the work is done 2023-09-22 13:56:23 -04:00
GiantLuigi4
76a2a704dd update gradle 2023-09-21 22:40:01 -04:00
GiantLuigi4
be68ca40f0 more refactoring 2023-06-08 14:01:15 -04:00
GiantLuigi4
55be33ac44 update input handling to match latest MCEF 2023-06-08 12:00:54 -04:00
GiantLuigi4
4c0b89de04 e 2023-06-07 17:00:04 -04:00
GiantLuigi4
0c2f13439f well then 2023-06-07 16:05:44 -04:00
GiantLuigi4
c2c7df3b16 more dedup 2023-06-07 15:58:42 -04:00
GiantLuigi4
727808adbc deduplication 2023-06-07 15:51:40 -04:00
GiantLuigi4
0749e35431 remove excess facing properties 2023-06-07 14:35:05 -04:00
GiantLuigi4
44a2dd5b37 oops 2023-06-07 14:12:20 -04:00
GiantLuigi4
7283da4c87 connected textures go brr 2023-06-07 14:00:50 -04:00
GiantLuigi4
0f5f9e43cc waaaaaa 2023-06-06 23:12:06 -04:00
GiantLuigi4
d6ed36063d keybinding 2023-06-06 17:56:54 -04:00
GiantLuigi4
b4754dd15c translation stuff, update MCEF, change homepage 2023-06-06 17:25:48 -04:00
GiantLuigi4
58bc77a72a hm 2023-06-06 16:06:58 -04:00
GiantLuigi4
f9a7649b0e optimize minepad model and texture 2023-06-06 16:03:50 -04:00
GiantLuigi4
7c89d3a9b8 minepad rendering improvements 2023-06-06 15:02:10 -04:00
GiantLuigi4
7db99e2195 tweaks to keyboard handling 2023-06-05 21:57:45 -04:00
GiantLuigi4
26dab07419 fix laser mouse crosshair 2023-06-05 18:29:14 -04:00
GiantLuigi4
9cfbc07b44 long overdue redo of s2c networking, fix a crash from the laser pointer 2023-06-05 18:23:05 -04:00
GiantLuigi4
5ce9e4574d fix issue where turning on the back of the screen would break both sides of the screen 2023-06-05 16:57:47 -04:00
GiantLuigi4
78160917eb laser pointer work 2023-06-05 15:58:32 -04:00
GiantLuigi4
c066176c79 laser renderer tweaks 2023-06-04 22:53:04 -04:00
GiantLuigi4
de2bc44a8e cursors 2023-06-04 22:14:13 -04:00
GiantLuigi4
e1ae67c7a2 bump MCEF version, fix a typo in the lang file, fix some bugs with page opening 2023-06-04 00:03:06 -04:00
GiantLuigi4
e2f6ac39a5 fix keyboard model, fix upgrade stacking&serialization, fix keyboard collision shape 2023-06-02 23:19:13 -04:00
GiantLuigi4
5d3426706f new config option, fix a clicking issues with clicking on the display 2023-06-02 21:50:46 -04:00
GiantLuigi4
246eb45d90 prevent mouse from changing outside of the browser 2023-06-02 17:23:45 -04:00
GiantLuigi4
54d49a1e02 yes 2023-06-02 16:57:39 -04:00
GiantLuigi4
0dda6eafb7 loot tables, and some code cleanup 2023-06-02 16:55:32 -04:00
GiantLuigi4
f16414f724 also forgot to fix this because I'm dumb, lol 2023-06-02 15:23:17 -04:00
GiantLuigi4
bb7b3a9034 forgot some defaults 2023-06-02 15:21:55 -04:00
GiantLuigi4
116f7290d0 more minepad stuff, switch off of cloth config 2023-06-02 15:19:27 -04:00
GiantLuigi4
7d3de1fcc5 switch config systems; configs can now be modified on the fly and have comments and such 2023-06-02 13:36:59 -04:00
GiantLuigi4
4ac3edb4af slight tweaks, start looking into a potential way to sync videos 2023-06-01 22:39:28 -04:00
GiantLuigi4
7c7d008589 a small change 2023-06-01 17:19:43 -04:00
GiantLuigi4
a9b205e651 oop
lol
2023-05-31 23:14:08 -04:00
GiantLuigi4
52f7695c1c kinda fix screen configurator, tweak some code 2023-05-31 23:12:22 -04:00
GiantLuigi4
64cfb61a27 excuse me
what
2023-05-31 21:42:52 -04:00
GiantLuigi4
0219b56d26 m o u s e 2023-05-31 21:31:13 -04:00
GiantLuigi4
53b12a3294 more minepad stuff; need to copy some code from MCEF and look at why mouse input isn't working properly 2023-05-31 15:49:15 -04:00
GiantLuigi4
5780cd1199 Merge remote-tracking branch 'upstream/master' 2023-05-31 15:31:23 -04:00
GiantLuigi4
3719448331 start of minepad stuff 2023-05-31 15:31:14 -04:00
Mysticpasta1
dcf23fe6e1 thing 2023-05-05 19:17:35 -05:00
Mysticpasta1
c197bffaf7 Update build.gradle 2023-03-14 19:45:12 -05:00
GiantLuigi4
bc16cf9769 large reworks of network code, various fixes 2023-03-14 13:00:34 -04:00
GiantLuigi4
3c141d9e1b redo like literally all of networking 2023-03-12 16:33:58 -04:00
Mysticpasta1
ff55cbf1b2 Merge branch 'master' of https://github.com/Mysticpasta1/webdisplays 2023-03-09 21:29:34 -06:00
Mysticpasta1
0d0c201fba laser pointer fixed also fixed block screen gui url changing thing 2023-03-09 21:28:42 -06:00
GiantLuigi4
2aa3b3f456
Merge pull request #5 from GiantLuigi4/master
various thhingingses
2023-03-09 22:28:32 -05:00
GiantLuigi4
b01e15ab73 various thhingingses 2023-03-09 21:50:12 -05:00
Mysticpasta1
b9716dd537 Update ServerEventHandler.java 2023-03-09 15:42:45 -06:00
Mysticpasta1
9e8d46d8ab things 2023-03-09 04:33:35 -06:00
Mysticpasta1
3b5ad2112f right clicking function active 2023-03-09 03:26:22 -06:00
Mysticpasta1
f4dbd00f9d revert 2023-03-08 10:59:12 -06:00
Mysticpasta1
cd31a5efab better syncing hopefully 2023-03-08 09:12:24 -06:00
Mysticpasta1
3f22a1a4ab push for ai 2023-03-08 07:20:05 -06:00
Mysticpasta1
7a33e30de7 setURL for the player when null 2023-03-07 19:20:21 -06:00
Mysticpasta1
26f6aa5de4 Fixed almost all sync issues except one 2023-03-07 11:15:24 -06:00
Mysticpasta1
a4f9fdca7a try syncing it 2023-03-06 21:50:17 -06:00
Mysticpasta1
cf70556ce8 Update build.gradle 2023-03-05 23:45:43 -06:00
Mysticpasta1
d9e75f6ada
Merge pull request #4 from GiantLuigi4/master
a couple of tweaks
2023-03-05 22:17:50 -06:00
Mysticpasta1
9dbe5b78f2 Fixed Recipes and Advancements 2023-03-05 22:17:26 -06:00
GiantLuigi4
5e23f8272f
Merge branch 'Mysticpasta1:master' into master 2023-03-05 21:26:38 -05:00
GiantLuigi4
c9589d9e3c better linker handling, remove excess imports in BlockKeyboardRight 2023-03-05 21:25:48 -05:00
GiantLuigi4
06597c4506 better keyboard handling, VR keyboard, and also you can turn on displays while crouching 2023-03-05 21:03:38 -05:00
Mysticpasta1
efd632083b Merge branch 'master' of https://github.com/Mysticpasta1/webdisplays 2023-03-05 19:25:02 -06:00
Mysticpasta1
cb570bb85f Update build.gradle 2023-03-05 19:24:53 -06:00
Mysticpasta1
b588e975bc
Merge pull request #3 from GiantLuigi4/master
slight tweaks to networking code
2023-03-05 19:24:31 -06:00
GiantLuigi4
f78f3bb686 update gradle&mod compiles again 2023-03-05 20:18:44 -05:00
GiantLuigi4
bc7de9a7b6 slight tweaks to networking code 2023-03-05 20:10:03 -05:00
Mysticpasta1
e5c3731236 Update build.gradle 2023-03-05 17:08:22 -06:00
Mysticpasta1
83e0094a56 revert beep commit 2023-03-05 17:01:56 -06:00
Mysticpasta1
99187b3081 deobf dependencies 2023-03-05 16:48:16 -06:00
Mysticpasta1
aea8513eb0 beep 2023-03-05 09:29:50 -06:00
Mysticpasta1
1ec3c5e5d9 Update build.gradle 2023-03-05 07:02:51 -06:00
Mysticpasta1
b9bf414b47 Update build.gradle 2023-03-05 04:39:21 -06:00
Mysticpasta1
ea294e1cd6 minor bugs fix 2023-03-05 04:18:02 -06:00
Mysticpasta1
3335a0e866 Update build.gradle 2023-03-05 03:18:30 -06:00
Mysticpasta1
d66be53fb8 Key input 2023-03-05 03:04:46 -06:00
Mysticpasta1
57beebfc02
Merge pull request #2 from GiantLuigi4/master
rework keyboards
2023-03-03 23:49:53 -06:00
GiantLuigi4
374b4ee993 rework keyboards 2023-03-03 21:14:24 -05:00
Mysticpasta1
7d66708a5e push something to WD 2023-03-03 03:02:52 -06:00
Mysticpasta1
883269c20c Fix Server side crash 2023-03-02 14:12:58 -06:00
Mysticpasta1
e5ee14536a Client Safety 2023-03-02 13:55:33 -06:00
Mysticpasta1
1f7563cc34 clean up more code 2023-03-02 13:30:35 -06:00
Mysticpasta1
7fb2170e34 initial port to 1.19.2 forge (windows only) 2023-03-02 04:42:06 -06:00
376 changed files with 12317 additions and 11161 deletions

22
LICENSE
View File

@ -1 +1,21 @@
This mod and its source code is now in public domain. Feel free to do whatever you want with it; make forks, distribute it... whatever I would appreciate it, of course, if you credited me 😊 Thank you!
MIT License
Copyright (c) 2023 CinemaMod Group
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,18 +1,25 @@
# WebDisplays for Minecraft 1.12.2
This is the WebDisplays mod for Minecraft 1.12.2. I don't have time to maintain it anymore, so I changed the license recently and anybody is welcome to create forks and/or re-distribute it. For more info see [LICENSE](LICENSE).
# WebDisplays
WebDisplays is a mod for creating and interacting with web browsers in Minecraft. You can create screens in your world and browse the internet.
### Wiki
* The Wiki that details all blocks/items can be found on my website https://montoyo.net/wdwiki/
WebDisplays was originally written by montoyo. It is currently maintained by CinemaMod Group.
### Things before release
* Release ready. Targeted release date: 17/02/2018.
Discussion: https://discord.gg/rNrh5kW8Ty
### Delayed things
* Plugin API
* The Shop
* CC Interface, if CC gets updated...
* Center camera to screen when using keyboard
* minePad management: check GuiContainer.draggedStack for minePad
* In-game command to add/remove blacklisted domains
* Config: RPMP (Real pixels per Minecraft pixels)
* Disable miniserv in solo
## Install
Download WebDisplays from either:
- CurseForge: https://legacy.curseforge.com/minecraft/mc-mods/webdisplays
- Modrinth: https://modrinth.com/mod/webdisplays
**WebDisplays Requires MCEF!** You must install MCEF in order for WebDisplays to work.
Download MCEF from either:
- CurseForge: https://legacy.curseforge.com/minecraft/mc-mods/mcef
- Modrinth: https://modrinth.com/mod/mcef
<img src='https://github.com/CinemaMod/webdisplays/assets/30220598/2acfd365-fa87-4adb-970a-33bb5c79f7ba' width='500'>
<img src='https://github.com/CinemaMod/webdisplays/assets/30220598/4e9985a3-d09f-4ab4-8016-37733d4f4a99' width='500'>
## Wiki
[Outdated Wiki from the original creator](https://montoyo.net/wdwiki/index.php?title=Main_Page)
[Outdated Getting Started](https://montoyo.net/wdwiki/index.php?title=Screen)

12
TODO.md Normal file
View File

@ -0,0 +1,12 @@
### Delayed things
* Plugin API
* Center camera to screen when using keyboard
* Allow actual cursor to be used via aiming it at the screen
* maybe aim at the focused element instead of the center of the screen, depends on if that information can be extracted
* minePad management: check GuiContainer.draggedStack for minePad
* In-game command to add/remove blacklisted domains
* CC Interface (for when it's actually possible, since the screens are client only currently, but a config option is planned to change that)
* Redstone controls (same reason as CC interface)
* Potentially redo minisrv logic?
* Perhaps hook it up to vanilla networking
* Maybe don't use it at all in single player

View File

@ -1,101 +1,179 @@
plugins {
id 'dev.architectury.loom' version '0.12.0-SNAPSHOT'
id 'io.github.juuxel.loom-quiltflower' version '1.6.0'
id 'java'
id 'idea'
id 'maven-publish'
id 'com.github.johnrengelman.shadow' version '8.1.1'
id 'net.neoforged.moddev.legacyforge' version '2.0.103'
}
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
// Only add ProGuard if building with it
def enableProguard = project.hasProperty("enableProguard") && project.enableProguard.toBoolean()
if (enableProguard) {
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'com.guardsquare:proguard-gradle:7.7.0'
}
}
}
archivesBaseName = project.archives_base_name
version = project.mod_version
group = project.maven_group
base {
archivesName = mod_id
}
group = mod_group_id
version = "${minecraft_version}-${mod_version}"
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
println "Java: ${System.getProperty 'java.version'}"
repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
maven { url "https://maven.shedaniel.me/" }
maven { url 'https://jitpack.io' }
maven {
url = "https://maven.parchmentmc.org"
mavenCentral()
maven { url = "https://libraries.minecraft.net/" }
maven { url = "https://cursemaven.com" }
maven { url = "https://maven.parchmentmc.org" }
maven { url = 'https://mcef-download.cinemamod.com/repositories/releases/' }
maven { url = "https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/" }
maven { url = "https://maven.theillusivec4.top/" }
maven { url = "https://repo.lucko.me/" }
maven { url = "https://maven.kosmx.dev/" }
maven { url = "https://modmaven.dev" }
flatDir { dir "libs" }
}
legacyForge {
version = "${minecraft_version}-${forge_version}"
// Access transformer
accessTransformers = files("src/main/resources/META-INF/accesstransformer.cfg")
// Parchment mappings
parchment {
minecraftVersion = minecraft_version
mappingsVersion = mapping_lasting_version
}
maven {
name = "cursemaven"
url = "https://www.cursemaven.com"
}
}
loom {
accessWidenerPath = file("src/main/resources/webdisplays.accesswidener")
}
runs {
configureEach {
systemProperty 'forge.logging.console.level', 'debug'
logLevel = org.slf4j.event.Level.DEBUG
}
dependencies {
// To change the versions see the gradle.properties file
minecraft "com.mojang:minecraft:${project.minecraft_version}"
mappings loom.layered() {
officialMojangMappings()
parchment("org.parchmentmc.data:parchment-1.18.2:2022.05.02@zip")
}
forge "net.minecraftforge:forge:${project.forge_version}"
client {
client()
programArgument "-mixin.config=${mod_id}.mixins.json"
systemProperty 'mixin.debug.export', 'true'
}
modImplementation "com.github.Mysticpasta1:mcef-forge:11826a2d11"
modImplementation "curse.maven:cloth_config_forge-348521:3546623"
// Uncomment the following line to enable the deprecated Fabric API modules.
// These are included in the Fabric API production distribution and allow you to update your mod to the latest modules at a later more convenient time.
server {
server()
programArgument "-mixin.config=${mod_id}.mixins.json"
}
// modImplementation "net.fabricmc.fabric-api:fabric-api-deprecated:${project.fabric_version}"
}
loom {
forge {
mixinConfigs = [
"webdisplays.mixin.json"
]
}
}
processResources {
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
}
tasks.withType(JavaCompile).configureEach {
// Minecraft 1.18 (1.18-pre2) upwards uses Java 17.
it.options.release = 17
}
java {
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
// if it is present.
// If you remove this line, sources will not be generated.
withSourcesJar()
}
jar {
from("LICENSE") {
rename { "${it}_${project.archivesBaseName}"}
}
}
// configure the maven publication
publishing {
publications {
mavenJava(MavenPublication) {
from components.java
data {
data()
programArguments.addAll '--mod', mod_id, '--all',
'--output', file('src/generated/resources/').absolutePath,
'--existing', file('src/main/resources/').absolutePath
}
}
mods {
"${mod_id}" {
sourceSet sourceSets.main
}
}
}
sourceSets.main.resources {
srcDir 'src/generated/resources'
}
dependencies {
// MCEF dependency
modImplementation("com.cinemamod:mcef-forge:2.1.1-1.20.1") {
transitive = false
}
// Optional mods (make sure versions exist)
modRuntimeOnly "curse.maven:spark-361579:4738952"
modCompileOnly "curse.maven:vivecraft-667903:4794431"
modImplementation "software.bernie.geckolib:geckolib-forge-${minecraft_version}:${geckolib_version}"
modCompileOnly "top.theillusivec4.curios:curios-forge:${curios_version}:api"
modRuntimeOnly "top.theillusivec4.curios:curios-forge:${curios_version}"
// Mixin Extras
compileOnly annotationProcessor("io.github.llamalad7:mixinextras-common:0.4.1")
modImplementation "io.github.llamalad7:mixinextras-forge:0.4.1"
}
tasks.named('jar', Jar) {
manifest {
attributes([
'Specification-Title': mod_name,
'Specification-Vendor': mod_authors,
'Specification-Version': '1',
'Implementation-Title': project.name,
'Implementation-Version': project.version,
'Implementation-Vendor': mod_authors,
'MixinConfigs': "${mod_id}.mixins.json"
])
}
// Exclude ProGuard renamed files if ProGuard is used
if (enableProguard) {
exclude 'META-INF/versions/**'
}
}
// Generate sources jar
tasks.register('sourcesJar', Jar) {
dependsOn classes
archiveClassifier = 'sources'
from sourceSets.main.allSource
}
// Reobfuscation handling
tasks.named('reobfJar') {
if (enableProguard) {
dependsOn 'proguard'
input = file("${buildDir}/libs/${mod_id}-${minecraft_version}-${mod_version}-proguard.jar")
} else {
dependsOn 'jar'
input = tasks.jar.archiveFile.get().asFile
}
}
// ProGuard configuration (if enabled)
if (enableProguard) {
tasks.register('proguard', proguard.gradle.ProGuardTask) {
dependsOn tasks.jar
configuration 'proguard.pro'
libraryjars "${System.getProperty('java.home')}/jmods"
def inputJar = tasks.jar.archiveFile.get().asFile
injars inputJar
outjars "${buildDir}/libs/${mod_id}-${minecraft_version}-${mod_version}-proguard.jar"
}
}
publishing {
publications {
mavenJava(MavenPublication) {
artifactId = mod_id
artifact reobfJar
artifact sourcesJar
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
// Notice: This block does NOT have the same function as the block in the top level.
// The repositories here will be used for publishing your artifact, not for
// retrieving dependencies.
maven {
name = "local"
url = layout.buildDirectory.dir("repo")
}
}
}

1
cursors.piskel Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,17 +1,36 @@
# Done to increase the memory available to gradle.
# Gradle settings
org.gradle.jvmargs=-Xmx3G
loom.platform=forge
org.gradle.daemon=false
org.gradle.parallel=true
org.gradle.caching=true
# Fabric Properties
# check these on https://fabricmc.net/develop
minecraft_version=1.18.2
yarn_mappings=1.18.2+build.3
loader_version=0.14.8
# ProGuard
enableProguard=false
# Mod Properties
mod_version = 1.0.0
maven_group = net.montoyo.wd
archives_base_name = webdisplays
# Mod properties
mod_id=webdisplays
mod_name=WebDisplays
mod_version=2.0.3
mod_group_id=com.cinemamod
mod_authors=CinemaMod Group
mod_description=Web browser displays for Minecraft
mod_license=All Rights Reserved
mod_credits=CinemaMod Group
# Dependencies
forge_version=1.18.2-40.1.52
# Minecraft/Forge versions
minecraft_version=1.20.1
forge_version=47.3.4
minecraft_version_range=[1.20.1,1.21)
forge_version_range=[47,)
loader_version_range=[47,)
# Parchment mappings
mapping_channel=parchment
mapping_version=2023.09.03-1.20.1
mapping_lasting_version=2023.09.03
# Other mod versions
jei_version=15.20.0.112
player_anim_version=1.0.2-rc1+1.20
geckolib_version=4.2.1
curios_version=5.5.0+1.20.1

View File

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip

0
gradlew vendored Normal file → Executable file
View File

View File

@ -1,23 +1,11 @@
pluginManagement {
repositories {
pluginManagement {
repositories {
//jcenter() // jcenter will be stopped in 2022
mavenCentral()
maven {
name = 'Fabric'
url = 'https://maven.fabricmc.net/'
}
maven { url "https://maven.architectury.dev/" }
maven { url "https://files.minecraftforge.net/maven/" }
maven {
name = 'Cotton'
url = 'https://server.bbkr.space/artifactory/libs-release/'
}
gradlePluginPortal()
}
}
mavenCentral()
mavenLocal()
gradlePluginPortal()
maven { url = 'https://maven.neoforged.net/releases' }
maven { url = 'https://maven.parchmentmc.org' } // Add this line
}
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
}

View File

@ -4,40 +4,59 @@
package net.montoyo.wd;
import com.cinemamod.mcef.MCEF;
import com.mojang.authlib.GameProfile;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.server.ServerLifecycleHooks;
import net.montoyo.wd.utilities.Log;
import net.montoyo.wd.core.HasAdvancement;
import net.montoyo.wd.core.JSServerRequest;
import net.montoyo.wd.data.GuiData;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.utilities.*;
import net.montoyo.wd.utilities.math.Vector2i;
import net.montoyo.wd.utilities.math.Vector3i;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.data.Rotation;
import net.montoyo.wd.utilities.serialization.NameUUIDPair;
import org.joml.Vector3d;
import javax.annotation.Nonnull;
import static net.minecraftforge.api.distmarker.Dist.CLIENT;
import java.util.UUID;
public class SharedProxy {
public void preInit() {
}
public void init() {
MCEF.scheduleForInit((cef) -> onCefInit());
}
public void postInit() {
}
public void onCefInit() {
}
@Deprecated(forRemoval = true)
public Level getWorld(ResourceKey<Level> dim) {
return getServer().getLevel(dim);
}
public BlockGetter getWorld(NetworkEvent.Context context) {
if (context.getSender() != null) return context.getSender().level();
return null;
}
public void enqueue(Runnable r) {
ServerLifecycleHooks.getCurrentServer().addTickable(r);
}
@ -46,7 +65,7 @@ public class SharedProxy {
Log.error("Called SharedProxy.displayGui() on server side...");
}
public void trackScreen(TileEntityScreen tes, boolean track) {
public void trackScreen(ScreenBlockEntity tes, boolean track) {
}
public void onAutocompleteResult(NameUUIDPair pairs[]) {
@ -65,11 +84,11 @@ public class SharedProxy {
public void screenUpdateAutoVolumeInGui(Vector3i pos, BlockSide side, boolean av) {
}
public void displaySetPadURLGui(String padURL) {
public void displaySetPadURLGui(ItemStack is, String padURL) {
Log.error("Called SharedProxy.displaySetPadURLGui() on server side...");
}
public void openMinePadGui(int padId) {
public void openMinePadGui(UUID padId) {
Log.error("Called SharedProxy.openMinePadGui() on server side...");
}
@ -110,4 +129,20 @@ public class SharedProxy {
return false;
}
public double distanceTo(ScreenBlockEntity tes, Vec3 position) {
double dist = Double.POSITIVE_INFINITY;
for (int i = 0; i < tes.screenCount(); i++) {
ScreenData scrn = tes.getScreen(i);
Vector3d pos = new Vector3d(
scrn.side.right.x * scrn.size.x / 2d + scrn.size.y * scrn.side.up.x / 2d,
scrn.side.right.y * scrn.size.x / 2d + scrn.size.y * scrn.side.up.y / 2d,
scrn.side.right.z * scrn.size.x / 2d + scrn.size.y * scrn.side.up.z / 2d
).add(tes.getBlockPos().getX(), tes.getBlockPos().getY(), tes.getBlockPos().getZ());
double dist2 = position.distanceToSqr(pos.x, pos.y, pos.z);
dist = Math.min(dist, dist2);
}
return dist;
}
}

View File

@ -5,13 +5,11 @@
package net.montoyo.wd;
import com.google.gson.Gson;
import me.shedaniel.autoconfig.AutoConfig;
import me.shedaniel.autoconfig.ConfigHolder;
import me.shedaniel.autoconfig.serializer.Toml4jConfigSerializer;
import net.minecraft.ChatFormatting;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
@ -20,59 +18,55 @@ import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraftforge.client.event.ClientChatEvent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.ServerChatEvent;
import net.minecraftforge.event.entity.item.ItemTossEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.event.server.ServerStoppingEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.wd.block.WDBlockContainer;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.client.gui.controls.*;
import net.montoyo.wd.config.ModConfig;
import net.montoyo.wd.client.gui.camera.KeyboardCamera;
import net.montoyo.wd.config.ClientConfig;
import net.montoyo.wd.config.CommonConfig;
import net.montoyo.wd.controls.ScreenControlRegistry;
import net.montoyo.wd.core.*;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.init.ItemInit;
import net.montoyo.wd.init.TileInit;
import net.montoyo.wd.miniserv.server.Server;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageServerInfo;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.client_bound.S2CMessageServerInfo;
import net.montoyo.wd.registry.BlockRegistry;
import net.montoyo.wd.registry.ItemRegistry;
import net.montoyo.wd.registry.TileRegistry;
import net.montoyo.wd.registry.WDTabs;
import net.montoyo.wd.utilities.DistSafety;
import net.montoyo.wd.utilities.Log;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.serialization.Util;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.ArrayList;
import java.util.Objects;
import java.util.UUID;
@Mod("webdisplays")
public class WebDisplays {
public static final String MOD_VERSION = "1.1";
public static WebDisplays INSTANCE;
public static SharedProxy PROXY = DistExecutor.<SharedProxy>runForDist(() -> ClientProxy::new, () -> SharedProxy::new);
public static WDCreativeTab CREATIVE_TAB;
public static SharedProxy PROXY = null;
public static final ResourceLocation ADV_PAD_BREAK = new ResourceLocation("webdisplays", "webdisplays/pad_break");
public static final String BLACKLIST_URL = "mod://webdisplays/blacklisted.html";
public static final Gson GSON = new Gson();
@ -94,54 +88,40 @@ public class WebDisplays {
//Config
public static final double PAD_RATIO = 59.0 / 30.0;
public String homePage;
public double padResX;
public double padResY;
private int lastPadId = 0;
public boolean doHardRecipe;
private boolean hasOC;
private boolean hasCC;
private List<String> blacklist;
public boolean disableOwnershipThief;
public double unloadDistance2;
public double loadDistance2;
public int maxResX;
public int maxResY;
public int maxScreenX;
public int maxScreenY;
public int miniservPort;
public long miniservQuota;
public boolean enableSoundDistance;
public float ytVolume;
public float avDist100;
public float avDist0;
// mod detection
private boolean hasOC;
private boolean hasCC;
public WebDisplays() {
INSTANCE = this;
AutoConfig.register(ModConfig.class, Toml4jConfigSerializer::new);
ConfigHolder<ModConfig> configHolder = AutoConfig.getConfigHolder(ModConfig.class);
ModConfig config = configHolder.getConfig();
configHolder.save();
this.blacklist = config.main.blacklist;
doHardRecipe = config.main.hardRecipes;
this.homePage = config.main.homepage;
disableOwnershipThief = config.main.disableOwnershipThief;
unloadDistance2 = config.client.unloadDistance * config.client.unloadDistance;
loadDistance2 = config.client.loadDistance * config.client.loadDistance;
this.maxResX = config.main.maxResolutionX;
this.maxResY = config.main.maxResolutionY;
this.miniservPort = config.main.miniservPort;
this.miniservQuota = config.main.miniservQuota * 1024L;
this.maxScreenX = config.main.maxScreenSizeX;
this.maxScreenY = config.main.maxScreenSizeY;
enableSoundDistance = config.client.autoVolumeControl.enableAutoVolume;
this.ytVolume = (float) config.client.autoVolumeControl.ytVolume;
avDist100 = (float) config.client.autoVolumeControl.dist100;
avDist0 = (float) config.client.autoVolumeControl.dist0;
CREATIVE_TAB = new WDCreativeTab();
if(FMLEnvironment.dist.isClient()) {
PROXY = DistSafety.createProxy();
} else {
PROXY = new SharedProxy();
}
if (FMLEnvironment.dist.isClient()) {
// proxies are annoying, so from now on, I'mma be just registering stuff in here
FMLJavaModLoadingContext.get().getModEventBus().addListener(ClientProxy::onKeybindRegistry);
MinecraftForge.EVENT_BUS.addListener(ClientProxy::onDrawSelection);
MinecraftForge.EVENT_BUS.addListener(KeyboardCamera::updateCamera);
MinecraftForge.EVENT_BUS.addListener(KeyboardCamera::gameTick);
ClientConfig.init();
}
CommonConfig.init();
//Criterions
criterionPadBreak = new Criterion("pad_break");
criterionUpgradeScreen = new Criterion("upgrade_screen");
@ -149,23 +129,19 @@ public class WebDisplays {
criterionKeyboardCat = new Criterion("keyboard_cat");
registerTrigger(criterionPadBreak, criterionUpgradeScreen, criterionLinkPeripheral, criterionKeyboardCat);
//Read configuration
padResY = config.main.padHeight;
padResX = padResY * PAD_RATIO;
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
bus.addListener(Messages::registryNetworkPackets);
BlockInit.init(bus);
ItemInit.init(bus);
ItemInit.registerUpgrade();
ItemInit.registerComponents();
TileInit.init(bus);
WDNetworkRegistry.init();
SOUNDS.register(bus);
onRegisterSounds();
WDTabs.init(bus);
BlockRegistry.init(bus);
ItemRegistry.init(bus);
TileRegistry.init(bus);
PROXY.preInit();
MinecraftForge.EVENT_BUS.register(this);
//Other things
PROXY.init();
@ -182,6 +158,10 @@ public class WebDisplays {
t.printStackTrace();
}
} */
if (!FMLEnvironment.production) {
ScreenControlRegistry.init();
}
}
@SubscribeEvent
@ -191,23 +171,24 @@ public class WebDisplays {
}
}
@SubscribeEvent
public void onRegisterSounds(RegistryEvent.Register<SoundEvent> ev) {
soundTyping = registerSound(ev, "keyboardType");
soundUpgradeAdd = registerSound(ev, "upgradeAdd");
soundUpgradeDel = registerSound(ev, "upgradeDel");
soundScreenCfg = registerSound(ev, "screencfgOpen");
soundServer = registerSound(ev, "server");
soundIronic = registerSound(ev, "ironic");
public void onRegisterSounds() {
soundTyping = registerSound("keyboard_type");
soundUpgradeAdd = registerSound("upgrade_add");
soundUpgradeDel = registerSound("upgrade_del");
soundScreenCfg = registerSound("screencfg_open");
soundServer = registerSound("server");
soundIronic = registerSound("ironic");
}
ArrayList<ResourceKey<Level>> serverStartedDimensions = new ArrayList<>();
@SubscribeEvent
public void onWorldLoad(WorldEvent.Load ev) {
if (ev.getWorld() instanceof Level level) {
if (ev.getWorld().isClientSide() || level.dimension() != Level.OVERWORLD)
public void onWorldLoad(LevelEvent.Load ev) {
if (ev.getLevel() instanceof Level level) {
if (ev.getLevel().isClientSide() || level.dimension() != Level.OVERWORLD)
return;
File worldDir = Objects.requireNonNull(ev.getWorld().getServer()).getServerDirectory();
File worldDir = Objects.requireNonNull(ev.getLevel().getServer()).getServerDirectory();
File f = new File(worldDir, "wd_next.txt");
if (f.exists()) {
@ -231,29 +212,34 @@ public class WebDisplays {
if (miniservPort != 0) {
Server sv = Server.getInstance();
sv.setPort(miniservPort);
sv.setDirectory(new File(worldDir, "wd_filehost"));
sv.start();
if(!serverStartedDimensions.contains(level.dimension())) {
sv.setPort(miniservPort);
sv.setDirectory(new File(worldDir, "wd_filehost"));
sv.start();
serverStartedDimensions.add(level.dimension());
}
}
}
}
@SubscribeEvent
public void onWorldLeave(WorldEvent.Unload ev) throws IOException {
if(ev.getWorld() instanceof Level level) {
if (ev.getWorld().isClientSide() || level.dimension() != Level.OVERWORLD)
public void onWorldLeave(LevelEvent.Unload ev) throws IOException {
if(ev.getLevel() instanceof Level level) {
if (ev.getLevel().isClientSide() || level.dimension() != Level.OVERWORLD)
return;
Server sw = Server.getInstance();
sw.stopServer();
serverStartedDimensions.remove(level.dimension());
}
}
@SubscribeEvent
public void onWorldSave(WorldEvent.Save ev) {
if(ev.getWorld() instanceof Level level) {
if (ev.getWorld().isClientSide() || level.dimension() != Level.OVERWORLD)
public void onWorldSave(LevelEvent.Save ev) {
if(ev.getLevel() instanceof Level level) {
if (ev.getLevel().isClientSide() || level.dimension() != Level.OVERWORLD)
return;
File f = new File(Objects.requireNonNull(ev.getWorld().getServer()).getServerDirectory(), "wd_next.txt");
File f = new File(Objects.requireNonNull(ev.getLevel().getServer()).getServerDirectory(), "wd_next.txt");
try {
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
@ -267,10 +253,10 @@ public class WebDisplays {
@SubscribeEvent
public void onToss(ItemTossEvent ev) {
if(!ev.getEntityItem().getLevel().isClientSide) {
ItemStack is = ev.getEntityItem().getItem();
if(!ev.getEntity().level().isClientSide) {
ItemStack is = ev.getEntity().getItem();
if(is.getItem() == ItemInit.itemMinePad.get()) {
if(is.getItem() == ItemRegistry.MINEPAD.get()) {
CompoundTag tag = is.getTag();
if(tag == null) {
@ -288,12 +274,12 @@ public class WebDisplays {
@SubscribeEvent
public void onPlayerCraft(PlayerEvent.ItemCraftedEvent ev) {
if(doHardRecipe && ev.getCrafting().getItem() == ItemInit.itemCraftComp.get() && (CraftComponent.EXTENSION_CARD.makeItemStack().is(ev.getCrafting().getItem()))) {
if((ev.getPlayer() instanceof ServerPlayer && !hasPlayerAdvancement((ServerPlayer) ev.getPlayer(), ADV_PAD_BREAK)) || PROXY.hasClientPlayerAdvancement(ADV_PAD_BREAK) != HasAdvancement.YES) {
ev.getCrafting().setDamageValue(CraftComponent.BAD_EXTENSION_CARD.ordinal());
if(CommonConfig.hardRecipes && ItemRegistry.isCompCraftItem(ev.getCrafting().getItem()) && (CraftComponent.EXTCARD.makeItemStack().is(ev.getCrafting().getItem()))) {
if((ev.getEntity() instanceof ServerPlayer && !hasPlayerAdvancement((ServerPlayer) ev.getEntity(), ADV_PAD_BREAK)) || PROXY.hasClientPlayerAdvancement(ADV_PAD_BREAK) != HasAdvancement.YES) {
ev.getCrafting().setDamageValue(CraftComponent.BADEXTCARD.ordinal());
if(!ev.getPlayer().getLevel().isClientSide)
ev.getPlayer().getLevel().playSound(null, ev.getPlayer().getX(), ev.getPlayer().getY(), ev.getPlayer().getZ(), SoundEvents.ITEM_BREAK, SoundSource.MASTER, 1.0f, 1.0f);
if(!ev.getEntity().level().isClientSide)
ev.getEntity().level().playSound(null, ev.getEntity().getX(), ev.getEntity().getY(), ev.getEntity().getZ(), SoundEvents.ITEM_BREAK, SoundSource.MASTER, 1.0f, 1.0f);
}
}
}
@ -305,35 +291,35 @@ public class WebDisplays {
@SubscribeEvent
public void onLogIn(PlayerEvent.PlayerLoggedInEvent ev) {
if(!ev.getPlayer().getLevel().isClientSide && ev.getPlayer() instanceof ServerPlayer) {
IWDDCapability cap =
ev.getPlayer().getCapability(WDDCapability.Provider.cap, null).orElseThrow(RuntimeException::new);
if (!CommonConfig.joinMessage) {
return;
}
if(cap == null)
Log.warning("Player %s (%s) has null IWDDCapability!", ev.getPlayer().getName(), ev.getPlayer().getGameProfile().getId().toString());
else if(cap.isFirstRun()) {
Util.toast(ev.getPlayer(), ChatFormatting.LIGHT_PURPLE, "welcome1");
Util.toast(ev.getPlayer(), ChatFormatting.LIGHT_PURPLE, "welcome2");
Util.toast(ev.getPlayer(), ChatFormatting.LIGHT_PURPLE, "welcome3");
if(!ev.getEntity().level().isClientSide && ev.getEntity() instanceof ServerPlayer) {
IWDDCapability cap = ev.getEntity().getCapability(WDDCapability.Provider.cap, null).orElseThrow(RuntimeException::new);
if(cap.isFirstRun()) {
Util.toast(ev.getEntity(), ChatFormatting.LIGHT_PURPLE, "welcome1");
Util.toast(ev.getEntity(), ChatFormatting.LIGHT_PURPLE, "welcome2");
Util.toast(ev.getEntity(), ChatFormatting.LIGHT_PURPLE, "welcome3");
cap.clearFirstRun();
}
PacketDistributor.PacketTarget packetDistrutor = PacketDistributor.PLAYER
.with(
() ->
(ServerPlayer) ev.getPlayer());
PacketDistributor.PacketTarget packetDistrutor = PacketDistributor.PLAYER.with(
() -> (ServerPlayer) ev.getEntity()
);
CMessageServerInfo message = new CMessageServerInfo(miniservPort);
S2CMessageServerInfo message = new S2CMessageServerInfo(miniservPort);
Messages.INSTANCE.send(packetDistrutor, message);
WDNetworkRegistry.INSTANCE.send(packetDistrutor, message);
}
}
@SubscribeEvent
public void onLogOut(PlayerEvent.PlayerLoggedOutEvent ev) {
if(!ev.getPlayer().getLevel().isClientSide)
Server.getInstance().getClientManager().revokeClientKey(ev.getPlayer().getGameProfile().getId());
if(!ev.getEntity().level().isClientSide)
Server.getInstance().getClientManager().revokeClientKey(ev.getEntity().getGameProfile().getId());
}
@SubscribeEvent
@ -345,7 +331,7 @@ public class WebDisplays {
@SubscribeEvent
public void onPlayerClone(PlayerEvent.Clone ev) {
IWDDCapability src = ev.getOriginal().getCapability(WDDCapability.Provider.cap, null).orElse(new WDDCapability.Factory().call());
IWDDCapability dst = ev.getPlayer().getCapability(WDDCapability.Provider.cap, null).orElse(new WDDCapability.Factory().call());
IWDDCapability dst = ev.getEntity().getCapability(WDDCapability.Provider.cap, null).orElse(new WDDCapability.Factory().call());
if(src == null) {
Log.error("src is null");
@ -362,7 +348,7 @@ public class WebDisplays {
@SubscribeEvent
public void onServerChat(ServerChatEvent ev) {
String msg = ev.getMessage().trim().replaceAll("\\s+", " ").toLowerCase();
String msg = ev.getMessage().getString().replaceAll("\\s+", " ").toLowerCase();
StringBuilder sb = new StringBuilder(msg.length());
for(int i = 0; i < msg.length(); i++) {
char chr = msg.charAt(i);
@ -373,7 +359,7 @@ public class WebDisplays {
if(sb.toString().equals("ironic he could save others from death but not himself")) {
Player ply = ev.getPlayer();
ply.getLevel().playSound(null, ply.getX(), ply.getY(), ply.getZ(), soundIronic, SoundSource.PLAYERS, 1.0f, 1.0f);
ply.level().playSound(null, ply.getX(), ply.getY(), ply.getZ(), soundIronic, SoundSource.PLAYERS, 1.0f, 1.0f);
}
}
@ -396,12 +382,13 @@ public class WebDisplays {
return new WebDisplays().lastPadId++;
}
private static SoundEvent registerSound(RegistryEvent.Register<SoundEvent> ev, String resName) {
ResourceLocation resLoc = new ResourceLocation("webdisplays", resName);
SoundEvent ret = new SoundEvent(resLoc);
ret.setRegistryName(resLoc);
public static DeferredRegister<SoundEvent> SOUNDS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, "webdisplays");
ev.getRegistry().register(ret);
private static SoundEvent registerSound(String resName) {
ResourceLocation resLoc = new ResourceLocation("webdisplays", resName);
SoundEvent ret = SoundEvent.createVariableRangeEvent(resLoc);
SOUNDS.register(resName, () -> ret);
return ret;
}
@ -421,7 +408,9 @@ public class WebDisplays {
public static boolean isSiteBlacklisted(String url) {
try {
URL url2 = new URL(Util.addProtocol(url));
return new ModConfig.Main().blacklist.stream().anyMatch(str -> str.equalsIgnoreCase(url2.getHost()));
for (String str : CommonConfig.Browser.blacklist)
if (str.equalsIgnoreCase(url2.getHost())) return true;
return false;
} catch(MalformedURLException ex) {
return false;
}
@ -430,6 +419,5 @@ public class WebDisplays {
public static String applyBlacklist(String url) {
return isSiteBlacklisted(url) ? BLACKLIST_URL : url;
}
}

View File

@ -1,279 +0,0 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.TileEntityInterfaceBase;
import net.montoyo.wd.entity.TileEntityKeyboard;
import net.montoyo.wd.entity.TileEntityPeripheralBase;
import net.montoyo.wd.entity.TileEntityServer;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageCloseGui;
import org.jetbrains.annotations.Nullable;
public class BlockKeyboardLeft extends BlockPeripheral {
public static final EnumProperty<DefaultPeripheral> type = EnumProperty.create("type", DefaultPeripheral.class);
public static final DirectionProperty facing = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
private static final Property<?>[] properties = new Property<?>[] { type, facing };
public BlockKeyboardLeft() {
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
// @Nullable TODO: Fix
// @Override
// public BlockState getStateForPlacement(BlockPlaceContext context) {
// Direction rot = Direction.fromYRot(placer.getYHeadRot());
// return defaultBlockState().setValue(type, DefaultPeripheral.fromMetadata(meta)).setValue(facing, rot);
//
//
// return getStateForPlacement(context);
// }
//
// public BlockState getStateForPlacement(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction nocare, float hitX,
// float hitY, float hitZ, int meta, @Nonnull LivingEntity placer, InteractionHand hand) {
// }
// @Override
// public void getSubBlocks(CreativeTabs tab, NonNullList<ItemStack> list) {
// for(DefaultPeripheral dp : DefaultPeripheral.values())
// list.add(new ItemStack(getItem(), 1, dp.toMetadata(0)));
// }
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// DefaultPeripheral dp = DefaultPeripheral.fromMetadata(meta);
// IBlockState state = getDefaultState().withProperty(type, dp);
//
// if(dp.hasFacing())
// state = state.withProperty(facing, (meta >> 2) & 3);
//
// return state;
// }
//
// @Override
// public int getMetaFromState(IBlockState state) {
// return state.getValue(type).toMetadata(state.getValue(facing));
// }
/*@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
BlockEntityType.BlockEntitySupplier<? extends BlockEntity> cls = state.getValue(type).getTEClass();
if(cls == null)
return null;
try {
return cls.create(pos, state);
} catch(Throwable t) {
Log.errorEx("Couldn't instantiate peripheral TileEntity:", t);
}
return null;
} */
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
// @Override
// public int damageDropped(IBlockState state) {
// return state.getValue(type).toMetadata(0);
// }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(player.isShiftKeyDown())
return InteractionResult.FAIL;
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityKeyboard)
return ((TileEntityKeyboard) te).onRightClick(player, hand);
else if(te instanceof TileEntityServer) {
((TileEntityServer) te).onPlayerRightClick(player);
return InteractionResult.PASS;
} else
return InteractionResult.FAIL;
}
// @Override
// public boolean isFullCube(IBlockState state) { TODO: FIx.
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isFullBlock(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isOpaqueCube(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return state.getValue(type) == DefaultPeripheral.KEYBOARD ? BlockKeyboardRight.KEYBOARD_AABB : Shapes.block();
}
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClientSide)
return;
if(state.getValue(type) == DefaultPeripheral.KEYBOARD) {
//Keyboard special treatment
Direction f = state.getValue(facing);
Vec3i dir = f.getClockWise().getNormal();
BlockPos left = pos.offset(dir);
BlockPos right = pos.subtract(dir);
if(!world.isEmptyBlock(pos.below()) && BlockKeyboardRight.checkNeighborhood(world, pos, null)) {
if(world.isEmptyBlock(right) && !world.isEmptyBlock(right.below()) && BlockKeyboardRight.checkNeighborhood(world, right, pos)) {
world.setBlock(right, BlockInit.blockKbRight.get().defaultBlockState().setValue(BlockKeyboardRight.facing, f), 3);
world.setBlock(pos.offset(f.getNormal()), BlockInit.blockKeyBoard.get().defaultBlockState().setValue(BlockKeyboardRight.facing, f), 3);
return;
} else if(world.isEmptyBlock(left) && !world.isEmptyBlock(left.below()) && BlockKeyboardRight.checkNeighborhood(world, left, pos)) {
world.setBlock(left, state, 3);
world.setBlock(pos.offset(f.getNormal()), BlockInit.blockKeyBoard.get().defaultBlockState().setValue(BlockKeyboardRight.facing, f), 3);
return;
}
}
//Not good; remove this shit...
world.setBlockAndUpdate(pos, Blocks.AIR.defaultBlockState());
if(!(placer instanceof Player) || !((Player) placer).isCreative()) {
// dropBlockAsItem(world, pos, state, 0); TODO: Loottable?
}
} else if(placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer)
((TileEntityServer) te).setOwner((Player) placer);
else if(te instanceof TileEntityInterfaceBase)
((TileEntityInterfaceBase) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
private void removeRightPiece(Level world, BlockPos pos) {
for(Direction nf: Direction.Plane.HORIZONTAL) {
BlockPos np = pos.offset(nf.getNormal());
if(world.getBlockState(np).getBlock() instanceof BlockKeyboardRight) {
world.setBlock(np, Blocks.AIR.defaultBlockState(), 3);
break;
}
}
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityPeripheralBase)
((TileEntityPeripheralBase) te).onNeighborChange(neighborType, neighbor);
if(world.isClientSide || state.getValue(type) != DefaultPeripheral.KEYBOARD)
return;
if(neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ() && world.isEmptyBlock(neighbor)) {
removeRightPiece(world, pos);
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
// dropBlockAsItem(world, pos, state, 0); //TODO Loottable
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if(!world.isClientSide) {
if(state.getBlock() == this && state.getValue(type) == DefaultPeripheral.KEYBOARD)
removeRightPiece(world, pos);
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if(!world.isClientSide && world.getBlockState(pos).getValue(type) == DefaultPeripheral.KEYBOARD) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if(rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityKeyboard)
((TileEntityKeyboard) te).simulateCat(entity);
}
}
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -1,208 +0,0 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.core.IPeripheral;
import net.montoyo.wd.entity.TileEntityKeyboard;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.init.TileInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Vector3i;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.lwjgl.system.CallbackI;
import java.util.List;
import java.util.Objects;
public class BlockKeyboardRight extends Block implements IPeripheral {
public static final DirectionProperty facing = BlockStateProperties.HORIZONTAL_FACING;
public static final VoxelShape KEYBOARD_AABB = Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0 / 16.0, 1.0);
public BlockKeyboardRight() {
super(Properties.of(Material.STONE)
.strength(1.5f, 10.f));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(facing);
}
@Override
public boolean isCollisionShapeFullBlock(BlockState state, BlockGetter level, BlockPos pos) {
return false;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return KEYBOARD_AABB;
}
private TileEntityKeyboard getTileEntity(Level world, BlockPos pos) {
for (Direction nf : Direction.Plane.HORIZONTAL) {
BlockPos np = pos.offset(nf.getNormal());
BlockState ns = world.getBlockState(np);
if(ns.getBlock() instanceof BlockPeripheral && ns.getValue(BlockPeripheral.type) == DefaultPeripheral.KEYBOARD) {
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof TileEntityKeyboard)
return (TileEntityKeyboard) te;
break;
}
}
return null;
}
@Override
public boolean connect(Level world, BlockPos pos, BlockState state, Vector3i scrPos, BlockSide scrSide) {
TileEntityKeyboard keyboard = getTileEntity(world, pos);
return keyboard != null && keyboard.connect(world, pos, state, scrPos, scrSide);
}
public static boolean checkNeighborhood(Level world, BlockPos bp, BlockPos ignore) {
for (Direction neighbor : Direction.Plane.HORIZONTAL) {
BlockPos np = bp.offset(neighbor.getNormal());
if (ignore == null || !np.equals(ignore)) {
BlockState state = world.getBlockState(np);
if (state.getBlock() instanceof BlockPeripheral) {
if (state.getValue(BlockPeripheral.type) == DefaultPeripheral.KEYBOARD)
return false;
} else if (state.getBlock() instanceof BlockKeyboardRight)
return false;
}
}
return true;
}
public void removeLeftPiece(Level world, BlockPos pos, boolean dropItem) {
for (Direction nf : Direction.Plane.HORIZONTAL) {
BlockPos np = pos.offset(nf.getNormal());
BlockState ns = world.getBlockState(np);
if (ns.getBlock() instanceof BlockPeripheral && ns.getValue(BlockPeripheral.type) == DefaultPeripheral.KEYBOARD) {
/* if(dropItem)
if(world instanceof ServerLevel serverWorld) {
// ns.getBlock().getDrops(ns, serverWorld, np,0);
} */
world.setBlock(np, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL_IMMEDIATE);
break;
}
}
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos neighbor, boolean isMoving) {
if (world.isClientSide())
return;
if (neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ()) {
removeLeftPiece(world, pos, true);
world.setBlock(pos, Blocks.AIR.defaultBlockState(), Block.UPDATE_ALL_IMMEDIATE);
}
}
@Override
public boolean onDestroyedByPlayer(BlockState state, Level world, BlockPos pos, Player ply, boolean willHarvest, FluidState fluid) {
if (!world.isClientSide)
removeLeftPiece(world, pos, !ply.isCreative());
return super.onDestroyedByPlayer(state, world, pos, ply, willHarvest, fluid);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if (!world.isClientSide && rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
TileEntityKeyboard tek = getTileEntity(world, pos);
if (tek != null)
tek.simulateCat(entity);
}
}
@Override
public boolean canBeReplaced(BlockState state, BlockPlaceContext context) {
if (!context.getItemInHand().isEmpty()) //Keyboard
return false;
//Special checks for the keyboard
BlockPos pos = context.getClickedPos().offset(context.getHorizontalDirection().getNormal());
if (context.getLevel().getBlockState(pos.below()) == Blocks.AIR.defaultBlockState() || !BlockKeyboardRight.checkNeighborhood(context.getLevel(), pos, null))
return true;
int f = (int) Math.floor(((double) (context.getPlayer().getYRot() * 4.0f / 360.0f)) + 2.5) & 3;
Vec3i dir = Direction.from2DDataValue(f).getNormal();
BlockPos left = pos.offset(dir);
BlockPos right = pos.subtract(dir);
if (context.getLevel().getBlockState(right) == Blocks.AIR.defaultBlockState() && !(context.getLevel().getBlockState(right.below()) == Blocks.AIR.defaultBlockState()) && BlockKeyboardRight.checkNeighborhood(context.getLevel(), right, null))
return false;
else
return !(context.getLevel().getBlockState(left) == Blocks.AIR.defaultBlockState() && !(context.getLevel().getBlockState(left.below()) == Blocks.AIR.defaultBlockState()) && BlockKeyboardRight.checkNeighborhood(context.getLevel(), left, null));
}
@Override
public @NotNull InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.isShiftKeyDown()) {
ItemStack itemStack = player.getItemInHand(hand);
if (canBeReplaced(state, new BlockPlaceContext(player, hand, itemStack, hit))) {
int f = (int) Math.floor(((double) (player.getYRot() * 4.0f / 360.0f)) + 2.5) & 3;
Vec3i dir = Direction.from2DDataValue(f).getNormal();
level.setBlock(pos.offset(dir), BlockInit.blockKeyBoard.get().defaultBlockState(), UPDATE_ALL_IMMEDIATE);
return InteractionResult.SUCCESS;
}
}
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.PASS;
TileEntityKeyboard tek = getTileEntity(level, pos);
if(tek != null)
return tek.onRightClick(player, hand);
return InteractionResult.PASS;
}
}

View File

@ -1,283 +0,0 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.mcef.utilities.Log;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.TileEntityInterfaceBase;
import net.montoyo.wd.entity.TileEntityKeyboard;
import net.montoyo.wd.entity.TileEntityPeripheralBase;
import net.montoyo.wd.entity.TileEntityServer;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageCloseGui;
import org.jetbrains.annotations.Nullable;
public class BlockPeripheral extends WDBlockContainer {
public static final EnumProperty<DefaultPeripheral> type = EnumProperty.create("type", DefaultPeripheral.class);
public static final DirectionProperty facing = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
private static final Property<?>[] properties = new Property<?>[] { type, facing };
public BlockPeripheral() {
super(BlockBehaviour.Properties.of(Material.STONE).strength(1.5f, 10.f));
// setName("peripheral");
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
// @Nullable TODO: Fix
// @Override
// public BlockState getStateForPlacement(BlockPlaceContext context) {
// Direction rot = Direction.fromYRot(placer.getYHeadRot());
// return defaultBlockState().setValue(type, DefaultPeripheral.fromMetadata(meta)).setValue(facing, rot);
//
//
// return getStateForPlacement(context);
// }
//
// public BlockState getStateForPlacement(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction nocare, float hitX,
// float hitY, float hitZ, int meta, @Nonnull LivingEntity placer, InteractionHand hand) {
// }
// @Override
// public void getSubBlocks(CreativeTabs tab, NonNullList<ItemStack> list) {
// for(DefaultPeripheral dp : DefaultPeripheral.values())
// list.add(new ItemStack(getItem(), 1, dp.toMetadata(0)));
// }
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// DefaultPeripheral dp = DefaultPeripheral.fromMetadata(meta);
// IBlockState state = getDefaultState().withProperty(type, dp);
//
// if(dp.hasFacing())
// state = state.withProperty(facing, (meta >> 2) & 3);
//
// return state;
// }
//
// @Override
// public int getMetaFromState(IBlockState state) {
// return state.getValue(type).toMetadata(state.getValue(facing));
// }
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
BlockEntityType.BlockEntitySupplier<? extends BlockEntity> cls = state.getValue(type).getTEClass();
if(cls == null)
return null;
try {
return cls.create(pos, state);
} catch(Throwable t) {
Log.errorEx("Couldn't instantiate peripheral TileEntity:", t);
}
return null;
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
// @Override
// public int damageDropped(IBlockState state) {
// return state.getValue(type).toMetadata(0);
// }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(player.isShiftKeyDown())
return InteractionResult.FAIL;
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityPeripheralBase)
return ((TileEntityPeripheralBase) te).onRightClick(player, hand);
else if(te instanceof TileEntityServer) {
((TileEntityServer) te).onPlayerRightClick(player);
return InteractionResult.PASS;
} else
return InteractionResult.FAIL;
}
// @Override
// public boolean isFullCube(IBlockState state) { TODO: FIx.
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isFullBlock(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isOpaqueCube(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return state.getValue(type) == DefaultPeripheral.KEYBOARD ? BlockKeyboardRight.KEYBOARD_AABB : Shapes.block();
}
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClientSide)
return;
if(state.getValue(type) == DefaultPeripheral.KEYBOARD) {
//Keyboard special treatment
Direction f = state.getValue(facing);
Vec3i dir = f.getClockWise().getNormal();
BlockPos left = pos.offset(dir);
BlockPos right = pos.subtract(dir);
if(!world.isEmptyBlock(pos.below()) && BlockKeyboardRight.checkNeighborhood(world, pos, null)) {
if(world.isEmptyBlock(right) && !world.isEmptyBlock(right.below()) && BlockKeyboardRight.checkNeighborhood(world, right, pos)) {
world.setBlock(right, BlockInit.blockKbRight.get().defaultBlockState().setValue(BlockKeyboardRight.facing, f), 3);
return;
} else if(world.isEmptyBlock(left) && !world.isEmptyBlock(left.below()) && BlockKeyboardRight.checkNeighborhood(world, left, pos)) {
world.setBlock(left, state, 3);
world.setBlock(pos, BlockInit.blockKbRight.get().defaultBlockState().setValue(BlockKeyboardRight.facing, f), 3);
return;
}
}
//Not good; remove this shit...
world.setBlockAndUpdate(pos, Blocks.AIR.defaultBlockState());
if(!(placer instanceof Player) || !((Player) placer).isCreative()) {
// dropBlockAsItem(world, pos, state, 0); TODO: Loottable?
}
} else if(placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer)
((TileEntityServer) te).setOwner((Player) placer);
else if(te instanceof TileEntityInterfaceBase)
((TileEntityInterfaceBase) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
private void removeRightPiece(Level world, BlockPos pos) {
for(Direction nf: Direction.Plane.HORIZONTAL) {
BlockPos np = pos.offset(nf.getNormal());
if(world.getBlockState(np).getBlock() instanceof BlockKeyboardRight) {
world.setBlock(np, Blocks.AIR.defaultBlockState(), 3);
break;
}
}
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityPeripheralBase)
((TileEntityPeripheralBase) te).onNeighborChange(neighborType, neighbor);
if(world.isClientSide || state.getValue(type) != DefaultPeripheral.KEYBOARD)
return;
if(neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ() && world.isEmptyBlock(neighbor)) {
removeRightPiece(world, pos);
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
// dropBlockAsItem(world, pos, state, 0); //TODO Loottable
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if(!world.isClientSide) {
if(state.getBlock() == this && state.getValue(type) == DefaultPeripheral.KEYBOARD)
removeRightPiece(world, pos);
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if(!world.isClientSide && world.getBlockState(pos).getValue(type) == DefaultPeripheral.KEYBOARD) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if(rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityKeyboard)
((TileEntityKeyboard) te).simulateCat(entity);
}
}
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -1,225 +0,0 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.mcef.utilities.Log;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.*;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageCloseGui;
import org.jetbrains.annotations.Nullable;
public class BlockRCTRL extends WDBlockContainer {
public static final EnumProperty<DefaultPeripheral> type = BlockPeripheral.type;
public static final DirectionProperty facing = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
private static final Property<?>[] properties = new Property<?>[] {type, facing};
public BlockRCTRL() {
super(BlockBehaviour.Properties.of(Material.STONE).strength(1.5f, 10.f));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
// @Nullable TODO: Fix
// @Override
// public BlockState getStateForPlacement(BlockPlaceContext context) {
// Direction rot = Direction.fromYRot(placer.getYHeadRot());
// return defaultBlockState().setValue(type, DefaultPeripheral.fromMetadata(meta)).setValue(facing, rot);
//
//
// return getStateForPlacement(context);
// }
//
// public BlockState getStateForPlacement(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction nocare, float hitX,
// float hitY, float hitZ, int meta, @Nonnull LivingEntity placer, InteractionHand hand) {
// }
// @Override
// public void getSubBlocks(CreativeTabs tab, NonNullList<ItemStack> list) {
// for(DefaultPeripheral dp : DefaultPeripheral.values())
// list.add(new ItemStack(getItem(), 1, dp.toMetadata(0)));
// }
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// DefaultPeripheral dp = DefaultPeripheral.fromMetadata(meta);
// IBlockState state = getDefaultState().withProperty(type, dp);
//
// if(dp.hasFacing())
// state = state.withProperty(facing, (meta >> 2) & 3);
//
// return state;
// }
//
// @Override
// public int getMetaFromState(IBlockState state) {
// return state.getValue(type).toMetadata(state.getValue(facing));
// }
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new TileEntityRCtrl(pos, state);
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
// @Override
// public int damageDropped(IBlockState state) {
// return state.getValue(type).toMetadata(0);
// }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(player.isShiftKeyDown())
return InteractionResult.FAIL;
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
System.out.println(te);
if(te instanceof TileEntityRCtrl)
return ((TileEntityRCtrl) te).onRightClick(player, hand);
else if(te instanceof TileEntityServer) {
((TileEntityServer) te).onPlayerRightClick(player);
return InteractionResult.PASS;
} else
return InteractionResult.FAIL;
}
// @Override
// public boolean isFullCube(IBlockState state) { TODO: FIx.
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isFullBlock(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isOpaqueCube(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClientSide)
return;
if(placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer)
((TileEntityServer) te).setOwner((Player) placer);
else if(te instanceof TileEntityInterfaceBase)
((TileEntityInterfaceBase) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityPeripheralBase)
((TileEntityPeripheralBase) te).onNeighborChange(neighborType, neighbor);
if(world.isClientSide)
return;
if(neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ() && world.isEmptyBlock(neighbor)) {
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
// dropBlockAsItem(world, pos, state, 0); //TODO Loottable
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if(!world.isClientSide) {
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if(!world.isClientSide) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if(rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityKeyboard)
((TileEntityKeyboard) te).simulateCat(entity);
}
}
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -1,225 +0,0 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.mcef.utilities.Log;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.*;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageCloseGui;
import org.jetbrains.annotations.Nullable;
public class BlockRedCTRL extends WDBlockContainer {
public static final EnumProperty<DefaultPeripheral> type = BlockPeripheral.type;
public static final DirectionProperty facing = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
private static final Property<?>[] properties = new Property<?>[] {type, facing};
public BlockRedCTRL() {
super(BlockBehaviour.Properties.of(Material.STONE).strength(1.5f, 10.f));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
// @Nullable TODO: Fix
// @Override
// public BlockState getStateForPlacement(BlockPlaceContext context) {
// Direction rot = Direction.fromYRot(placer.getYHeadRot());
// return defaultBlockState().setValue(type, DefaultPeripheral.fromMetadata(meta)).setValue(facing, rot);
//
//
// return getStateForPlacement(context);
// }
//
// public BlockState getStateForPlacement(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction nocare, float hitX,
// float hitY, float hitZ, int meta, @Nonnull LivingEntity placer, InteractionHand hand) {
// }
// @Override
// public void getSubBlocks(CreativeTabs tab, NonNullList<ItemStack> list) {
// for(DefaultPeripheral dp : DefaultPeripheral.values())
// list.add(new ItemStack(getItem(), 1, dp.toMetadata(0)));
// }
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// DefaultPeripheral dp = DefaultPeripheral.fromMetadata(meta);
// IBlockState state = getDefaultState().withProperty(type, dp);
//
// if(dp.hasFacing())
// state = state.withProperty(facing, (meta >> 2) & 3);
//
// return state;
// }
//
// @Override
// public int getMetaFromState(IBlockState state) {
// return state.getValue(type).toMetadata(state.getValue(facing));
// }
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new TileEntityRedCtrl(pos, state);
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
// @Override
// public int damageDropped(IBlockState state) {
// return state.getValue(type).toMetadata(0);
// }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(player.isShiftKeyDown())
return InteractionResult.FAIL;
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityRedCtrl)
return ((TileEntityRedCtrl) te).onRightClick(player, hand);
else if(te instanceof TileEntityServer) {
((TileEntityServer) te).onPlayerRightClick(player);
return InteractionResult.PASS;
} else
return InteractionResult.FAIL;
}
// @Override
// public boolean isFullCube(IBlockState state) { TODO: FIx.
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isFullBlock(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isOpaqueCube(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClientSide)
return;
if(placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer)
((TileEntityServer) te).setOwner((Player) placer);
else if(te instanceof TileEntityInterfaceBase)
((TileEntityInterfaceBase) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityPeripheralBase)
((TileEntityPeripheralBase) te).onNeighborChange(neighborType, neighbor);
if(world.isClientSide)
return;
if(neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ() && world.isEmptyBlock(neighbor)) {
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
// dropBlockAsItem(world, pos, state, 0); //TODO Loottable
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if(!world.isClientSide) {
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if(!world.isClientSide) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if(rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityKeyboard)
((TileEntityKeyboard) te).simulateCat(entity);
}
}
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -1,226 +0,0 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.mcef.utilities.Log;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.TileEntityInterfaceBase;
import net.montoyo.wd.entity.TileEntityKeyboard;
import net.montoyo.wd.entity.TileEntityPeripheralBase;
import net.montoyo.wd.entity.TileEntityServer;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.client.CMessageCloseGui;
import org.jetbrains.annotations.Nullable;
public class BlockServer extends WDBlockContainer{
public static final EnumProperty<DefaultPeripheral> type = BlockPeripheral.type;
public static final DirectionProperty facing = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
private static final Property<?>[] properties = new Property<?>[] {type, facing};
public BlockServer() {
super(BlockBehaviour.Properties.of(Material.STONE).strength(1.5f, 10.f));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
// @Nullable TODO: Fix
// @Override
// public BlockState getStateForPlacement(BlockPlaceContext context) {
// Direction rot = Direction.fromYRot(placer.getYHeadRot());
// return defaultBlockState().setValue(type, DefaultPeripheral.fromMetadata(meta)).setValue(facing, rot);
//
//
// return getStateForPlacement(context);
// }
//
// public BlockState getStateForPlacement(@Nonnull Level world, @Nonnull BlockPos pos, @Nonnull Direction nocare, float hitX,
// float hitY, float hitZ, int meta, @Nonnull LivingEntity placer, InteractionHand hand) {
// }
// @Override
// public void getSubBlocks(CreativeTabs tab, NonNullList<ItemStack> list) {
// for(DefaultPeripheral dp : DefaultPeripheral.values())
// list.add(new ItemStack(getItem(), 1, dp.toMetadata(0)));
// }
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// DefaultPeripheral dp = DefaultPeripheral.fromMetadata(meta);
// IBlockState state = getDefaultState().withProperty(type, dp);
//
// if(dp.hasFacing())
// state = state.withProperty(facing, (meta >> 2) & 3);
//
// return state;
// }
//
// @Override
// public int getMetaFromState(IBlockState state) {
// return state.getValue(type).toMetadata(state.getValue(facing));
// }
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return new TileEntityServer(pos, state);
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
// @Override
// public int damageDropped(IBlockState state) {
// return state.getValue(type).toMetadata(0);
// }
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if(player.isShiftKeyDown())
return InteractionResult.FAIL;
if(player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer) {
((TileEntityServer) te).onPlayerRightClick(player);
return InteractionResult.PASS;
} else
return InteractionResult.FAIL;
}
// @Override
// public boolean isFullCube(IBlockState state) { TODO: FIx.
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isFullBlock(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isNormalCube(IBlockState state, IBlockAccess world, BlockPos pos) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean isOpaqueCube(IBlockState state) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
//
// @Override
// public boolean doesSideBlockRendering(IBlockState state, IBlockAccess world, BlockPos pos, EnumFacing face) {
// return state.getValue(type) != DefaultPeripheral.KEYBOARD;
// }
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if(world.isClientSide)
return;
if(placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if(te instanceof TileEntityServer)
((TileEntityServer) te).setOwner((Player) placer);
else if(te instanceof TileEntityInterfaceBase)
((TileEntityInterfaceBase) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityPeripheralBase)
((TileEntityPeripheralBase) te).onNeighborChange(neighborType, neighbor);
if(world.isClientSide)
return;
if(neighbor.getX() == pos.getX() && neighbor.getY() == pos.getY() - 1 && neighbor.getZ() == pos.getZ() && world.isEmptyBlock(neighbor)) {
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
// dropBlockAsItem(world, pos, state, 0); //TODO Loottable
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if(!world.isClientSide) {
Messages.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new CMessageCloseGui(pos));
}
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
if(!world.isClientSide) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if(rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
BlockEntity te = world.getBlockEntity(pos);
if(te != null && te instanceof TileEntityKeyboard)
((TileEntityKeyboard) te).simulateCat(entity);
}
}
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -0,0 +1,142 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.KeyboardBlockEntity;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.client_bound.S2CMessageCloseGui;
import org.jetbrains.annotations.NotNull;
public class KeyboardBlockLeft extends PeripheralBlock {
public static final EnumProperty<DefaultPeripheral> TYPE = EnumProperty.create("type", DefaultPeripheral.class);
public static final DirectionProperty FACING = DirectionProperty.create("facing", Direction.NORTH, Direction.EAST, Direction.SOUTH, Direction.WEST);
// public static final DirectionProperty HALF = DirectionProperty.create("facing", Direction.EAST, Direction.WEST);
public static final VoxelShape[] KEYBOARD_AABBS = new VoxelShape[]{
Shapes.box(0.0, 0.0, 3.0 / 16, 1.0, 1.0 / 16.0, 1.0),
Shapes.box(0.0, 0.0, 0.0, 1.0, 1.0 / 16.0, 13 / 16.0),
Shapes.box(3.0 / 16, 0.0, 0.0, 1.0, 1.0 / 16.0, 1.0),
Shapes.box(0.0, 0.0, 0.0, 13 / 16.0, 1.0 / 16.0, 1.0),
};
private static final Property<?>[] properties = new Property<?>[] {TYPE, FACING};
public KeyboardBlockLeft() {
super(DefaultPeripheral.KEYBOARD);
}
// TODO: make non static (for extensibility purposes)
public static KeyboardBlockEntity getTileEntity(BlockState state, Level world, BlockPos pos) {
if (state.getBlock() instanceof KeyboardBlockLeft) {
BlockEntity te = world.getBlockEntity(pos); // TODO: check?
if (te instanceof KeyboardBlockEntity)
return (KeyboardBlockEntity) te;
}
BlockPos relative = pos.relative(KeyboardBlockLeft.mapDirection(state.getValue(FACING).getOpposite()));
BlockState ns = world.getBlockState(relative);
if (ns.getBlock() instanceof PeripheralBlock) {
BlockEntity te = world.getBlockEntity(relative); // TODO: check?
if (te instanceof KeyboardBlockEntity)
return (KeyboardBlockEntity) te;
}
return null;
}
public static Direction mapDirection(Direction facing) {
return switch (facing) {
case NORTH -> Direction.EAST;
case EAST -> Direction.SOUTH;
case SOUTH -> Direction.WEST;
case WEST -> Direction.NORTH;
default -> facing;
};
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if (!world.isClientSide && rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
KeyboardBlockEntity tek = KeyboardBlockLeft.getTileEntity(state, world, pos);
if (tek != null)
tek.simulateCat(entity);
}
}
@Override
public @NotNull InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.PASS;
KeyboardBlockEntity tek = KeyboardBlockLeft.getTileEntity(state, level, pos);
if (tek != null)
return tek.onRightClick(player, hand);
return InteractionResult.PASS;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return KEYBOARD_AABBS[state.getValue(FACING).ordinal() - 2];
}
@Override
public VoxelShape getOcclusionShape(BlockState arg, BlockGetter arg2, BlockPos arg3) {
return Shapes.empty();
}
private static void removeRightPiece(BlockState state, Level world, BlockPos pos) {
BlockPos relative = pos.relative(KeyboardBlockLeft.mapDirection(state.getValue(FACING)));
BlockState ns = world.getBlockState(relative);
if (ns.getBlock() instanceof KeyboardBlockRight)
world.setBlock(relative, Blocks.AIR.defaultBlockState(), 3);
}
public static void remove(BlockState state, Level world, BlockPos pos, boolean setState, boolean drop) {
removeRightPiece(state, world, pos);
if (setState)
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new S2CMessageCloseGui(pos));
}
@Override
public void onRemove(BlockState arg, Level arg2, BlockPos arg3, BlockState arg4, boolean bl) {
if (!arg2.isClientSide)
remove(arg, arg2, arg3, false, false);
super.onRemove(arg, arg2, arg3, arg4, bl);
}
}

View File

@ -0,0 +1,116 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.wd.core.IPeripheral;
import net.montoyo.wd.entity.KeyboardBlockEntity;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.client_bound.S2CMessageCloseGui;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector3i;
import org.jetbrains.annotations.NotNull;
import static net.montoyo.wd.block.KeyboardBlockLeft.KEYBOARD_AABBS;
import static net.montoyo.wd.block.PeripheralBlock.point;
// TODO: merge into KeyboardLeft
public class KeyboardBlockRight extends Block implements IPeripheral {
public static final DirectionProperty FACING = BlockStateProperties.HORIZONTAL_FACING;
public KeyboardBlockRight() {
super(Properties.copy(Blocks.STONE)
.strength(1.5f, 10.f));
}
private static void removeLeftPiece(BlockState state, Level world, BlockPos pos) {
BlockPos relative = pos.relative(KeyboardBlockLeft.mapDirection(state.getValue(FACING).getOpposite()));
BlockState ns = world.getBlockState(relative);
if (ns.getBlock() instanceof KeyboardBlockLeft)
world.setBlock(relative, Blocks.AIR.defaultBlockState(), 3);
}
public static void remove(BlockState state, Level world, BlockPos pos, boolean setState, boolean drop) {
removeLeftPiece(state, world, pos);
if (setState)
world.setBlock(pos, Blocks.AIR.defaultBlockState(), 3);
WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new S2CMessageCloseGui(pos));
}
@Override
public void onRemove(BlockState arg, Level arg2, BlockPos arg3, BlockState arg4, boolean bl) {
if (!arg2.isClientSide)
remove(arg, arg2, arg3, false, false);
super.onRemove(arg, arg2, arg3, arg4, bl);
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(FACING);
}
@Override
public boolean isCollisionShapeFullBlock(BlockState state, BlockGetter level, BlockPos pos) {
return false;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return KEYBOARD_AABBS[state.getValue(FACING).ordinal() - 2];
}
@Override
public boolean connect(Level world, BlockPos pos, BlockState state, Vector3i scrPos, BlockSide scrSide) {
KeyboardBlockEntity keyboard = KeyboardBlockLeft.getTileEntity(state, world, pos);
return keyboard != null && keyboard.connect(world, pos, state, scrPos, scrSide);
}
@Override
public void entityInside(BlockState state, Level world, BlockPos pos, Entity entity) {
double rpos = (entity.getY() - ((double) pos.getY())) * 16.0;
if (!world.isClientSide && rpos >= 1.0 && rpos <= 2.0 && Math.random() < 0.25) {
KeyboardBlockEntity tek = KeyboardBlockLeft.getTileEntity(state, world, pos);
if (tek != null)
tek.simulateCat(entity);
}
}
@Override
public @NotNull InteractionResult use(BlockState state, Level level, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.PASS;
KeyboardBlockEntity tek = KeyboardBlockLeft.getTileEntity(state, level, pos);
if (tek != null)
return tek.onRightClick(player, hand);
return InteractionResult.PASS;
}
@Override
public VoxelShape getOcclusionShape(BlockState arg, BlockGetter arg2, BlockPos arg3) {
return Shapes.empty();
}
}

View File

@ -0,0 +1,141 @@
/*
* Copyright (C) 2019 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.network.PacketDistributor;
import net.montoyo.wd.core.DefaultPeripheral;
import net.montoyo.wd.entity.AbstractInterfaceBlockEntity;
import net.montoyo.wd.entity.AbstractPeripheralBlockEntity;
import net.montoyo.wd.entity.ServerBlockEntity;
import net.montoyo.wd.item.ItemLinker;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.client_bound.S2CMessageCloseGui;
import net.montoyo.wd.utilities.Log;
import org.jetbrains.annotations.Nullable;
public class PeripheralBlock extends WDContainerBlock {
DefaultPeripheral type;
public PeripheralBlock(DefaultPeripheral type) {
super(BlockBehaviour.Properties.copy(Blocks.STONE).strength(1.5f, 10.f));
this.type = type;
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
BlockEntityType.BlockEntitySupplier<? extends BlockEntity> cls = type.getTEClass();
if (cls == null)
return null;
try {
return cls.create(pos, state);
} catch (Throwable t) {
Log.errorEx("Couldn't instantiate peripheral TileEntity:", t);
}
return null;
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
@Override
public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
if (player.isShiftKeyDown())
return InteractionResult.FAIL;
if (player.getItemInHand(hand).getItem() instanceof ItemLinker)
return InteractionResult.FAIL;
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof AbstractPeripheralBlockEntity)
return ((AbstractPeripheralBlockEntity) te).onRightClick(player, hand);
else if (te instanceof ServerBlockEntity) {
((ServerBlockEntity) te).onPlayerRightClick(player);
return InteractionResult.SUCCESS;
} else
return InteractionResult.FAIL;
}
@Override
public VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
return Shapes.block();
}
@Override
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack stack) {
if (world.isClientSide)
return;
if (placer instanceof Player) {
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof ServerBlockEntity)
((ServerBlockEntity) te).setOwner((Player) placer);
else if (te instanceof AbstractInterfaceBlockEntity)
((AbstractInterfaceBlockEntity) te).setOwner((Player) placer);
}
}
@Override
public PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block neighborType, BlockPos neighbor, boolean isMoving) {
BlockEntity te = world.getBlockEntity(pos);
if (te instanceof AbstractPeripheralBlockEntity)
((AbstractPeripheralBlockEntity) te).onNeighborChange(neighborType, neighbor);
}
@Override
public void playerDestroy(Level world, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
if (!world.isClientSide) {
WDNetworkRegistry.INSTANCE.send(PacketDistributor.NEAR.with(() -> point(world, pos)), new S2CMessageCloseGui(pos));
}
super.playerDestroy(world, player, pos, state, blockEntity, tool);
}
@Override
public void onBlockExploded(BlockState state, Level level, BlockPos pos, Explosion explosion) {
playerDestroy(level, null, pos, level.getBlockState(pos), null, null);
}
public static PacketDistributor.TargetPoint point(Player exclude, Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint((ServerPlayer) exclude, bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
public static PacketDistributor.TargetPoint point(Level world, BlockPos bp) {
return new PacketDistributor.TargetPoint(bp.getX(), bp.getY(), bp.getZ(), 64.0, world.dimension());
}
}

View File

@ -12,196 +12,158 @@ import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.BooleanProperty;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.material.PushReaction;
import net.minecraft.world.phys.BlockHitResult;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.config.ModConfig;
import net.montoyo.wd.config.CommonConfig;
import net.montoyo.wd.core.DefaultUpgrade;
import net.montoyo.wd.core.IUpgrade;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.data.SetURLData;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.init.BlockInit;
import net.montoyo.wd.item.WDItem;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.item.ItemLaserPointer;
import net.montoyo.wd.utilities.*;
import net.montoyo.wd.utilities.math.Vector2i;
import net.montoyo.wd.utilities.math.Vector3f;
import net.montoyo.wd.utilities.math.Vector3i;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.serialization.Util;
import org.jetbrains.annotations.NotNull;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
public class BlockScreen extends BaseEntityBlock {
public class ScreenBlock extends BaseEntityBlock {
public static final BooleanProperty hasTE = BooleanProperty.create("haste");
public static final BooleanProperty emitting = BooleanProperty.create("emitting");
private static final Property<?>[] properties = new Property<?>[] { hasTE, emitting };
public static final DirectionProperty FACING = BlockStateProperties.FACING;
private static final Property<?>[] properties = new Property<?>[]{hasTE, emitting};
private static final int BAR_BOT = 1;
private static final int BAR_RIGHT = 2;
private static final int BAR_TOP = 4;
private static final int BAR_LEFT = 8;
public BlockScreen(Properties properties) {
public ScreenBlock(Properties properties) {
super(properties.strength(1.5f, 10.f));
// setCreativeTab(WebDisplays.CREATIVE_TAB);
// setName("screen");
this.registerDefaultState(this.defaultBlockState().setValue(hasTE, false).setValue(emitting, false));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties).add(FACING);
}
public void onRemove(BlockState p_60515_, Level p_60516_, BlockPos p_60517_, BlockState p_60518_, boolean p_60519_) {
// TODO: make this also get called on client?
if (p_60518_.getBlock() == p_60515_.getBlock()) return;
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
public static boolean isntScreenBlock(Level world, Vector3i pos) {
return world.getBlockState(pos.toBlock()).getBlock() != BlockInit.blockScreen.get();
}
@org.jetbrains.annotations.Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return super.getStateForPlacement(context);
}
@Override
public BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor level, BlockPos currentPos, BlockPos neighborPos) {
return super.updateShape(state, direction, neighborState, level, currentPos, neighborPos);
}
/* @Override
@Nonnull
public BlockState getExtendedState(@Nonnull BlockState ret, Level world, BlockPos bpos) {
Vector3i pos = new Vector3i(bpos);
for(BlockSide side : BlockSide.values()) {
int icon = 0;
if(isntScreenBlock(world, side.up.clone().add(pos))) icon |= BAR_TOP;
if(isntScreenBlock(world, side.down.clone().add(pos))) icon |= BAR_BOT;
if(isntScreenBlock(world, side.left.clone().add(pos))) icon |= BAR_LEFT;
if(isntScreenBlock(world, side.right.clone().add(pos))) icon |= BAR_RIGHT;
ret = ret.setValue(sideFlags[side.ordinal()], icon);
for (BlockSide value : BlockSide.values()) {
Vector3i vec = new Vector3i(p_60517_.getX(), p_60517_.getY(), p_60517_.getZ());
Multiblock.findOrigin(p_60516_, vec, value, null);
BlockPos bp = new BlockPos(vec.x, vec.y, vec.z);
if (!bp.equals(p_60517_)) {
p_60516_.removeBlockEntity(bp);
p_60516_.setBlock(
bp, p_60516_.getBlockState(bp).setValue(hasTE, false),
11
);
}
}
return ret;
}*/
// @Override
// @Nonnull
// public IBlockState getStateFromMeta(int meta) {
// return getDefaultState().withProperty(hasTE, (meta & 1) != 0).withProperty(emitting, (meta & 2) != 0);
// }
//
public int getMetaFromState(BlockState state) {
int ret = 0;
if(state.getValue(hasTE))
ret |= 1;
if(state.getValue(emitting))
ret |= 2;
return ret;
super.onRemove(p_60515_, p_60516_, p_60517_, p_60518_, p_60519_);
}
@Override
public InteractionResult use(BlockState state, Level world, BlockPos position, Player player, InteractionHand hand, BlockHitResult hit) {
ItemStack heldItem = player.getItemInHand(hand);
if(heldItem.isEmpty())
boolean isUpgrade = false;
if (heldItem.isEmpty())
heldItem = null; //Easier to work with
else if(!(heldItem.getItem() instanceof IUpgrade))
else if (!(isUpgrade = heldItem.getItem() instanceof IUpgrade))
return InteractionResult.FAIL;
else if (heldItem.getItem() instanceof ItemLaserPointer)
return InteractionResult.FAIL; // laser pointer already handles stuff
// handling the off hand leads to double clicking
if (!isUpgrade && hand == InteractionHand.OFF_HAND)
return InteractionResult.FAIL;
if(world.isClientSide)
if (world.isClientSide)
return InteractionResult.FAIL;
boolean sneaking = player.isShiftKeyDown();
Vector3i pos = new Vector3i(position);
BlockSide side = BlockSide.values()[hit.getDirection().ordinal()];
Multiblock.findOrigin(world, pos, side, null);
TileEntityScreen te = (TileEntityScreen) world.getBlockEntity(pos.toBlock());
ScreenBlockEntity te = (ScreenBlockEntity) world.getBlockEntity(pos.toBlock());
if(te != null && te.getScreen(side) != null) {
TileEntityScreen.Screen scr = te.getScreen(side);
if (te != null && te.getScreen(side) != null) {
ScreenData scr = te.getScreen(side);
if(sneaking) { //Set URL
if((scr.rightsFor(player) & ScreenRights.CHANGE_URL) == 0)
if (sneaking) { //Right Click
if ((scr.rightsFor(player) & ScreenRights.CHANGE_URL) == 0)
Util.toast(player, "restrictions");
else
(new SetURLData(pos, scr.side, scr.url)).sendTo((ServerPlayer) player);
return InteractionResult.SUCCESS;
} else if(heldItem != null && !te.hasUpgrade(side, heldItem)) { //Add upgrade
if((scr.rightsFor(player) & ScreenRights.MANAGE_UPGRADES) == 0) {
Util.toast(player, "restrictions");
return InteractionResult.SUCCESS;
} else if (heldItem != null) {
if (!te.hasUpgrade(side, heldItem)) {
if ((scr.rightsFor(player) & ScreenRights.MANAGE_UPGRADES) == 0) {
Util.toast(player, "restrictions");
return InteractionResult.CONSUME;
}
if (te.addUpgrade(side, heldItem, player, false)) {
if (!player.isCreative())
heldItem.shrink(1);
Util.toast(player, ChatFormatting.AQUA, "upgradeOk");
if (player instanceof ServerPlayer)
WebDisplays.INSTANCE.criterionUpgradeScreen.trigger(((ServerPlayer) player).getAdvancements());
} else
Util.toast(player, "upgradeError");
return InteractionResult.CONSUME;
}
if(te.addUpgrade(side, heldItem, player, false)) {
if(!player.isCreative())
heldItem.shrink(1);
Util.toast(player, ChatFormatting.AQUA, "upgradeOk");
if(player instanceof ServerPlayer)
WebDisplays.INSTANCE.criterionUpgradeScreen.trigger(((ServerPlayer) player).getAdvancements());
} else
Util.toast(player, "upgradeError");
return InteractionResult.SUCCESS;
} else { //Click
if((scr.rightsFor(player) & ScreenRights.CLICK) == 0) {
} else {
if ((scr.rightsFor(player) & ScreenRights.INTERACT) == 0) {
Util.toast(player, "restrictions");
return InteractionResult.SUCCESS;
return InteractionResult.CONSUME;
}
Vector2i tmp = new Vector2i();
if(hit2pixels(side, hit.getBlockPos(), pos, scr, (float) hit.getLocation().x, (float) hit.getLocation().y, (float) hit.getLocation().z, tmp))
te.click(side, tmp);
return InteractionResult.SUCCESS;
float hitX = ((float) hit.getLocation().x) - (float) te.getBlockPos().getX();
float hitY = ((float) hit.getLocation().y) - (float) te.getBlockPos().getY();
float hitZ = ((float) hit.getLocation().z) - (float) te.getBlockPos().getZ();
if (hit2pixels(side, hit.getBlockPos(), new Vector3i(hit.getBlockPos()), scr, hitX, hitY, hitZ, tmp))
te.click(side, tmp);
return InteractionResult.CONSUME;
}
} else if(sneaking) {
Util.toast(player, "turnOn");
return InteractionResult.SUCCESS;
}
// else if(sneaking) {
// Util.toast(player, "turnOn");
// return InteractionResult.SUCCESS;
// }
Vector2i size = Multiblock.measure(world, pos, side);
if(size.x < 2 || size.y < 2) {
if (size.x < 2 && size.y < 2) {
Util.toast(player, "tooSmall");
return InteractionResult.SUCCESS;
}
if(size.x > WebDisplays.INSTANCE.maxScreenX || size.y > WebDisplays.INSTANCE.maxScreenY) {
Util.toast(player, "tooBig", WebDisplays.INSTANCE.maxScreenX, WebDisplays.INSTANCE.maxScreenY);
if (size.x > CommonConfig.Screen.maxScreenSizeX || size.y > CommonConfig.Screen.maxScreenSizeY) {
Util.toast(player, "tooBig", CommonConfig.Screen.maxScreenSizeX, CommonConfig.Screen.maxScreenSizeY);
return InteractionResult.SUCCESS;
}
Vector3i err = Multiblock.check(world, pos, size, side);
if(err != null) {
if (err != null) {
Util.toast(player, "invalid", err.toString());
return InteractionResult.SUCCESS;
}
@ -209,60 +171,58 @@ public class BlockScreen extends BaseEntityBlock {
boolean created = false;
Log.info("Player %s (UUID %s) created a screen at %s of size %dx%d", player.getName(), player.getGameProfile().getId().toString(), pos.toString(), size.x, size.y);
if(te == null) {
if (te == null) {
BlockPos bp = pos.toBlock();
world.setBlockAndUpdate(bp, world.getBlockState(bp).setValue(hasTE, true));
te = (TileEntityScreen) world.getBlockEntity(bp);
te = (ScreenBlockEntity) world.getBlockEntity(bp);
created = true;
}
te.addScreen(side, size, null, player, !created);
te.addScreen(side, size, null, player, true);
return InteractionResult.SUCCESS;
}
@Override
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos source, boolean isMoving) {
if(block != this && !world.isClientSide && !state.getValue(emitting)) {
for(BlockSide side: BlockSide.values()) {
public void neighborChanged(BlockState state, Level world, BlockPos pos, Block block, BlockPos source,
boolean isMoving) {
if (block != this && !world.isClientSide && !state.getValue(emitting)) {
for (BlockSide side : BlockSide.values()) {
Vector3i vec = new Vector3i(pos);
Multiblock.findOrigin(world, vec, side, null);
TileEntityScreen tes = (TileEntityScreen) world.getBlockEntity(vec.toBlock());
if(tes != null && tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_INPUT)) {
ScreenBlockEntity tes = (ScreenBlockEntity) world.getBlockEntity(vec.toBlock());
if (tes != null && tes.hasUpgrade(side, DefaultUpgrade.REDINPUT)) {
Direction facing = Direction.from2DDataValue(side.reverse().ordinal()); //Opposite face
vec.sub(pos.getX(), pos.getY(), pos.getZ()).neg();
tes.updateJSRedstone(side, new Vector2i(vec.dot(side.right), vec.dot(side.up)), world.getSignal(pos, facing));
// tes.updateJSRedstone(side, new Vector2i(vec.dot(side.right), vec.dot(side.up)), world.getSignal(pos, facing));
}
}
}
}
public static boolean hit2pixels(BlockSide side, BlockPos bpos, Vector3i pos, TileEntityScreen.Screen scr, float hitX, float hitY, float hitZ, Vector2i dst) {
public static boolean hit2pixels(BlockSide side, BlockPos bpos, Vector3i pos, ScreenData scr, float hitX, float hitY, float hitZ, Vector2i dst) {
if(side.right.x < 0)
hitX -= 1.f;
if(side.right.z < 0 || side == BlockSide.TOP || side == BlockSide.BOTTOM)
hitZ -= 1.f;
Vector3f rel = new Vector3f(pos.toBlock().getX(), pos.toBlock().getY(), pos.toBlock().getZ());
rel.sub(hitX, hitY, hitZ);
Vector3f rel = new Vector3f(hitX, hitY, hitZ);
float cx = Math.abs(rel.dot(side.right.toFloat()) - 2.f / 16.f);
float cy = Math.abs(rel.dot(side.up.toFloat()) - 2.f / 16.f);
// this dot is acting as a "get distance from plane" where the plane is the edge of the screen
float cx = rel.dot(side.right.toFloat()) - 2.f / 16.f;
float cy = rel.dot(side.up.toFloat()) - 2.f / 16.f;
float sw = ((float) scr.size.x) - 4.f / 16.f;
float sh = ((float) scr.size.y) - 4.f / 16.f;
cx /= sw;
cy /= sh;
cx = cx - 0.05f;
cy = cy - 0.05f;
if(cx >= 0 && cx <= 1 && cy >= 0 && cy <= 1) {
if(side != BlockSide.BOTTOM)
if (cx >= 0.f && cx <= 1.0 && cy >= 0.f && cy <= 1.f) {
if (side != BlockSide.BOTTOM)
cy = 1.f - cy;
switch(scr.rotation) {
switch (scr.rotation) {
case ROT_90:
cy = 1.0f - cy;
break;
@ -275,15 +235,12 @@ public class BlockScreen extends BaseEntityBlock {
case ROT_270:
cx = 1.0f - cx;
break;
default:
break;
}
cx *= (float) scr.resolution.x;
cy *= (float) scr.resolution.y;
if(scr.rotation.isVertical) {
if (scr.rotation.isVertical) {
dst.x = (int) cy;
dst.y = (int) cx;
} else {
@ -297,49 +254,41 @@ public class BlockScreen extends BaseEntityBlock {
return false;
}
@org.jetbrains.annotations.Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
int meta = getMetaFromState(state);
if((meta & 1) == 0)
return null;
return ((meta & 1) == 0) ? null : new TileEntityScreen(pos, state);
}
/************************************************* DESTRUCTION HANDLING *************************************************/
private void onDestroy(Level world, BlockPos pos, Player ply) {
if(!world.isClientSide) {
if (!world.isClientSide) {
Vector3i bp = new Vector3i(pos);
Multiblock.BlockOverride override = new Multiblock.BlockOverride(bp, Multiblock.OverrideAction.SIMULATE);
for(BlockSide bs: BlockSide.values())
for (BlockSide bs : BlockSide.values())
destroySide(world, bp.clone(), bs, override, ply);
}
}
private void destroySide(Level world, Vector3i pos, BlockSide side, Multiblock.BlockOverride override, Player source) {
private void destroySide(Level world, Vector3i pos, BlockSide side, Multiblock.BlockOverride override, Player
source) {
Multiblock.findOrigin(world, pos, side, override);
BlockPos bp = pos.toBlock();
BlockEntity te = world.getBlockEntity(bp);
if(te != null && te instanceof TileEntityScreen) {
((TileEntityScreen) te).onDestroy(source);
if (te instanceof ScreenBlockEntity) {
((ScreenBlockEntity) te).onDestroy(source);
world.setBlock(bp, world.getBlockState(bp).setValue(hasTE, false), Block.UPDATE_ALL_IMMEDIATE); //Destroy tile entity.
}
}
@Override
public boolean onDestroyedByPlayer(BlockState state, Level level, BlockPos pos, Player player, boolean willHarvest, FluidState fluid) {
public boolean onDestroyedByPlayer(BlockState state, Level level, BlockPos pos, Player player,
boolean willHarvest, FluidState fluid) {
onDestroy(level, pos, player);
return super.onDestroyedByPlayer(state, level, pos, player, willHarvest, fluid);
}
@Override
public void setPlacedBy(Level world, @NotNull BlockPos pos, @NotNull BlockState state, @org.jetbrains.annotations.Nullable LivingEntity whoDidThisShit, @NotNull ItemStack stack) {
if(world.isClientSide)
public void setPlacedBy(Level world, @NotNull BlockPos pos, @NotNull BlockState
state, @org.jetbrains.annotations.Nullable LivingEntity whoDidThisShit, @NotNull ItemStack stack) {
if (world.isClientSide)
return;
Multiblock.BlockOverride override = new Multiblock.BlockOverride(new Vector3i(pos), Multiblock.OverrideAction.IGNORE);
@ -352,14 +301,16 @@ public class BlockScreen extends BaseEntityBlock {
neighbors[4] = new Vector3i(pos.getX(), pos.getY(), pos.getZ() + 1);
neighbors[5] = new Vector3i(pos.getX(), pos.getY(), pos.getZ() - 1);
for(Vector3i neighbor: neighbors) {
if(world.getBlockState(neighbor.toBlock()).getBlock() instanceof BlockScreen) {
for(BlockSide bs: BlockSide.values())
for (Vector3i neighbor : neighbors) {
if (world.getBlockState(neighbor.toBlock()).getBlock() instanceof ScreenBlock) {
for (BlockSide bs : BlockSide.values())
destroySide(world, neighbor.clone(), bs, override, (whoDidThisShit instanceof Player) ? ((Player) whoDidThisShit) : null);
}
}
}
/************************************************* STUFF THAT'S UNLIKELY TO BE TOUCHED BUT NEEDS TO BE HERE *************************************************/
@Override
public @NotNull PushReaction getPistonPushReaction(BlockState state) {
return PushReaction.IGNORE;
@ -375,23 +326,18 @@ public class BlockScreen extends BaseEntityBlock {
return state.getValue(emitting);
}
// @Override //TODO: Add this
// protected BlockItem createItemBlock() {
// return new ItemBlockScreen(this);
// }
private static class ItemBlockScreen extends BlockItem implements WDItem {
public ItemBlockScreen(BlockScreen screen) {
super(screen, new Properties());
}
@Nullable
@Override
public String getWikiName(@Nonnull ItemStack is) {
return is.getItem().getName(is).getString();
}
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return state.getValue(hasTE) ? new ScreenBlockEntity(pos, state) : null;
}
@Override
public RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
builder.add(properties);
}
}

View File

@ -1,35 +0,0 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
public abstract class WDBlock extends Block {
protected BlockItem itemBlock;
public WDBlock(Properties properties) {
super(properties);
}
protected void setName(String name) {
setRegistryName(name);
}
public void makeItemBlock() {
if(itemBlock != null)
throw new RuntimeException("WDBlock.makeItemBlock() called twice!");
itemBlock = new BlockItem(this, new Item.Properties());
itemBlock.setRegistryName(getRegistryName());
}
public BlockItem getItem() {
return itemBlock;
}
}

View File

@ -1,41 +0,0 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block;
import net.montoyo.wd.WebDisplays;
public abstract class WDBlockContainer extends BaseEntityBlock {
protected static BlockItem itemBlock;
public WDBlockContainer(Properties arg) {
super(arg);
}
protected void setName(String name) {
// setRegistryName(name);
}
protected static BlockItem createItemBlock(Block block) {
return new BlockItem(block, new Item.Properties().tab(WebDisplays.CREATIVE_TAB));
}
public static void makeItemBlock(Block block) {
if(itemBlock != null)
throw new RuntimeException("WDBlockContainer.makeItemBlock() called twice!");
itemBlock = createItemBlock(block);
// itemBlock.setRegistryName(getName().getString());
}
public BlockItem getItem() {
return itemBlock;
}
}

View File

@ -0,0 +1,22 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.block;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.level.block.BaseEntityBlock;
public abstract class WDContainerBlock extends BaseEntityBlock {
protected static BlockItem itemBlock;
public WDContainerBlock(Properties arg) {
super(arg);
}
public BlockItem getItem() {
return itemBlock;
}
}

View File

@ -0,0 +1,54 @@
package net.montoyo.wd.block.item;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.montoyo.wd.block.KeyboardBlockLeft;
import net.montoyo.wd.registry.BlockRegistry;
public class KeyboardItem extends BlockItem {
public KeyboardItem(Block arg, Properties arg2) {
super(arg, arg2);
}
@Override
protected boolean placeBlock(BlockPlaceContext arg, BlockState arg2) {
Direction facing = arg.getHorizontalDirection();
arg2 = arg2.setValue(KeyboardBlockLeft.FACING, facing);
Direction d = KeyboardBlockLeft.mapDirection(facing);
if (isValid(arg.getClickedPos(), arg.getLevel(), arg2, d)) {
Block kbRight = BlockRegistry.blockKbRight.get();
BlockState rightState = kbRight.defaultBlockState();
rightState = rightState.setValue(KeyboardBlockLeft.FACING, facing);
if (!arg.getLevel().setBlock(
arg.getClickedPos().relative(d),
rightState,
11
)) return false;
return arg.getLevel().setBlock(arg.getClickedPos(), arg2, 11);// 161
} else if (isValid(arg.getClickedPos().relative(d.getOpposite(), 2), arg.getLevel(), arg2, d)) {
Block kbRight = BlockRegistry.blockKbRight.get();
BlockState rightState = kbRight.defaultBlockState();
rightState = rightState.setValue(KeyboardBlockLeft.FACING, facing);
if (!arg.getLevel().setBlock(
arg.getClickedPos(),
rightState,
11
)) return false;
return arg.getLevel().setBlock(arg.getClickedPos().relative(d.getOpposite()), arg2, 11);// 161
}
return false;
}
private boolean isValid(BlockPos pos, Level level, BlockState state, Direction d) {
return level.getBlockState(pos.relative(d)).isAir();
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,371 +1,370 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.client;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.montoyo.mcef.api.IBrowser;
import net.montoyo.mcef.api.IJSQueryCallback;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.block.BlockScreen;
import net.montoyo.wd.core.DefaultUpgrade;
import net.montoyo.wd.core.IScreenQueryHandler;
import net.montoyo.wd.core.IUpgrade;
import net.montoyo.wd.core.JSServerRequest;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessageScreenCtrl;
import net.montoyo.wd.utilities.*;
import java.util.*;
@OnlyIn(Dist.CLIENT)
public final class JSQueryDispatcher {
private static final class QueryData {
private final IBrowser browser;
private final String query;
private final String args;
private final IJSQueryCallback callback;
private QueryData(IBrowser b, String q, String a, IJSQueryCallback cb) {
browser = b;
query = q;
args = a;
callback = cb;
}
}
public static final class ServerQuery {
private static int lastId = 0;
private final TileEntityScreen tes;
private final BlockSide side;
private final IJSQueryCallback callback;
private final int id;
private ServerQuery(TileEntityScreen t, BlockSide s, IJSQueryCallback cb) {
tes = t;
side = s;
callback = cb;
id = lastId++;
}
public TileEntityScreen getTileEntity() {
return tes;
}
public BlockSide getSide() {
return side;
}
public TileEntityScreen.Screen getScreen() {
return tes.getScreen(side);
}
public void success(String resp) {
callback.success(resp);
}
public void error(int errId, String errStr) {
callback.failure(errId, errStr);
}
}
private final ClientProxy proxy;
private final ArrayDeque<QueryData> queue = new ArrayDeque<>();
private final ClientProxy.ScreenSidePair lookupResult = new ClientProxy.ScreenSidePair();
private final HashMap<String, IScreenQueryHandler> handlers = new HashMap<>();
private final ArrayList<ServerQuery> serverQueries = new ArrayList<>();
private final Minecraft mc = Minecraft.getInstance();
public JSQueryDispatcher(ClientProxy proxy) {
this.proxy = proxy;
registerDefaults();
}
public void enqueueQuery(IBrowser b, String q, String a, IJSQueryCallback cb) {
synchronized(queue) {
queue.offer(new QueryData(b, q, a, cb));
}
}
public void handleQueries() {
while(true) {
QueryData next;
synchronized(queue) {
next = queue.poll();
}
if(next == null)
break;
if(proxy.findScreenFromBrowser(next.browser, lookupResult)) {
Object[] args = (next.args == null) ? new Object[0] : parseArgs(next.args);
if(args == null)
next.callback.failure(400, "Malformed request parameters");
else {
try {
handlers.get(next.query).handleQuery(next.callback, lookupResult.tes, lookupResult.side, args);
} catch(Throwable t) {
Log.warningEx("Could not execute JS query %s(%s)", t, next.query, (next.args == null) ? "" : next.args);
next.callback.failure(500, "Internal error");
}
}
} else
next.callback.failure(403, "A screen is required");
}
}
public boolean canHandleQuery(String q) {
return handlers.containsKey(q);
}
private static Object[] parseArgs(String args) {
ArrayList<String> array = new ArrayList<>();
int lastIdx = 0;
boolean inString = false;
boolean escape = false;
boolean hadString = false;
for(int i = 0; i < args.length(); i++) {
char chr = args.charAt(i);
if(inString) {
if(escape)
escape = false;
else {
if(chr == '\"')
inString = false;
else if(chr == '\\')
escape = true;
}
} else if(chr == '\"') {
if(hadString)
return null;
inString = true;
hadString = true;
} else if(chr == ',') {
array.add(args.substring(lastIdx, i).trim());
lastIdx = i + 1;
hadString = false;
}
}
if(inString)
return null; //Non terminated string
array.add(args.substring(lastIdx).trim());
Object[] ret = new Object[array.size()];
for(int i = 0; i < ret.length; i++) {
String str = array.get(i);
if(str.isEmpty())
return null; //Nah...
if(str.charAt(0) == '\"') //String
ret[i] = str.substring(1, str.length() - 1);
else {
try {
ret[i] = Double.parseDouble(str);
} catch(NumberFormatException ex) {
return null;
}
}
}
return ret;
}
public void register(String query, IScreenQueryHandler handler) {
handlers.put(query.toLowerCase(), handler);
}
public ServerQuery fulfillQuery(int id) {
int toRemove = -1;
for(int i = 0; i < serverQueries.size(); i++) {
ServerQuery sq = serverQueries.get(i);
if(sq.id == id) {
toRemove = i;
break;
}
}
if(toRemove < 0)
return null;
else
return serverQueries.remove(toRemove);
}
private void makeServerQuery(TileEntityScreen tes, BlockSide side, IJSQueryCallback cb, JSServerRequest type, Object ... data) {
ServerQuery ret = new ServerQuery(tes, side, cb);
serverQueries.add(ret);
Messages.INSTANCE.sendToServer(SMessageScreenCtrl.jsRequest(tes, side, ret.id, type, data));
}
private void registerDefaults() {
register("GetSize", (cb, tes, side, args) -> {
Vector2i size = tes.getScreen(side).size;
cb.success("{\"x\":" + size.x + ",\"y\":" + size.y + "}");
});
register("GetRedstoneAt", (cb, tes, side, args) -> {
if(!tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_INPUT)) {
cb.failure(403, "Missing upgrade");
return;
}
if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) {
TileEntityScreen.Screen scr = tes.getScreen(side);
int x = ((Double) args[0]).intValue();
int y = ((Double) args[1]).intValue();
if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y)
cb.failure(403, "Out of range");
else {
BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock();
int level = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting) ? 0 : tes.getLevel().getSignal(bpos, Direction.values()[side.reverse().ordinal()]);
cb.success("{\"level\":" + level + "}");
}
} else
cb.failure(400, "Wrong arguments");
});
register("GetRedstoneArray", (cb, tes, side, args) -> {
if(tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_INPUT)) {
final Direction facing = Direction.values()[side.reverse().ordinal()];
final StringJoiner resp = new StringJoiner(",", "{\"levels\":[", "]}");
tes.forEachScreenBlocks(side, bp -> {
if(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting))
resp.add("0");
else
resp.add("" + tes.getLevel().getSignal(bp, facing));
});
cb.success(resp.toString());
} else
cb.failure(403, "Missing upgrade");
});
register("ClearRedstone", (cb, tes, side, args) -> {
if(tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_OUTPUT)) {
if(tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId()))
makeServerQuery(tes, side, cb, JSServerRequest.CLEAR_REDSTONE);
else
cb.success("{\"status\":\"notOwner\"}");
} else
cb.failure(403, "Missing upgrade");
});
register("SetRedstoneAt", (cb, tes, side, args) -> {
if(args.length != 3 || !Arrays.stream(args).allMatch((obj) -> obj instanceof Double)) {
cb.failure(400, "Wrong arguments");
return;
}
if(!tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_OUTPUT)) {
cb.failure(403, "Missing upgrade");
return;
}
if(!tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId())) {
cb.success("{\"status\":\"notOwner\"}");
return;
}
int x = ((Double) args[0]).intValue();
int y = ((Double) args[1]).intValue();
boolean state = ((Double) args[2]) > 0.0;
Vector2i size = tes.getScreen(side).size;
if(x < 0 || x >= size.x || y < 0 || y >= size.y) {
cb.failure(403, "Out of range");
return;
}
makeServerQuery(tes, side, cb, JSServerRequest.SET_REDSTONE_AT, x, y, state);
});
register("IsEmitting", (cb, tes, side, args) -> {
if(!tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_OUTPUT)) {
cb.failure(403, "Missing upgrade");
return;
}
if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) {
TileEntityScreen.Screen scr = tes.getScreen(side);
int x = ((Double) args[0]).intValue();
int y = ((Double) args[1]).intValue();
if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y)
cb.failure(403, "Out of range");
else {
BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock();
boolean e = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting);
cb.success("{\"emitting\":" + (e ? "true" : "false") + "}");
}
} else
cb.failure(400, "Wrong arguments");
});
register("GetEmissionArray", (cb, tes, side, args) -> {
if(tes.hasUpgrade(side, DefaultUpgrade.REDSTONE_OUTPUT)) {
final StringJoiner resp = new StringJoiner(",", "{\"emission\":[", "]}");
tes.forEachScreenBlocks(side, bp -> resp.add(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting) ? "1" : "0"));
cb.success(resp.toString());
} else
cb.failure(403, "Missing upgrade");
});
register("GetLocation", (cb, tes, side, args) -> {
if(!tes.hasUpgrade(side, DefaultUpgrade.GPS)) {
cb.failure(403, "Missing upgrade");
return;
}
BlockPos bp = tes.getBlockPos();
cb.success("{\"x\":" + bp.getX() + ",\"y\":" + bp.getY() + ",\"z\":" + bp.getZ() + ",\"side\":\"" + side + "\"}");
});
register("GetUpgrades", (cb, tes, side, args) -> {
final StringBuilder sb = new StringBuilder("{\"upgrades\":[");
final ArrayList<ItemStack> upgrades = tes.getScreen(side).upgrades;
for(int i = 0; i < upgrades.size(); i++) {
if(i > 0)
sb.append(',');
sb.append('\"');
sb.append(Util.addSlashes(((IUpgrade) upgrades.get(i).getItem()).getJSName(upgrades.get(i))));
sb.append('\"');
}
cb.success(sb.append("]}").toString());
});
register("IsOwner", (cb, tes, side, args) -> {
boolean res = (tes.getScreen(side).owner != null && tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId()));
cb.success("{\"isOwner\":" + (res ? "true}" : "false}"));
});
register("GetRotation", (cb, tes, side, args) -> cb.success("{\"rotation\":" + tes.getScreen(side).rotation.ordinal() + "}"));
register("GetSide", (cb, tes, side, args) -> cb.success("{\"side\":" + tes.getScreen(side).side.ordinal() + "}"));
}
}
///*
// * Copyright (C) 2018 BARBOTIN Nicolas
// */
//
//package net.montoyo.wd.client;
//
//import net.minecraft.client.Minecraft;
//import net.minecraft.core.BlockPos;
//import net.minecraft.core.Direction;
//import net.minecraft.world.item.ItemStack;
//import net.minecraftforge.api.distmarker.Dist;
//import net.minecraftforge.api.distmarker.OnlyIn;
//import net.montoyo.wd.block.BlockScreen;
//import net.montoyo.wd.core.DefaultUpgrade;
//import net.montoyo.wd.core.IScreenQueryHandler;
//import net.montoyo.wd.core.IUpgrade;
//import net.montoyo.wd.core.JSServerRequest;
//import net.montoyo.wd.entity.TileEntityScreen;
//import net.montoyo.wd.net.WDNetworkRegistry;
//import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl;
//import net.montoyo.wd.utilities.*;
//
//import java.util.*;
//
//@OnlyIn(Dist.CLIENT)
//public final class JSQueryDispatcher {
//
// private static final class QueryData {
//
// private final IBrowser browser;
// private final String query;
// private final String args;
// private final IJSQueryCallback callback;
//
// private QueryData(IBrowser b, String q, String a, IJSQueryCallback cb) {
// browser = b;
// query = q;
// args = a;
// callback = cb;
// }
//
// }
//
// public static final class ServerQuery {
//
// private static int lastId = 0;
//
// private final TileEntityScreen tes;
// private final BlockSide side;
// private final IJSQueryCallback callback;
// private final int id;
//
// private ServerQuery(TileEntityScreen t, BlockSide s, IJSQueryCallback cb) {
// tes = t;
// side = s;
// callback = cb;
// id = lastId++;
// }
//
// public TileEntityScreen getTileEntity() {
// return tes;
// }
//
// public BlockSide getSide() {
// return side;
// }
//
// public TileEntityScreen.Screen getScreen() {
// return tes.getScreen(side);
// }
//
// public void success(String resp) {
// callback.success(resp);
// }
//
// public void error(int errId, String errStr) {
// callback.failure(errId, errStr);
// }
//
// }
//
// private final ClientProxy proxy;
// private final ArrayDeque<QueryData> queue = new ArrayDeque<>();
// private final ClientProxy.ScreenSidePair lookupResult = new ClientProxy.ScreenSidePair();
// private final HashMap<String, IScreenQueryHandler> handlers = new HashMap<>();
// private final ArrayList<ServerQuery> serverQueries = new ArrayList<>();
// private final Minecraft mc = Minecraft.getInstance();
//
// public JSQueryDispatcher(ClientProxy proxy) {
// this.proxy = proxy;
// registerDefaults();
// }
//
// public void enqueueQuery(IBrowser b, String q, String a, IJSQueryCallback cb) {
// synchronized(queue) {
// queue.offer(new QueryData(b, q, a, cb));
// }
// }
//
// public void handleQueries() {
// while(true) {
// QueryData next;
// synchronized(queue) {
// next = queue.poll();
// }
//
// if(next == null)
// break;
//
// if(proxy.findScreenFromBrowser(next.browser, lookupResult)) {
// Object[] args = (next.args == null) ? new Object[0] : parseArgs(next.args);
//
// if(args == null)
// next.callback.failure(400, "Malformed request parameters");
// else {
// try {
// handlers.get(next.query).handleQuery(next.callback, lookupResult.tes, lookupResult.side, args);
// } catch(Throwable t) {
// Log.warningEx("Could not execute JS query %s(%s)", t, next.query, (next.args == null) ? "" : next.args);
// next.callback.failure(500, "Internal error");
// }
// }
// } else
// next.callback.failure(403, "A screen is required");
// }
// }
//
// public boolean canHandleQuery(String q) {
// return handlers.containsKey(q);
// }
//
// private static Object[] parseArgs(String args) {
// ArrayList<String> array = new ArrayList<>();
// int lastIdx = 0;
// boolean inString = false;
// boolean escape = false;
// boolean hadString = false;
//
// for(int i = 0; i < args.length(); i++) {
// char chr = args.charAt(i);
//
// if(inString) {
// if(escape)
// escape = false;
// else {
// if(chr == '\"')
// inString = false;
// else if(chr == '\\')
// escape = true;
// }
// } else if(chr == '\"') {
// if(hadString)
// return null;
//
// inString = true;
// hadString = true;
// } else if(chr == ',') {
// array.add(args.substring(lastIdx, i).trim());
// lastIdx = i + 1;
// hadString = false;
// }
// }
//
// if(inString)
// return null; //Non terminated string
//
// array.add(args.substring(lastIdx).trim());
// Object[] ret = new Object[array.size()];
//
// for(int i = 0; i < ret.length; i++) {
// String str = array.get(i);
// if(str.isEmpty())
// return null; //Nah...
//
// if(str.charAt(0) == '\"') //String
// ret[i] = str.substring(1, str.length() - 1);
// else {
// try {
// ret[i] = Double.parseDouble(str);
// } catch(NumberFormatException ex) {
// return null;
// }
// }
// }
//
// return ret;
// }
//
// public void register(String query, IScreenQueryHandler handler) {
// handlers.put(query.toLowerCase(), handler);
// }
//
// public ServerQuery fulfillQuery(int id) {
// int toRemove = -1;
//
// for(int i = 0; i < serverQueries.size(); i++) {
// ServerQuery sq = serverQueries.get(i);
//
// if(sq.id == id) {
// toRemove = i;
// break;
// }
// }
//
// if(toRemove < 0)
// return null;
// else
// return serverQueries.remove(toRemove);
// }
//
// private void makeServerQuery(TileEntityScreen tes, BlockSide side, IJSQueryCallback cb, JSServerRequest type, Object ... data) {
// ServerQuery ret = new ServerQuery(tes, side, cb);
// serverQueries.add(ret);
//
// WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.jsRequest(tes, side, ret.id, type, data));
// }
//
// private void registerDefaults() {
// VideoType.registerQueries(this);
//
// register("GetSize", (cb, tes, side, args) -> {
// Vector2i size = tes.getScreen(side).size;
// cb.success("{\"x\":" + size.x + ",\"y\":" + size.y + "}");
// });
//
// register("GetRedstoneAt", (cb, tes, side, args) -> {
// if(!tes.hasUpgrade(side, DefaultUpgrade.REDINPUT)) {
// cb.failure(403, "Missing upgrade");
// return;
// }
//
// if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) {
// TileEntityScreen.Screen scr = tes.getScreen(side);
// int x = ((Double) args[0]).intValue();
// int y = ((Double) args[1]).intValue();
//
// if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y)
// cb.failure(403, "Out of range");
// else {
// BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock();
// int level = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting) ? 0 : tes.getLevel().getSignal(bpos, Direction.values()[side.reverse().ordinal()]);
// cb.success("{\"level\":" + level + "}");
// }
// } else
// cb.failure(400, "Wrong arguments");
// });
//
// register("GetRedstoneArray", (cb, tes, side, args) -> {
// if(tes.hasUpgrade(side, DefaultUpgrade.REDINPUT)) {
// final Direction facing = Direction.values()[side.reverse().ordinal()];
// final StringJoiner resp = new StringJoiner(",", "{\"levels\":[", "]}");
//
// tes.forEachScreenBlocks(side, bp -> {
// if(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting))
// resp.add("0");
// else
// resp.add("" + tes.getLevel().getSignal(bp, facing));
// });
//
// cb.success(resp.toString());
// } else
// cb.failure(403, "Missing upgrade");
// });
//
// register("ClearRedstone", (cb, tes, side, args) -> {
// if(tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) {
// if(tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId()))
// makeServerQuery(tes, side, cb, JSServerRequest.CLEAR_REDSTONE);
// else
// cb.success("{\"status\":\"notOwner\"}");
// } else
// cb.failure(403, "Missing upgrade");
// });
//
// register("SetRedstoneAt", (cb, tes, side, args) -> {
// if(args.length != 3 || !Arrays.stream(args).allMatch((obj) -> obj instanceof Double)) {
// cb.failure(400, "Wrong arguments");
// return;
// }
//
// if(!tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) {
// cb.failure(403, "Missing upgrade");
// return;
// }
//
// if(!tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId())) {
// cb.success("{\"status\":\"notOwner\"}");
// return;
// }
//
// int x = ((Double) args[0]).intValue();
// int y = ((Double) args[1]).intValue();
// boolean state = ((Double) args[2]) > 0.0;
//
// Vector2i size = tes.getScreen(side).size;
// if(x < 0 || x >= size.x || y < 0 || y >= size.y) {
// cb.failure(403, "Out of range");
// return;
// }
//
// makeServerQuery(tes, side, cb, JSServerRequest.SET_REDSTONE_AT, x, y, state);
// });
//
// register("IsEmitting", (cb, tes, side, args) -> {
// if(!tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) {
// cb.failure(403, "Missing upgrade");
// return;
// }
//
// if(args.length == 2 && args[0] instanceof Double && args[1] instanceof Double) {
// TileEntityScreen.Screen scr = tes.getScreen(side);
// int x = ((Double) args[0]).intValue();
// int y = ((Double) args[1]).intValue();
//
// if(x < 0 || x >= scr.size.x || y < 0 || y >= scr.size.y)
// cb.failure(403, "Out of range");
// else {
// BlockPos bpos = (new Vector3i(tes.getBlockPos())).addMul(side.right, x).addMul(side.up, y).toBlock();
// boolean e = tes.getLevel().getBlockState(bpos).getValue(BlockScreen.emitting);
// cb.success("{\"emitting\":" + (e ? "true" : "false") + "}");
// }
// } else
// cb.failure(400, "Wrong arguments");
// });
//
// register("GetEmissionArray", (cb, tes, side, args) -> {
// if(tes.hasUpgrade(side, DefaultUpgrade.REDOUTPUT)) {
// final StringJoiner resp = new StringJoiner(",", "{\"emission\":[", "]}");
// tes.forEachScreenBlocks(side, bp -> resp.add(tes.getLevel().getBlockState(bp).getValue(BlockScreen.emitting) ? "1" : "0"));
// cb.success(resp.toString());
// } else
// cb.failure(403, "Missing upgrade");
// });
//
// register("GetLocation", (cb, tes, side, args) -> {
// if(!tes.hasUpgrade(side, DefaultUpgrade.GPS)) {
// cb.failure(403, "Missing upgrade");
// return;
// }
//
// BlockPos bp = tes.getBlockPos();
// cb.success("{\"x\":" + bp.getX() + ",\"y\":" + bp.getY() + ",\"z\":" + bp.getZ() + ",\"side\":\"" + side + "\"}");
// });
//
// register("GetUpgrades", (cb, tes, side, args) -> {
// final StringBuilder sb = new StringBuilder("{\"upgrades\":[");
// final ArrayList<ItemStack> upgrades = tes.getScreen(side).upgrades;
//
// for(int i = 0; i < upgrades.size(); i++) {
// if(i > 0)
// sb.append(',');
//
// sb.append('\"');
// sb.append(Util.addSlashes(((IUpgrade) upgrades.get(i).getItem()).getJSName(upgrades.get(i))));
// sb.append('\"');
// }
//
// cb.success(sb.append("]}").toString());
// });
//
// register("IsOwner", (cb, tes, side, args) -> {
// boolean res = (tes.getScreen(side).owner != null && tes.getScreen(side).owner.uuid.equals(mc.player.getGameProfile().getId()));
// cb.success("{\"isOwner\":" + (res ? "true}" : "false}"));
// });
//
// register("GetRotation", (cb, tes, side, args) -> cb.success("{\"rotation\":" + tes.getScreen(side).rotation.ordinal() + "}"));
// register("GetSide", (cb, tes, side, args) -> cb.success("{\"side\":" + tes.getScreen(side).side.ordinal() + "}"));
// }
//
//}

View File

@ -1,28 +0,0 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.client;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.montoyo.wd.client.renderers.IModelBaker;
public class ResourceModelPair {
private final ModelResourceLocation resLoc;
private final IModelBaker model;
public ResourceModelPair(ModelResourceLocation rl, IModelBaker m) {
resLoc = rl;
model = m;
}
public ModelResourceLocation getResourceLocation() {
return resLoc;
}
public IModelBaker getModel() {
return model;
}
}

View File

@ -1,27 +0,0 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
/*
package net.montoyo.wd.client;
import net.minecraft.client.resources.model.ModelResourceLocation;
import net.minecraft.world.level.block.state.BlockState;
import javax.annotation.Nonnull;
public class StaticStateMapper {
private final ModelResourceLocation resLoc;
public StaticStateMapper(ModelResourceLocation rl) {
resLoc = rl;
}
@Override
@Nonnull
protected ModelResourceLocation getModelResourceLocation(@Nonnull BlockState state) {
return resLoc;
}
} */

View File

@ -4,103 +4,127 @@
package net.montoyo.wd.client;
import net.montoyo.mcef.api.IScheme;
import net.montoyo.mcef.api.ISchemeResponseData;
import net.montoyo.mcef.api.ISchemeResponseHeaders;
import net.montoyo.mcef.api.SchemePreResponse;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.miniserv.Constants;
import net.montoyo.wd.miniserv.client.Client;
import net.montoyo.wd.miniserv.client.ClientTaskGetFile;
import net.montoyo.wd.utilities.Log;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.serialization.Util;
import org.cef.callback.CefCallback;
import org.cef.handler.CefResourceHandler;
import org.cef.misc.IntRef;
import org.cef.misc.StringRef;
import org.cef.network.CefRequest;
import org.cef.network.CefResponse;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.UUID;
public class WDScheme implements IScheme {
public class WDScheme implements CefResourceHandler {
private static final String ERROR_PAGE = "<!DOCTYPE html><html><head></head><body><h1>%d %s</h1><hr /><i>Miniserv powered by WebDisplays</i></body></html>";
private ClientTaskGetFile task;
private boolean isErrorPage;
String url;
boolean onlyError = false;
public WDScheme(String url) {
this.url = url;
}
@Override
public SchemePreResponse processRequest(String url) {
url = url.substring("wd://".length());
public boolean processRequest(CefRequest cefRequest, CefCallback cefCallback) {
url = cefRequest.getURL();
url = url.substring("webdisplays://".length());
int pos = url.indexOf('/');
if(pos < 0)
return SchemePreResponse.NOT_HANDLED;
if (pos < 0)
return false;
String uuidStr = url.substring(0, pos);
String fileStr = url.substring(pos + 1);
try {
fileStr = URLDecoder.decode(fileStr, "UTF-8");
} catch(UnsupportedEncodingException ex) {
Log.warningEx("UTF-8 isn't supported... yeah... and I'm a billionaire...", ex);
}
fileStr = URLDecoder.decode(fileStr, StandardCharsets.UTF_8);
if(uuidStr.isEmpty() || Util.isFileNameInvalid(fileStr))
return SchemePreResponse.NOT_HANDLED;
if (uuidStr.isEmpty() || Util.isFileNameInvalid(fileStr)) {
// invalid URL or no UUID
onlyError = true;
cefCallback.Continue();
return true;
}
UUID uuid;
try {
uuid = UUID.fromString(uuidStr);
} catch(IllegalArgumentException ex) {
return SchemePreResponse.NOT_HANDLED; //Invalid UUID
} catch (IllegalArgumentException ex) {
// invalid UUID
onlyError = true;
cefCallback.Continue();
return true;
}
task = new ClientTaskGetFile(uuid, fileStr);
return Client.getInstance().addTask(task) ? SchemePreResponse.HANDLED_CONTINUE : SchemePreResponse.NOT_HANDLED;
boolean doContinue = Client.getInstance().addTask(task);
if (doContinue) cefCallback.Continue();
return doContinue;
}
@Override
public void getResponseHeaders(ISchemeResponseHeaders resp) {
Log.info("Waiting for response...");
int status = task.waitForResponse();
Log.info("Got response %d", status);
public void getResponseHeaders(CefResponse cefResponse, IntRef contentLength, StringRef redir) {
int status;
if (onlyError) {
status = Constants.GETF_STATUS_BAD_NAME;
} else {
Log.info("Waiting for response...");
status = task.waitForResponse();
Log.info("Got response %d", status);
if(status == 0) {
//OK
int extPos = task.getFileName().lastIndexOf('.');
if(extPos >= 0) {
String mime = ((ClientProxy) WebDisplays.PROXY).getMCEF().mimeTypeFromExtension(task.getFileName().substring(extPos + 1));
if (status == 0) {
//OK
int extPos = task.getFileName().lastIndexOf('.');
if (extPos >= 0) {
String mime = mapMime(task.getFileName().substring(extPos + 1));
if(mime != null)
resp.setMimeType(mime);
if (mime != null)
cefResponse.setMimeType(mime);
}
cefResponse.setStatus(200);
cefResponse.setStatusText("OK");
contentLength.set(0);
return;
}
resp.setStatus(200);
resp.setStatusText("OK");
resp.setResponseLength(-1);
return;
}
int errCode;
String errStr;
if(status == Constants.GETF_STATUS_NOT_FOUND) {
if (status == Constants.GETF_STATUS_NOT_FOUND) {
errCode = 404;
errStr = "Not Found";
} else if (status == Constants.GETF_STATUS_TIMED_OUT) {
errCode = 408;
errStr = "Timed Out";
} else if (status == Constants.GETF_STATUS_BAD_NAME) {
errCode = 418;
errStr = "I'm a teapot";
} else {
errCode = 500;
errStr = "Internal Server Error";
}
resp.setStatus(errCode);
resp.setStatusText(errStr);
// reporting the actual status and text makes CEF not display the page
cefResponse.setStatus(200);
cefResponse.setStatusText("OK");
cefResponse.setMimeType("text/html");
try {
dataToWrite = String.format(ERROR_PAGE, errCode, errStr).getBytes("UTF-8");
dataOffset = 0;
amountToWrite = dataToWrite.length;
isErrorPage = true;
resp.setResponseLength(amountToWrite);
} catch(UnsupportedEncodingException ex) {
resp.setResponseLength(0);
}
dataToWrite = String.format(ERROR_PAGE, errCode, errStr).getBytes(StandardCharsets.UTF_8);
dataOffset = 0;
amountToWrite = dataToWrite.length;
isErrorPage = true;
contentLength.set(0);
}
private byte[] dataToWrite;
@ -108,10 +132,10 @@ public class WDScheme implements IScheme {
private int amountToWrite;
@Override
public boolean readResponse(ISchemeResponseData data) {
if(dataToWrite == null) {
if(isErrorPage) {
data.setAmountRead(0);
public boolean readResponse(byte[] output, int bytesToRead, IntRef bytesRead, CefCallback cefCallback) {
if (dataToWrite == null) {
if (isErrorPage) {
bytesRead.set(0);
return false;
}
@ -119,25 +143,25 @@ public class WDScheme implements IScheme {
dataOffset = 3; //packet ID + size
amountToWrite = task.getDataLength();
if(amountToWrite <= 0) {
if (amountToWrite <= 0) {
dataToWrite = null;
data.setAmountRead(0);
bytesRead.set(0);
return false;
}
}
int toWrite = data.getBytesToRead();
if(toWrite > amountToWrite)
int toWrite = bytesToRead;
if (toWrite > amountToWrite)
toWrite = amountToWrite;
System.arraycopy(dataToWrite, dataOffset, data.getDataArray(), 0, toWrite);
data.setAmountRead(toWrite);
System.arraycopy(dataToWrite, dataOffset, output, 0, toWrite);
bytesRead.set(toWrite);
dataOffset += toWrite;
amountToWrite -= toWrite;
if(amountToWrite <= 0) {
if(!isErrorPage)
if (amountToWrite <= 0) {
if (!isErrorPage)
task.nextData();
dataToWrite = null;
@ -146,4 +170,46 @@ public class WDScheme implements IScheme {
return true;
}
@Override
public void cancel() {
Log.info("Scheme query canceled or finished.");
if (!onlyError)
task.cancel();
}
public static String mapMime(String ext) {
switch (ext) {
case "htm":
case "html":
return "text/html";
case "css":
return "text/css";
case "js":
return "text/javascript";
case "png":
return "image/png";
case "jpg":
case "jpeg":
return "image/jpeg";
case "gif":
return "image/gif";
case "svg":
return "image/svg+xml";
case "xml":
return "text/xml";
case "txt":
return "text/plain";
default:
return null;
}
}
}

View File

@ -0,0 +1,116 @@
package net.montoyo.wd.client.audio;
import net.minecraft.client.resources.sounds.Sound;
import net.minecraft.client.resources.sounds.SoundInstance;
import net.minecraft.client.sounds.AudioStream;
import net.minecraft.client.sounds.SoundBufferLibrary;
import net.minecraft.client.sounds.SoundManager;
import net.minecraft.client.sounds.WeighedSoundEvents;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.util.valueproviders.SampledFloat;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.ScreenData;
import org.jetbrains.annotations.Nullable;
import java.util.concurrent.CompletableFuture;
public class WDAudioSource implements SoundInstance {
private static final ResourceLocation location = new ResourceLocation("webdisplays:audio_source");
private static final WeighedSoundEvents events = new WeighedSoundEvents(
location, "webdisplays.browser"
);
private static final SampledFloat CONST_1 = new SampledFloat() {
@Override
public float sample(RandomSource pRandom) {
return 1.0f;
}
};
private final Sound sound = new Sound(
"unused",
CONST_1,
CONST_1,
1, Sound.Type.SOUND_EVENT,
true, false,
100
);
ScreenBlockEntity blockEntity;
ScreenData data;
public WDAudioSource(ScreenBlockEntity blockEntity, ScreenData data) {
this.blockEntity = blockEntity;
this.data = data;
}
@Override
public ResourceLocation getLocation() {
return location;
}
@Nullable
@Override
public WeighedSoundEvents resolve(SoundManager pManager) {
return events;
}
@Override
public CompletableFuture<AudioStream> getStream(SoundBufferLibrary soundBuffers, Sound sound, boolean looping) {
return null;
}
@Override
public Sound getSound() {
return sound;
}
@Override
public SoundSource getSource() {
return SoundSource.RECORDS;
}
@Override
public boolean isLooping() {
return true;
}
@Override
public boolean isRelative() {
return false;
}
@Override
public int getDelay() {
return 0;
}
@Override
public float getVolume() {
return blockEntity.ytVolume;
}
@Override
public float getPitch() {
return 1;
}
@Override
public double getX() {
return blockEntity.getBlockPos().getX();
}
@Override
public double getY() {
return blockEntity.getBlockPos().getY();
}
@Override
public double getZ() {
return blockEntity.getBlockPos().getZ();
}
@Override
public Attenuation getAttenuation() {
return Attenuation.LINEAR;
}
}

View File

@ -4,53 +4,59 @@
package net.montoyo.wd.client.gui;
import com.mojang.blaze3d.platform.InputConstants;
import com.sun.jna.platform.unix.X11;
import com.cinemamod.mcef.MCEFBrowser;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.loading.FMLPaths;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.gui.camera.KeyboardCamera;
import net.montoyo.wd.client.gui.controls.Button;
import net.montoyo.wd.client.gui.controls.Control;
import net.montoyo.wd.client.gui.controls.Label;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessageScreenCtrl;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.controls.builtin.ClickControl;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl;
import net.montoyo.wd.utilities.Log;
import net.montoyo.wd.utilities.TypeData;
import net.montoyo.wd.utilities.Util;
import org.apache.commons.lang3.CharUtils;
import org.cef.browser.CefBrowserOsr;
import org.jline.utils.Display;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector2i;
import net.montoyo.wd.utilities.serialization.TypeData;
import net.montoyo.wd.utilities.serialization.Util;
import org.cef.browser.CefBrowser;
import org.cef.misc.CefCursorType;
import org.joml.Matrix4f;
import org.joml.Vector4f;
import org.lwjgl.glfw.GLFW;
import org.vivecraft.client_vr.gameplay.VRPlayer;
import org.vivecraft.client_vr.gameplay.screenhandlers.KeyboardHandler;
import java.awt.event.KeyEvent;
import java.io.*;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Map;
import static com.mojang.blaze3d.platform.InputConstants.*;
import static java.awt.event.KeyEvent.*;
import java.util.function.Consumer;
@OnlyIn(Dist.CLIENT)
public class GuiKeyboard extends WDScreen {
private static final String WARNING_FNAME = "wd_keyboard_warning.txt";
private TileEntityScreen tes;
private ScreenBlockEntity tes;
private BlockSide side;
private ScreenData data;
private final ArrayList<TypeData> evStack = new ArrayList<>();
private BlockPos kbPos;
private boolean showWarning = true;
@ -65,7 +71,7 @@ public class GuiKeyboard extends WDScreen {
super(Component.nullToEmpty(null));
}
public GuiKeyboard(TileEntityScreen tes, BlockSide side, BlockPos kbPos) {
public GuiKeyboard(ScreenBlockEntity tes, BlockSide side, BlockPos kbPos) {
this();
this.tes = tes;
this.side = side;
@ -77,6 +83,30 @@ public class GuiKeyboard extends WDScreen {
vars.put("showWarning", showWarning ? 1.0 : 0.0);
}
private static final boolean vivecraftPresent;
static {
boolean vivePres = false;
if (ModList.get().isLoaded("vivecraft")) vivePres = true;
// I believe the non-mixin version of vivecraft is not a proper mod, so
// detect the mod reflectively if the mod is not found
else {
try {
Class<?> clazz = Class.forName("org.vivecraft.gameplay.screenhandlers.KeyboardHandler");
//noinspection ConstantConditions
if (clazz == null) vivePres = false;
else {
Method m = clazz.getMethod("setOverlayShowing", boolean.class);
//noinspection ConstantConditions
vivePres = m != null;
}
} catch (Throwable ignored) {
vivePres = false;
}
}
vivecraftPresent = vivePres;
}
@Override
public void init() {
super.init();
@ -122,64 +152,77 @@ public class GuiKeyboard extends WDScreen {
defaultBackground = showWarning;
syncTicks = 5;
if (vivecraftPresent)
if (VRPlayer.get() != null)
KeyboardHandler.setOverlayShowing(true);
KeyboardCamera.focus(tes, side);
data = tes.getScreen(side);
CefBrowser browser = data.browser;
((MCEFBrowser) browser).setCursor(CefCursorType.fromId(data.mouseType));
((MCEFBrowser) browser).setCursorChangeListener((id) -> {
data.mouseType = id;
((MCEFBrowser) browser).setCursor(CefCursorType.fromId(id));
});
}
@Override
public void removed() {
super.removed();
if (vivecraftPresent)
if (VRPlayer.get() != null)
KeyboardHandler.setOverlayShowing(false);
KeyboardCamera.focus(null, null);
CefBrowser browser = data.browser;
if (browser instanceof MCEFBrowser mcef) {
mcef.setCursor(CefCursorType.POINTER);
mcef.setCursorChangeListener((cursor) -> data.mouseType = cursor);
}
}
@Override
public void onClose() {
removed();
super.onClose();
this.minecraft.popGuiLayer();
}
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
key(keyCode, scanCode, true, modifiers);
if (quitOnEscape && keyCode == GLFW.GLFW_KEY_ESCAPE) {
onClose();
return true;
}
addKey(new TypeData(TypeData.Action.PRESS, keyCode, modifiers, scanCode));
return super.keyPressed(keyCode, scanCode, modifiers);
}
@Override
public boolean charTyped(char codePoint, int modifiers) {
addKey(new TypeData(TypeData.Action.TYPE, codePoint, modifiers, 0));
return super.charTyped(codePoint, modifiers);
}
@Override
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
key(keyCode, scanCode, false, modifiers);
addKey(new TypeData(TypeData.Action.RELEASE, keyCode, modifiers, scanCode));
return super.keyPressed(keyCode, scanCode, modifiers);
}
public void key(int keyCode, int scanCode, boolean pressed, int mod) {
if (pressed) {
if(quitOnEscape && keyCode == GLFW.GLFW_KEY_ESCAPE) {
Minecraft.getInstance().setScreen(null);
}
void addKey(TypeData data) {
tes.type(side, "[" + WebDisplays.GSON.toJson(data) + "]", kbPos);
int chr = getChar(keyCode, scanCode);
evStack.add(new TypeData(TypeData.Action.PRESS, chr, mod));
evStack.add(new TypeData(TypeData.Action.RELEASE, chr, mod));
if (keyCode != 0)
evStack.add(new TypeData(TypeData.Action.TYPE, chr, mod));
if (!evStack.isEmpty() && !syncRequested())
requestSync();
}
}
public int getChar(int keyCode, int scanCode) {
String keystr = GLFW.glfwGetKeyName(keyCode, scanCode);
if(keystr == null){
keystr = "\0";
}
if(keyCode == GLFW.GLFW_KEY_ENTER){
return 13;
}
if (keyCode == GLFW.GLFW_KEY_SPACE) {
return 32;
}
if(keystr.length() == 0){
return -1;
}
if(hasShiftDown()) {
keystr = keystr.toUpperCase(Locale.ROOT);
return CefBrowserOsr.remapKeycode(keyCode, keystr.charAt(keystr.length() - 1));
} else {
return CefBrowserOsr.remapKeycode(keyCode, keystr.charAt(keystr.length() - 1));
}
evStack.add(data);
if (!evStack.isEmpty() && !syncRequested())
requestSync();
}
@Override
protected void sync() {
if(!evStack.isEmpty()) {
Messages.INSTANCE.sendToServer(SMessageScreenCtrl.type(tes, side, WebDisplays.GSON.toJson(evStack), kbPos));
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.type(tes, side, WebDisplays.GSON.toJson(evStack), kbPos));
evStack.clear();
}
}
@ -207,7 +250,7 @@ public class GuiKeyboard extends WDScreen {
private boolean hasUserReadWarning() {
try {
File f = new File(FMLPaths.GAMEDIR.name(), WARNING_FNAME);
File f = new File(FMLPaths.GAMEDIR.get().toString(), WARNING_FNAME);
if(f.exists()) {
BufferedReader br = new BufferedReader(new FileReader(f));
@ -225,7 +268,7 @@ public class GuiKeyboard extends WDScreen {
private void writeUserAcknowledge() {
try {
File f = new File(FMLPaths.GAMEDIR.name(), WARNING_FNAME);
File f = new File(FMLPaths.GAMEDIR.get().toString(), WARNING_FNAME);
BufferedWriter bw = new BufferedWriter(new FileWriter(f));
bw.write("read\n");
@ -240,4 +283,89 @@ public class GuiKeyboard extends WDScreen {
return bp.equals(kbPos) || (bp.equals(tes.getBlockPos()) && side == this.side);
}
protected void mouse(double mouseX, double mouseY, Consumer<Vector2i> func) {
float pct = Minecraft.getInstance().getPartialTick();
double fov = Minecraft.getInstance().gameRenderer.getFov(
Minecraft.getInstance().getEntityRenderDispatcher().camera,
pct, true
);
mouseX /= width;
mouseY /= height;
mouseX -= 0.5;
mouseY -= 0.5;
mouseY = -mouseY;
Matrix4f proj = Minecraft.getInstance().gameRenderer.getProjectionMatrix(fov);
Entity e = Minecraft.getInstance().getEntityRenderDispatcher().camera.getEntity();
PoseStack camera = new PoseStack();
float[] angle = KeyboardCamera.getAngle(e, pct);
camera.mulPose(Axis.XP.rotationDegrees(angle[0]));
camera.mulPose(Axis.YP.rotationDegrees(angle[1] + 180.0F));
Vector4f coord = new Vector4f(2f * (float) mouseX, 2 * (float) mouseY, 0, 1f);
coord.add(proj.invert().transform(coord));
coord = camera.last().pose().invert().transform(coord);
Vec3 vec3 = e.getEyePosition(pct);
Vec3 vec31 = new Vec3(coord.x, coord.y, coord.z).normalize();
BlockHitResult result = tes.trace(side, vec3, vec31);
if (result.getType() != HitResult.Type.MISS) {
tes.interact(result, func);
}
}
@Override
public void mouseMoved(double mouseX, double mouseY) {
mouse(mouseX, mouseY, (hit) -> {
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, hit, -1);
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.laserMove(tes, side, hit));
});
super.mouseMoved(mouseX, mouseY);
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
mouse(mouseX, mouseY, (hit) -> {
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, hit, -1);
tes.handleMouseEvent(side, ClickControl.ControlType.DOWN, hit, button);
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.laserDown(tes, side, hit, button));
});
KeyboardCamera.setMouse(button, true);
return super.mouseClicked(mouseX, mouseY, button);
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
mouse(mouseX, mouseY, (hit) -> {
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, hit, -1);
tes.handleMouseEvent(side, ClickControl.ControlType.UP, hit, button);
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.laserUp(tes, side, button));
});
KeyboardCamera.setMouse(button, false);
return super.mouseReleased(mouseX, mouseY, button);
}
@Override
public void tick() {
double mouseX = Minecraft.getInstance().mouseHandler.xpos() / Minecraft.getInstance().getWindow().getWidth();
double mouseY = Minecraft.getInstance().mouseHandler.ypos() / Minecraft.getInstance().getWindow().getHeight();
mouse(mouseX * width, mouseY * height, (hit) -> {
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, hit, -1);
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.laserMove(tes, side, hit));
});
super.tick();
}
}

View File

@ -4,180 +4,354 @@
package net.montoyo.wd.client.gui;
import com.cinemamod.mcef.MCEFBrowser;
import com.google.gson.JsonObject;
import com.mojang.blaze3d.platform.InputConstants;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.core.BlockPos;
import net.minecraft.locale.Language;
import net.minecraft.network.chat.Component;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.browser.WDBrowser;
import net.montoyo.wd.utilities.browser.handlers.js.Scripts;
import net.montoyo.wd.utilities.data.BlockSide;
import org.cef.misc.CefCursorType;
import org.lwjgl.glfw.GLFW;
import java.util.Optional;
import static net.minecraftforge.api.distmarker.Dist.CLIENT;
import static org.lwjgl.opengl.GL11.glColor4f;
@OnlyIn(CLIENT)
public class GuiMinePad extends WDScreen {
private ClientProxy.PadData pad;
private double vx;
private double vy;
private double vw;
private double vh;
private ClientProxy.PadData pad;
private double vx;
private double vy;
private double vw;
private double vh;
public GuiMinePad() {
super(Component.nullToEmpty(null));
}
public GuiMinePad() {
super(Component.nullToEmpty(null));
}
public GuiMinePad(ClientProxy.PadData pad) {
this();
this.pad = pad;
}
public GuiMinePad(ClientProxy.PadData pad) {
this();
this.pad = pad;
}
@Override
public void init() {
super.init();
int trueWidth, trueHeight;
vw = ((double) width) - 32.0f;
vh = vw / WebDisplays.PAD_RATIO;
vx = 16.0f;
vy = (((double) height) - vh) / 2.0f;
}
@Override
public void init() {
vw = ((double) width) - 32.0f;
vh = vw / WebDisplays.PAD_RATIO;
vx = 16.0f;
vy = (((double) height) - vh) / 2.0f;
private static void addRect(BufferBuilder bb, double x, double y, double w, double h) {
bb.vertex(x, y, 0.0).endVertex();
bb.vertex(x + w, y, 0.0).endVertex();
bb.vertex(x + w, y + h, 0.0).endVertex();
bb.vertex(x, y + h, 0.0).endVertex();
}
trueWidth = width;
trueHeight = height;
@Override
public void render(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
renderBackground(poseStack);
this.width = (int) vw;
this.height = (int) vh;
RenderSystem.disableTexture();
RenderSystem.disableCull();
RenderSystem.setShaderColor(0.73f, 0.73f, 0.73f, 1.0f);
super.init();
Tesselator t = Tesselator.getInstance();
BufferBuilder bb = t.getBuilder();
bb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
addRect(bb, vx, vy - 16, vw, 16);
addRect(bb, vx, vy + vh, vw, 16);
addRect(bb, vx - 16, vy, 16, vh);
addRect(bb, vx + vw, vy, 16, vh);
t.end();
((MCEFBrowser) pad.view).setCursor(CefCursorType.fromId(pad.activeCursor));
((MCEFBrowser) pad.view).setCursorChangeListener((id) -> {
pad.activeCursor = id;
((MCEFBrowser) pad.view).setCursor(CefCursorType.fromId(id));
});
}
RenderSystem.enableTexture();
private static void addRect(BufferBuilder bb, double x, double y, double w, double h) {
bb.vertex(x, y, 0.0).color(255, 255, 255, 255).endVertex();
bb.vertex(x + w, y, 0.0).color(255, 255, 255, 255).endVertex();
bb.vertex(x + w, y + h, 0.0).color(255, 255, 255, 255).endVertex();
bb.vertex(x, y + h, 0.0).color(255, 255, 255, 255).endVertex();
}
if (pad.view != null) {
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
pad.view.draw(poseStack, vx, vy + vh, vx + vw, vy);
}
@Override
public void render(GuiGraphics graphics, int mouseX, int mouseY, float ptt) {
width = trueWidth;
height = trueHeight;
renderBackground(graphics);
width = (int) vw;
height = (int) vh;
RenderSystem.enableCull();
}
RenderSystem.disableCull();
RenderSystem.setShaderColor(0.73f, 0.73f, 0.73f, 1.0f);
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
key(keyCode, scanCode, true);
return super.keyPressed(keyCode, scanCode, modifiers);
}
Tesselator t = Tesselator.getInstance();
BufferBuilder bb = t.getBuilder();
bb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
addRect(bb, vx, vy - 16, vw, 16);
addRect(bb, vx, vy + vh, vw, 16);
addRect(bb, vx - 16, vy, 16, vh);
addRect(bb, vx + vw, vy, 16, vh);
t.end();
if (pad.view != null) {
// pad.view.draw(poseStack, vx, vy + vh, vx + vw, vy);
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.disableDepthTest();
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
RenderSystem.setShaderTexture(0, ((MCEFBrowser) pad.view).getRenderer().getTextureID());
t = Tesselator.getInstance();
BufferBuilder buffer = t.getBuilder();
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
double x1 = vx;
double y1 = vy;
double x2 = vx + vw;
double y2 = vy + vh;
buffer.vertex(graphics.pose().last().pose(), (float) x1, (float) y1, 0.0f).uv(0.0F, 0.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(graphics.pose().last().pose(), (float) x2, (float) y1, 0.0f).uv(1.0F, 0.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(graphics.pose().last().pose(), (float) x2, (float) y2, 0.0f).uv(1.0F, 1.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(graphics.pose().last().pose(), (float) x1, (float) y2, 0.0f).uv(0.0F, 1.0F).color(255, 255, 255, 255).endVertex();
t.end();
RenderSystem.enableDepthTest();
}
RenderSystem.enableCull();
@Override
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
key(keyCode, scanCode, false);
return super.keyPressed(keyCode, scanCode, modifiers);
}
graphics.drawString(
minecraft.font, Language.getInstance().getOrDefault(
"webdisplays.gui.minepad.close"
), (int) vx + 4, (int) vy - minecraft.font.lineHeight - 3, 16777215, true
);
}
public void key(int keyCode, int scanCode, boolean pressed) {
Optional<Character> key = getChar(keyCode, scanCode);
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
return this.keyChanged(keyCode, scanCode, modifiers, true) || super.keyPressed(keyCode, scanCode, modifiers);
}
if (pad.view != null && key.isPresent()) {
char c = key.get();
@Override
public boolean keyReleased(int keyCode, int scanCode, int modifiers) {
return this.keyChanged(keyCode, scanCode, modifiers, false) || super.keyReleased(keyCode, scanCode, modifiers);
}
if (pressed)
pad.view.injectKeyPressedByKeyCode(keyCode, c, 0);
else
pad.view.injectKeyReleasedByKeyCode(keyCode, c, 0);
@Override
public boolean charTyped(char codePoint, int modifiers) {
if (pad.view != null) {
((MCEFBrowser) pad.view).sendKeyTyped(codePoint, modifiers);
return true;
} else {
return super.charTyped(codePoint, modifiers);
}
}
if (c != 0)
pad.view.injectKeyTyped(c, 0);
}
/* copied from MCEF */
public boolean keyChanged(int keyCode, int scanCode, int modifiers, boolean pressed) {
assert minecraft != null;
if ((modifiers & GLFW.GLFW_MOD_SHIFT) == GLFW.GLFW_MOD_SHIFT && keyCode == GLFW.GLFW_KEY_ESCAPE) {
onClose();
return true;
}
}
InputConstants.Key iuKey = InputConstants.getKey(keyCode, scanCode);
String keystr = iuKey.getDisplayName().getString();
// System.out.println("KEY STR " + keystr);
if (keystr.length() == 0)
return false;
@Override
public void mouseMoved(double mouseX, double mouseY) {
super.mouseMoved(mouseX, mouseY);
mouse(-1, false, (int) mouseX, (int) mouseY);
}
char key = keystr.charAt(keystr.length() - 1);
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
mouse(button, true, (int) mouseX, (int) mouseY);
return super.mouseClicked(mouseX, mouseY, button);
}
if (keystr.equals("Enter")) {
keyCode = 10;
key = '\n';
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
mouse(button, false, (int) mouseX, (int) mouseY);
return super.mouseReleased(mouseX, mouseY, button);
}
if (pad.view != null) {
if (pressed)
((MCEFBrowser) pad.view).sendKeyPress(keyCode, scanCode, modifiers);
else
((MCEFBrowser) pad.view).sendKeyRelease(keyCode, scanCode, modifiers);
public void mouse(int btn, boolean pressed, int sx, int sy) {
if (pressed && key == '\n')
if (modifiers != 0) ((MCEFBrowser) pad.view).sendKeyTyped('\r', modifiers);
return true;
}
int vx = screen2DisplayX((int) this.vx);
int vy = screen2DisplayY((int) this.vy);
int vh = screen2DisplayX((int) this.vh);
int vw = screen2DisplayY((int) this.vw);
return false;
}
if (pad.view != null && sx >= vx && sx <= vx + vw && sy >= vy && sy <= vy + vh) {
sx -= vx;
sy -= vy;
sy = vh - sy;
@Override
public void mouseMoved(double mouseX, double mouseY) {
super.mouseMoved(mouseX, mouseY);
mouse(-1, false, (int) mouseX, (int) mouseY, 0);
}
//Scale again according to the webview
sx = (int) (((double) sx) / ((double) vw) * WebDisplays.INSTANCE.padResX);
sy = (int) (((double) sy) / ((double) vh) * WebDisplays.INSTANCE.padResY);
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
mouse(button, true, (int) mouseX, (int) mouseY, 0);
return super.mouseClicked(mouseX, mouseY, button);
}
if (btn == -1)
pad.view.injectMouseMove(sx, sy, 0, false);
else
pad.view.injectMouseButton(sx, sy, 0, btn + 1, pressed, 1);
@Override
public boolean mouseReleased(double mouseX, double mouseY, int button) {
mouse(button, false, (int) mouseX, (int) mouseY, 0);
return super.mouseReleased(mouseX, mouseY, button);
}
}
}
@Override
public boolean mouseScrolled(double mouseX, double mouseY, double amount) {
double mx = (mouseX - vx) / vw;
double my = (mouseY - vy) / vh;
int sx = (int) (mx * WebDisplays.INSTANCE.padResX);
int sy = (int) (my * WebDisplays.INSTANCE.padResY);
// TODO: this doesn't work, and I don't understand why?
((MCEFBrowser) pad.view).sendMouseWheel(sx, sy, amount, (hasControlDown() && !hasAltDown() && !hasShiftDown()) ? GLFW.GLFW_MOD_CONTROL : 0);
public static Optional<Character> getChar(int keyCode, int scanCode) {
String keystr = GLFW.glfwGetKeyName(keyCode, scanCode);
if(keystr == null){
keystr = "\0";
}
if(keyCode == GLFW.GLFW_KEY_ENTER){
keystr = "\n";
}
if(keystr.length() == 0){
return Optional.empty();
}
return super.mouseScrolled(mouseX, mouseY, amount);
}
return Optional.of(keystr.charAt(keystr.length() - 1));
}
public void capturedMouse(double scaledX, double scaledY, int sx, int sy) {
double centerX = (int) (0.5 * (double) this.minecraft.getWindow().getGuiScaledWidth());
double centerY = (int) (0.5 * (double) this.minecraft.getWindow().getGuiScaledHeight());
@Override
public void tick() {
if(pad.view == null)
minecraft.setScreen(null); //In case the user dies with the pad in the hand
}
if (sx == (int) centerX && sy == (int) centerY) return;
@Override
public boolean isForBlock(BlockPos bp, BlockSide side) {
return false;
}
double mx = (centerX - vx) / vw;
double my = (centerY - vy) / vh;
double scaledCentX = (mx * WebDisplays.INSTANCE.padResX);
double scaledCentY = (my * WebDisplays.INSTANCE.padResY);
double deltX = scaledX - scaledCentX;
double deltY = scaledY - scaledCentY;
String scr = Scripts.MOUSE_EVENT;
pad.view.executeJavaScript(
scr
.replace("%xCoord%", "" + (int) centerX)
.replace("%yCoord%", "" + (int) centerY)
.replace("%xDelta%", "" + (deltX))
.replace("%yDelta%", "" + (deltY)),
"WebDisplays", 0
);
// lock mouse
try {
double xpos = (this.minecraft.getWindow().getScreenWidth() / 2);
double ypos = (this.minecraft.getWindow().getScreenHeight() / 2);
GLFW.glfwSetCursorPos(minecraft.getWindow().getWindow(), xpos, ypos);
} catch (Throwable ignored) {
}
}
public void mouse(int btn, boolean pressed, int sx, int sy, double scrollAmount) {
double mx = (sx - vx) / vw;
double my = (sy - vy) / vh;
if (pad.view != null && mx >= 0 && mx <= 1) {
//Scale again according to the webview
int scaledX = (int) (mx * WebDisplays.INSTANCE.padResX);
int scaledY = (int) (my * WebDisplays.INSTANCE.padResY);
if (btn == -1) {
if (locked)
capturedMouse(mx * WebDisplays.INSTANCE.padResX, my * WebDisplays.INSTANCE.padResY, sx, sy);
else ((MCEFBrowser) pad.view).sendMouseMove(scaledX, scaledY);
} else if (pressed)
((MCEFBrowser) pad.view).sendMousePress(scaledX, scaledY, btn);
else ((MCEFBrowser) pad.view).sendMouseRelease(scaledX, scaledY, btn);
pad.view.setFocus(true);
}
}
public static Optional<Character> getChar(int keyCode, int scanCode) {
String keystr = GLFW.glfwGetKeyName(keyCode, scanCode);
if (keystr == null) {
keystr = "\0";
}
if (keyCode == GLFW.GLFW_KEY_ENTER) {
keystr = "\n";
}
if (keystr.length() == 0) {
return Optional.empty();
}
return Optional.of(keystr.charAt(keystr.length() - 1));
}
@Override
public void tick() {
if (pad.view == null)
minecraft.setScreen(null); //In case the user dies with the pad in the hand
pollElement();
}
@Override
public boolean isForBlock(BlockPos bp, BlockSide side) {
return false;
}
@Override
public void removed() {
super.removed();
InputConstants.updateRawMouseInput(
minecraft.getWindow().getWindow(),
Minecraft.getInstance().options.rawMouseInput().get()
);
if (pad.view instanceof MCEFBrowser browser) {
browser.setCursor(CefCursorType.POINTER);
browser.setCursorChangeListener((cursor) -> {
pad.activeCursor = cursor;
});
}
}
@Override
public void onClose() {
super.onClose();
removed();
this.minecraft.popGuiLayer();
}
boolean locked = false;
double lockCenterX = -1;
double lockCenterY = -1;
protected void updateCrd(JsonObject obj) {
if (obj.getAsJsonPrimitive("exists").getAsBoolean()) {
locked = true;
RenderSystem.recordRenderCall(() -> {
InputConstants.updateRawMouseInput(
minecraft.getWindow().getWindow(),
obj.getAsJsonPrimitive("unadjust").getAsBoolean()
);
GLFW.glfwSetInputMode(Minecraft.getInstance().getWindow().getWindow(), 208897, GLFW.GLFW_CURSOR_DISABLED);
});
lockCenterX = obj.getAsJsonPrimitive("x").getAsDouble() + obj.getAsJsonPrimitive("w").getAsDouble() / 2;
lockCenterY = obj.getAsJsonPrimitive("y").getAsDouble() + obj.getAsJsonPrimitive("h").getAsDouble() / 2;
} else {
if (locked) {
locked = false;
RenderSystem.recordRenderCall(()->{
InputConstants.updateRawMouseInput(
minecraft.getWindow().getWindow(),
Minecraft.getInstance().options.rawMouseInput().get()
);
GLFW.glfwSetInputMode(Minecraft.getInstance().getWindow().getWindow(), 208897, GLFW.GLFW_CURSOR_NORMAL);
GLFW.glfwSetCursor(Minecraft.getInstance().getWindow().getWindow(), CefCursorType.fromId(pad.activeCursor).glfwId);
});
}
}
}
protected void pollElement() {
if (pad.view instanceof WDBrowser browser) {
JsonObject object = browser.pointerLockElement().getObj();
if (object != null) updateCrd(object);
}
}
}

View File

@ -7,17 +7,11 @@ package net.montoyo.wd.client.gui;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.montoyo.mcef.api.API;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.client.gui.controls.Button;
import net.montoyo.wd.client.gui.controls.TextField;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessageRedstoneCtrl;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.Vector3i;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector3i;
import javax.annotation.Nullable;
@ -53,18 +47,18 @@ public class GuiRedstoneCtrl extends WDScreen {
tfFallingEdge.setText(fallingEdgeURL);
}
@GuiSubscribe
public void onClick(Button.ClickEvent ev) {
if(ev.getSource() == btnOk) {
API mcef = ((ClientProxy) WebDisplays.PROXY).getMCEF();
String rising = mcef.punycode(Util.addProtocol(tfRisingEdge.getText()));
String falling = mcef.punycode(Util.addProtocol(tfFallingEdge.getText()));
Messages.INSTANCE.sendToServer(new SMessageRedstoneCtrl(dimension, pos, rising, falling));
}
minecraft.setScreen(null);
}
// @GuiSubscribe
// public void onClick(Button.ClickEvent ev) {
// if(ev.getSource() == btnOk) {
// API mcef = ((ClientProxy) WebDisplays.PROXY).getMCEF();
//
// String rising = mcef.punycode(Util.addProtocol(tfRisingEdge.getText()));
// String falling = mcef.punycode(Util.addProtocol(tfFallingEdge.getText()));
// WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageRedstoneCtrl(pos, rising, falling));
// }
//
// minecraft.setScreen(null);
// }
@Override
public boolean isForBlock(BlockPos bp, BlockSide side) {

View File

@ -15,11 +15,17 @@ import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.gui.controls.*;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.item.WDItem;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessageScreenCtrl;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl;
import net.montoyo.wd.utilities.*;
import net.montoyo.wd.utilities.math.Vector2i;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.data.Rotation;
import net.montoyo.wd.utilities.serialization.NameUUIDPair;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nullable;
import java.util.ArrayList;
@ -29,7 +35,7 @@ import java.util.UUID;
public class GuiScreenConfig extends WDScreen {
//Screen data
private final TileEntityScreen tes;
private final ScreenBlockEntity tes;
private final BlockSide side;
private NameUUIDPair owner;
private NameUUIDPair[] friends;
@ -118,7 +124,7 @@ public class GuiScreenConfig extends WDScreen {
private CheckBox[] friendBoxes;
private CheckBox[] otherBoxes;
public GuiScreenConfig(Component component, TileEntityScreen tes, BlockSide side, NameUUIDPair[] friends, int fr, int or) {
public GuiScreenConfig(Component component, ScreenBlockEntity tes, BlockSide side, NameUUIDPair[] friends, int fr, int or) {
super(component);
this.tes = tes;
this.side = side;
@ -133,20 +139,20 @@ public class GuiScreenConfig extends WDScreen {
loadFrom(new ResourceLocation("webdisplays", "gui/screencfg.json"));
friendBoxes = new CheckBox[] { boxFResolution, boxFUpgrades, boxFOthers, boxFFriends, boxFClick, boxFSetUrl };
boxFResolution.setUserdata(ScreenRights.CHANGE_RESOLUTION);
boxFResolution.setUserdata(ScreenRights.MODIFY_SCREEN);
boxFUpgrades.setUserdata(ScreenRights.MANAGE_UPGRADES);
boxFOthers.setUserdata(ScreenRights.MANAGE_OTHER_RIGHTS);
boxFFriends.setUserdata(ScreenRights.MANAGE_FRIEND_LIST);
boxFClick.setUserdata(ScreenRights.CLICK);
boxFClick.setUserdata(ScreenRights.INTERACT);
boxFSetUrl.setUserdata(ScreenRights.CHANGE_URL);
otherBoxes = new CheckBox[] { boxOResolution, boxOUpgrades, boxOClick, boxOSetUrl };
boxOResolution.setUserdata(ScreenRights.CHANGE_RESOLUTION);
boxOResolution.setUserdata(ScreenRights.MODIFY_SCREEN);
boxOUpgrades.setUserdata(ScreenRights.MANAGE_UPGRADES);
boxOClick.setUserdata(ScreenRights.CLICK);
boxOClick.setUserdata(ScreenRights.INTERACT);
boxOSetUrl.setUserdata(ScreenRights.CHANGE_URL);
TileEntityScreen.Screen scr = tes.getScreen(side);
ScreenData scr = tes.getScreen(side);
if(scr != null) {
owner = scr.owner;
rotation = scr.rotation;
@ -190,7 +196,7 @@ public class GuiScreenConfig extends WDScreen {
}
private void clickSetRes() {
TileEntityScreen.Screen scr = tes.getScreen(side);
ScreenData scr = tes.getScreen(side);
if(scr == null)
return; //WHATDAFUQ?
@ -201,7 +207,7 @@ public class GuiScreenConfig extends WDScreen {
throw new NumberFormatException(); //I'm lazy
if(x != scr.resolution.x || y != scr.resolution.y)
Messages.INSTANCE.sendToServer(SMessageScreenCtrl.vec2(tes, side, SMessageScreenCtrl.CTRL_SET_RESOLUTION, new Vector2i(x, y)));
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.resolution(tes, side, new Vector2i(x, y)));
} catch(NumberFormatException ex) {
//Roll back
tfResX.setText("" + scr.resolution.x);
@ -219,7 +225,7 @@ public class GuiScreenConfig extends WDScreen {
clickSetRes();
else if(ev.getSource() == btnChangeRot) {
Rotation[] rots = Rotation.values();
Messages.INSTANCE.sendToServer(new SMessageScreenCtrl(tes, side, rots[(rotation.ordinal() + 1) % rots.length]));
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageScreenCtrl(tes, side, rots[(rotation.ordinal() + 1) % rots.length]));
}
}
@ -282,7 +288,7 @@ public class GuiScreenConfig extends WDScreen {
@GuiSubscribe
public void onRemovePlayer(List.EntryClick ev) {
if(ev.getSource() == lstFriends)
Messages.INSTANCE.sendToServer(new SMessageScreenCtrl(tes, side, (NameUUIDPair) ev.getUserdata(), true));
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageScreenCtrl(tes, side, (NameUUIDPair) ev.getUserdata(), true));
}
@GuiSubscribe
@ -312,13 +318,12 @@ public class GuiScreenConfig extends WDScreen {
} catch(NumberFormatException ex) {
cbLockRatio.setChecked(false);
}
} else if(ev.getSource() == cbAutoVolume)
Messages.INSTANCE.sendToServer(SMessageScreenCtrl.autoVol(tes, side, ev.isChecked()));
} else if(ev.getSource() == cbAutoVolume) WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.autoVol(tes, side, ev.isChecked()));
}
@GuiSubscribe
public void onRemoveUpgrade(UpgradeGroup.ClickEvent ev) {
Messages.INSTANCE.sendToServer(new SMessageScreenCtrl(tes, side, ev.getMouseOverStack()));
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageScreenCtrl(tes, side, ev.getMouseOverStack()));
}
public boolean isFriendCheckbox(CheckBox cb) {
@ -339,7 +344,7 @@ public class GuiScreenConfig extends WDScreen {
if(adding) {
if(!hasFriend(pairs[0]))
Messages.INSTANCE.sendToServer(new SMessageScreenCtrl(tes, side, pairs[0], false));
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageScreenCtrl(tes, side, pairs[0], false));
tfFriend.setDisabled(false);
tfFriend.clear();
@ -428,7 +433,7 @@ public class GuiScreenConfig extends WDScreen {
@Override
protected void sync() {
Messages.INSTANCE.sendToServer(new SMessageScreenCtrl(tes, side, friendRights, otherRights));
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageScreenCtrl(tes, side, friendRights, otherRights));
Log.info("Sent sync packet");
}
@ -456,7 +461,7 @@ public class GuiScreenConfig extends WDScreen {
flag = (myRights & ScreenRights.MANAGE_OTHER_RIGHTS) == 0;
grpOthers.setDisabled(flag);
flag = (myRights & ScreenRights.CHANGE_RESOLUTION) == 0;
flag = (myRights & ScreenRights.MODIFY_SCREEN) == 0;
tfResX.setDisabled(flag);
tfResY.setDisabled(flag);
btnChangeRot.setDisabled(flag);
@ -503,5 +508,16 @@ public class GuiScreenConfig extends WDScreen {
return "Screen_Configurator";
}
// reason: allow closing the UI, lol
@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
if (keyCode == GLFW.GLFW_KEY_ESCAPE) {
Minecraft.getInstance().setScreen(null);
return true;
}
return super.keyPressed(keyCode, scanCode, modifiers);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -7,125 +7,147 @@ package net.montoyo.wd.client.gui;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.common.Mod;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.client.gui.controls.Button;
import net.montoyo.wd.client.gui.controls.Event;
import net.montoyo.wd.client.gui.controls.TextField;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.init.ItemInit;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessagePadCtrl;
import net.montoyo.wd.net.server.SMessageScreenCtrl;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.Vector3i;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.item.ItemMinePad2;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.server_bound.C2SMessageMinepadUrl;
import net.montoyo.wd.net.server_bound.C2SMessageScreenCtrl;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.serialization.Util;
import net.montoyo.wd.utilities.math.Vector3i;
import java.io.IOException;
import java.util.Map;
import java.util.UUID;
@Mod.EventBusSubscriber
@Mod.EventBusSubscriber(Dist.CLIENT)
public class GuiSetURL2 extends WDScreen {
//Screen data
private TileEntityScreen tileEntity;
private BlockSide screenSide;
private Vector3i remoteLocation;
//Pad data
private final boolean isPad;
//Common
private final String screenURL;
@FillControl
private TextField tfURL;
@FillControl
private Button btnShutDown;
@FillControl
private Button btnCancel;
@FillControl
private Button btnOk;
public GuiSetURL2(TileEntityScreen tes, BlockSide side, String url, Vector3i rl) {
super(Component.nullToEmpty(null));
tileEntity = tes;
screenSide = side;
remoteLocation = rl;
isPad = false;
screenURL = url;
}
public GuiSetURL2(String url) {
super(Component.nullToEmpty(null));
isPad = true;
screenURL = url;
}
@Override
public void init() {
super.init();
loadFrom(new ResourceLocation("webdisplays", "gui/seturl.json"));
tfURL.setText(screenURL);
}
@Override
protected void addLoadCustomVariables(Map<String, Double> vars) {
vars.put("isPad", isPad ? 1.0 : 0.0);
}
@GuiSubscribe
public void onButtonClicked(Button.ClickEvent ev) {
if(ev.getSource() == btnCancel)
minecraft.setScreen(null);
else if(ev.getSource() == btnOk)
validate(tfURL.getText());
else if(ev.getSource() == btnShutDown) {
if(isPad)
Messages.INSTANCE.sendToServer(new SMessagePadCtrl(""));
minecraft.setScreen(null);
}
}
@GuiSubscribe
public void onEnterPressed(TextField.EnterPressedEvent ev) {
validate(ev.getText());
}
private void validate(String url) {
if(!url.isEmpty()) {
url = Util.addProtocol(url);
url = ((ClientProxy) WebDisplays.PROXY).getMCEF().punycode(url);
if(isPad) {
Messages.INSTANCE.sendToServer(new SMessagePadCtrl(url));
ItemStack held = minecraft.player.getItemInHand(InteractionHand.MAIN_HAND);
if(held.getItem().equals(ItemInit.itemMinePad.get()) && held.getTag() != null && held.getTag().contains("PadID")) {
ClientProxy.PadData pd = ((ClientProxy) WebDisplays.PROXY).getPadByID(held.getTag().getInt("PadID"));
if(pd != null && pd.view != null)
pd.view.loadURL(WebDisplays.applyBlacklist(url));
}
} else
Messages.INSTANCE.sendToServer(SMessageScreenCtrl.setURL(tileEntity, screenSide, url, remoteLocation));
}
minecraft.setScreen(null);
}
@Override
public boolean isForBlock(BlockPos bp, BlockSide side) {
return (remoteLocation != null && remoteLocation.equalsBlockPos(bp)) || (bp.equals(tileEntity.getBlockPos()) && side == screenSide);
}
//Screen data
private ScreenBlockEntity tileEntity;
private BlockSide screenSide;
private Vector3i remoteLocation;
//Pad data
private ItemStack stack;
private final boolean isPad;
//Common
private final String screenURL;
@FillControl
private TextField tfURL;
@FillControl
private Button btnShutDown;
@FillControl
private Button btnCancel;
@FillControl
private Button btnOk;
public GuiSetURL2(ScreenBlockEntity tes, BlockSide side, String url, Vector3i rl) {
super(Component.nullToEmpty(null));
tileEntity = tes;
screenSide = side;
remoteLocation = rl;
isPad = false;
screenURL = url;
}
public GuiSetURL2(ItemStack is, String url) {
super(Component.nullToEmpty(null));
isPad = true;
stack = is;
screenURL = url;
}
@Override
public void init() {
super.init();
loadFrom(new ResourceLocation("webdisplays", "gui/seturl.json"));
tfURL.setText(screenURL);
}
@Override
protected void addLoadCustomVariables(Map<String, Double> vars) {
vars.put("isPad", isPad ? 1.0 : 0.0);
}
protected UUID getUUID() {
if (stack == null || !(stack.getItem() instanceof ItemMinePad2))
throw new RuntimeException("Get UUID is being called for a non-minepad UI");
if (!stack.hasTag() || !stack.getTag().contains("PadID"))
stack.getOrCreateTag().putUUID("PadID", UUID.randomUUID());
return stack.getTag().getUUID("PadID");
}
@GuiSubscribe
public void onButtonClicked(Button.ClickEvent ev) {
if (ev.getSource() == btnCancel)
minecraft.setScreen(null);
else if (ev.getSource() == btnOk)
validate(tfURL.getText());
else if (ev.getSource() == btnShutDown) {
if (isPad) {
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageMinepadUrl(
getUUID(),
""
));
stack.getTag().remove("PadID");
}
minecraft.setScreen(null);
}
}
@GuiSubscribe
public void onEnterPressed(TextField.EnterPressedEvent ev) {
validate(ev.getText());
}
private void validate(String url) {
if (!url.isEmpty()) {
try {
ScreenBlockEntity.url(url);
} catch (IOException e) {
throw new RuntimeException(e);
}
url = Util.addProtocol(url);
// url = ((ClientProxy) WebDisplays.PROXY).getMCEF().punycode(url);
if (isPad) {
UUID uuid = getUUID();
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageMinepadUrl(uuid, url));
stack.getTag().putString("PadURL", url);
ClientProxy.PadData pd = ((ClientProxy) WebDisplays.PROXY).getPadByID(uuid);
if (pd != null && pd.view != null) {
pd.view.loadURL(WebDisplays.applyBlacklist(url));
}
} else
WDNetworkRegistry.INSTANCE.sendToServer(C2SMessageScreenCtrl.setURL(tileEntity, screenSide, url, remoteLocation));
}
minecraft.setScreen(null);
}
@Override
public boolean isForBlock(BlockPos bp, BlockSide side) {
return (remoteLocation != null && remoteLocation.equalsBlockPos(bp)) || (bp.equals(tileEntity.getBlockPos()) && side == screenSide);
}
}

View File

@ -7,6 +7,7 @@ package net.montoyo.wd.client.gui;
import com.mojang.blaze3d.platform.Lighting;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.resources.language.I18n;
@ -77,15 +78,16 @@ public class RenderRecipe extends Screen {
Log.info("Loaded %d recipes", recipes.size());
nextRecipe();
}
@Override
public void render(PoseStack poseStack, int mouseX, int mouseY, float partialTick) {
renderBackground(poseStack);
public void render(GuiGraphics context, int mouseX, int mouseY, float partialTick) {
// renderBackground(poseStack);
renderBackground(context);
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.setShaderTexture(0, CRAFTING_TABLE_GUI_TEXTURES);
blit(poseStack, x, y, 0, 0, SIZE_X, SIZE_Y);
font.draw(poseStack, I18n.get("container.crafting"), x + 28, y + 6, 0x404040);
// context.blit(x, y, 0, 0, SIZE_X, SIZE_Y);
// font.draw(poseStack, I18n.get("container.crafting"), x + 28, y + 6, 0x404040);
Lighting.setupForFlatItems();
// RenderSystem.disableLighting(); //TODO: Need this?
@ -98,15 +100,15 @@ public class RenderRecipe extends Screen {
int x = this.x + 30 + sx * 18;
int y = this.y + 17 + sy * 18;
renderItem.renderAndDecorateItem(minecraft.player, is, x, y, 0);
renderItem.renderGuiItemDecorations(font, is, x, y, null);
context.renderItem(is, x, y);
context.renderItemDecorations(font, is, x, y);
}
}
}
if(recipeResult != null) {
renderItem.renderAndDecorateItem(minecraft.player, recipeResult, x + 124, y + 35, 0);
renderItem.renderGuiItemDecorations(font, recipeResult, x + 124, y + 35, null);
context.renderItem(recipeResult, x, y);
context.renderItemDecorations(font, recipeResult, x, y);
}
// GlStateManager.enableLighting();
@ -127,7 +129,7 @@ public class RenderRecipe extends Screen {
}
}
recipeResult = recipe.getResultItem();
// recipeResult = recipe.getResultItem();
}
private void nextRecipe() {

View File

@ -7,12 +7,12 @@ package net.montoyo.wd.client.gui;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.network.chat.Style;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.FormattedCharSequence;
@ -23,10 +23,13 @@ import net.montoyo.wd.client.gui.controls.Event;
import net.montoyo.wd.client.gui.loading.FillControl;
import net.montoyo.wd.client.gui.loading.GuiLoader;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import net.montoyo.wd.net.Messages;
import net.montoyo.wd.net.server.SMessageACQuery;
import net.montoyo.wd.net.WDNetworkRegistry;
import net.montoyo.wd.net.server_bound.C2SMessageACQuery;
import net.montoyo.wd.utilities.*;
import org.lwjgl.glfw.GLFW;
import net.montoyo.wd.utilities.data.Bounds;
import net.montoyo.wd.utilities.math.Vector3i;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.serialization.NameUUIDPair;
import javax.annotation.Nullable;
import java.io.IOException;
@ -113,17 +116,19 @@ public abstract class WDScreen extends Screen {
}
@Override
public void render(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void render(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
if(defaultBackground)
renderBackground(poseStack);
RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
for(Control ctrl: controls)
ctrl.draw(poseStack, mouseX, mouseY, ptt);
for(Control ctrl: postDrawList)
ctrl.postDraw(poseStack, mouseX, mouseY, ptt);
}
@Override
public boolean charTyped(char codePoint, int modifiers) {
boolean typed = false;
@ -138,8 +143,21 @@ public abstract class WDScreen extends Screen {
public boolean mouseClicked(double mouseX, double mouseY, int button) {
boolean clicked = false;
for(Control ctrl: controls)
clicked = clicked || ctrl.mouseClicked(mouseX, mouseY, button);
Control clickedEl = null;
for(Control ctrl: controls) {
clicked = ctrl.mouseClicked(mouseX, mouseY, button);
if (clicked) {
clickedEl = ctrl;
break; // don't assume the compiler will optimize stuff
}
}
if (clicked) {
for (Control control : controls) {
if (control != clickedEl)
control.unfocus();
}
}
return clicked;
}
@ -151,7 +169,7 @@ public abstract class WDScreen extends Screen {
for(Control ctrl: controls)
mouseReleased = mouseReleased || ctrl.mouseReleased(mouseX, mouseY, button);
return mouseReleased || mouseClicked(mouseX, mouseY, button);
return mouseReleased;
}
@Override
@ -167,7 +185,7 @@ public abstract class WDScreen extends Screen {
@Override
protected void init() {
CURRENT_SCREEN = this;
minecraft.keyboardHandler.setSendRepeatsToGui(true);
// minecraft.keyboardHandler.setSendRepeatsToGui(true);
}
@Override
@ -180,7 +198,7 @@ public abstract class WDScreen extends Screen {
for(Control ctrl : controls)
ctrl.destroy();
Minecraft.getInstance().keyboardHandler.setSendRepeatsToGui(false);
// Minecraft.getInstance().keyboardHandler.setSendRepeatsToGui(false);
CURRENT_SCREEN = null;
}
@ -209,9 +227,9 @@ public abstract class WDScreen extends Screen {
boolean down = false;
for (Control ctrl : controls)
down = down || ctrl.keyDown(keyCode);
down = down || ctrl.keyDown(keyCode, scanCode, modifiers);
if (Minecraft.getInstance().screen instanceof GuiKeyboard) {
if (this instanceof GuiKeyboard) {
return down;
} else {
return new GuiServer(new Vector3i(), new NameUUIDPair()).keyPressed(keyCode, scanCode, modifiers);
@ -223,7 +241,7 @@ public abstract class WDScreen extends Screen {
boolean up = false;
for(Control ctrl : controls)
up = up || ctrl.keyUp(keyCode);
up = up || ctrl.keyUp(keyCode, scanCode, modifiers);
return up || super.keyReleased(keyCode, scanCode, modifiers);
}
@ -264,7 +282,9 @@ public abstract class WDScreen extends Screen {
}
public void loadFrom(ResourceLocation resLoc) {
JsonObject root = GuiLoader.getJson(resLoc);
try {
JsonObject root = GuiLoader.getJson(resLoc);
if(root == null)
throw new RuntimeException("Could not load GUI file " + resLoc.toString());
@ -312,6 +332,10 @@ public abstract class WDScreen extends Screen {
if(root.has("center") && root.get("center").getAsBoolean())
centerControls();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
@ -324,7 +348,7 @@ public abstract class WDScreen extends Screen {
}
protected void requestAutocomplete(String beginning, boolean matchExact) {
Messages.INSTANCE.sendToServer(new SMessageACQuery(beginning, matchExact));
WDNetworkRegistry.INSTANCE.sendToServer(new C2SMessageACQuery(beginning, matchExact));
}
public void onAutocompleteResult(NameUUIDPair pairs[]) {
@ -356,12 +380,12 @@ public abstract class WDScreen extends Screen {
}
}
public void drawItemStackTooltip(PoseStack poseStack, ItemStack is, int x, int y) {
renderTooltip(poseStack, is, x, y); //Since it's protected...
public void drawItemStackTooltip(GuiGraphics poseStack, ItemStack is, int x, int y) {
poseStack.renderTooltip(Minecraft.getInstance().font, is, x, y); //Since it's protected...
}
public void drawTooltip(PoseStack poseStack, List<String> lines, int x, int y) {
renderTooltip(poseStack, lines.stream().map(a -> FormattedCharSequence.forward(a, Style.EMPTY)).collect(Collectors.toList()), x, y, font); //This is also protected...
public void drawTooltip(GuiGraphics poseStack, List<String> lines, int x, int y) {
poseStack.renderTooltip(Minecraft.getInstance().font, lines.stream().map(a -> FormattedCharSequence.forward(a, Style.EMPTY)).collect(Collectors.toList()), x, y); //This is also protected...
}
public void requirePostDraw(Control ctrl) {

View File

@ -0,0 +1,273 @@
package net.montoyo.wd.client.gui.camera;
import net.minecraft.client.Minecraft;
import net.minecraft.commands.arguments.EntityAnchorArgument;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec2;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.event.ViewportEvent;
import net.minecraftforge.event.TickEvent;
import net.montoyo.wd.client.gui.GuiKeyboard;
import net.montoyo.wd.config.ClientConfig;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.utilities.browser.WDBrowser;
import net.montoyo.wd.utilities.browser.handlers.js.queries.ElementCenterQuery;
import net.montoyo.wd.utilities.data.BlockSide;
public class KeyboardCamera {
private static ScreenBlockEntity tes;
private static BlockSide side;
private static double oxCrd = -1;
private static double xCrd = -1;
private static double nxCrd = -1;
private static double oyCrd = -1;
private static double yCrd = -1;
private static double nyCrd = -1;
private static double nextX = -1;
private static double nextY = -1;
private static double focalX = -1;
private static double focalY = -1;
private static final boolean[] mouseStatus = new boolean[2];
protected static Vec2 pxToHit(ScreenData scr, Vec2 dst) {
float cx, cy;
if (scr.rotation.isVertical) {
cy = dst.x;
cx = dst.y;
} else {
cx = dst.x;
cy = dst.y;
}
cx /= (float) scr.resolution.x;
cy /= (float) scr.resolution.y;
switch (scr.rotation) {
case ROT_270:
cx = 1.0f - cx;
break;
case ROT_180:
cx = 1.0f - cx;
cy = 1.0f - cy;
break;
case ROT_90:
cy = 1.0f - cy;
break;
}
if (side != BlockSide.BOTTOM)
cy = 1.0f - cy;
float swInverse = (((float) scr.size.x) - 4.f / 16.f);
float shInverse = (((float) scr.size.y) - 4.f / 16.f);
cx *= swInverse;
cy *= shInverse;
if (side.right.x > 0 || side.right.z > 0)
cx += 1.f;
if (side == BlockSide.TOP || side == BlockSide.BOTTOM)
cy -= 1.f;
return new Vec2(cx + (2 / 16f), cy + (2 / 16f));
}
protected static void updateCrd(ElementCenterQuery lock) {
ScreenData scr = tes.getScreen(side);
if (scr != null) {
Vec2 c;
if (!mouseStatus[0] && !mouseStatus[1]) {
if (lock.hasFocused()) {
if (ClientConfig.Input.keyboardCamera) {
nextX = lock.getX();
nextY = lock.getY();
c = pxToHit(scr, new Vec2((float) nextX, (float) nextY));
} else c = new Vec2(scr.size.x / 2f, scr.size.y / 2f);
} else c = new Vec2(scr.size.x / 2f, scr.size.y / 2f);
// } else c = new Vec2((float) focalX, (float) focalY);
} else return;
focalX = c.x;
focalY = c.y;
nextX = c.x;
nextY = c.y;
if (nextX < 0) nextX = 0;
else if (nextX > scr.size.x) nextX = scr.size.x;
if (nextY < 0) nextY = 0;
else if (nextY > scr.size.y) nextY = scr.size.y;
float scl = Math.max(scr.size.x, scr.size.y);
double mx = Minecraft.getInstance().mouseHandler.xpos();
mx /= Minecraft.getInstance().getWindow().getWidth();
double my = Minecraft.getInstance().mouseHandler.ypos();
my /= Minecraft.getInstance().getWindow().getHeight();
Vec2 v2 = new Vec2((float) mx, (float) my).add(-0.5f);
nextX += v2.x * scl;
nextY -= v2.y * scl;
}
}
protected static void pollElement() {
ScreenBlockEntity teTmp = tes;
BlockSide sdTmp = side;
// async nonsense can occur here
if (teTmp == null || sdTmp == null) return;
ScreenData scr = teTmp.getScreen(sdTmp);
if (scr != null) {
if (scr.browser instanceof WDBrowser wdBrowser) {
wdBrowser.focusedElement().dispatch(scr.browser);
updateCrd(((WDBrowser) scr.browser).focusedElement());
}
}
}
public static float[] getAngle(Entity e, double pct) {
BlockEntity tes = KeyboardCamera.tes;
BlockSide side = KeyboardCamera.side;
if (tes == null) return new float[]{Float.NaN, 0};
if (side == null) return new float[]{Float.NaN, 0};
double coxCrd = Mth.lerp(0.5 * pct, oxCrd, xCrd);
double coyCrd = Mth.lerp(0.5 * pct, oyCrd, yCrd);
double focalX = tes.getBlockPos().getX() +
side.right.x * (coxCrd - 1) + side.up.x * coyCrd + Math.abs(side.forward.x) * 0.5;
double focalY = tes.getBlockPos().getY() +
side.right.y * (coxCrd - 1) + side.up.y * coyCrd + Math.abs(side.forward.y) * 0.5;
double focalZ = tes.getBlockPos().getZ() +
side.right.z * (coxCrd - 1) + side.up.z * coyCrd + Math.abs(side.forward.z) * 0.5;
focalX += side.forward.x * 0.5f;
focalY += side.forward.y * 0.5f;
focalZ += side.forward.z * 0.5f;
float[] angle = lookAt(
e, EntityAnchorArgument.Anchor.EYES,
new Vec3(focalX, focalY, focalZ)
);
return angle;
}
public static void setMouse(int side, boolean pressed) {
mouseStatus[side] = pressed;
}
public static void updateCamera(ViewportEvent.ComputeCameraAngles event) {
if (tes == null) {
xCrd = -1;
yCrd = -1;
return; // nothing to do
}
if (xCrd == -1) return;
if (yCrd == -1) return;
float[] angle = getAngle(event.getCamera().getEntity(), event.getPartialTick());
if (Float.isNaN(angle[0])) return;
// float xRot = event.getYaw(); // left right
// float yRot = event.getPitch(); // up down
// TODO: smooth in/out
event.setYaw(angle[1]);
event.setPitch(angle[0]);
}
public static void focus(ScreenBlockEntity screen, BlockSide side) {
KeyboardCamera.tes = screen;
KeyboardCamera.side = side;
}
public static float[] lookAt(Entity entity, EntityAnchorArgument.Anchor pAnchor, Vec3 pTarget) {
Vec3 vec3 = pAnchor.apply(entity);
double d0 = pTarget.x - vec3.x;
double d1 = pTarget.y - vec3.y;
double d2 = pTarget.z - vec3.z;
double d3 = Math.sqrt(d0 * d0 + d2 * d2);
float xr = (Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * (double) (180F / (float) Math.PI)))));
float yr = (Mth.wrapDegrees((float) (Mth.atan2(d2, d0) * (double) (180F / (float) Math.PI)) - 90.0F));
return new float[]{xr, yr};
}
protected static int delay = 8;
public static void gameTick(TickEvent.ClientTickEvent event) {
if (mouseStatus[0] || mouseStatus[1]) {
oxCrd = Mth.lerp(0.5, oxCrd, xCrd);
oyCrd = Mth.lerp(0.5, oyCrd, yCrd);
return;
}
if (event.phase.equals(TickEvent.Phase.END)) {
if (side == null) {
delay = 1;
oxCrd = -1;
oyCrd = -1;
xCrd = -1;
yCrd = -1;
nxCrd = -1;
nyCrd = -1;
return;
}
if (!(Minecraft.getInstance().screen instanceof GuiKeyboard)) {
tes = null;
side = null;
return;
}
pollElement();
double anxx = nextX;
double anxy = nextY;
if (
anxx == -1 || anxy == -1 ||
nxCrd == -1 || nyCrd == -1 ||
oxCrd == -1 || oyCrd == -1 ||
xCrd == -1 || yCrd == -1
) {
ScreenData data = tes.getScreen(side);
if (data == null)
return;
anxx = data.size.x / 2.0;
anxy = data.size.y / 2.0;
if (nxCrd == -1) {
oxCrd = xCrd = anxx;
oyCrd = yCrd = anxy;
}
}
nxCrd = anxx;
nyCrd = anxy;
oxCrd = Mth.lerp(0.5, oxCrd, xCrd);
xCrd = Mth.lerp(0.15, xCrd, nxCrd);
oyCrd = Mth.lerp(0.5, oyCrd, yCrd);
yCrd = Mth.lerp(0.15, yCrd, nyCrd);
}
}
}

View File

@ -5,10 +5,16 @@
package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentContents;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.Style;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.lwjgl.glfw.GLFW;
import java.util.function.Supplier;
public class Button extends Control {
protected final net.minecraft.client.gui.components.Button btn;
@ -31,17 +37,23 @@ public class Button extends Control {
}
}
public Button() {
btn = new net.minecraft.client.gui.components.Button(0,0, 0, 0, Component.nullToEmpty(null), a -> {});
btn = net.minecraft.client.gui.components.Button.builder(Component.nullToEmpty(""), a -> {})
.bounds(0, 0, 0, 0)
.build();
}
public Button(String text, int x, int y, int width) {
btn = new net.minecraft.client.gui.components.Button(x, y, width, 20, Component.nullToEmpty(text), a -> {});
btn = net.minecraft.client.gui.components.Button.builder(Component.nullToEmpty(text), a -> {})
.bounds(x, y, width, 20)
.build();
}
public Button(String text, int x, int y) {
btn = new net.minecraft.client.gui.components.Button(0, 0, x, y, Component.nullToEmpty(text), a -> {});
btn = net.minecraft.client.gui.components.Button.builder(Component.nullToEmpty(text), a -> {})
.bounds(0, 0, x, y)
.build();
}
@Override
@ -71,7 +83,8 @@ public class Button extends Control {
}
@Override
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
btn.setFGColor(16777215);
btn.render(poseStack, mouseX, mouseY, ptt);
}
@ -103,18 +116,17 @@ public class Button extends Control {
@Override
public void setPos(int x, int y) {
btn.x = x;
btn.y = y;
btn.setPosition(x, y);
}
@Override
public int getX() {
return btn.x;
return btn.getX();
}
@Override
public int getY() {
return btn.y;
return btn.getY();
}
public net.minecraft.client.gui.components.Button getMcButton() {
@ -158,7 +170,7 @@ public class Button extends Control {
}
@Override
public boolean keyUp(int key) {
public boolean keyUp(int key, int scanCode, int modifiers) {
if(key == GLFW.GLFW_KEY_LEFT_SHIFT || key == GLFW.GLFW_KEY_RIGHT_SHIFT) {
shiftDown = false;
btn.setFGColor(originalColor);
@ -170,7 +182,7 @@ public class Button extends Control {
}
@Override
public boolean keyDown(int key) {
public boolean keyDown(int key, int scanCode, int modifiers) {
if(key == GLFW.GLFW_KEY_LEFT_SHIFT || key == GLFW.GLFW_KEY_RIGHT_SHIFT) {
shiftDown = true;
btn.setFGColor(shiftColor);
@ -204,11 +216,13 @@ public class Button extends Control {
@Override
public void load(JsonOWrapper json) {
super.load(json);
btn.x = json.getInt("x", 0);
btn.y = json.getInt("y", 0);
btn.setPosition(
json.getInt("x", 0),
json.getInt("y", 0)
);
btn.setWidth(json.getInt("width", 200));
btn.setHeight(json.getInt("height", 20));
btn.setMessage(Component.nullToEmpty(tr(json.getString("label", btn.getMessage().getContents()))));
btn.setMessage(Component.nullToEmpty(tr(json.getString("label", btn.getMessage().getContents().toString()))));
btn.active = json.getBool("active", btn.active);
btn.visible = json.getBool("visible", btn.visible);

View File

@ -7,17 +7,14 @@ package net.montoyo.wd.client.gui.controls;
import com.google.common.collect.Lists;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents;
import net.minecraftforge.event.world.ChunkDataEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class CheckBox extends BasicControl {
private static final ResourceLocation texUnchecked = new ResourceLocation("webdisplays", "textures/gui/checkbox.png");
@ -72,29 +69,28 @@ public class CheckBox extends BasicControl {
checked = !checked;
mc.getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
parent.actionPerformed(new CheckedEvent(this));
return true;
}
return true;
}
return false;
}
@Override
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
if(visible) {
// GlStateManager.disableAlpha();
poseStack.pushPose();
RenderSystem.setShaderTexture(2, checked ? texChecked : texUnchecked);
RenderSystem.bindTexture(2);
poseStack.pose().pushPose();
RenderSystem.enableBlend();
fillTexturedRect(poseStack, x, y, WIDTH, HEIGHT, 0.0, 0.0, 1.0, 1.0);
poseStack.blit(
checked ? texChecked : texUnchecked, x, y, 0, 0, 0, WIDTH, HEIGHT, WIDTH, HEIGHT
);
RenderSystem.disableBlend();
RenderSystem.bindTexture(-1);
poseStack.popPose();
poseStack.pose().popPose();
boolean inside = (!disabled && mouseX >= x && mouseX <= x + WIDTH + 2 + labelW && mouseY >= y && mouseY < y + HEIGHT);
font.draw(poseStack, label, x + WIDTH + 2, y + 4, inside ? 0xFF0080FF : COLOR_WHITE);
poseStack.drawString(Minecraft.getInstance().font, label, x + WIDTH + 2, y + 4, inside ? 0xFF0080FF : COLOR_WHITE, false);
}
}
@ -140,7 +136,7 @@ public class CheckBox extends BasicControl {
}
@Override
public void postDraw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void postDraw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
if(tooltip != null && !disabled && mouseX >= x && mouseX <= x + WIDTH + 2 + labelW && mouseY >= y && mouseY < y + HEIGHT)
parent.drawTooltip(poseStack, tooltip, mouseX, mouseY);
}

View File

@ -5,10 +5,10 @@
package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics;
import net.montoyo.wd.client.gui.loading.GuiLoader;
import net.montoyo.wd.client.gui.loading.JsonAWrapper;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.lwjgl.opengl.GL11;
import java.util.ArrayList;
@ -36,24 +36,24 @@ public abstract class Container extends BasicControl {
}
@Override
public boolean keyUp(int key) {
public boolean keyUp(int key, int scanCode, int modifiers) {
boolean up = false;
if(!disabled) {
for(Control ctrl : childs)
up = up || ctrl.keyUp(key);
up = up || ctrl.keyUp(key, scanCode, modifiers);
}
return up;
}
@Override
public boolean keyDown(int key) {
public boolean keyDown(int key, int scanCode, int modifiers) {
boolean down = false;
if(!disabled) {
for(Control ctrl : childs)
down = down || ctrl.keyDown(key);
down = down || ctrl.keyDown(key, scanCode, modifiers);
}
return down;
@ -67,8 +67,10 @@ public abstract class Container extends BasicControl {
mouseX -= x + paddingX;
mouseY -= y + paddingY;
for(Control ctrl : childs)
clicked = clicked || ctrl.mouseClicked(mouseX, mouseY, mouseButton);
for(Control ctrl : childs) {
clicked = ctrl.mouseClicked(mouseX, mouseY, mouseButton);
if (clicked) break; // don't assume compiler optimizations
}
}
return clicked;
@ -136,13 +138,13 @@ public abstract class Container extends BasicControl {
}
@Override
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
if(visible) {
mouseX -= x + paddingX;
mouseY -= y + paddingY;
poseStack.pushPose();
poseStack.translate(x + paddingX, y + paddingY, 0.0);
poseStack.pose().pushPose();
poseStack.pose().translate(x + paddingX, y + paddingY, 0.0);
if(disabled) {
for(Control ctrl : childs)
@ -152,7 +154,7 @@ public abstract class Container extends BasicControl {
ctrl.draw(poseStack, mouseX, mouseY, ptt);
}
poseStack.popPose();
poseStack.pose().popPose();
}
}
@ -187,4 +189,10 @@ public abstract class Container extends BasicControl {
return null;
}
@Override
public void unfocus() {
for (Control control : childs) {
control.unfocus();
}
}
}

View File

@ -8,20 +8,26 @@ import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import com.mojang.math.Matrix4f;
import net.minecraft.client.KeyboardHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.resources.language.I18n;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.montoyo.wd.client.gui.WDScreen;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import net.montoyo.wd.utilities.Bounds;
import org.lwjgl.glfw.GLFW;
import net.montoyo.wd.utilities.data.Bounds;
import org.joml.Matrix4f;
import static org.lwjgl.opengl.GL11.GL_TEXTURE_2D;
import static org.lwjgl.opengl.GL11.glEnable;
import java.util.Arrays;
import static com.mojang.math.Axis.XP;
@OnlyIn(Dist.CLIENT)
public abstract class Control {
public static final int COLOR_BLACK = 0xFF000000;
@ -61,11 +67,11 @@ public abstract class Control {
return false;
}
public boolean keyUp(int key) {
public boolean keyUp(int key, int scanCode, int modifiers) {
return false;
}
public boolean keyDown(int key) {
public boolean keyDown(int key, int scanCode, int modifiers) {
return false;
}
@ -73,6 +79,9 @@ public abstract class Control {
return false;
}
public void unfocus() {
}
public boolean mouseReleased(double mouseX, double mouseY, int state) {
return false;
}
@ -89,10 +98,10 @@ public abstract class Control {
return false;
}
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
}
public void postDraw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void postDraw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
}
public void destroy() {
@ -108,7 +117,7 @@ public abstract class Control {
public abstract int getHeight();
public abstract void setPos(int x, int y);
public void fillRect(int x, double y, int w, int h, int color) {
public void fillRect(MultiBufferSource.BufferSource source, int x, double y, int w, int h, int color) {
double x1 = (double) x;
double y1 = (double) y;
double x2 = (double) (x + w);
@ -118,34 +127,38 @@ public abstract class Control {
int g = (color >> 8 ) & 0xFF;
int b = color & 0xFF;
RenderSystem.setShaderColor(((float) r) / 255.f, ((float) g) / 255.f, ((float) b) / 255.f, ((float) a) / 255.f);
RenderSystem.disableTexture();
float[] sdrCol = Arrays.copyOf(RenderSystem.getShaderColor(), 4);
RenderSystem.setShaderColor(1, 1, 1, 1f);
// RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
vBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
vBuffer.vertex(x1, y2, 0.0).endVertex();
vBuffer.vertex(x2, y2, 0.0).endVertex();
vBuffer.vertex(x2, y1, 0.0).endVertex();
vBuffer.vertex(x1, y1, 0.0).endVertex();
tessellator.end();
VertexConsumer consumer = source.getBuffer(RenderType.gui());
consumer.vertex(x1, y2, 0.0).color(r, g, b, a).endVertex();
consumer.vertex(x2, y2, 0.0).color(r, g, b, a).endVertex();
consumer.vertex(x2, y1, 0.0).color(r, g, b, a).endVertex();
consumer.vertex(x1, y1, 0.0).color(r, g, b, a).endVertex();
RenderSystem.setShaderColor(sdrCol[0], sdrCol[1], sdrCol[2], sdrCol[3]);
RenderSystem.disableBlend();
RenderSystem.enableTexture();glEnable(GL_TEXTURE_2D);
// RenderSystem.enableTexture();
}
public void fillTexturedRect(PoseStack poseStack, int x, int y, int w, int h, double u1, double v1, double u2, double v2) {
double x1 = (double) x;
double y1 = (double) y;
double x2 = (double) (x + w);
double y2 = (double) (y + h);
float x1 = x;
float y1 = y;
float x2 = (x + w);
float y2 = (y + h);
vBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
vBuffer.vertex(x1, y2, 0.0).uv((float) u1, (float) v2).color(255, 255, 255, 255).endVertex();
vBuffer.vertex(x2, y2, 0.0).uv((float) u2, (float) v2).color(255, 255, 255, 255).endVertex();
vBuffer.vertex(x2, y1, 0.0).uv((float) u2, (float) v1).color(255, 255, 255, 255).endVertex();
vBuffer.vertex(x1, y1, 0.0).uv((float) u1, (float) v1).color(255, 255, 255, 255).endVertex();
tessellator.end();
RenderSystem.setShader(GameRenderer::getPositionColorTexShader);
Matrix4f p = poseStack.last().pose();
vBuffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX);
vBuffer.vertex(p, x1, y2, 0.0f).color(255, 255, 255, 255).uv((float) u1, (float) v2).endVertex();
vBuffer.vertex(p, x2, y2, 0.0f).color(255, 255, 255, 255).uv((float) u2, (float) v2).endVertex();
vBuffer.vertex(p, x2, y1, 0.0f).color(255, 255, 255, 255).uv((float) u2, (float) v1).endVertex();
vBuffer.vertex(p, x1, y1, 0.0f).color(255, 255, 255, 255).uv((float) u1, (float) v1).endVertex();
BufferUploader.drawWithShader(vBuffer.end());
}
public static void blend(boolean enable) {
@ -163,11 +176,11 @@ public abstract class Control {
RenderSystem.setShaderTexture(0, resLoc);
}
public void drawBorder(PoseStack poseStack, int x, int y, int w, int h, int color) {
public void drawBorder(GuiGraphics poseStack, int x, int y, int w, int h, int color) {
drawBorder(poseStack, x, y, w, h, color, 1.0);
}
public void drawBorder(PoseStack poseStack, int x, int y, int w, int h, int color, double sz) {
public void drawBorder(GuiGraphics poseStack, int x, int y, int w, int h, int color, double sz) {
double x1 = (double) x;
double y1 = (double) y;
double x2 = (double) (x + w);
@ -177,8 +190,9 @@ public abstract class Control {
int g = (color >> 8 ) & 0xFF;
int b = color & 0xFF;
float[] sdrCol = Arrays.copyOf(RenderSystem.getShaderColor(), 4);
RenderSystem.setShaderColor(((float) r) / 255.f, ((float) g) / 255.f, ((float) b) / 255.f, ((float) a) / 255.f);
RenderSystem.enableTexture();
// RenderSystem.enableTexture();
RenderSystem.enableBlend();
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
@ -208,36 +222,46 @@ public abstract class Control {
vBuffer.vertex(x2 - sz, y1, 0.0).endVertex();
tessellator.end();
RenderSystem.setShaderColor(sdrCol[0], sdrCol[1], sdrCol[2], sdrCol[3]);
RenderSystem.disableBlend();
RenderSystem.enableTexture();
// RenderSystem.enableTexture();
}
public PoseStack beginFramebuffer(RenderTarget fbo, float vpW, float vpH) {
public GuiGraphics beginFramebuffer(RenderTarget fbo, float vpW, float vpH) {
GuiGraphics tmpGraphics = new GuiGraphics(Minecraft.getInstance(), Minecraft.getInstance().renderBuffers().bufferSource());
fbo.bindWrite(true);
RenderSystem.backupProjectionMatrix();
RenderSystem.setProjectionMatrix(Matrix4f.orthographic(0.0f, vpW, vpH, 0.0f, -1.0f,1.0f));
RenderSystem.setProjectionMatrix(new Matrix4f().ortho(0.0f, vpW, vpH, 0.0f, -1.0f,1.0f), VertexSorting.ORTHOGRAPHIC_Z);
PoseStack poseStack = RenderSystem.getModelViewStack();
tmpGraphics.pose().last().pose().set(RenderSystem.getModelViewStack().last().pose());
tmpGraphics.pose().last().normal().set(RenderSystem.getModelViewStack().last().normal());
PoseStack poseStack = tmpGraphics.pose();
poseStack.pushPose();
poseStack.setIdentity();
// poseStack.mulPose(Vector3f.XP.rotationDegrees(180.0f));
poseStack.mulPose(XP.rotationDegrees(180.0f));
RenderSystem.getModelViewStack().pushPose();
RenderSystem.getModelViewStack().last().pose().set(poseStack.last().pose());
RenderSystem.getModelViewStack().last().normal().set(poseStack.last().normal());
RenderSystem.applyModelViewMatrix();
if(!fbo.useDepth)
RenderSystem.disableDepthTest();
return poseStack;
return tmpGraphics;
}
public void endFramebuffer(PoseStack poseStack, RenderTarget fbo) {
public void endFramebuffer(GuiGraphics poseStack, RenderTarget fbo) {
if(!fbo.useDepth)
RenderSystem.enableDepthTest();
RenderSystem.colorMask(true, true, true, true);
RenderSystem.restoreProjectionMatrix();
poseStack.popPose();
poseStack.pose().popPose();
RenderSystem.getModelViewStack().popPose();
RenderSystem.applyModelViewMatrix();
fbo.unbindWrite();
mc.getMainRenderTarget().bindWrite(true);

View File

@ -7,12 +7,13 @@ package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import net.montoyo.wd.utilities.Bounds;
import net.montoyo.wd.utilities.data.Bounds;
import static org.lwjgl.opengl.GL11.*;
import java.util.Arrays;
public class ControlGroup extends Container {
@ -94,22 +95,23 @@ public class ControlGroup extends Container {
}
@Override
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
super.draw(poseStack, mouseX, mouseY, ptt);
if(visible) {
poseStack.pushPose();
poseStack.pose().pushPose();
float[] sdrCol = Arrays.copyOf(RenderSystem.getShaderColor(), 4);
RenderSystem.setShaderColor(0.5f, 0.5f, 0.5f, 1.f);
RenderSystem.disableTexture();
// RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA);
double x1 = (double) x;
double y1 = (double) y;
double x2 = (double) (x + width);
double y2 = (double) (y + height);
double x1 = x;
double y1 = y;
double x2 = (x + width);
double y2 = (y + height);
double bp = 4.0;
double lw = (double) labelW;
double lw = labelW;
x1 += bp;
y1 += bp;
@ -158,12 +160,14 @@ public class ControlGroup extends Container {
vBuffer.vertex(x2 - 1.0, y1, 0.0).endVertex();
tessellator.end();
RenderSystem.setShaderColor(sdrCol[0], sdrCol[1], sdrCol[2], sdrCol[3]);
RenderSystem.disableBlend();
RenderSystem.enableTexture();
poseStack.popPose();
// RenderSystem.enableTexture();
poseStack.pose().popPose();
if(labelW != 0)
font.drawShadow(poseStack, label, x + 10 + ((int) bp), y, labelColor, labelShadowed);
poseStack.drawString(Minecraft.getInstance().font, label, x + 10 + ((int) bp), y, labelColor, labelShadowed);
}
}
@ -176,6 +180,13 @@ public class ControlGroup extends Container {
height = bounds.getHeight() + paddingY * 2;
}
@Override
public void unfocus() {
for (Control control : childs) {
control.unfocus();
}
}
@Override
public void load(JsonOWrapper json) {
super.load(json);

View File

@ -6,8 +6,10 @@ package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.resources.ResourceLocation;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
public class Icon extends BasicControl {
@ -44,17 +46,17 @@ public class Icon extends BasicControl {
}
@Override
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
if(texture != null) {
poseStack.pushPose();
RenderSystem.enableTexture();
poseStack.pose().pushPose();
// RenderSystem.enableTexture();
RenderSystem.setShaderTexture(1, texture);
RenderSystem.bindTexture(1);
RenderSystem.enableBlend();
fillTexturedRect(poseStack, x, y, width, height, u1, v1, u2, v2);
fillTexturedRect(poseStack.pose(), x, y, width, height, u1, v1, u2, v2);
RenderSystem.disableBlend();
RenderSystem.bindTexture(-1);
poseStack.popPose();
poseStack.pose().popPose();
}
}

View File

@ -5,6 +5,8 @@
package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
public class Label extends BasicControl {
@ -72,9 +74,12 @@ public class Label extends BasicControl {
}
@Override
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
if(visible)
font.drawShadow(poseStack, label, x, y, color, shadowed);
poseStack.drawString(
Minecraft.getInstance().font,
label, x, y, color, shadowed
);
}
@Override

View File

@ -9,8 +9,13 @@ import com.mojang.blaze3d.pipeline.TextureTarget;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL20;
import java.util.ArrayList;
@ -96,19 +101,21 @@ public class List extends BasicControl {
if(fbo != null)
fbo.destroyBuffers();
fbo = new TextureTarget(parent.screen2DisplayX(width), parent.screen2DisplayY(height), false, Minecraft.ON_OSX);
fbo = new TextureTarget(parent.screen2DisplayX(width), parent.screen2DisplayY(height), true, Minecraft.ON_OSX);
fbo.setFilterMode(GL_NEAREST);
fbo.bindWrite(false);
fbo.bindWrite(true);
RenderSystem.clearColor(0.0f, 0.0f, 0.0f, 1.f); //Set alpha to 1
RenderSystem.clearDepth(GL_COLOR_BUFFER_BIT);
fbo.unbindWrite();
mc.getMainRenderTarget().bindWrite(true);
update = true;
}
private void renderToFBO() {
PoseStack poseStack = beginFramebuffer(fbo, width, height);
poseStack.pushPose();
fillRect(0, 0, width, height, COLOR_BLACK);
private void renderToFBO(MultiBufferSource.BufferSource source) {
GuiGraphics graphics = beginFramebuffer(fbo, width, height);
GL11.glColorMask(true, true, true, true);
RenderSystem.applyModelViewMatrix();
graphics.fill(0, 0, width, height, COLOR_BLACK);
RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
int offset = 4 - getYOffset();
@ -120,13 +127,13 @@ public class List extends BasicControl {
break;
int color = (i == selected) ? selColor : COLOR_WHITE;
font.draw(poseStack, content.get(i).text, 4, i * 12 + offset, color);
graphics.drawString(font, content.get(i).text, 4, i * 12 + offset, color);
}
}
drawBorder(poseStack, 0, 0, width, height, 0xFF808080);
endFramebuffer(poseStack, fbo);
poseStack.popPose();
graphics.renderOutline(0, 0, width, height, 0xFF808080);
graphics.flush();
endFramebuffer(graphics, fbo);
}
@Override
@ -241,13 +248,16 @@ public class List extends BasicControl {
if(isInScrollbar(mouseX, mouseY)) {
scrolling = true;
scrollGrab = mouseY - (y + 1 + scrollPos);
} else if(selected >= 0)
parent.actionPerformed(new EntryClick(this));
return true;
} else if(selected >= 0) {
System.out.println(parent.actionPerformed(new EntryClick(this)));
return true;
}
return true;
return false;
}
return true;
return false;
}
@Override
@ -308,19 +318,18 @@ public class List extends BasicControl {
}
@Override
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void draw(GuiGraphics graphics, int mouseX, int mouseY, float ptt) {
if(visible) {
if(update) {
renderToFBO();
renderToFBO(graphics.bufferSource());
update = false;
}
fbo.bindRead(); //TODO: Make sure is right
RenderSystem.setShaderTexture(0, fbo.getColorTextureId());
RenderSystem.setShaderColor(1.f, 1.f, 1.f, 1.f);
fillTexturedRect(poseStack, x, y, width, height, 0.0, 1.0, 1.0, 0.0);
fbo.unbindRead();
fillTexturedRect(graphics.pose(), x, y, width, height, 0.0, 1.0, 1.0, 0.0);
fillRect(x + width - 5, y + 1 + scrollPos, 4, scrollSize, (scrolling || isInScrollbar(mouseX, mouseY)) ? 0xFF202020 : 0xFF404040);
fillRect(graphics.bufferSource(), x + width - 5, y + 1 + scrollPos, 4, scrollSize, (scrolling || isInScrollbar(mouseX, mouseY)) ? 0xFF202020 : 0xFF404040);
}
}

View File

@ -5,13 +5,18 @@
package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.network.chat.Component;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import org.cef.browser.CefBrowserOsr;
import org.lwjgl.glfw.GLFW;
import java.util.ArrayList;
import static java.awt.event.KeyEvent.VK_ENTER;
import static org.lwjgl.glfw.GLFW.*;
public class TextField extends Control {
public static class EnterPressedEvent extends Event<TextField> {
@ -94,40 +99,48 @@ public class TextField extends Control {
public TextField() {
field = new EditBox(font, 1, 1, 198, 20, Component.nullToEmpty(""));
setFocused(false);
}
public TextField(int x, int y, int width, int height) {
field = new EditBox(font, x + 1, y + 1, width - 2, height - 2, Component.nullToEmpty(""));
setFocused(false);
}
public TextField(int x, int y, int width, int height, String text) {
field = new EditBox(font, x + 1, y + 1, width - 2, height - 2, Component.nullToEmpty(""));
field.setValue(text);
setFocused(false);
}
// TODO: make this public static in CefBrowserOSR
private long mapScanCode(int key, char c) {
if (key == GLFW_KEY_LEFT_CONTROL || key == GLFW_KEY_RIGHT_CONTROL) return 29;
return switch (key) {
case GLFW_KEY_DELETE -> 83;
case GLFW_KEY_LEFT -> 75;
case GLFW_KEY_DOWN -> 80;
case GLFW_KEY_UP -> 72;
case GLFW_KEY_RIGHT -> 77;
case GLFW_KEY_PAGE_DOWN -> 81;
case GLFW_KEY_PAGE_UP -> 73;
case GLFW_KEY_END -> 79;
case GLFW_KEY_HOME -> 71;
case VK_ENTER, GLFW_KEY_ENTER, GLFW_KEY_KP_ENTER -> 28;
default -> GLFW.glfwGetKeyScancode(key);
};
}
@Override
public boolean keyDown(int key) {
if(key == GLFW.GLFW_KEY_BACKSPACE) {
String old;
if(enabled && field.isFocused())
old = field.getValue();
else
old = null;
if(field.getValue().length() > 0)
field.setValue(field.getValue().substring(0, field.getValue().length() - 1));
if(enabled && field.isFocused() && !field.getValue().equals(old)) {
for(TextChangeListener tcl : listeners)
tcl.onTextChange(this, old, field.getValue());
parent.actionPerformed(new TextChangedEvent(this, old));
}
}
return false;
public boolean keyDown(int key, int scanCode, int modifiers) {
return field.keyPressed(key, scanCode, modifiers);
}
@Override
public boolean keyUp(int key, int scanCode, int modifiers) {
return field.keyReleased(key, scanCode, modifiers);
}
@Override
public boolean keyTyped(int keyCode, int modifier) {
if(keyCode == GLFW.GLFW_KEY_ENTER || keyCode == GLFW.GLFW_KEY_KP_ENTER)
@ -141,26 +154,56 @@ public class TextField extends Control {
else
old = null;
field.charTyped((char) keyCode, modifier);
if(enabled && field.isFocused() && !field.getValue().equals(old)) {
for(TextChangeListener tcl : listeners)
tcl.onTextChange(this, old, field.getValue());
parent.actionPerformed(new TextChangedEvent(this, old));
}
return field.charTyped((char) keyCode, modifier);
}
return false;
}
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
return field.mouseClicked(mouseX, mouseY, mouseButton);
if (field.mouseClicked(mouseX, mouseY, mouseButton)) {
setFocused(true);
return true;
}
return false;
}
@Override
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void unfocus() {
setFocused(false);
}
@Override
public boolean mouseReleased(double mouseX, double mouseY, int state) {
return field.mouseReleased(mouseX, mouseY, state);
}
@Override
public boolean mouseClickMove(double mouseX, double mouseY, int button, double dragX, double dragY) {
return field.mouseClicked(mouseX, mouseY, 0);
}
@Override
public boolean mouseMove(double mouseX, double mouseY) {
field.mouseMoved(mouseX, mouseY);
return true;
}
@Override
public boolean mouseScroll(double mouseX, double mouseY, double amount) {
return field.mouseScrolled(mouseX, mouseY, amount);
}
@Override
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
field.render(poseStack, mouseX, mouseY, ptt);
}
@ -211,23 +254,26 @@ public class TextField extends Control {
@Override
public void setPos(int x, int y) {
field.x = x + 1;
field.y = y + 1;
field.setPosition(
x + 1,
y + 1
);
}
@Override
public int getX() {
return field.x - 1;
return field.getX() - 1;
}
@Override
public int getY() {
return field.y - 1;
return field.getY() - 1;
}
public void setDisabled(boolean en) {
enabled = !en;
field.setFocus(enabled);
if (!en)
field.setFocused(false);
}
public boolean isDisabled() {
@ -235,12 +281,11 @@ public class TextField extends Control {
}
public void enable() {
field.setFocus(true);
enabled = true;
}
public void disable() {
field.setFocus(false);
field.setFocused(false);
enabled = false;
}
@ -261,7 +306,7 @@ public class TextField extends Control {
}
public void setFocused(boolean val) {
field.setFocus(val);
field.setFocused(val);
}
public boolean hasFocus() {
@ -269,15 +314,7 @@ public class TextField extends Control {
}
public void focus() {
field.setFocus(true);
}
public void setMaxLength(int len) {
field.setMaxLength(len);
}
public int getMaxLength() {
return field.getMaxLength(); //TODO: access transformer
field.setFocused(true);
}
public void setTextColor(int color) {
@ -314,8 +351,10 @@ public class TextField extends Control {
@Override
public void load(JsonOWrapper json) {
super.load(json);
field.x = json.getInt("x", 0) + 1;
field.y = json.getInt("y", 0) + 1;
field.setPosition(
json.getInt("x", 0) + 1,
json.getInt("y", 0) + 1
);
field.setWidth(json.getInt("width", 200) - 2);
field.setHeight(json.getInt("height", 22) - 2);
field.setValue(tr(json.getString("text", "")));
@ -328,7 +367,7 @@ public class TextField extends Control {
field.setTextColor(textColor);
field.setTextColorUneditable(disabledColor);
field.setFocus(enabled);
setFocused(false);
}
}

View File

@ -6,9 +6,10 @@ package net.montoyo.wd.client.gui.controls;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.eventbus.api.IEventBus;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import java.util.ArrayList;
@ -27,23 +28,23 @@ public class UpgradeGroup extends BasicControl {
}
@Override
public void draw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void draw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
if(upgrades != null) {
int x = this.x;
for(ItemStack is: upgrades) {
if(is == overStack && !disabled)
fillRect(x, y, 16, 16, 0x80FF0000);
fillRect(poseStack.bufferSource(), x, y, 16, 16, 0x80FF0000);
renderItem.renderAndDecorateItem(mc.player, is, x, y, 0);
renderItem.renderAndDecorateItem(is, font.lineHeight, x, y); //TODO is lineHeight right?
poseStack.renderItem(is, x, y);
poseStack.renderItemDecorations(font, is, x, y);
x += 18;
}
}
}
@Override
public void postDraw(PoseStack poseStack, int mouseX, int mouseY, float ptt) {
public void postDraw(GuiGraphics poseStack, int mouseX, int mouseY, float ptt) {
if(overStack != null)
parent.drawItemStackTooltip(poseStack, overStack, mouseX, mouseY);
}
@ -103,9 +104,15 @@ public class UpgradeGroup extends BasicControl {
@Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
if(mouseButton == 0) {
clickStack = overStack;
return true;
// don't process the click if it's not inbounds, lol
if (
mouseX >= x && mouseX <= x + width &&
mouseY >= y && mouseX <= y + height
) {
clickStack = overStack;
return true;
}
}
return false;

View File

@ -6,7 +6,7 @@ package net.montoyo.wd.client.gui.controls;
import net.minecraft.network.chat.Component;
import net.montoyo.wd.client.gui.loading.JsonOWrapper;
import net.montoyo.wd.utilities.Util;
import net.montoyo.wd.utilities.serialization.Util;
import net.montoyo.wd.utilities.VideoType;
import java.net.MalformedURLException;

View File

@ -62,24 +62,15 @@ public class GuiLoader {
return ret;
}
public static JsonObject getJson(ResourceLocation resLoc) {
public static JsonObject getJson(ResourceLocation resLoc) throws IOException {
JsonObject ret = RESOURCES.get(resLoc);
if(ret == null) {
Resource resource;
try {
resource = Minecraft.getInstance().getResourceManager().getResource(resLoc);
} catch(IOException e) {
Log.errorEx("Couldn't load JSON UI from file", e);
throw new RuntimeException(e);
}
resource = Minecraft.getInstance().getResourceManager().getResource(resLoc).get();
JsonParser parser = new JsonParser();
ret = parser.parse(new InputStreamReader(resource.getInputStream())).getAsJsonObject();
try {
resource.close();
} catch(IOException e) {}
ret = parser.parse(new InputStreamReader(resource.open())).getAsJsonObject();
RESOURCES.put(resLoc, ret);
}

View File

@ -9,7 +9,17 @@ import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.item.ItemStack;
public interface IItemRenderer {
void render(PoseStack stack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight);
/**
* @param pose the pose stack
* @param stack the item stack
* @param handSideSign TODO:
* @param swingProgress TODO:
* @param equipProgress TODO:
* @param multiBufferSource the buffer source
* @param packedLight packed light
* @return whether or not to cancel vanilla rendering
*/
boolean render(PoseStack pose, ItemStack stack, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight);
}

View File

@ -1,15 +0,0 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.client.renderers;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
public interface IModelBaker extends IDynamicBakedModel{
void loadTextures(TextureAtlas texMap);
}

View File

@ -4,112 +4,127 @@
package net.montoyo.wd.client.renderers;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import com.mojang.math.Vector3f;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.BufferUtils;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.registry.ItemRegistry;
import net.montoyo.wd.item.ItemLaserPointer;
import org.joml.Matrix4f;
import java.nio.FloatBuffer;
import static org.lwjgl.opengl.GL11.*;
import static com.mojang.math.Axis.*;
@OnlyIn(Dist.CLIENT)
public final class LaserPointerRenderer implements IItemRenderer {
private static final float PI = (float) Math.PI;
private final Tesselator t = Tesselator.getInstance();
private final BufferBuilder bb = t.getBuilder();
private final VertexBuffer vb = new VertexBuffer();
private final FloatBuffer matrix1 = BufferUtils.createFloatBuffer(16);
private final FloatBuffer renderBuffer = BufferUtils.createFloatBuffer(8);
public boolean isOn = false;
public LaserPointerRenderer() {
for(int i = 0; i < 8; i++)
renderBuffer.put(0.0f);
renderBuffer.position(0);
}
@Override
public void render(PoseStack poseStack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight) {
//This whole method is a fucking hack
float sqrtSwingProg = (float) Math.sqrt(swingProgress);
float sinSqrtSwingProg1 = (float) Math.sin(sqrtSwingProg * PI);
RenderSystem.disableCull();
RenderSystem.disableTexture();
poseStack.pushPose();
//Laser pointer
poseStack.pushPose();
poseStack.translate(handSideSign * -0.4f * sinSqrtSwingProg1, (float) (0.2f * Math.sin(sqrtSwingProg * PI * 2.0f)), (float) (-0.2f * Math.sin(swingProgress * PI)));
poseStack.translate(handSideSign * 0.56f, -0.52f - equipProgress * 0.6f, -0.72f);
poseStack.mulPose(Vector3f.YP.rotationDegrees((float) (handSideSign * (45.0f - Math.sin(swingProgress * swingProgress * PI) * 20.0f))));
poseStack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f));
poseStack.mulPose(Vector3f.XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f));
poseStack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * -30.0f));
poseStack.translate(0.0f, 0.2f, 0.0f);
poseStack.mulPose(Vector3f.XP.rotationDegrees(10.0f));
poseStack.scale(1.0f / 16.0f, 1.0f / 16.0f, 1.0f / 16.0f);
RenderSystem.setShaderColor(0.5f, 0.5f, 0.5f, 1.0f);
bb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
bb.vertex(0.0, 0.0, 0.0).endVertex();
bb.vertex(1.0, 0.0, 0.0).endVertex();
bb.vertex(1.0, 0.0, 4.0).endVertex();
bb.vertex(0.0, 0.0, 4.0).endVertex();
bb.vertex(0.0, 0.0, 0.0).endVertex();
bb.vertex(0.0, -1.0, 0.0).endVertex();
bb.vertex(0.0, -1.0, 4.0).endVertex();
bb.vertex(0.0, 0.0, 4.0).endVertex();
bb.vertex(1.0, 0.0, 0.0).endVertex();
bb.vertex(1.0, -1.0, 0.0).endVertex();
bb.vertex(1.0, -1.0, 4.0).endVertex();
bb.vertex(1.0, 0.0, 4.0).endVertex();
bb.vertex(0.0, -1.0, 4.0).endVertex();
bb.vertex(1.0, -1.0, 4.0).endVertex();
bb.vertex(1.0, 0.0, 4.0).endVertex();
bb.vertex(0.0, 0.0, 4.0).endVertex();
t.end();
if(isOn) {
poseStack.translate(0.5f, -0.5f, 0.0f);
matrix1.position(0);
RenderSystem.getModelViewMatrix(); //Hax to get that damn position
}
poseStack.popPose();
if(isOn) {
//Actual laser
poseStack.pushPose();
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.DST_ALPHA);
RenderSystem.setShaderColor(1.0f, 0.0f, 0.0f, 0.5f);
RenderSystem.lineWidth(3.0f);
matrix1.position(12);
renderBuffer.put(matrix1.get());
renderBuffer.put(matrix1.get());
renderBuffer.put(matrix1.get() - 0.02f); //I know this is stupid, but it's the only thing that worked...
renderBuffer.put(matrix1.get());
renderBuffer.position(0);
RenderSystem.drawElements(GL_LINES, 0, GL_UNSIGNED_INT);
poseStack.popPose();
}
RenderSystem.enableTexture(); //Fix for shitty minecraft fire
RenderSystem.enableCull();
}
private final Tesselator t = Tesselator.getInstance();
private final BufferBuilder bb = t.getBuilder();
public LaserPointerRenderer() {
}
public static boolean isOn() {
if (Minecraft.getInstance().screen != null) return false;
Minecraft mc = Minecraft.getInstance();
return mc.player != null && mc.level != null &&
(
ClientProxy.mouseOn ||
ItemLaserPointer.isOn()
) &&
mc.player.getItemInHand(InteractionHand.MAIN_HAND).getItem().equals(ItemRegistry.LASER_POINTER.get()) &&
(mc.hitResult == null || mc.hitResult.getType() == HitResult.Type.BLOCK || mc.hitResult.getType() == HitResult.Type.MISS);
}
@Override
public boolean render(PoseStack poseStack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight) {
RenderSystem.disableCull();
// RenderSystem.disableTexture();
RenderSystem.enableDepthTest();
RenderSystem.enableBlend();
float PI = (float) Math.PI;
float sqrtSwingProg = (float) Math.sqrt(swingProgress);
float sinSqrtSwingProg1 = (float) Math.sin(sqrtSwingProg * PI);
RenderSystem.setShader(GameRenderer::getPositionColorShader);
var matrix0 = poseStack.last().pose();
//Laser pointer
poseStack.pushPose();
poseStack.translate(handSideSign * -0.4f * sinSqrtSwingProg1, (float) (0.2f * Math.sin(sqrtSwingProg * PI * 2.0f)), (float) (-0.2f * Math.sin(swingProgress * PI)));
poseStack.translate(handSideSign * 0.56f, -0.52f - equipProgress * 0.6f, -0.72f);
poseStack.mulPose(YP.rotationDegrees((float) (handSideSign * (45.0f - Math.sin(swingProgress * swingProgress * PI) * 20.0f))));
poseStack.mulPose(ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f));
poseStack.mulPose(XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f));
poseStack.mulPose(YP.rotationDegrees(handSideSign * -30.0f));
poseStack.translate(0.0f, 0.2f, 0.0f);
poseStack.mulPose(XP.rotationDegrees(10.0f));
poseStack.scale(1.0f / 16.0f, 1.0f / 16.0f, 1.0f / 16.0f);
var matrix = poseStack.last().pose();
bb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
bb.vertex(matrix, 0.0f, 0.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, 0.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, 0.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, -1.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, -1.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, 0.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, -1.0f, 0.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, -1.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, -1.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, -1.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 1.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
bb.vertex(matrix, 0.0f, 0.0f, 4.0f).color(0.5f, 0.5f, 0.5f, 1.0f).endVertex();
if (isOn()) drawLineBetween(bb, matrix0, matrix, new Vec3(0.5f, -0.5f, 0.5f), new Vec3(-40.0f, 4000.5f, -100.0f));
t.end();
RenderSystem.disableBlend();
RenderSystem.disableDepthTest();
// RenderSystem.enableTexture(); //Fix for shitty minecraft fire
RenderSystem.enableCull();
poseStack.popPose();
return true;
}
private static void drawLineBetween(BufferBuilder bb, Matrix4f matrix0, Matrix4f matrix, Vec3 local, Vec3 target) {
//Calculate distance between points -> length of the line
float distance = (float) local.distanceTo(target) / 2;
float quarterWidth = 0.25f;
float biggerWidth = 10;
bb.vertex(matrix, 0.25f, -0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix, quarterWidth + 0.25f, -0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, biggerWidth - 6f, 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, -6f, 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix, 0.25f, -0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix, 0.25f, -quarterWidth - 0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, -6f, -biggerWidth + 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, -6f, 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix, quarterWidth + 0.25f, -0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix, quarterWidth + 0.25f, -quarterWidth - 0.25f, 0.5f).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, biggerWidth - 6f, -biggerWidth + 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
bb.vertex(matrix0, biggerWidth - 6f, 3f, -distance).color((float) 0.5, (float) 0.0, (float) 0.0, (float) 1.0).endVertex();
}
}

View File

@ -4,132 +4,161 @@
package net.montoyo.wd.client.renderers;
import com.cinemamod.mcef.MCEFBrowser;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f;
import com.mojang.math.Vector3f;
import com.mojang.blaze3d.vertex.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.config.ClientConfig;
import net.montoyo.wd.item.ItemMinePad2;
import static org.lwjgl.opengl.GL12.GL_RESCALE_NORMAL;
import static com.mojang.math.Axis.*;
@OnlyIn(Dist.CLIENT)
public final class MinePadRenderer implements IItemRenderer {
private static final float PI = (float) Math.PI;
private final Minecraft mc = Minecraft.getInstance();
private final ResourceLocation tex = new ResourceLocation("webdisplays", "textures/models/minepad.png");
// private final ModelMinePad model = new ModelMinePad();
private final ClientProxy clientProxy = (ClientProxy) WebDisplays.PROXY;
private float sinSqrtSwingProg1;
private float sinSqrtSwingProg2;
private float sinSwingProg1;
private float sinSwingProg2;
// public static void drawAxis() {
// glDisable(GL_TEXTURE_2D);
// glBegin(GL_LINES);
// glColor4f(1.f, 0.f, 0.f, 1.f); glVertex3d(0.0, 0.0, 0.0);
// glColor4f(1.f, 0.f, 0.f, 1.f); glVertex3d(5.0, 0.0, 0.0);
// glColor4f(0.f, 1.f, 0.f, 1.f); glVertex3d(0.0, 0.0, 0.0);
// glColor4f(0.f, 1.f, 0.f, 1.f); glVertex3d(0.0, 5.0, 0.0);
// glColor4f(0.f, 0.f, 1.f, 1.f); glVertex3d(0.0, 0.0, 0.0);
// glColor4f(0.f, 0.f, 1.f, 1.f); glVertex3d(0.0, 0.0, 5.0);
// glEnd();
// glEnable(GL_TEXTURE_2D);
// }
@Override
public final void render(PoseStack stack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight) {
//Pre-compute values
float sqrtSwingProg = (float) Math.sqrt(swingProgress);
sinSqrtSwingProg1 = (float) Math.sin(sqrtSwingProg * PI);
sinSqrtSwingProg2 = (float) Math.sin(sqrtSwingProg * PI * 2.0f);
sinSwingProg1 = (float) Math.sin(swingProgress * PI);
sinSwingProg2 = (float) Math.sin(swingProgress * swingProgress * PI);
RenderSystem.disableCull();
// glEnable(GL_RESCALE_NORMAL);
//Render arm
stack.pushPose();
renderArmFirstPerson(stack, multiBufferSource, packedLight, equipProgress, handSideSign);
stack.popPose();
//Prepare minePad transform
stack.pushPose();
stack.translate(handSideSign * -0.4f * sinSqrtSwingProg1, 0.2f * sinSqrtSwingProg2, -0.2f * sinSwingProg1);
stack.translate(handSideSign * 0.56f, -0.52f - equipProgress * 0.6f, -0.72f);
stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * (45.0f - sinSwingProg2 * 20.0f)));
stack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f));
stack.mulPose(Vector3f.XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f));
stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * -45.0f));
if(handSideSign >= 0.0f)
stack.translate(-1.065f, 0.0f, 0.0f);
else {
stack.translate(0.0f, 0.0f, -0.2f);
stack.mulPose(Vector3f.YP.rotationDegrees(20.0f));
stack.translate(-0.475f, -0.1f, 0.0f);
stack.mulPose(Vector3f.ZP.rotationDegrees(1.0f));
}
//Render model
stack.pushPose();
stack.mulPose(Vector3f.XP.rotationDegrees(-90.0f));
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
RenderSystem.setShaderTexture(0, tex);
// model.render(1.f / 16.f);
stack.popPose();
//Render web view
if(is.getTag() != null && is.getTag().contains("PadID")) {
ClientProxy.PadData pd = clientProxy.getPadByID(is.getTag().getInt("PadID"));
if(pd != null) {
stack.translate(0.063f, 0.28f, 0.001f);
RenderSystem.disableTexture();
pd.view.draw(stack,0.0, 0.0, 27.65 / 32.0 + 0.01, 14.0 / 32.0 + 0.002);
}
}
stack.popPose();
// glDisable(GL_RESCALE_NORMAL);
RenderSystem.enableCull();
}
private void renderArmFirstPerson(PoseStack stack, MultiBufferSource buffer, int combinedLight, float equipProgress, float handSideSign) {
float tx = -0.3f * sinSqrtSwingProg1;
float ty = 0.4f * sinSqrtSwingProg2;
float tz = -0.4f * sinSwingProg1;
stack.translate(handSideSign * (tx + 0.64000005f), ty - 0.6f - equipProgress * 0.6f, tz - 0.71999997f);
stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * 45.0f));
stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * 70.0f));
stack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * sinSwingProg2 * -20.0f));
stack.translate(-handSideSign, 3.6f, 3.5f);
stack.mulPose(Vector3f.ZP.rotationDegrees(handSideSign * 120.0f));
stack.mulPose(Vector3f.XP.rotationDegrees(200.0f));
stack.mulPose(Vector3f.YP.rotationDegrees(handSideSign * -135.0f));
stack.translate(handSideSign * 5.6f, 0.0f, 0.0f);
PlayerRenderer playerRenderer = (PlayerRenderer) mc.getEntityRenderDispatcher().getRenderer(mc.player);
RenderSystem.setShaderTexture(0, mc.player.getSkinTextureLocation());
if(handSideSign >= 0.0f)
playerRenderer.renderRightHand(stack, buffer, combinedLight, mc.player);
else
playerRenderer.renderLeftHand(stack, buffer, combinedLight, mc.player);
}
private static final float PI = (float) Math.PI;
private final Minecraft mc = Minecraft.getInstance();
private final ResourceLocation tex = new ResourceLocation("webdisplays", "textures/item/model/minepad.png");
private final ModelMinePad model = new ModelMinePad();
private final ClientProxy clientProxy = (ClientProxy) WebDisplays.PROXY;
private float sinSqrtSwingProg1;
private float sinSqrtSwingProg2;
private float sinSwingProg1;
private float sinSwingProg2;
public static boolean renderAtSide(float handSideSign) {
float relSide = handSideSign;
if (Minecraft.getInstance().player.getMainArm() == HumanoidArm.LEFT) relSide *= -1;
// by default, the player holds the device off to the side
// if they are crouching, they hold it infront of them
// however, if they are holding two at once, then it once again should just be held off to the side
boolean sideHold = Minecraft.getInstance().player.isShiftKeyDown() != ClientConfig.sidePad;
if (
(relSide < 0 && Minecraft.getInstance().player.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof ItemMinePad2) ||
(relSide > 0 && Minecraft.getInstance().player.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof ItemMinePad2)
) sideHold = true;
return sideHold;
}
@Override
public final boolean render(PoseStack stack, ItemStack is, float handSideSign, float swingProgress, float equipProgress, MultiBufferSource multiBufferSource, int packedLight) {
//Pre-compute values
float sqrtSwingProg = (float) Math.sqrt(swingProgress);
sinSqrtSwingProg1 = (float) Math.sin(sqrtSwingProg * PI);
sinSqrtSwingProg2 = (float) Math.sin(sqrtSwingProg * PI * 2.0f);
sinSwingProg1 = (float) Math.sin(swingProgress * PI);
sinSwingProg2 = (float) Math.sin(swingProgress * swingProgress * PI);
boolean sideHold = renderAtSide(handSideSign);
//Render arm
stack.pushPose();
renderArmFirstPerson(stack, multiBufferSource, packedLight, equipProgress, handSideSign);
stack.popPose();
// if (!sideHold && handSideSign == 1 && mc.player.getItemInHand(InteractionHand.OFF_HAND).isEmpty()) {
// stack.pushPose();
// renderArmFirstPerson(stack, multiBufferSource, packedLight, 0, -handSideSign);
// stack.popPose();
// }
//Prepare minePad transform
stack.pushPose();
stack.translate(handSideSign * -0.4f * sinSqrtSwingProg1, 0.2f * sinSqrtSwingProg2, -0.2f * sinSwingProg1);
stack.translate(handSideSign * 0.56f, -0.52f - equipProgress * 0.6f, -0.72f);
stack.mulPose(YP.rotationDegrees(handSideSign * (45.0f - sinSwingProg2 * 20.0f)));
stack.mulPose(ZP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * -20.0f));
stack.mulPose(XP.rotationDegrees(sinSqrtSwingProg1 * -80.0f));
stack.mulPose(YP.rotationDegrees(handSideSign * -45.0f));
if (sideHold) {
stack.translate(0.0f, 0.0f, -0.2f);
stack.mulPose(YP.rotationDegrees(20.0f * -handSideSign));
float total = 0.475f;
float off = -0.025f; // gotta love magic numbers
stack.translate(-(total - off) + (off * handSideSign), -0.1f, 0.0f);
stack.mulPose(ZP.rotationDegrees(1.0f));
} else if (handSideSign >= 0) // right hand
stack.translate(-1.065f, 0.0f, 0.0f);
else // left hand
stack.translate(0.065f, 0.0f, 0.0f);
//Render model
stack.translate(0.063f, 0.28f, 0.001f);
model.render(multiBufferSource, stack);
stack.translate(-0.063f, -0.28f, -0.001f);
// force draw so the browser can be drawn ontop of the model
multiBufferSource.getBuffer(RenderType.LINES);
if (is.getTag() != null && is.getTag().contains("PadID")) {
ClientProxy.PadData pd = clientProxy.getPadByID(is.getTag().getUUID("PadID"));
//Render web view
if (pd != null) {
double x1 = 0.0;
double y1 = 0.0;
double x2 = 27.65 / 32.0 + 0.01;
double y2 = 14.0 / 32.0 + 0.002;
stack.translate(0.063f, 0.28f, 0.001f);
// RenderSystem.setShaderTexture(0, tex);
RenderSystem.disableDepthTest();
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
RenderSystem.setShaderTexture(0, ((MCEFBrowser) pd.view).getRenderer().getTextureID());
Tesselator t = Tesselator.getInstance();
BufferBuilder buffer = t.getBuilder();
buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
buffer.vertex(stack.last().pose(), (float) x1, (float) y1, 0.0f).uv(0.0F, 1.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(stack.last().pose(), (float) x2, (float) y1, 0.0f).uv(1.0F, 1.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(stack.last().pose(), (float) x2, (float) y2, 0.0f).uv(1.0F, 0.0F).color(255, 255, 255, 255).endVertex();
buffer.vertex(stack.last().pose(), (float) x1, (float) y2, 0.0f).uv(0.0F, 0.0F).color(255, 255, 255, 255).endVertex();
t.end();
RenderSystem.enableDepthTest();
}
}
stack.popPose();
RenderSystem.enableCull();
return true;
}
private void renderArmFirstPerson(PoseStack stack, MultiBufferSource buffer, int combinedLight, float equipProgress, float handSideSign) {
float tx = -0.3f * sinSqrtSwingProg1;
float ty = 0.4f * sinSqrtSwingProg2;
float tz = -0.4f * sinSwingProg1;
stack.translate(handSideSign * (tx + 0.64000005f), ty - 0.6f - equipProgress * 0.6f, tz - 0.71999997f);
stack.mulPose(YP.rotationDegrees(handSideSign * 45.0f));
stack.mulPose(YP.rotationDegrees(handSideSign * sinSqrtSwingProg1 * 70.0f));
stack.mulPose(ZP.rotationDegrees(handSideSign * sinSwingProg2 * -20.0f));
stack.translate(-handSideSign, 3.6f, 3.5f);
stack.mulPose(ZP.rotationDegrees(handSideSign * 120.0f));
stack.mulPose(XP.rotationDegrees(200.0f));
stack.mulPose(YP.rotationDegrees(handSideSign * -135.0f));
stack.translate(handSideSign * 5.6f, 0.0f, 0.0f);
PlayerRenderer playerRenderer = (PlayerRenderer) mc.getEntityRenderDispatcher().getRenderer(mc.player);
RenderSystem.setShaderTexture(0, mc.player.getSkinTextureLocation());
if (handSideSign >= 0.0f)
playerRenderer.renderRightHand(stack, buffer, combinedLight, mc.player);
else
playerRenderer.renderLeftHand(stack, buffer, combinedLight, mc.player);
}
}

View File

@ -4,60 +4,70 @@
package net.montoyo.wd.client.renderers;
/*import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.model.Model;
import net.minecraft.client.model.geom.ModelPart;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
@OnlyIn(Dist.CLIENT)
public final class ModelMinePad extends Model {
public final class ModelMinePad {
public void render(MultiBufferSource buffers, PoseStack stack) {
// TODO: this needs completing
// TODO: I'd like this to be able to load a model from a JSON if possible
double x1 = 0.0;
double y1 = 0.0;
double x2 = 27.65 / 32.0 + 0.01;
double y2 = 14.0 / 32.0 + 0.002;
Matrix4f positionMatrix = stack.last().pose();
Tesselator t = Tesselator.getInstance();
BufferBuilder vb = t.getBuilder();
RenderSystem.setShader(GameRenderer::getPositionColorShader);
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
vb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
vb.vertex(positionMatrix, (float) x1, (float) y1, 0.0f).color(0, 0, 0, 255).endVertex();
vb.vertex(positionMatrix, (float) x2, (float) y1, 0.0f).color(0, 0, 0, 255).endVertex();
vb.vertex(positionMatrix, (float) x2, (float) y2, 0.0f).color(0, 0, 0, 255).endVertex();
vb.vertex(positionMatrix, (float) x1, (float) y2, 0.0f).color(0, 0, 0, 255).endVertex();
t.end();
int width = 32;
int height = 32;
float padding = 1f / 23;
float padding1 = 1f / 21;
float z = 0;
VertexConsumer consumer = buffers.getBuffer(RenderType.entityCutout(new ResourceLocation("webdisplays:textures/item/model/minepad_item.png")));
consumer.vertex(positionMatrix, (float) x1, (float) y1 - padding, z).color(255, 255, 255, 255).uv(1f / width, 12f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x2, (float) y1 - padding, z).color(255, 255, 255, 255).uv(19f / width, 12f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x2, (float) y2 + padding, z).color(255, 255, 255, 255).uv(19f / width, 0).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x1, (float) y2 + padding, z).color(255, 255, 255, 255).uv(1f / width, 0).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// fields
private final ModelPart base;
private final ModelPart left;
private final ModelPart right;
public ModelMinePad() {
super();
textureWidth = 64;
textureHeight = 32;
base = new ModelPart(this, 0, 0);
base.addBox(0F, 0F, 0F, 14, 1, 9);
base.setRotationPoint(1F, 0F, 3.5F);
base.setTextureSize(64, 32);
base.mirror = true;
clearRotation(base);
left = new ModelRenderer(this, 0, 10);
left.addBox(0F, 0F, 0F, 1, 1, 7);
left.setRotationPoint(0F, 0F, 4.5F);
left.setTextureSize(64, 32);
left.mirror = true;
clearRotation(left);
right = new ModelRenderer(this, 30, 10);
right.addBox(0F, 0F, 0F, 1, 1, 7);
right.setRotationPoint(15F, 0F, 4.5F);
right.setTextureSize(64, 32);
right.mirror = true;
clearRotation(right);
}
public final void render(float f5) {
base.render(f5);
left.render(f5);
right.render(f5);
}
private void clearRotation(ModelPart model) {
model.rotateAngleX = 0.0f;
model.rotateAngleY = 0.0f;
model.rotateAngleZ = 0.0f;
}
@Override
public void renderToBuffer(PoseStack poseStack, VertexConsumer buffer, int packedLight, int packedOverlay, float red, float green, float blue, float alpha) {
}
}*/
consumer.vertex(positionMatrix, (float) x1 - padding1, (float) y1, z).color(255, 255, 255, 255).uv(0f / width, 10f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x2 + padding1, (float) y1, z).color(255, 255, 255, 255).uv(20f / width, 10f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x2 + padding1, (float) y2, z).color(255, 255, 255, 255).uv(20f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
consumer.vertex(positionMatrix, (float) x1 - padding1, (float) y2, z).color(255, 255, 255, 255).uv(0f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x2, (float) y2 + padding, z - padding).color(255, 255, 255, 255).uv(0f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x2, (float) y2 + padding, z).color(255, 255, 255, 255).uv(1f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x2, (float) y1 - padding, z).color(255, 255, 255, 255).uv(1f / width, 2f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x2, (float) y1 - padding, z - padding).color(255, 255, 255, 255).uv(0f / width, 2f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
//
// consumer.vertex(positionMatrix, (float) x1, (float) y1 - padding, z - padding).color(255, 255, 255, 255).uv(0f / width, 2f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x1, (float) y1 - padding, z).color(255, 255, 255, 255).uv(1f / width, 2f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x1, (float) y2 + padding, z).color(255, 255, 255, 255).uv(1f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
// consumer.vertex(positionMatrix, (float) x1, (float) y2 + padding, z - padding).color(255, 255, 255, 255).uv(0f / width, 1f / height).overlayCoords(OverlayTexture.NO_OVERLAY).uv2(LightTexture.FULL_BRIGHT).normal(0.25f, 0.5f, 1).endVertex();
}
}

View File

@ -5,164 +5,232 @@
package net.montoyo.wd.client.renderers;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.ModelState;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.Material;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
import net.minecraftforge.client.model.data.IModelData;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Vector3f;
import net.montoyo.wd.utilities.Vector3i;
import net.minecraftforge.client.model.data.ModelData;
import net.minecraftforge.client.model.data.ModelProperty;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector3f;
import net.montoyo.wd.utilities.math.Vector3i;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.function.Function;
public class ScreenBaker implements IModelBaker {
private static final List<BakedQuad> noQuads = ImmutableList.of();
private final TextureAtlasSprite[] texs = new TextureAtlasSprite[16];
private final BlockSide[] blockSides = BlockSide.values();
private final Direction[] blockFacings = Direction.values();
private final ModelState modelState;
private final Function<net.minecraft.client.resources.model.Material, TextureAtlasSprite> spriteGetter;
private final ItemOverrides overrides;
private final ItemTransforms itemTransforms;
public ScreenBaker(ModelState modelState, Function<net.minecraft.client.resources.model.Material, TextureAtlasSprite> spriteGetter, ItemOverrides overrides, ItemTransforms itemTransforms) {
this.modelState = modelState;
this.spriteGetter = spriteGetter;
this.overrides = overrides;
this.itemTransforms = itemTransforms;
}
@Override
public void loadTextures(TextureAtlas texMap) {
for(int i = 0; i < texs.length; i++)
texs[i] = texMap.getSprite(new ResourceLocation("webdisplays", "blocks/screen" + i));
}
private void putVertex(int[] buf, int pos, Vector3f vpos, TextureAtlasSprite tex, Vector3f uv, Vector3i normal) {
buf[pos * 7 + 0] = Float.floatToRawIntBits(vpos.x);
buf[pos * 7 + 1] = Float.floatToRawIntBits(vpos.y);
buf[pos * 7 + 2] = Float.floatToRawIntBits(vpos.z);
buf[pos * 7 + 3] = 0xFFFFFFFF; //Color, let this white...
buf[pos * 7 + 4] = Float.floatToRawIntBits(tex.getU(uv.x));
buf[pos * 7 + 5] = Float.floatToRawIntBits(tex.getV(uv.y));
int nx = (normal.x * 127) & 0xFF;
int ny = (normal.y * 127) & 0xFF;
int nz = (normal.z * 127) & 0xFF;
buf[pos * 7 + 6] = nx | (ny << 8) | (nz << 16);
}
private Vector3f rotateVec(Vector3f vec, BlockSide side) {
switch(side) {
case BOTTOM: return new Vector3f(vec.x, 1.0f, 1.0f - vec.z);
case TOP: return new Vector3f(vec.x, 0.0f, vec.z);
case NORTH: return new Vector3f(vec.x, vec.z, 1.0f);
case SOUTH: return new Vector3f(vec.x, 1.0f - vec.z, 0.0f);
case WEST: return new Vector3f(1.f , vec.x, vec.z);
case EAST: return new Vector3f(0.0f, 1.0f - vec.x, vec.z);
}
throw new RuntimeException("Unknown block side " + side);
}
private Vector3f rotateTex(BlockSide side, float u, float v) {
switch(side) {
case BOTTOM: return new Vector3f(u, 16.f - v, 0.0f);
case TOP: return new Vector3f(u, v, 0.0f);
case NORTH: return new Vector3f(16.f - u, 16.f - v, 0.0f);
case SOUTH: return new Vector3f(u, v, 0.0f);
case WEST: return new Vector3f(v, 16.f - u, 0.0f);
case EAST: return new Vector3f(16.f - v, u, 0.0f);
}
throw new RuntimeException("Unknown block side " + side);
}
private BakedQuad bakeSide(BlockSide side, TextureAtlasSprite tex) {
int[] data = new int[7 * 4];
putVertex(data, 3, rotateVec(new Vector3f(0.0f, 0.0f, 0.0f), side), tex, rotateTex(side, 0.0f, 0.0f ), side.backward);
putVertex(data, 2, rotateVec(new Vector3f(0.0f, 0.0f, 1.0f), side), tex, rotateTex(side, 0.0f, 16.0f ), side.backward);
putVertex(data, 1, rotateVec(new Vector3f(1.0f, 0.0f, 1.0f), side), tex, rotateTex(side, 16.0f, 16.0f), side.backward);
putVertex(data, 0, rotateVec(new Vector3f(1.0f, 0.0f, 0.0f), side), tex, rotateTex(side, 16.0f, 0.0f ), side.backward);
return new BakedQuad(data, 0xFFFFFFFF, blockFacings[side.ordinal()], tex, true);
}
@NotNull
@Override
public List<BakedQuad> getQuads(@org.jetbrains.annotations.Nullable BlockState state, @org.jetbrains.annotations.Nullable Direction side, @NotNull Random random, @NotNull IModelData iModelData) {
if(side == null)
return noQuads;
BlockState bs = state;
List<BakedQuad> ret = new ArrayList<>();
int sid = BlockSide.reverse(side.ordinal());
BlockSide s = blockSides[sid];
TextureAtlasSprite tex = texs[15];
if(bs != null) {
IntegerProperty[] sideFlags = new IntegerProperty[6];
for(int i = 0; i < sideFlags.length; i++)
sideFlags[i] = IntegerProperty.create("neighbor" + i, 0, 15);
tex = texs[bs.getValue(sideFlags[sid])];
}
ret.add(bakeSide(s, tex));
return ret;
}
@Override
public boolean useAmbientOcclusion() {
return true;
}
@Override
public boolean isGui3d() {
return true;
}
@Override
public boolean usesBlockLight() {
return false;
}
@Override
public boolean isCustomRenderer() {
return false;
}
@Override
@Nonnull
public TextureAtlasSprite getParticleIcon() {
return texs[15];
}
@Override
@Nonnull
public ItemTransforms getTransforms() {
return ItemTransforms.NO_TRANSFORMS;
}
@Override
@Nonnull
public ItemOverrides getOverrides() {
return ItemOverrides.EMPTY;
}
public class ScreenBaker implements BakedModel {
private static final List<BakedQuad> noQuads = ImmutableList.of();
private final TextureAtlasSprite[] texs = new TextureAtlasSprite[16];
private final BlockSide[] blockSides = BlockSide.values();
private final Direction[] blockFacings = Direction.values();
private final ModelState modelState;
private final Function<net.minecraft.client.resources.model.Material, TextureAtlasSprite> spriteGetter;
private final ItemOverrides overrides;
private final ItemTransforms itemTransforms;
IntegerModelProperty[] TEXTURES = new IntegerModelProperty[6];
public ScreenBaker(ModelState modelState, Function<net.minecraft.client.resources.model.Material, TextureAtlasSprite> spriteGetter, ItemOverrides overrides, ItemTransforms itemTransforms) {
this.modelState = modelState;
this.spriteGetter = spriteGetter;
this.overrides = overrides;
this.itemTransforms = itemTransforms;
for (int i = 0; i < texs.length; i++) {
texs[i] = spriteGetter.apply(ScreenModelLoader.MATERIALS_SIDES[i]);
}
for (int i = 0; i < TEXTURES.length; i++) {
TEXTURES[i] = new IntegerModelProperty();
}
}
private void putVertex(int[] buf, int pos, Vector3f vpos, TextureAtlasSprite tex, Vector3f uv, Vector3i normal) {
pos *= 8;
buf[pos] = Float.floatToRawIntBits(vpos.x);
buf[pos + 1] = Float.floatToRawIntBits(vpos.y);
buf[pos + 2] = Float.floatToRawIntBits(vpos.z);
buf[pos + 3] = 0xFFFFFFFF; //Color, let this white...
buf[pos + 4] = Float.floatToRawIntBits(tex.getU(uv.x));
buf[pos + 5] = Float.floatToRawIntBits(tex.getV(uv.y));
int nx = (normal.x * 127) & 0xFF;
int ny = (normal.y * 127) & 0xFF;
int nz = (normal.z * 127) & 0xFF;
buf[pos + 7] = nx | (ny << 8) | (nz << 16);
}
private Vector3f rotateVec(Vector3f vec, BlockSide side) {
return switch (side) {
case BOTTOM -> new Vector3f(vec.x, 1.0f, 1.0f - vec.z);
case TOP -> new Vector3f(vec.x, 0.0f, vec.z);
case NORTH -> new Vector3f(vec.x, vec.z, 1.0f);
case SOUTH -> new Vector3f(vec.x, 1.0f - vec.z, 0.0f);
case WEST -> new Vector3f(1.f, vec.x, vec.z);
case EAST -> new Vector3f(0.0f, 1.0f - vec.x, vec.z);
//noinspection UnnecessaryDefault
default -> throw new RuntimeException("Unknown block side " + side);
};
}
private Vector3f rotateTex(BlockSide side, float u, float v) {
return switch (side) {
case BOTTOM, NORTH -> new Vector3f(16.f - u, 16.f - v, 0.0f);
case TOP -> new Vector3f(16.f - u, v, 0.0f);
case SOUTH -> new Vector3f(u, v, 0.0f);
case WEST -> new Vector3f(16.f - v, u, 0.0f);
case EAST -> new Vector3f(v, 16.f - u, 0.0f);
//noinspection UnnecessaryDefault
default -> throw new RuntimeException("Unknown block side " + side);
};
}
private BakedQuad bakeSide(BlockSide side, TextureAtlasSprite tex) {
int[] data = new int[8 * 4];
// I have no idea
int rotation = switch (side) {
case NORTH, TOP, BOTTOM -> 2;
case SOUTH -> 0;
case EAST -> 1;
case WEST -> 3;
//noinspection UnnecessaryDefault
default -> throw new RuntimeException("Unknown block side " + side);
};
putVertex(data, (rotation + 3) % 4, rotateVec(new Vector3f(0.0f, 0.0f, 0.0f), side), tex, rotateTex(side, 16.0f, 0.0f), side.backward);
putVertex(data, (rotation + 2) % 4, rotateVec(new Vector3f(0.0f, 0.0f, 1.0f), side), tex, rotateTex(side, 16.0f, 16.0f), side.backward);
putVertex(data, (rotation + 1) % 4, rotateVec(new Vector3f(1.0f, 0.0f, 1.0f), side), tex, rotateTex(side, 0.0f, 16.0f), side.backward);
putVertex(data, (rotation) % 4, rotateVec(new Vector3f(1.0f, 0.0f, 0.0f), side), tex, rotateTex(side, 0.0f, 0.0f), side.backward);
return new BakedQuad(data, 0xFFFFFFFF, blockFacings[side.ordinal()].getOpposite(), tex, true);
}
@Override
public List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, RandomSource random) {
return getQuads(state, side, random, ModelData.EMPTY, null);
}
@Override
public @NotNull List<BakedQuad> getQuads(@Nullable BlockState state, @Nullable Direction side, @NotNull RandomSource rand, @NotNull ModelData data, @Nullable RenderType renderType) {
if (side == null)
return noQuads;
List<BakedQuad> ret = new ArrayList<>();
int sid = BlockSide.reverse(side.ordinal());
BlockSide s = blockSides[sid];
TextureAtlasSprite tex = texs[15];
if (data.has(TEXTURES[side.ordinal()]))
tex = texs[data.get(TEXTURES[side.ordinal()])];
ret.add(bakeSide(s, tex));
return ret;
}
protected byte check(BlockState state, BlockAndTintGetter level, BlockPos pos, Vector3i dir) {
BlockState u = level.getBlockState(pos.offset(dir.x, dir.y, dir.z));
BlockState d = level.getBlockState(pos.offset(-dir.x, -dir.y, -dir.z));
if (
u.getBlock() == state.getBlock() &&
d.getBlock() != state.getBlock()
) return (byte) 1; // away
else if (
d.getBlock() == state.getBlock() &&
u.getBlock() != state.getBlock()
) return (byte) 2; // to
else if (
d.getBlock() != state.getBlock() &&
u.getBlock() != state.getBlock()
) return (byte) 3; // both
return (byte) 0; // none
}
@Override
public @NotNull ModelData getModelData(@NotNull BlockAndTintGetter level, @NotNull BlockPos pos, @NotNull BlockState state, @NotNull ModelData modelData) {
ModelData.Builder builder = ModelData.builder();
final int BAR_BOTTOM = 1;
final int BAR_RIGHT = 2;
final int BAR_TOP = 4;
final int BAR_LEFT = 8;
for (int i = 0; i < TEXTURES.length; i++) {
BlockSide side = blockSides[i];
// check up and down
int res = switch (check(state, level, pos, side.up)) {
case 1 -> BAR_BOTTOM;
case 2 -> BAR_TOP;
case 3 -> BAR_TOP | BAR_BOTTOM;
default -> 0;
};
// check left and right
res |= switch (check(state, level, pos, side.right)) {
case 1 -> BAR_LEFT;
case 2 -> BAR_RIGHT;
case 3 -> BAR_LEFT | BAR_RIGHT;
default -> 0;
};
builder.with(TEXTURES[i], res);
}
return builder.build();
}
@Override
public boolean useAmbientOcclusion() {
return true;
}
@Override
public boolean isGui3d() {
return true;
}
@Override
public boolean usesBlockLight() {
return false;
}
@Override
public boolean isCustomRenderer() {
return false;
}
@Override
@Nonnull
public TextureAtlasSprite getParticleIcon() {
return texs[15];
}
@Override
@Nonnull
public ItemTransforms getTransforms() {
return ItemTransforms.NO_TRANSFORMS;
}
@Override
@Nonnull
public ItemOverrides getOverrides() {
return ItemOverrides.EMPTY;
}
//@formatter:off
public static final class IntegerModelProperty extends ModelProperty<Integer> {}
//@formatter:on
}

View File

@ -2,56 +2,65 @@ package net.montoyo.wd.client.renderers;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraftforge.client.ForgeHooksClient;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.IModelLoader;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
import net.minecraftforge.client.model.geometry.IGeometryLoader;
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Function;
public class ScreenModelLoader implements IModelLoader<ScreenModelLoader.ScreenModelGeometry> {
public class ScreenModelLoader implements IGeometryLoader<ScreenModelLoader.ScreenModelGeometry> {
public static final ResourceLocation SCREEN_LOADER = new ResourceLocation("webdisplays", "screen_loader");
public static final ResourceLocation SCREEN_SIDE = new ResourceLocation("webdisplays", "block/screen");
public static final Material MATERIAL_SIDE = ForgeHooksClient.getBlockMaterial(SCREEN_SIDE);
@Override
public void onResourceManagerReload(ResourceManager resourceManager) {
private static final ResourceLocation[] SIDES = new ResourceLocation[16];
public static final Material[] MATERIALS_SIDES = new Material[16];
static {
for (int i = 0; i < SIDES.length; i++) {
SIDES[i] = new ResourceLocation(SCREEN_SIDE.getNamespace(), SCREEN_SIDE.getPath() + i);
MATERIALS_SIDES[i] = ForgeHooksClient.getBlockMaterial(SIDES[i]);
}
}
@Override
public ScreenModelGeometry read(JsonDeserializationContext deserializationContext, JsonObject modelContents) {
public ScreenModelGeometry read(JsonObject jsonObject, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException {
return new ScreenModelGeometry();
}
public static class ScreenModelGeometry implements IModelGeometry<ScreenModelGeometry> {
public static class ScreenModelGeometry implements IUnbakedGeometry<ScreenModelGeometry> {
@Override
public BakedModel bake(IModelConfiguration owner, ModelBakery modelBakery, Function<net.minecraft.client.resources.model.Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides itemOverrides, ResourceLocation resourceLocation) {
return new ScreenBaker(modelState, spriteGetter, itemOverrides, owner.getCameraTransforms());
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation) {
return new ScreenBaker(modelState, spriteGetter, overrides, context.getTransforms());
}
// @Override
// public void resolveParents(Function<ResourceLocation, UnbakedModel> modelGetter, IGeometryBakingContext context) {
// IUnbakedGeometry.super.resolveParents(modelGetter, context);
// }
// @Override
// public Set<String> getConfigurableComponentNames() {
// return IUnbakedGeometry.super.getConfigurableComponentNames();
// }
@Override
public Collection<net.minecraft.client.resources.model.Material> getTextures(IModelConfiguration owner, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors) {
return List.of(MATERIAL_SIDE);
}
// TODO: ?
// @Override
// public Collection<Material> getMaterials(IGeometryBakingContext iGeometryBakingContext, Function<ResourceLocation, UnbakedModel> function, Set<Pair<String, String>> set) {
// return Arrays.asList(MATERIALS_SIDES);
// }
}
}

View File

@ -4,205 +4,186 @@
package net.montoyo.wd.client.renderers;
import com.mojang.blaze3d.platform.GlStateManager;
import com.cinemamod.mcef.MCEFBrowser;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.world.phys.AABB;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.client.ClientProxy;
import net.montoyo.wd.entity.TileEntityScreen;
import net.montoyo.wd.utilities.Vector3f;
import net.montoyo.wd.utilities.Vector3i;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.utilities.math.Vector3f;
import net.montoyo.wd.utilities.math.Vector3i;
import org.jetbrains.annotations.NotNull;
import static com.mojang.math.Vector3f.*;
import static org.lwjgl.opengl.GL11.*;
import static com.mojang.math.Axis.*;
public class ScreenRenderer implements BlockEntityRenderer<TileEntityScreen> {
public class ScreenRenderer implements BlockEntityRenderer<ScreenBlockEntity> {
public ScreenRenderer() {
}
public static class ScreenRendererProvider implements BlockEntityRendererProvider<ScreenBlockEntity> {
@Override
public @NotNull BlockEntityRenderer<ScreenBlockEntity> create(@NotNull Context arg) {
return new ScreenRenderer();
}
}
private final Vector3f mid = new Vector3f();
private final Vector3i tmpi = new Vector3i();
private final Vector3f tmpf = new Vector3f();
@Override
public void render(ScreenBlockEntity te, float partialTick, @NotNull PoseStack poseStack, @NotNull MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
if (!te.isLoaded())
return;
public static class ScreenRendererProvider implements BlockEntityRendererProvider<TileEntityScreen> {
@Override
public @NotNull BlockEntityRenderer<TileEntityScreen> create(@NotNull Context arg) {
return new ScreenRenderer();
}
}
private final Vector3f mid = new Vector3f();
private final Vector3i tmpi = new Vector3i();
private final Vector3f tmpf = new Vector3f();
@Override
public void render(TileEntityScreen te, float partialTick, @NotNull PoseStack poseStack, @NotNull MultiBufferSource bufferSource, int packedLight, int packedOverlay) {
if(!te.isLoaded())
return;
//Disable lighting
RenderSystem.enableTexture();
RenderSystem.disableCull();
RenderSystem.disableBlend();
for(int i = 0; i < te.screenCount(); i++) {
TileEntityScreen.Screen scr = te.getScreen(i);
if(scr.browser == null) {
scr.browser = ((ClientProxy) WebDisplays.PROXY).getMCEF().createBrowser(WebDisplays.applyBlacklist(scr.url));
if(scr.rotation.isVertical)
scr.browser.resize(scr.resolution.y, scr.resolution.x);
else
scr.browser.resize(scr.resolution.x, scr.resolution.y);
scr.doTurnOnAnim = true;
scr.turnOnTime = System.currentTimeMillis();
}
tmpi.set(scr.side.right);
tmpi.mul(scr.size.x);
tmpi.addMul(scr.side.up, scr.size.y);
tmpf.set(tmpi);
mid.set(0.5, 0.5, 0.5);
mid.addMul(tmpf, 0.5f);
tmpf.set(scr.side.left);
mid.addMul(tmpf, 0.5f);
tmpf.set(scr.side.down);
mid.addMul(tmpf, 0.5f);
poseStack.pushPose();
poseStack.translate(mid.x, mid.y, mid.z);
switch(scr.side) {
case BOTTOM:
poseStack.mulPose(XP.rotation(90.f + 49.8f));
break;
case TOP:
poseStack.mulPose(XN.rotation(90.f + 49.8f));
break;
case NORTH:
poseStack.mulPose(YN.rotationDegrees(180.f));
break;
case SOUTH:
break;
case WEST:
poseStack.mulPose(YN.rotationDegrees(90.f));
break;
case EAST:
poseStack.mulPose(YP.rotationDegrees(90.f));
break;
}
if(scr.doTurnOnAnim) {
long lt = System.currentTimeMillis() - scr.turnOnTime;
float ft = ((float) lt) / 100.0f;
if(ft >= 1.0f) {
ft = 1.0f;
scr.doTurnOnAnim = false;
}
poseStack.scale(ft, ft, 1.0f);
}
if(!scr.rotation.isNull)
poseStack.mulPose(ZP.rotationDegrees(scr.rotation.angle));
float sw = ((float) scr.size.x) * 0.5f - 2.f / 16.f;
float sh = ((float) scr.size.y) * 0.5f - 2.f / 16.f;
if(scr.rotation.isVertical) {
float tmp = sw;
sw = sh;
sh = tmp;
}
Tesselator tesselator = Tesselator.getInstance();
BufferBuilder builder = tesselator.getBuilder();
//TODO: Use tesselator
RenderSystem.enableDepthTest();
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
RenderSystem._setShaderTexture(0, scr.browser.getTextureID());
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
builder.vertex(poseStack.last().pose(),-sw, -sh, 0.505f).uv(0.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), sw, -sh, 0.505f).uv(1.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), sw, sh, 0.505f).uv(1.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(),-sw, sh, 0.505f).uv(0.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
tesselator.end();//Minecraft does shit with mah texture otherwise...
RenderSystem.disableDepthTest();
poseStack.popPose();
}
//Disable lighting
// RenderSystem.enableTexture();
// RenderSystem.disableCull();
RenderSystem.disableBlend();
for (int i = 0; i < te.screenCount(); i++) {
ScreenData scr = te.getScreen(i);
if (scr.browser == null) {
double dist = WebDisplays.PROXY.distanceTo(te, Minecraft.getInstance().getEntityRenderDispatcher().camera.getPosition());
if (dist <= WebDisplays.INSTANCE.loadDistance2 * 16)
scr.createBrowser(te, true);
else continue;
}
// TODO: manually backface cull the screens
tmpi.set(scr.side.right);
tmpi.mul(scr.size.x);
tmpi.addMul(scr.side.up, scr.size.y);
tmpf.set(tmpi);
mid.set(0.5, 0.5, 0.5);
mid.addMul(tmpf, 0.5f);
tmpf.set(scr.side.left);
mid.addMul(tmpf, 0.5f);
tmpf.set(scr.side.down);
mid.addMul(tmpf, 0.5f);
poseStack.pushPose();
poseStack.translate(mid.x, mid.y, mid.z);
switch (scr.side) {
case BOTTOM:
poseStack.mulPose(XP.rotation(90.f + 49.8f));
break;
case TOP:
poseStack.mulPose(XN.rotation(90.f + 49.8f));
break;
case NORTH:
poseStack.mulPose(YN.rotationDegrees(180.f));
break;
case SOUTH:
break;
case WEST:
poseStack.mulPose(YN.rotationDegrees(90.f));
break;
case EAST:
poseStack.mulPose(YP.rotationDegrees(90.f));
break;
}
if (scr.doTurnOnAnim) {
long lt = System.currentTimeMillis() - scr.turnOnTime;
float ft = ((float) lt) / 100.0f;
if (ft >= 1.0f) {
ft = 1.0f;
scr.doTurnOnAnim = false;
}
poseStack.scale(ft, ft, 1.0f);
}
if (!scr.rotation.isNull)
poseStack.mulPose(ZP.rotationDegrees(scr.rotation.angle));
float sw = ((float) scr.size.x) * 0.5f - 2.f / 16.f;
float sh = ((float) scr.size.y) * 0.5f - 2.f / 16.f;
if (scr.rotation.isVertical) {
float tmp = sw;
sw = sh;
sh = tmp;
}
Tesselator tesselator = Tesselator.getInstance();
BufferBuilder builder = tesselator.getBuilder();
//TODO: don't use tesselator
RenderSystem.enableDepthTest();
RenderSystem.setShader(GameRenderer::getPositionTexColorShader);
RenderSystem._setShaderTexture(0, ((MCEFBrowser) scr.browser).getRenderer().getTextureID());
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f);
builder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
builder.vertex(poseStack.last().pose(), -sw, -sh, 0.505f).uv(0.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), sw, -sh, 0.505f).uv(1.f, 1.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), sw, sh, 0.505f).uv(1.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
builder.vertex(poseStack.last().pose(), -sw, sh, 0.505f).uv(0.f, 0.f).color(1.f, 1.f, 1.f, 1.f).endVertex();
tesselator.end();//Minecraft does shit with mah texture otherwise...
RenderSystem.disableDepthTest();
// TODO: it'd be neat to draw a mouse cursor on the screen
// // debug hit2pixels
// HitResult result = Minecraft.getInstance().hitResult;
// VertexConsumer consumer = bufferSource.getBuffer(RenderType.lines());
// poseStack.translate(-sw, -sh, 0);
// if (result instanceof BlockHitResult hit) {
// BlockPos bpos = hit.getBlockPos();
//
// Vector3i pos = new Vector3i(hit.getBlockPos());
// float hitX = ((float) result.getLocation().x) - (float) te.getBlockPos().getX();
// float hitY = ((float) result.getLocation().y) - (float) te.getBlockPos().getY();
// float hitZ = ((float) result.getLocation().z) - (float) te.getBlockPos().getZ();
// Vector2i tmp = new Vector2i();
//
// if (BlockScreen.hit2pixels(scr.side, bpos, pos, scr, hitX, hitY, hitZ, tmp)) {
// float x = tmp.x / (float) scr.resolution.x * scr.size.x;
// float y = tmp.y / (float) scr.resolution.y * scr.size.y;
// y = scr.size.y - y;
//
// x /= scr.size.x;
// y /= scr.size.y;
// x *= sw * 2;
// y *= sh * 2;
//
// LevelRenderer.renderLineBox(
// poseStack,
// consumer, new AABB(
// x - 0.01, y - 0.01, 0.5 - 0.01,
// x + 0.01, y + 0.01, 0.5 + 0.01
// ),
// 1f, 0, 0, 1f
// );
// }
// }
poseStack.popPose();
}
//Bounding box debugging
/*poseStack.pushPose();
poseStack.translate(-te.getBlockPos().getX(), -te.getBlockPos().getY(), -te.getBlockPos().getZ());
renderAABB(te.getRenderBoundingBox());
poseStack.popPose();*/
//Re-enable lighting
RenderSystem.enableCull();
}
public void renderAABB(AABB bb) {
RenderSystem.disableTexture();
RenderSystem.enableBlend();
RenderSystem.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
RenderSystem.disableCull();
RenderSystem.setShaderColor(0.f, 0.5f, 1.f, 0.75f);
RenderSystem.depthMask(false);
Tesselator t = new Tesselator();
BufferBuilder vb = t.getBuilder();
VertexBuffer tb = new VertexBuffer();
vb.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
//Bottom
vb.vertex(bb.minX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.minY, bb.maxZ).endVertex();
vb.vertex(bb.minX, bb.minY, bb.maxZ).endVertex();
//Top
vb.vertex(bb.minX, bb.maxY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.maxZ).endVertex();
vb.vertex(bb.minX, bb.maxY, bb.maxZ).endVertex();
//Left
vb.vertex(bb.minX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.minX, bb.minY, bb.maxZ).endVertex();
vb.vertex(bb.minX, bb.maxY, bb.maxZ).endVertex();
vb.vertex(bb.minX, bb.maxY, bb.minZ).endVertex();
//Right
vb.vertex(bb.maxX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.minY, bb.maxZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.maxZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.minZ).endVertex();
//Front
vb.vertex(bb.minX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.minY, bb.minZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.minZ).endVertex();
vb.vertex(bb.minX, bb.maxY, bb.minZ).endVertex();
//Back
vb.vertex(bb.minX, bb.minY, bb.maxZ).endVertex();
vb.vertex(bb.maxX, bb.minY, bb.maxZ).endVertex();
vb.vertex(bb.maxX, bb.maxY, bb.maxZ).endVertex();
vb.vertex(bb.minX, bb.maxY, bb.maxZ).endVertex();
tb.draw();
RenderSystem.depthMask(true);
RenderSystem.enableCull();
RenderSystem.enableTexture();
RenderSystem.disableBlend();
}
// //Bounding box debugging
// poseStack.pushPose();
// poseStack.translate(-te.getBlockPos().getX(), -te.getBlockPos().getY(), -te.getBlockPos().getZ());
// LevelRenderer.renderLineBox(
// poseStack, bufferSource.getBuffer(RenderType.LINES),
// te.getRenderBoundingBox(), 1, 1, 1, 1f
// );
// poseStack.popPose();
//Re-enable lighting
// RenderSystem.enableCull();
}
}

View File

@ -0,0 +1,133 @@
package net.montoyo.wd.config;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.config.annoconfg.AnnoCFG;
import net.montoyo.wd.config.annoconfg.annotation.format.*;
import net.montoyo.wd.config.annoconfg.annotation.value.Default;
import net.montoyo.wd.config.annoconfg.annotation.value.DoubleRange;
import net.montoyo.wd.config.annoconfg.annotation.value.IntRange;
@Config(type = ModConfig.Type.CLIENT)
public class ClientConfig {
@SuppressWarnings("unused")
private static final AnnoCFG CFG = new AnnoCFG(FMLJavaModLoadingContext.get().getModEventBus(), ClientConfig.class);
public static void init() {
// loads the class
}
@Name("load_distance")
@Comment("How far (in blocks) you can be before a screen starts rendering")
@Translation("config.webdisplays.load_distance")
@DoubleRange(minV = 0, maxV = Double.MAX_VALUE)
@Default(valueD = 30)
public static double loadDistance = 30.0;
@Name("unload_distance")
@Comment("How far you can be before a screen stops rendering")
@Translation("config.webdisplays.unload_distance")
@DoubleRange(minV = 0, maxV = Double.MAX_VALUE)
@Default(valueD = 32)
public static double unloadDistance = 32.0;
@Name("pad_resolution")
@Comment({
"The resolution that minePads should use",
"Smaller values produce lower qualities, higher values produce higher qualities",
"Due to how web browsers work however, the larger this value is, the smaller text is",
"Also, higher values will invariably lag more",
"A good goto value for this would be the height of your monitor, in pixels",
"A standard monitor is (at least currently) 1080",
})
@Translation("config.webdisplays.pad_res")
@IntRange(minV = 0, maxV = Integer.MAX_VALUE)
@Default(valueI = 720)
public static int padResolution = 720;
@Name("side_pad")
@Comment({
"When this is true, the minePad is placed off to the side of the screen when held, so it's visible but doesn't take up too much of the screen",
"When this is false, the minePad is placed closer to the center of the screen, allow it to be seen better, but taking up more of your view",
})
@Translation("config.webdisplays.side_pad")
@Default(valueBoolean = true)
public static boolean sidePad = true;
@Comment({
"Options relating to input handling"
})
@CFGSegment("input")
public static class Input {
@Name("keyboard_camera")
@Comment({
"If this is on, then the camera will try to focus on the selected element while a keyboard is in use",
"Elsewise, it'll try to focus on the center of the screen",
})
@Translation("config.webdisplays.keyboard_camera")
@Default(valueBoolean = true)
public static boolean keyboardCamera = true;
@Name("switch_buttons")
@Comment("If the left and right buttons should be swapped when using a laser")
@Translation("config.webdisplays.switch_buttons")
@DoubleRange(minV = 0, maxV = Double.MAX_VALUE)
@Default(valueD = 30)
public static boolean switchButtons = true;
}
// @Comment({
// "AutoVolume makes audio fade off based on distance",
// "Currently, this seems to not work"
// })
// @CFGSegment("auto_volume")
// public static class AutoVolumeControl {
// @Name("enabled")
// @Comment("Whether or not auto volume should be enabled")
// @Translation("config.webdisplays.auto_vol")
// @Default(valueBoolean = true)
// public static boolean enableAutoVolume = true;
//
// @Name("youtube_volume")
// @Comment("How loud youtube should be by default")
// @Translation("config.webdisplays.yt_vol")
// @DoubleRange(minV = 0, maxV = 100)
// @Default(valueD = 100)
// public static double ytVolume = 100.0;
//
// @Name("dist0")
// @Comment("Distance after which you can't hear anything (in blocks)")
// @Translation("config.webdisplays.d0")
// @DoubleRange(minV = 0, maxV = Double.MAX_VALUE)
// @Default(valueD = 30)
// public static double dist0 = 30.0;
//
// @Name("dist100")
// @Comment("Distance after which the sound starts dropping (in blocks)")
// @Translation("config.webdisplays.d100")
// @DoubleRange(minV = 0, maxV = Double.MAX_VALUE)
// @Default(valueD = 10)
// public static double dist100 = 10.0;
// }
@SuppressWarnings("unused")
public static void postLoad() {
if (unloadDistance < loadDistance + 2.0)
unloadDistance = loadDistance + 2.0;
// if (AutoVolumeControl.dist0 < AutoVolumeControl.dist100 + 0.1)
// AutoVolumeControl.dist0 = AutoVolumeControl.dist100 + 0.1;
// cache pad resolution
WebDisplays.INSTANCE.padResY = padResolution;
WebDisplays.INSTANCE.padResX = WebDisplays.INSTANCE.padResY * WebDisplays.PAD_RATIO;
// cache unload/load distances
WebDisplays.INSTANCE.unloadDistance2 = unloadDistance * unloadDistance;
WebDisplays.INSTANCE.loadDistance2 = loadDistance * loadDistance;
// WebDisplays.INSTANCE.ytVolume = (float) AutoVolumeControl.ytVolume;
// WebDisplays.INSTANCE.avDist100 = (float) AutoVolumeControl.dist100;
// WebDisplays.INSTANCE.avDist0 = (float) AutoVolumeControl.dist0;
}
}

View File

@ -0,0 +1,127 @@
package net.montoyo.wd.config;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.config.annoconfg.AnnoCFG;
import net.montoyo.wd.config.annoconfg.annotation.format.*;
import net.montoyo.wd.config.annoconfg.annotation.value.Default;
import net.montoyo.wd.config.annoconfg.annotation.value.IntRange;
import net.montoyo.wd.config.annoconfg.annotation.value.LongRange;
@SuppressWarnings("DefaultAnnotationParam")
@Config(type = ModConfig.Type.COMMON)
public class CommonConfig {
@SuppressWarnings("unused")
private static final AnnoCFG CFG = new AnnoCFG(FMLJavaModLoadingContext.get().getModEventBus(), CommonConfig.class);
public static void init() {
// loads the class
}
@Name("hard_recipes")
@Comment("If true, breaking the minePad is required to craft upgrades.")
@Translation("config.webdisplays.hard_recipes")
@Default(valueBoolean = true)
public static boolean hardRecipes = true;
@Name("join_message")
@Comment("Whether or not webdisplays should thank the user for using the mod")
@Translation("config.webdisplays.join_message")
@Default(valueBoolean = true)
public static boolean joinMessage = true;
@Name("disable_ownership_thief")
@Comment("If true, the ownership thief item will be disabled")
@Translation("config.webdisplays.disable_thief")
@Default(valueBoolean = false)
public static boolean disableOwnershipThief = false;
@Comment("Options for the browsers (both the minePad and the screens)")
@CFGSegment("browser_options")
public static class Browser {
@Name("blacklist")
@Comment("The page which screens should open up to when turning on")
@Translation("config.webdisplays.blacklist")
@Default(valueStr = "")
public static String[] blacklist = new String[0];
@Name("home_page")
@Comment("The page which screens should open up to when turning on")
@Translation("config.webdisplays.home_page")
@Default(valueStr = "mod://webdisplays/main.html")
public static String homepage = "mod://webdisplays/main.html";
}
@Comment("Options for the in world screen blocks")
@CFGSegment("screen_options")
public static class Screen {
@Name("max_resolution_x")
@Comment("The maximum value screen's horizontal resolution, in pixels")
@Translation("config.webdisplays.max_res_x")
@IntRange(minV = 0, maxV = Integer.MAX_VALUE)
@Default(valueI = 1920)
public static int maxResolutionX = 1920;
@Name("max_resolution_y")
@Comment("The maximum value screen's vertical resolution, in pixels")
@Translation("config.webdisplays.max_res_y")
@IntRange(minV = 0, maxV = Integer.MAX_VALUE)
@Default(valueI = 1080)
public static int maxResolutionY = 1080;
@Name("max_width")
@Comment("The maximum width for the screen multiblock, in blocks")
@Translation("config.webdisplays.max_width")
@IntRange(minV = 0, maxV = Integer.MAX_VALUE)
@Default(valueI = 16)
public static int maxScreenSizeX = 16;
@Name("max_height")
@Comment("The maximum height for the screen multiblock, in blocks")
@Translation("config.webdisplays.max_height")
@IntRange(minV = 0, maxV = Integer.MAX_VALUE)
@Default(valueI = 16)
public static int maxScreenSizeY = 16;
}
@Comment("Options for the miniserver")
@CFGSegment("mini_server")
public static class MiniServ {
@Name("miniserv_port")
@Comment("The port used by miniserv. 0 to disable")
@Translation("config.webdisplays.miniserv_port")
@IntRange(minV = 0, maxV = Short.MAX_VALUE)
@Default(valueI = 25566)
public static int miniservPort = 25566;
@Name("miniserv_quota")
@Comment("The amount of data that can be uploaded to miniserv, in KiB (so 1024 = 1 MiO)")
@Translation("config.webdisplays.miniserv_quota")
@LongRange(minV = 0, maxV = Long.MAX_VALUE)
@Default(valueL = 1920)
public static long miniservQuota = 1024; //It's stored as a string anyway
}
@SuppressWarnings("unused")
public static void postLoad() {
WebDisplays.INSTANCE.miniservPort = MiniServ.miniservPort;
WebDisplays.INSTANCE.miniservQuota = MiniServ.miniservQuota * 1024L;
}
// //Comments & shit
// blacklist.setComment("An array of domain names you don't want to load.");
// padHeight.setComment("The minePad Y resolution in pixels. padWidth = padHeight * " + PAD_RATIO);
// hardRecipe.setComment("If true, breaking the minePad is required to craft upgrades.");
// homePage.setComment("The URL that will be loaded each time you create a screen");
// disableOT.setComment("If true, the ownership thief item will be disabled");
// loadDistance.setComment("All screens outside this range will be unloaded");
// unloadDistance.setComment("All unloaded screens inside this range will be loaded");
// maxResX.setComment("Maximum horizontal screen resolution, in pixels");
// maxResY.setComment("Maximum vertical screen resolution, in pixels");
// miniservPort.setComment("The port used by miniserv. 0 to disable.");
// miniservPort.setMaxValue(Short.MAX_VALUE);
// miniservQuota.setComment("The amount of data that can be uploaded to miniserv, in KiB (so 1024 = 1 MiO)");
// maxScreenX.setComment("Maximum screen width, in blocks. Resolution will be clamped by maxResolutionX.");
// maxScreenY.setComment("Maximum screen height, in blocks. Resolution will be clamped by maxResolutionY.");
}

View File

@ -1,121 +0,0 @@
package net.montoyo.wd.config;
import me.shedaniel.autoconfig.ConfigData;
import me.shedaniel.autoconfig.annotation.Config;
import me.shedaniel.autoconfig.annotation.ConfigEntry;
import net.minecraft.util.Mth;
import net.montoyo.mcef.easy_forge_compat.Configuration;
import java.util.List;
@Config(name = "webdisplays")
public class ModConfig implements ConfigData {
@ConfigEntry.Category("main")
public Main main = new Main();
@ConfigEntry.Category("client")
public Client client = new Client();
public static class Main {
@ConfigEntry.Gui.Tooltip
public List<String> blacklist = List.of();
@ConfigEntry.Gui.Tooltip
public int padHeight = 480;
@ConfigEntry.Gui.Tooltip
public boolean hardRecipes = true;
@ConfigEntry.Gui.Tooltip
public String homepage = "https://www.google.com";
@ConfigEntry.Gui.Tooltip
public boolean disableOwnershipThief = false;
@ConfigEntry.Gui.Tooltip
public int maxResolutionX = 1920;
@ConfigEntry.Gui.Tooltip
public int maxResolutionY = 1080;
@ConfigEntry.Gui.Tooltip
@ConfigEntry.BoundedDiscrete(max = Short.MAX_VALUE)
public int miniservPort = 25566;
@ConfigEntry.Gui.Tooltip
public long miniservQuota = 1024; //It's stored as a string anyway
@ConfigEntry.Gui.Tooltip
public int maxScreenSizeX = 16;
@ConfigEntry.Gui.Tooltip
public int maxScreenSizeY = 16;
}
public static class Client {
@ConfigEntry.Gui.Tooltip
public double loadDistance = 30.0;
@ConfigEntry.Gui.Tooltip
public double unloadDistance = 32.0;
@ConfigEntry.Gui.CollapsibleObject()
public AutoVolumeControl autoVolumeControl = new AutoVolumeControl();
public static class AutoVolumeControl {
@ConfigEntry.Gui.Tooltip
public boolean enableAutoVolume = true;
@ConfigEntry.Gui.Tooltip
public double ytVolume = 100.0;
@ConfigEntry.Gui.Tooltip
public double dist100 = 10.0;
@ConfigEntry.Gui.Tooltip
public double dist0 = 30.0;
}
}
@Override
public void validatePostLoad() throws ValidationException {
ConfigData.super.validatePostLoad();
main.miniservPort = Mth.clamp(main.miniservPort, 0, Short.MAX_VALUE);
client.autoVolumeControl.ytVolume = Mth.clamp(client.autoVolumeControl.ytVolume, 0.0, 100.0);
client.autoVolumeControl.dist0 = Mth.clamp(client.autoVolumeControl.dist0, 0.0, Double.MAX_VALUE);
client.autoVolumeControl.ytVolume = Mth.clamp(client.autoVolumeControl.dist100, 0.0, Double.MAX_VALUE);
if(client.unloadDistance < client.loadDistance + 2.0) {
client.unloadDistance = client.loadDistance + 2.0;
}
if(client.autoVolumeControl.dist0 < client.autoVolumeControl.dist100 + 0.1) {
client.autoVolumeControl.dist0 = client.autoVolumeControl.dist100 + 0.1;
}
}
// //Comments & shit
// blacklist.setComment("An array of domain names you don't want to load.");
// padHeight.setComment("The minePad Y resolution in pixels. padWidth = padHeight * " + PAD_RATIO);
// hardRecipe.setComment("If true, breaking the minePad is required to craft upgrades.");
// homePage.setComment("The URL that will be loaded each time you create a screen");
// disableOT.setComment("If true, the ownership thief item will be disabled");
// loadDistance.setComment("All screens outside this range will be unloaded");
// unloadDistance.setComment("All unloaded screens inside this range will be loaded");
// maxResX.setComment("Maximum horizontal screen resolution, in pixels");
// maxResY.setComment("Maximum vertical screen resolution, in pixels");
// miniservPort.setComment("The port used by miniserv. 0 to disable.");
// miniservPort.setMaxValue(Short.MAX_VALUE);
// miniservQuota.setComment("The amount of data that can be uploaded to miniserv, in KiB (so 1024 = 1 MiO)");
// maxScreenX.setComment("Maximum screen width, in blocks. Resolution will be clamped by maxResolutionX.");
// maxScreenY.setComment("Maximum screen height, in blocks. Resolution will be clamped by maxResolutionY.");
// enableAutoVol.setComment("If true, the volume of YouTube videos will change depending on how far you are");
// ytVolume.setComment("Volume for YouTube videos. This will have no effect if enableSoundDistance is set to false");
// ytVolume.setMinValue(0.0);
// ytVolume.setMaxValue(100.0);
// dist100.setComment("Distance after which the sound starts dropping (in blocks)");
// dist100.setMinValue(0.0);
// dist0.setComment("Distance after which you can't hear anything (in blocks)");
// dist0.setMinValue(0.0);
}

View File

@ -0,0 +1,219 @@
package net.montoyo.wd.config.annoconfg;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.config.ModConfigEvent;
import net.montoyo.wd.config.annoconfg.annotation.format.*;
import net.montoyo.wd.config.annoconfg.annotation.value.Default;
import net.montoyo.wd.config.annoconfg.annotation.value.DoubleRange;
import net.montoyo.wd.config.annoconfg.annotation.value.IntRange;
import net.montoyo.wd.config.annoconfg.annotation.value.LongRange;
import net.montoyo.wd.config.annoconfg.handle.UnsafeHandle;
import net.montoyo.wd.config.annoconfg.util.EnumType;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.function.Supplier;
public class AnnoCFG {
private ForgeConfigSpec mySpec;
private final HashMap<String, ConfigEntry> handles = new HashMap<>();
private static final ArrayList<AnnoCFG> configs = new ArrayList<>();
private final Method postInit;
public AnnoCFG(IEventBus bus, Class<?> clazz) {
bus.addListener(this::onConfigChange);
ForgeConfigSpec.Builder configBuilder = new ForgeConfigSpec.Builder();
setup("", configBuilder, clazz);
configs.add(this);
Method m = null;
try {
m = clazz.getDeclaredMethod("postLoad");
} catch (Throwable ignored) {
}
postInit = m;
Config configDescriptor = clazz.getAnnotation(Config.class);
if (configDescriptor != null) {
String pth = configDescriptor.path();
if (!pth.isEmpty()) pth = pth + "/";
switch (configDescriptor.type()) {
case SERVER -> create(ModConfig.Type.SERVER, pth + ModLoadingContext.get().getActiveNamespace() + "_server.toml");
case CLIENT -> create(ModConfig.Type.CLIENT, pth + ModLoadingContext.get().getActiveNamespace() + "_client.toml");
case COMMON -> create(ModConfig.Type.COMMON, pth + ModLoadingContext.get().getActiveNamespace() + "_common.toml");
default -> throw new RuntimeException("wat");
}
}
}
protected void setupCommentsAndTranslations(AnnotatedElement element, ForgeConfigSpec.Builder builder, String... additionalLines) {
Translation translation = element.getAnnotation(Translation.class);
Comment comment = element.getAnnotation(Comment.class);
StringBuilder builder1 = new StringBuilder();
if (comment != null) {
for (int i = 0; i < comment.value().length; i++) {
String s = comment.value()[i];
builder1.append(s);
if (i != comment.value().length - 1)
builder1.append("\n");
}
}
for (String additionalLine : additionalLines) builder1.append(additionalLine);
if (!builder1.isEmpty())
builder.comment(builder1.toString());
if (translation != null)
builder.translation(translation.value());
}
public void setup(String dir, ForgeConfigSpec.Builder builder, Class<?> clazz) {
if (dir.startsWith(".")) dir = dir.substring(1);
for (Field field : clazz.getFields()) {
if (field.canAccess(null)) {
Skip skip = field.getAnnotation(Skip.class);
if (skip != null) continue;
Name name = field.getAnnotation(Name.class);
String nameStr = field.getName();
if (name != null) nameStr = name.value();
setupCommentsAndTranslations(field, builder);
Supplier<?> value;
Default defaultValue = field.getAnnotation(Default.class);
try {
switch (EnumType.forClass(field.getType())) {
case INT -> {
IntRange range = field.getAnnotation(IntRange.class);
int v = defaultValue.valueI();
if (range != null) {
int min = range.minV();
int max = range.maxV();
value = builder.defineInRange(nameStr, v, min, max);
} else {
value = builder.define(nameStr, v);
}
}
case LONG -> {
LongRange range = field.getAnnotation(LongRange.class);
long v = defaultValue.valueL();
if (range != null) {
long min = range.minV();
long max = range.maxV();
value = builder.defineInRange(nameStr, v, min, max);
} else {
value = builder.define(nameStr, v);
}
}
case DOUBLE -> {
DoubleRange range = field.getAnnotation(DoubleRange.class);
double v = defaultValue.valueD();
if (range != null) {
double min = range.minV();
double max = range.maxV();
value = builder.defineInRange(nameStr, v, min, max);
} else {
value = builder.define(nameStr, v);
}
}
case BOOLEAN -> {
boolean b = defaultValue.valueBoolean();
value = builder.define(nameStr, b);
}
case OTHER -> {
Class<?> fieldType = field.getType();
if (fieldType.equals(String[].class)) {
Supplier<String> sup = builder.define(nameStr, defaultValue.valueStr());
value = () -> {
String v = sup.get();
return v.split(",");
};
} else if (fieldType.equals(String.class)) {
value = builder.define(nameStr, defaultValue.valueStr());
} else
throw new RuntimeException("NYI " + field.getType());
}
default -> throw new RuntimeException("NYI " + field.getType());
}
} catch (NullPointerException npe) {
String inf = "";
if (npe.getMessage().contains("\"value.Default\""))
inf = " this is likely due to a missing default.";
throw new RuntimeException("A null pointer occurred on " + field.getName() + inf, npe);
}
Object o;
try {
// without this line, this system freaks out due to using theUnsafe
//noinspection UnusedAssignment
o = field.get(null);
} catch (Throwable ignored) {
}
UnsafeHandle handle = new UnsafeHandle(field);
o = handle.get();
handle.set(o);
//noinspection FunctionalExpressionCanBeFolded
handles.put(dir + "." + nameStr, new ConfigEntry(
handle, value::get
));
}
}
// TODO: check if the nested class is a direct nesting
for (Class<?> nestMember : clazz.getClasses()) {
if (nestMember == clazz) continue;
if (!nestMember.getName().startsWith(clazz.getName())) continue;
CFGSegment segment = nestMember.getAnnotation(CFGSegment.class);
if (segment == null) {
System.out.println(nestMember);
throw new RuntimeException("NYI: default name");
}
String name = segment.value();
setupCommentsAndTranslations(nestMember, builder);
builder.push(name);
setup(dir + "." + name, builder, nestMember);
builder.pop();
}
mySpec = builder.build();
}
public void onConfigChange(ModConfigEvent event) {
if (
event.getConfig().getSpec().equals(mySpec) ||
event.getConfig().getSpec() == mySpec
) {
for (String s : handles.keySet()) {
ConfigEntry entry = handles.get(s);
entry.handle.set(entry.supplier.get());
}
}
try {
postInit.invoke(null);
} catch (Throwable err) {
err.printStackTrace();
}
}
public void create(ModConfig.Type type, String file) {
ModLoadingContext.get().registerConfig(type, mySpec, file);
}
}

View File

@ -0,0 +1,15 @@
package net.montoyo.wd.config.annoconfg;
import net.montoyo.wd.config.annoconfg.handle.UnsafeHandle;
import java.util.function.Supplier;
public class ConfigEntry {
UnsafeHandle handle;
Supplier<?> supplier;
public ConfigEntry(UnsafeHandle handle, Supplier<?> supplier) {
this.handle = handle;
this.supplier = supplier;
}
}

View File

@ -0,0 +1,9 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface CFGSegment {
String value();
}

View File

@ -0,0 +1,9 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Comment {
String[] value();
}

View File

@ -0,0 +1,12 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import net.minecraftforge.fml.config.ModConfig;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Config {
ModConfig.Type type();
String path() default "";
}

View File

@ -0,0 +1,9 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Name {
String value();
}

View File

@ -0,0 +1,8 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Skip {
}

View File

@ -0,0 +1,9 @@
package net.montoyo.wd.config.annoconfg.annotation.format;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Translation {
String value();
}

View File

@ -0,0 +1,16 @@
package net.montoyo.wd.config.annoconfg.annotation.value;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface Default {
byte valueB() default 0;
short valueS() default 0;
int valueI() default 0;
long valueL() default 0;
float valueF() default 0;
double valueD() default 0;
boolean valueBoolean() default false;
String valueStr() default "";
}

View File

@ -0,0 +1,10 @@
package net.montoyo.wd.config.annoconfg.annotation.value;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface DoubleRange {
double minV();
double maxV();
}

View File

@ -0,0 +1,10 @@
package net.montoyo.wd.config.annoconfg.annotation.value;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface IntRange {
int minV();
int maxV();
}

View File

@ -0,0 +1,10 @@
package net.montoyo.wd.config.annoconfg.annotation.value;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface LongRange {
long minV();
long maxV();
}

View File

@ -0,0 +1,86 @@
package net.montoyo.wd.config.annoconfg.handle;
import net.montoyo.wd.config.annoconfg.util.EnumType;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
import java.util.function.Consumer;
import java.util.function.Supplier;
public class UnsafeHandle {
private static final Unsafe theUnsafe;
static {
try {
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
theUnsafe = (Unsafe) f.get(null);
} catch (Throwable ignored) {
throw new RuntimeException("AnnoConfg: Failed to acquire an instance of the unsafe.");
}
}
private final long offset;
private final Consumer<Object> uploader;
private final Supplier<Object> getter;
public UnsafeHandle(Field f) {
this(null, f);
}
public UnsafeHandle(Object relative, Field f) {
offset = theUnsafe.staticFieldOffset(f);
if (relative == null) relative = theUnsafe.staticFieldBase(f);
Object finalRelative = relative;
if (f.getType().isPrimitive()) {
switch (EnumType.forClass(f.getType())) {
case BYTE -> {
uploader = (v) -> theUnsafe.putByte(finalRelative, offset, (byte) v);
getter = () -> theUnsafe.getByte(finalRelative, offset);
}
case SHORT -> {
uploader = (v) -> theUnsafe.putShort(finalRelative, offset, (short) v);
getter = () -> theUnsafe.getShort(finalRelative, offset);
}
case INT -> {
uploader = (v) -> theUnsafe.putInt(finalRelative, offset, (int) v);
getter = () -> theUnsafe.getInt(finalRelative, offset);
}
case LONG -> {
uploader = (v) -> theUnsafe.putLong(finalRelative, offset, (long) v);
getter = () -> theUnsafe.getLong(finalRelative, offset);
}
case FLOAT -> {
uploader = (v) -> theUnsafe.putFloat(finalRelative, offset, (float) v);
getter = () -> theUnsafe.getFloat(finalRelative, offset);
}
case DOUBLE -> {
uploader = (v) -> theUnsafe.putDouble(finalRelative, offset, (double) v);
getter = () -> theUnsafe.getDouble(finalRelative, offset);
}
case BOOLEAN -> {
uploader = (v) -> theUnsafe.putBoolean(finalRelative, offset, (boolean) v);
getter = () -> theUnsafe.getBoolean(finalRelative, offset);
}
default -> {
// TODO: check that I have all primitives?
uploader = null;
getter = () -> null;
}
}
} else {
uploader = (v) -> theUnsafe.putObject(finalRelative, offset, v);
getter = () -> theUnsafe.getObject(finalRelative, offset);
}
}
public void set(Object o) {
uploader.accept(o);
// System.out.println(getter.get());
}
public Object get() {
return getter.get();
}
}

View File

@ -0,0 +1,25 @@
package net.montoyo.wd.config.annoconfg.util;
public enum EnumType {
BYTE(byte.class),
SHORT(short.class),
INT(int.class),
LONG(long.class),
FLOAT(float.class),
DOUBLE(double.class),
BOOLEAN(boolean.class),
OTHER(Object.class),
;
Class<?> clazz;
EnumType(Class<?> clazz) {
this.clazz = clazz;
}
public static EnumType forClass(Class<?> clazz) {
for (EnumType value : EnumType.values())
if (value.clazz.equals(clazz)) return value;
return OTHER;
}
}

View File

@ -0,0 +1,38 @@
package net.montoyo.wd.controls;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.Objects;
import java.util.function.Function;
public abstract class ScreenControl {
private final ResourceLocation id;
public ScreenControl(ResourceLocation id) {
this.id = id;
}
public abstract void write(FriendlyByteBuf buf);
public abstract void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException;
@OnlyIn(Dist.CLIENT)
public abstract void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx);
public void checkPerms(int perms, Function<Integer, Boolean> checker, ServerPlayer player) throws MissingPermissionException {
if (!checker.apply(perms)) {
throw new MissingPermissionException(perms, Objects.requireNonNull(player));
}
}
public final ResourceLocation getId() {
return id;
}
}

View File

@ -0,0 +1,77 @@
package net.montoyo.wd.controls;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.loading.FMLEnvironment;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.builtin.*;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.Log;
import java.lang.reflect.Method;
import java.util.HashMap;
// TODO: enable deferred registry of these
public class ScreenControlRegistry {
private static final HashMap<ResourceLocation, ScreenControlType<?>> CONTROL_TYPES = new HashMap<>();
public static void register(ResourceLocation name, ScreenControlType<?> type) {
if (CONTROL_TYPES.containsKey(name)) {
Log.warning("ScreenControlRegistry#CONTROL_TYPES already contains an entry with name " + name);
throw new IllegalArgumentException("Cannot have two entries with the same name.");
}
CONTROL_TYPES.put(name, type);
// lil thing for sanity
// avoids the pain the dist cleaner causes, hopefully
if (!FMLEnvironment.production) {
if (FMLEnvironment.dist.isClient()) {
boolean shouldThrow = false;
try {
Method m = type.clazz.getMethod("handleClient", BlockPos.class, BlockSide.class, ScreenBlockEntity.class, NetworkEvent.Context.class);
OnlyIn onlyIn = m.getAnnotation(OnlyIn.class);
if (onlyIn == null) shouldThrow = true;
Dist d = onlyIn.value(); // idc if this throws, lol
if (d != Dist.CLIENT) shouldThrow = true;
} catch (Throwable ignored) {
}
if (shouldThrow) {
Log.warning("handleClient on ScreenControl classes MUST be marked with `@OnlyIn(Dist.CLIENT)`, but it is not on " + type.clazz);
throw new IllegalStateException(
"handleClient on ScreenControl classes MUST be marked with `@OnlyIn(Dist.CLIENT)`, but it is not on " + type.clazz
);
}
}
}
}
// if needed, the old code
// https://github.com/Mysticpasta1/webdisplays/blob/ff55cbf1b27773c15f44f17ad3364da3a16b6ed9/src/main/java/net/montoyo/wd/net/server/SMessageScreenCtrl.java#L281-L364
// https://github.com/Mysticpasta1/webdisplays/blob/5ce9e4574df356910645b0382628f74d1401e26d/src/main/java/net/montoyo/wd/net/client_bound/S2CMessageScreenUpdate.java#L261-L284
static {
register(SetURLControl.id, new ScreenControlType<>(SetURLControl.class, SetURLControl::new));
register(KeyTypedControl.id, new ScreenControlType<>(KeyTypedControl.class, KeyTypedControl::new));
register(AutoVolumeControl.id, new ScreenControlType<>(AutoVolumeControl.class, AutoVolumeControl::new));
register(JSRequestControl.id, new ScreenControlType<>(JSRequestControl.class, JSRequestControl::new));
register(LaserControl.id, new ScreenControlType<>(LaserControl.class, LaserControl::new));
register(ScreenModifyControl.id, new ScreenControlType<>(ScreenModifyControl.class, ScreenModifyControl::new));
register(ModifyFriendListControl.id, new ScreenControlType<>(ModifyFriendListControl.class, ModifyFriendListControl::new));
register(ManageRightsAndUpdgradesControl.id, new ScreenControlType<>(ManageRightsAndUpdgradesControl.class, ManageRightsAndUpdgradesControl::new));
register(ClickControl.id, new ScreenControlType<>(ClickControl.class, ClickControl::new));
register(OwnerControl.id, new ScreenControlType<>(OwnerControl.class, OwnerControl::new));
register(TurnOffControl.id, new ScreenControlType<>(TurnOffControl.class, (buf) -> TurnOffControl.INSTANCE));
}
public static ScreenControl parse(FriendlyByteBuf buf) {
return CONTROL_TYPES.get(new ResourceLocation(buf.readUtf()))
.deserializer.apply(buf);
}
public static void init() {
/* NO-OP: allows static init to run during mod init in dev env */
}
}

View File

@ -0,0 +1,15 @@
package net.montoyo.wd.controls;
import net.minecraft.network.FriendlyByteBuf;
import java.util.function.Function;
public class ScreenControlType<T extends ScreenControl> {
Class<T> clazz;
Function<FriendlyByteBuf, ScreenControl> deserializer;
public ScreenControlType(Class<T> clazz, Function<FriendlyByteBuf, ScreenControl> deserializer) {
this.clazz = clazz;
this.deserializer = deserializer;
}
}

View File

@ -0,0 +1,49 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.function.Function;
public class AutoVolumeControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:auto_volume");
boolean autoVol;
public AutoVolumeControl(boolean autoVol) {
super(id);
this.autoVol = autoVol;
}
public AutoVolumeControl(FriendlyByteBuf buf) {
super(id);
autoVol = buf.readBoolean();
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeBoolean(autoVol);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
// I feel like there's probably a better permission category
checkPerms(ScreenRights.MANAGE_UPGRADES, permissionChecker, ctx.getSender());
tes.setAutoVolume(side, autoVol);
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
tes.setAutoVolume(side, autoVol);
}
}

View File

@ -0,0 +1,62 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector2i;
import java.util.function.Function;
public class ClickControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:click");
public enum ControlType {
CLICK, MOVE, DOWN, UP
}
ControlType type;
Vector2i coord;
public ClickControl(ControlType type, Vector2i coord) {
this(type, coord, -1);
this.type = type;
}
public ClickControl(ControlType type, Vector2i coord, int button) {
super(id);
this.coord = coord;
}
public ClickControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
coord = new Vector2i(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
coord.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
throw new RuntimeException("Cannot call click control on server");
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
if (coord != null)
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, coord, -1);
tes.handleMouseEvent(side, type, coord, 1);
}
}

View File

@ -0,0 +1,62 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.JSServerRequest;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.function.Function;
public class JSRequestControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:js_req");
int reqId;
JSServerRequest reqType;
Object[] data;
public JSRequestControl(int reqId, JSServerRequest reqType, Object[] data) {
super(id);
this.reqId = reqId;
this.reqType = reqType;
this.data = data;
}
public JSRequestControl(FriendlyByteBuf buf) {
super(id);
reqId = buf.readInt();
reqType = JSServerRequest.fromID(buf.readByte());
if (reqType != null)
data = reqType.deserialize(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeInt(reqId);
buf.writeByte(reqType.ordinal());
if (!reqType.serialize(buf, data))
throw new RuntimeException("Could not serialize CTRL_JS_REQUEST " + reqType);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
ServerPlayer player = ctx.getSender();
// if (reqType == null || data == null) Log.warning("Caught invalid JS request from player %s (UUID %s)", player.getName(), player.getGameProfile().getId().toString());
// else tes.handleJSRequest(player, side, reqId, reqType, data);
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
throw new RuntimeException("TODO");
}
}

View File

@ -0,0 +1,52 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.function.Function;
public class KeyTypedControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:type");
String text;
BlockPos soundPos;
public KeyTypedControl(String text, BlockPos soundPos) {
super(id);
this.text = text;
this.soundPos = soundPos;
}
public KeyTypedControl(FriendlyByteBuf buf) {
super(id);
text = buf.readUtf();
soundPos = buf.readBlockPos();
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeUtf(text);
buf.writeBlockPos(soundPos);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
checkPerms(ScreenRights.INTERACT, permissionChecker, ctx.getSender());
tes.type(side, text, soundPos, ctx.getSender());
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
tes.type(side, text, soundPos);
}
}

View File

@ -0,0 +1,79 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector2i;
import java.util.function.Function;
public class LaserControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:laser");
public enum ControlType {
MOVE, DOWN, UP
}
ControlType type;
Vector2i coord;
int button;
public LaserControl(ControlType type, Vector2i coord) {
this(type, coord, -1);
}
public LaserControl(ControlType type, Vector2i coord, int button) {
super(id);
this.type = type;
this.coord = coord;
this.button = button;
}
public LaserControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
if (!type.equals(ControlType.UP))
coord = new Vector2i(buf);
if (!type.equals(ControlType.MOVE))
button = buf.readInt();
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
if (coord != null) coord.writeTo(buf);
if (type != ControlType.MOVE) buf.writeInt(button);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
// feel like this makes sense, but I wanna get opinions first
// checkPerms(ScreenRights.INTERACT, permissionChecker, ctx.getSender());
ServerPlayer sender = ctx.getSender();
switch (type) {
case UP -> tes.laserUp(side, sender, button);
case DOWN -> tes.laserDownMove(side, sender, coord, true, button);
case MOVE -> tes.laserDownMove(side, sender, coord, false, button);
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
if (coord != null)
tes.handleMouseEvent(side, ClickControl.ControlType.MOVE, coord, -1);
switch (type) {
case UP -> tes.handleMouseEvent(side, ClickControl.ControlType.UP, coord, button);
case DOWN -> tes.handleMouseEvent(side, ClickControl.ControlType.DOWN, coord, button);
}
}
}

View File

@ -0,0 +1,125 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenData;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.function.Function;
/**
* TODO: I'm considering merging this with {@link ModifyFriendListControl} to make ManageScreenControl
*/
@Deprecated
public class ManageRightsAndUpdgradesControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:mod_rights_upgrades");
public enum ControlType {
RIGHTS, UPGRADES
}
ControlType type;
boolean adding;
ItemStack toRemove;
private int friendRights;
private int otherRights;
public ManageRightsAndUpdgradesControl(boolean adding, ItemStack toRemove) {
super(id);
this.adding = adding;
type = ControlType.UPGRADES;
this.toRemove = toRemove;
}
public ManageRightsAndUpdgradesControl(int friendRights, int otherRights) {
super(id);
type = ControlType.RIGHTS;
this.friendRights = friendRights;
this.otherRights = otherRights;
}
public ManageRightsAndUpdgradesControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
switch (type) {
case UPGRADES -> {
adding = buf.readBoolean();
toRemove = buf.readItem();
}
case RIGHTS -> {
friendRights = buf.readInt();
otherRights = buf.readInt();
}
}
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
switch (type) {
case UPGRADES -> {
buf.writeBoolean(adding);
buf.writeItem(toRemove);
}
case RIGHTS -> {
buf.writeInt(friendRights);
buf.writeInt(otherRights);
}
}
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
ServerPlayer player = ctx.getSender();
switch (type) {
case UPGRADES -> {
checkPerms(ScreenRights.MANAGE_UPGRADES, permissionChecker, ctx.getSender());
if (adding)
throw new RuntimeException("Cannot add an upgrade from the client");
else tes.removeUpgrade(side, toRemove, player);
}
case RIGHTS -> {
ScreenData scr = tes.getScreen(side);
int fr = scr.owner.uuid.equals(player.getGameProfile().getId()) ? friendRights : scr.friendRights;
int or = (scr.rightsFor(player) & ScreenRights.MANAGE_OTHER_RIGHTS) == 0 ? scr.otherRights : otherRights;
if(scr.friendRights != fr || scr.otherRights != or)
tes.setRights(player, side, fr, or);
}
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
ServerPlayer player = ctx.getSender();
switch (type) {
case UPGRADES -> {
if (adding)
tes.addUpgrade(side, toRemove, player, true);
else tes.removeUpgrade(side, toRemove, player);
}
case RIGHTS -> {
ScreenData scr = tes.getScreen(side);
int fr = friendRights;
int or = otherRights;
if(scr.friendRights != fr || scr.otherRights != or)
tes.setRights(player, side, fr, or);
}
}
}
}

View File

@ -0,0 +1,56 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.serialization.NameUUIDPair;
import java.util.function.Function;
public class ModifyFriendListControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:mod_friend_list");
boolean adding;
NameUUIDPair friend;
public ModifyFriendListControl(NameUUIDPair pair, boolean adding) {
super(id);
this.adding = adding;
this.friend = pair;
}
public ModifyFriendListControl(FriendlyByteBuf buf) {
super(id);
adding = buf.readBoolean();
friend = new NameUUIDPair(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeBoolean(adding);
friend.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
ServerPlayer player = ctx.getSender();
checkPerms(ScreenRights.MANAGE_FRIEND_LIST, permissionChecker, ctx.getSender());
if (adding) tes.addFriend(player, side, friend);
else tes.removeFriend(player, side, friend);
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
throw new RuntimeException("TODO");
}
}

View File

@ -0,0 +1,47 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.serialization.NameUUIDPair;
import java.util.function.Function;
public class OwnerControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:set_owner");
NameUUIDPair owner;
public OwnerControl(NameUUIDPair pair) {
super(id);
this.owner = pair;
}
public OwnerControl(FriendlyByteBuf buf) {
super(id);
owner = new NameUUIDPair(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
owner.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
throw new RuntimeException("Cannot handle ownership theft packet from server");
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
tes.getScreen(side).owner = owner;
}
}

View File

@ -0,0 +1,74 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.data.Rotation;
import net.montoyo.wd.utilities.math.Vector2i;
import java.util.function.Function;
public class ScreenModifyControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:mod_screen");
public enum ControlType {
RESOLUTION, ROTATION
}
ControlType type;
Vector2i res;
Rotation rotation;
public ScreenModifyControl(Vector2i res) {
super(id);
this.type = ControlType.RESOLUTION;
this.res = res;
}
public ScreenModifyControl(Rotation rotation) {
super(id);
this.type = ControlType.ROTATION;
this.rotation = rotation;
}
public ScreenModifyControl(FriendlyByteBuf buf) {
super(id);
type = ControlType.values()[buf.readByte()];
if (type.equals(ControlType.RESOLUTION))
res = new Vector2i(buf);
else rotation = Rotation.values()[buf.readByte()];
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeByte(type.ordinal());
if (res != null) res.writeTo(buf);
else if (rotation != null) buf.writeByte(rotation.ordinal());
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
checkPerms(ScreenRights.MODIFY_SCREEN, permissionChecker, ctx.getSender());
switch (type) {
case RESOLUTION -> tes.setResolution(side, res);
case ROTATION -> tes.setRotation(side, rotation);
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
switch (type) {
case RESOLUTION -> tes.setResolution(side, res);
case ROTATION -> tes.setRotation(side, rotation);
}
}
}

View File

@ -0,0 +1,63 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.core.ScreenRights;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector3i;
import java.util.function.Function;
public class SetURLControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:set_url");
String url;
Vector3i remoteLocation;
public SetURLControl(String url, Vector3i remoteLocation) {
super(id);
this.url = url;
this.remoteLocation = remoteLocation;
}
public SetURLControl(FriendlyByteBuf buf) {
super(id);
url = buf.readUtf();
if (buf.readBoolean()) remoteLocation = new Vector3i(buf);
}
@Override
public void write(FriendlyByteBuf buf) {
buf.writeUtf(url);
buf.writeBoolean(remoteLocation != null);
if (remoteLocation != null) remoteLocation.writeTo(buf);
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
// TODO: deal with remote
checkPerms(ScreenRights.CHANGE_URL, permissionChecker, ctx.getSender());
try {
tes.setScreenURL(side, url);
} catch (Throwable err) {
err.printStackTrace();
}
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
try {
tes.setScreenURL(side, url);
} catch (Throwable err) {
err.printStackTrace();
}
}
}

View File

@ -0,0 +1,48 @@
package net.montoyo.wd.controls.builtin;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.network.NetworkEvent;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.controls.ScreenControl;
import net.montoyo.wd.core.MissingPermissionException;
import net.montoyo.wd.entity.ScreenBlockEntity;
import net.montoyo.wd.utilities.data.BlockSide;
import java.util.function.Function;
public class TurnOffControl extends ScreenControl {
public static final ResourceLocation id = new ResourceLocation("webdisplays:deactivate");
public static final TurnOffControl INSTANCE = new TurnOffControl();
public TurnOffControl() {
super(id);
}
@Override
public void write(FriendlyByteBuf buf) {
}
@Override
public void handleServer(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx, Function<Integer, Boolean> permissionChecker) throws MissingPermissionException {
throw new RuntimeException("Cannot handle deactivation packet from server");
}
@Override
@OnlyIn(Dist.CLIENT)
public void handleClient(BlockPos pos, BlockSide side, ScreenBlockEntity tes, NetworkEvent.Context ctx) {
if (side != null) {
WebDisplays.PROXY.closeGui(pos, side);
tes.disableScreen(side);
} else {
for (BlockSide value : BlockSide.values()) {
WebDisplays.PROXY.closeGui(pos, value);
tes.disableScreen(value);
}
}
}
}

View File

@ -1,24 +0,0 @@
/*
* Copyright (C) 2018 BARBOTIN Nicolas
*/
package net.montoyo.wd.core;
public enum AdvancementIcon {
WEB_DISPLAYS("wd"),
BROKEN_PAD("brokenpad"),
PIGEON("pigeon");
private final String name;
AdvancementIcon(String n) {
name = n;
}
@Override
public String toString() {
return name;
}
}

View File

@ -7,6 +7,7 @@ package net.montoyo.wd.core;
import java.util.List;
import java.util.Map;
// TODO: bring this back when SSR is implemented
public class CCArguments implements IComputerArgs {
private final Object[] args;

View File

@ -5,20 +5,18 @@
package net.montoyo.wd.core;
import net.minecraft.world.item.ItemStack;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.init.ItemInit;
import net.montoyo.wd.registry.ItemRegistry;
public enum CraftComponent {
STONE_KEY("stonekey", "Stone_Key"),
BLANK_UPGRADE("upgrade", "Blank_Upgrade"),
PERIPHERAL_BASE("peripheral", "Peripheral_Base"),
BATTERY_CELL("batcell", "Battery_Cell"),
BATTERY_PACK("batpack", "Battery_Pack"),
LASER_DIODE("laserdiode", "Laser_Diode"),
STONEKEY("stonekey", "StoneKey"),
UPGRADE("upgrade", "Upgrade"),
PERIPHERAL("peripheral", "Peripheral"),
BATCELL("batcell", "BatCell"),
BATPACK("batpack", "BatPack"),
LASERDIODE("laserdiode", "LaserDiode"),
BACKLIGHT("backlight", "Backlight"),
EXTENSION_CARD("extcard", "Blank_Upgrade"),
BAD_EXTENSION_CARD("badextcard", "Bad_Extension_Card");
EXTCARD("extcard", "ExtCard"),
BADEXTCARD("badextcard", "BadExtCard");
private final String name;
private final String wikiName;
@ -34,7 +32,6 @@ public enum CraftComponent {
}
public ItemStack makeItemStack() {
return new ItemStack(ItemInit.itemCraftComp.get(), 1);
return new ItemStack(ItemRegistry.getComputerCraftItem(ordinal()).get(), 1);
}
}

View File

@ -7,6 +7,7 @@ package net.montoyo.wd.core;
import com.google.gson.JsonObject;
import net.minecraft.advancements.CriterionTrigger;
import net.minecraft.advancements.critereon.AbstractCriterionTriggerInstance;
import net.minecraft.advancements.critereon.ContextAwarePredicate;
import net.minecraft.advancements.critereon.DeserializationContext;
import net.minecraft.advancements.critereon.EntityPredicate;
import net.minecraft.resources.ResourceLocation;
@ -19,10 +20,8 @@ import java.util.Arrays;
import java.util.HashMap;
public class Criterion implements CriterionTrigger<Criterion.Instance> {
public static class Instance extends AbstractCriterionTriggerInstance {
public Instance(ResourceLocation id, EntityPredicate.Composite arg2) {
public Instance(ResourceLocation id, ContextAwarePredicate arg2) {
super(id, arg2);
}
}
@ -60,16 +59,15 @@ public class Criterion implements CriterionTrigger<Criterion.Instance> {
@Override
public @NotNull Instance createInstance(JsonObject json, DeserializationContext context) {
return new Instance(id, EntityPredicate.Composite.fromJson(json, "instance", context));
return new Instance(id, EntityPredicate.fromJson(json, "instance", context));
}
public void trigger(PlayerAdvancements ply) {
ArrayList<Listener<Instance>> listeners = map.get(ply);
if(listeners != null) {
if (listeners != null) {
Listener[] copy = listeners.toArray(new Listener[0]); //We need to make a copy, otherwise we get a ConcurrentModificationException
Arrays.stream(copy).forEach(l -> l.run(ply));
}
}
}

View File

@ -8,22 +8,22 @@ import net.minecraft.util.StringRepresentable;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.montoyo.wd.entity.TileEntityKeyboard;
import net.montoyo.wd.entity.TileEntityRCtrl;
import net.montoyo.wd.entity.TileEntityRedCtrl;
import net.montoyo.wd.entity.TileEntityServer;
import net.montoyo.wd.entity.KeyboardBlockEntity;
import net.montoyo.wd.entity.RemoteControlBlockEntity;
import net.montoyo.wd.entity.RedstoneControlBlockEntity;
import net.montoyo.wd.entity.ServerBlockEntity;
import net.montoyo.wd.registry.BlockRegistry;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
public enum DefaultPeripheral implements StringRepresentable {
KEYBOARD("keyboard", "Keyboard", TileEntityKeyboard::new, TileEntityKeyboard::getBlockFromTE), //WITH FACING (< 3)
KEYBOARD("keyboard", "Keyboard", KeyboardBlockEntity::new, BlockRegistry.KEYBOARD_BLOCK), //WITH FACING (< 3)
// CC_INTERFACE("ccinterface", "ComputerCraft_Interface", TileEntityCCInterface.class),
// OC_INTERFACE("cointerface", "OpenComputers_Interface", TileEntityOCInterface.class),
REMOTE_CONTROLLER("remotectrl", "Remote_Controller", TileEntityRCtrl::new ,TileEntityRCtrl::getBlockFromTE), //WITHOUT FACING (>= 3)
REDSTONE_CONTROLLER("redstonectrl", "Redstone_Controller", TileEntityRedCtrl::new ,TileEntityRedCtrl::getBlockFromTE),
SERVER("server", "Server", TileEntityServer::new, TileEntityServer::getBlockFromTE);
REMOTE_CONTROLLER("remotectrl", "Remote_Controller", RemoteControlBlockEntity::new , BlockRegistry.REMOTE_CONTROLLER_BLOCK), //WITHOUT FACING (>= 3)
REDSTONE_CONTROLLER("redstonectrl", "Redstone_Controller", RedstoneControlBlockEntity::new , BlockRegistry.REDSTONE_CONTROL_BLOCK),
SERVER("server", "Server", ServerBlockEntity::new, BlockRegistry.SERVER_BLOCK);
private final String name;
private final String wikiName;

View File

@ -5,19 +5,16 @@
package net.montoyo.wd.core;
import net.minecraft.world.item.ItemStack;
import net.montoyo.wd.WebDisplays;
import net.montoyo.wd.config.ModConfig;
import net.montoyo.wd.init.ItemInit;
import net.montoyo.wd.item.ItemUpgrade;
public enum DefaultUpgrade {
LASER_MOUSE("lasermouse", "Laser_Sensor"),
REDSTONE_INPUT("redinput", "Redstone_Input_Port"),
REDSTONE_OUTPUT("redoutput", "Redstone_Output_Port"),
GPS("gps", "GPS_Module");
private final String name;
private final String wikiName;
LASERMOUSE("lasermouse", "LaserMouse"),
REDINPUT("redinput", "RedInput"),
REDOUTPUT("redoutput", "RedOutput"),
GPS("gps", "GPS");
public final String name;
public final String wikiName;
DefaultUpgrade(String n, String wn) {
name = n;
@ -29,7 +26,25 @@ public enum DefaultUpgrade {
return name;
}
public boolean matches(ItemStack is) {
return is.getItem() == ItemInit.itemUpgrade.get();
protected static boolean matches(ItemStack stack, DefaultUpgrade upgrade) {
if (stack.getItem() instanceof ItemUpgrade upgrade1)
return upgrade1.type == upgrade;
return false;
}
public boolean matchesLaserMouse(ItemStack is) {
return matches(is, LASERMOUSE);
}
public boolean matchesRedInput(ItemStack is) {
return matches(is, REDINPUT);
}
public boolean matchesRedOutput(ItemStack is) {
return matches(is, REDOUTPUT);
}
public boolean matchesGps(ItemStack is) {
return matches(is, GPS);
}
}

View File

@ -5,9 +5,7 @@
package net.montoyo.wd.core;
public enum HasAdvancement {
DONT_KNOW,
YES,
NO
}

View File

@ -7,10 +7,8 @@ package net.montoyo.wd.core;
import java.util.Map;
public interface IComputerArgs {
String checkString(int i);
int checkInteger(int i);
Map checkTable(int i);
int count();
}

View File

@ -7,11 +7,9 @@ package net.montoyo.wd.core;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.montoyo.wd.utilities.BlockSide;
import net.montoyo.wd.utilities.Vector3i;
import net.montoyo.wd.utilities.data.BlockSide;
import net.montoyo.wd.utilities.math.Vector3i;
public interface IPeripheral {
boolean connect(Level world, BlockPos blockPos, BlockState blockState, Vector3i screenPos, BlockSide screenSide);
}

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