9
0
mirror of https://github.com/VolmitSoftware/Iris.git synced 2026-01-04 15:41:30 +00:00

Compare commits

...

193 Commits

Author SHA1 Message Date
Brian Neumann-Fopiano
c3ac41f894 V+
lol
2024-08-15 12:58:01 -04:00
Julian Krings
d0688782b1 fix getEngineData NullPointer 2024-08-15 18:47:27 +02:00
Julian Krings
25b41fe62c add 1.21.1 support 2024-08-15 18:42:23 +02:00
repixelatedmc
68ad206252 Eh yeah should do 2024-08-12 08:08:23 +02:00
Brian Neumann-Fopiano
79d6f34879 v+ 2024-08-03 14:42:07 -04:00
Julian Krings
ceb6c15c97 tall_seagrass isnt sticking out of water anymore
by RePixelatedMC
2024-08-03 18:45:44 +02:00
Julian Krings
7cf43ad7ab fix world creation 2024-08-03 18:04:37 +02:00
Julian Krings
ab3397a373 fix pack download command 2024-08-03 15:30:56 +02:00
Julian Krings
8e9f78e982 fix region zoom 2024-08-03 13:03:50 +02:00
Julian Krings
61bbfee640 Update README.md 2024-08-02 18:20:25 +02:00
Brian Neumann-Fopiano
cf4796bd12 V+ 2024-07-31 18:45:13 -04:00
Julian Krings
bd89d8a308 change version to show 1.21 compat 2024-08-01 00:20:30 +02:00
Julian Krings
df2186d70f Merge pull request #1110 from VolmitSoftware/v1_21
1.21 Support
2024-07-31 23:52:10 +02:00
Julian Krings
f9638e830f update NMSTools 2024-07-30 12:56:27 +02:00
Julian Krings
cd55a7fed4 fix getBiomeColor for 1.19.2 2024-07-27 15:43:09 +02:00
Julian Krings
fc890a5ba1 fix missing getBiomeColor method 2024-07-27 15:42:51 +02:00
Julian Krings
2ea54b7f2f 1.21 nms bindings 2024-07-24 19:59:01 +02:00
Brian Fopiano
e90e3901f5 Merge pull request #1109 from VolmitSoftware/fixes
Fixes
2024-07-23 15:43:33 -04:00
Brian Fopiano
36d58f29ab Merge pull request #1108 from VolmitSoftware/better_nms
Better NMS
2024-07-23 15:43:21 -04:00
Brian Fopiano
864c7ae27c Merge pull request #1106 from VolmitDev/custom_data
improve custom block/item api to allow custom settings
2024-07-23 15:43:04 -04:00
Julian Krings
6d104a2d1c fix y-coordinate for getting biome 2024-07-23 20:05:05 +02:00
Julian Krings
89e754245d add maxTries to IrisLootTable to prevent crash 2024-07-21 16:00:02 +02:00
Julian Krings
4c68d99c6f fix returning black color in biomes without a color override 2024-07-21 15:50:45 +02:00
Julian Krings
f8f0a65f0a add debug info to the updater 2024-07-21 15:25:31 +02:00
Julian Krings
6ff74639b5 use custom nms gradle plugin 2024-07-18 17:17:05 +02:00
Julian Krings
af80f882da add slope condition to sear/shore/surface decorators 2024-07-09 16:25:07 +02:00
Julian Krings
84ce7372c3 implement dimension zoom options 2024-07-09 16:23:32 +02:00
Julian Krings
e31d39c5f7 fix worldedit selection not updating 2024-07-09 16:19:56 +02:00
Julian Krings
2296c1368b fix WorldEditLink 2024-07-09 16:19:22 +02:00
Brian Fopiano
21d7d96dbc Merge pull request #1107 from RePixelatedMC/master 2024-07-05 00:46:54 -04:00
RePixelatedMC
956e511fe0 Merge remote-tracking branch 'origin/master' 2024-07-04 22:02:42 +02:00
RePixelatedMC
e427887f8c Scary 2024-07-04 22:00:50 +02:00
Julian Krings
88ea43fbbe fix post processing for custom blocks not applying to objects 2024-06-28 18:14:52 +02:00
Julian Krings
29526a80a9 improve custom block/item api to allow custom settings 2024-06-25 13:35:34 +02:00
Julian Krings
48f901fc8c handle null pointer 2024-06-25 13:33:44 +02:00
Julian Krings
6c3f3dc889 update oraxen api 2024-06-24 13:17:11 +02:00
Julian Krings
743410d3ee add nms method to get biome color 2024-06-24 13:16:56 +02:00
Brian Neumann-Fopiano
acccbb028f V+ 2024-06-18 21:32:35 -04:00
Julian Krings
8b31fdc780 Merge pull request #1105 from VolmitDev/jigsaw_dist
Fix jigsaw spawn distances
2024-06-17 17:07:47 +02:00
CrazyDev22
55017b9ac2 Revert "Merge branch 'mca' into jigsaw_dist"
This reverts commit 0288d35c85, reversing
changes made to 8b3577dd0b.
2024-06-16 14:25:47 +02:00
Julian Krings
0288d35c85 Merge branch 'mca' into jigsaw_dist 2024-06-16 14:23:49 +02:00
Julian Krings
8b3577dd0b make divisor used for generating missing jigsaw placement values changeable 2024-06-16 14:06:24 +02:00
Brian Neumann-Fopiano
ced77ec70d V+ 2024-06-09 17:26:08 -04:00
Julian Krings
e1e90f5c8a add toolchain resolver 2024-06-08 08:27:17 +02:00
RePixelatedMC
dc3487583d Merge pull request #25 from VolmitSoftware/merge
merge
2024-06-05 09:53:26 +02:00
RePixelatedMC
e1d73ebcd5 Merge branch 'mca' into merge 2024-06-05 09:53:13 +02:00
RePixelatedMC
d7cf3b9500 no gui for now 2024-06-03 10:03:14 +02:00
Brian Fopiano
8ce4e3c6b2 Merge pull request #1104 from RePixelatedMC/master
small changes
2024-06-01 10:30:21 -04:00
RePixelatedMC
76f7d46b22 e 2024-06-01 16:26:21 +02:00
RePixelatedMC
cfc52ed909 Tuning + Fixed server distro reading for 1.20.6+ 2024-06-01 16:21:57 +02:00
RePixelatedMC
cee94d40e1 Merge branch 'master' of https://github.com/VolmitSoftware/Iris 2024-05-29 10:18:04 +02:00
RePixelatedMC
cad7166cbe Merge pull request #24 from VolmitDev/fix_jigsaw
minor changes to jigsaw
2024-05-25 15:41:05 +02:00
Julian Krings
c05fdbd0ec Merge pull request #1103 from VolmitDev/fix_jigsaw
minor changes to jigsaw placement
2024-05-25 15:39:07 +02:00
CrazyDev22
c9b26ebaff add better backwards compat 2024-05-25 15:34:51 +02:00
CrazyDev22
bee1973390 fix salt not being a long 2024-05-25 15:34:25 +02:00
RePixelatedMC
57efcab0b5 tall_seagrass isnt sticking out of water anymore 2024-05-22 16:55:07 +02:00
RePixelatedMC
b1ab2b84f8 Fixed /iris region going of a chunk instead of x,z coords
Added fast edit commands
- /iris std edit biome is now supported and opens the vscode biome of where you are standing at same with region.
2024-05-22 15:34:45 +02:00
RePixelatedMC
02601e5ee4 Cleanup 2024-05-22 13:32:29 +02:00
RePixelatedMC
070479acf3 Merge branch 'mca' of https://github.com/RePixelatedMC/Iris into PixelatedDev 2024-05-22 13:29:16 +02:00
RePixelatedMC
6b2ba74237 Iris lets the user ingame know when unstable. 2024-05-22 13:28:56 +02:00
RePixelatedMC
619de29710 Merge pull request #23 from VolmitDev/mca
improve iris world protection
2024-05-21 16:39:21 +02:00
CrazyDev22
12556fa98f improve iris world protection 2024-05-21 16:38:28 +02:00
RePixelatedMC
bef4c0497f Merge branch 'mca' of https://github.com/RePixelatedMC/Iris into PixelatedDev 2024-05-21 11:57:03 +02:00
RePixelatedMC
9193497d36 Merge pull request #22 from RePixelatedMC/v3.3
V3.3 x MCA?
2024-05-21 11:56:14 +02:00
RePixelatedMC
ca6affbde9 Merge branch 'master' into v3.3 2024-05-21 11:48:39 +02:00
RePixelatedMC
81c40ce228 Merge branch 'master' of https://github.com/RePixelatedMC/Iris into PixelatedDev 2024-05-21 11:23:52 +02:00
RePixelatedMC
6ba1d571f2 Fallback type when mm not on server 2024-05-21 11:23:24 +02:00
RePixelatedMC
b0663f9b6c Merge branch 'master' into PixelatedDev 2024-05-21 11:22:39 +02:00
RePixelatedMC
3ced6f3e9e Entity Fallback 2024-05-20 14:46:11 +02:00
RePixelatedMC
3146d61efe Merge pull request #19 from VolmitDev/mca
Sync
2024-05-20 14:04:32 +02:00
CrazyDev22
a967b6af85 replace datapack system with a dynamic one 2024-05-20 06:41:38 +02:00
Brian Fopiano
db3bc74364 Merge pull request #1092 from VolmitDev/fix_jigsaw
Jigsaw fixes
2024-05-19 18:21:11 -04:00
CrazyDev22
eb19d9a846 Merge branch 'refs/heads/master' into mca
# Conflicts:
#	build.gradle
#	core/src/main/java/com/volmit/iris/core/ServerConfigurator.java
#	core/src/main/java/com/volmit/iris/core/nms/INMSBinding.java
#	core/src/main/java/com/volmit/iris/engine/object/IrisDimension.java
2024-05-19 20:48:13 +02:00
Julian Krings
96dd299de7 Merge pull request #1102 from VolmitDev/v1_20_R4
move datapack upgrade command under dev
2024-05-19 19:11:43 +02:00
CrazyDev22
aee0806aa8 move datapack upgrade command under dev 2024-05-19 19:10:53 +02:00
Brian Fopiano
e39f13bbb4 Merge pull request #1101 from VolmitDev/v1_20_R4
add datapack upgrade command
2024-05-19 08:49:15 -04:00
CrazyDev22
52ec80d384 add datapack upgrade command 2024-05-19 14:40:19 +02:00
CrazyDev22
d9f8909bdc fix crash when using iris as main world 2024-05-18 23:36:03 +02:00
CrazyDev22
65aa9dc343 minor headless performance improvements 2024-05-18 23:34:53 +02:00
CrazyDev22
9bf7fdf174 headless performance improvements 2024-05-17 20:05:37 +02:00
CrazyDev22
dafb59e5a8 improve chunk existing check 2024-05-17 16:45:59 +02:00
CrazyDev22
79f86ca87d woops wrong height 2024-05-17 16:39:57 +02:00
RePixelatedMC
1749fcf6b5 Merge pull request #18 from VolmitDev/mca
1.20.4 Headless
2024-05-17 16:04:43 +02:00
CrazyDev22
e1a0481cdf implement Headless for 1.20.4 2024-05-17 16:01:21 +02:00
RePixelatedMC
4576b95814 Fixed width offset with /iris std map when dragging 2024-05-16 17:32:32 +02:00
RePixelatedMC
e113fa6a61 Merge branch 'mca' of https://github.com/RePixelatedMC/Iris into PixelatedDev 2024-05-16 16:55:51 +02:00
RePixelatedMC
07228afbff Noise benchmark reworkings 2024-05-16 16:55:14 +02:00
RePixelatedMC
afdffc2453 Merge pull request #17 from VolmitDev/fix_jigsaw
Sync jigsaw
2024-05-16 13:41:35 +02:00
CrazyDev22
6348442962 add y lock to fix offset when placing objects 2024-05-16 13:17:17 +02:00
CrazyDev22
fd10c005b0 disable warp to prevent x/z offsets 2024-05-16 13:15:34 +02:00
CrazyDev22
44500d6af9 fix translation not rotating 2024-05-16 13:12:49 +02:00
CrazyDev22
6ddb0b5304 update gson library 2024-05-16 13:12:11 +02:00
Brian Fopiano
8ce0976f88 Merge pull request #1100 from VolmitDev/v1_20_R4
add 1.20.6 support
2024-05-15 19:52:08 -04:00
CrazyDev22
8345a58f2b change safeguard message 2024-05-15 18:11:05 +02:00
CrazyDev22
f92234297e add 1.20.6 support 2024-05-15 18:07:12 +02:00
RePixelatedMC
6a5bcd5990 Merge pull request #16 from VolmitDev/fix_jigsaw
sync Jigsaw
2024-05-15 17:40:29 +02:00
RePixelatedMC
1fe6d9a636 Merge branch 'mca' of https://github.com/RePixelatedMC/Iris into PixelatedDev
# Conflicts:
#	core/src/main/java/com/volmit/iris/core/tools/IrisWorldDump.java
2024-05-15 09:29:48 +02:00
RePixelatedMC
97f6ab66c3 sync 2024-05-15 09:13:00 +02:00
RePixelatedMC
b78c182d94 Map for studio 2024-05-13 16:30:18 +02:00
CrazyDev22
09a0f83013 add terminating pool overwrite 2024-05-11 12:51:29 +02:00
CrazyDev22
f68d7420e3 woops forgot description for SpreadType 2024-05-11 12:50:40 +02:00
CrazyDev22
55c0fa5f32 add command to sample the distances between structures 2024-05-10 15:58:57 +02:00
CrazyDev22
8b5d1d0298 rewrite jigsaw placement logic to prevent placements from being too close 2024-05-10 15:58:26 +02:00
CrazyDev22
b70e94dc65 make manual jigsaw place use the same calculations as normal 2024-05-10 15:43:01 +02:00
CrazyDev22
49a6552168 add forcePlace option to suppress placement checks 2024-05-10 15:41:42 +02:00
Brian Fopiano
0dd6892b28 Merge pull request #1097 from RePixelatedMC/master
Eco Items support
2024-05-09 15:44:13 -04:00
RePixelatedMC
fec587edad Update README.md 2024-05-07 22:42:28 +02:00
RePixelatedMC
712937d661 Merge pull request #15 from VolmitDev/ecoitems
add Ecoitems support
2024-05-04 16:03:08 +02:00
CrazyDev22
ace434e7b0 add EcoItems support 2024-05-04 13:21:55 +02:00
RePixelatedMC
1e5aa6e8b0 Merge branch 'mca' of https://github.com/RePixelatedMC/Iris into PixelatedDev 2024-05-04 11:26:47 +02:00
RePixelatedMC
441b27f8f4 Merge branch 'VolmitSoftware:master' into mca 2024-05-04 11:26:23 +02:00
RePixelatedMC
3f3bf70212 Merge pull request #14 from VolmitDev/mca
Per World Dimension Types + better Datapack reload
2024-05-04 11:26:05 +02:00
RePixelatedMC
a12eddbedf sync 2024-05-04 11:25:17 +02:00
CrazyDev22
12abc1709e add missing method to NMSBinding1X 2024-05-03 21:18:00 +02:00
CrazyDev22
9e6035e7b4 remove debug code 2024-05-03 21:17:02 +02:00
CrazyDev22
20b41d65d3 fixes to the per world dimensions + optimizations with the register method 2024-05-03 21:01:10 +02:00
CrazyDev22
1593bb2088 make smartVanillaHeight also adjust the logicalHeight 2024-05-03 19:57:34 +02:00
CrazyDev22
d4f9a20379 more removal of unnecessary settings 2024-05-03 19:56:43 +02:00
CrazyDev22
6e247597a4 fix loading the wrong IrisDimension on startup 2024-05-03 19:55:58 +02:00
CrazyDev22
8a8be4545c remove unnecessary minecraft dimension height calculations 2024-05-03 19:11:55 +02:00
CrazyDev22
05f4955989 implement proper datapack reload+per world height 2024-05-03 19:01:33 +02:00
CrazyDev22
93469fb3b4 include translate option into the bounding box of jigsaw pieces 2024-05-01 20:01:10 +02:00
RePixelatedMC
a70258d69f Merge branch 'fix_jigsaw' of https://github.com/VolmitDev/Iris into PixelatedDev 2024-05-01 18:55:02 +02:00
CrazyDev22
c653d852e4 make jigsaw place command use the same method as normal gen 2024-05-01 18:46:22 +02:00
CrazyDev22
40163d25b8 add object shink command for fixing too large/small bounding boxes for objects 2024-05-01 18:44:45 +02:00
CrazyDev22
5b4265783e fix object w/h/d not changing with rotation 2024-05-01 18:42:23 +02:00
CrazyDev22
720417b6c8 fix shrinkwrap method 2024-05-01 18:39:42 +02:00
RePixelatedMC
bb78f412e0 Sync / Progress on dump 2024-05-01 12:21:48 +02:00
RePixelatedMC
a919b91efb Whohoo! we can now read mca files! 2024-04-30 11:14:35 +02:00
Brian Neumann-Fopiano
a3dcf031c9 v+ , and the other v+ lol 2024-04-29 15:45:41 -04:00
RePixelatedMC
56eb4b6b84 Iris is small now! still a bit too big for spigot probably 2024-04-28 11:56:18 +02:00
RePixelatedMC
393cb362db - "Hey stop that! Its my World not yours."
- Safeguard displays itself before the worlds now.
- TODO: Minimize jar 7.5 MB > Under Spigots limit
2024-04-28 11:22:10 +02:00
RePixelatedMC
64e422036c Merge branch 'fix_jigsaw' of https://github.com/VolmitDev/Iris into PixelatedDev 2024-04-27 17:14:16 +02:00
RePixelatedMC
468e7ef018 Merge pull request #1094 from RePixelatedMC/master
Update README.md
2024-04-27 12:42:50 +02:00
RePixelatedMC
e3e4ecbc5c Update README.md 2024-04-27 12:41:29 +02:00
RePixelatedMC
545ffc0e9d splash cleanup 2024-04-27 12:36:41 +02:00
RePixelatedMC
8125c8d5f4 fixes 2024-04-27 12:18:28 +02:00
RePixelatedMC
304b01d0cf Merge pull request #13 from VolmitDev/mca
add hotload
2024-04-27 10:54:38 +02:00
CrazyDev22
a5f687fd76 fix ServerConfigurator 2024-04-26 18:14:40 +02:00
CrazyDev22
fc1761a55b add nms method to hotload Datapacks 2024-04-26 18:14:22 +02:00
RePixelatedMC
e7c9cad7f6 Merge pull request #1093 from RePixelatedMC/3.2.5
3.2.5
2024-04-26 18:06:37 +02:00
RePixelatedMC
979af82122 here crazy 2024-04-26 11:16:09 +02:00
RePixelatedMC
71a62b9c73 Merge pull request #12 from VolmitDev/mca
fix NMSBindings
2024-04-24 17:58:44 +02:00
CrazyDev22
bb020cab25 fix NMSBindings 2024-04-24 17:55:40 +02:00
RePixelatedMC
1ad35c1310 sync multiple mca fixes 2024-04-24 16:01:11 +02:00
CrazyDev22
6470b2f4a9 fix another null pointer 2024-04-23 13:49:30 +02:00
CrazyDev22
c1d5ba55cd fix null pointer 2024-04-23 13:49:10 +02:00
CrazyDev22
100e450514 fix jigsaw piece collision 2024-04-23 13:48:47 +02:00
RePixelatedMC
0f1d1d9860 Merge remote-tracking branch 'VolmitDev/fix_jigsaw' into PixelatedDev 2024-04-23 12:31:26 +02:00
RePixelatedMC
178a462a4e e 2024-04-23 12:29:19 +02:00
RePixelatedMC
8f4ae613f0 Merge branch '3.2.5' of https://github.com/RePixelatedMC/Iris into PixelatedDev
# Conflicts:
#	core/src/main/java/com/volmit/iris/core/commands/CommandIris.java
2024-04-23 11:29:18 +02:00
RePixelatedMC
9e6963b6ce A lot of improvements thanks to CrazyDev! 2024-04-23 11:24:53 +02:00
CrazyDev22
cb9a73c60e rename IrisJigsawDistance to IrisJigsawMinDistance to avoid confusion 2024-04-23 10:28:04 +02:00
CrazyDev22
0e666a4c35 change rng noise for jigsaw component 2024-04-22 14:23:45 +02:00
CrazyDev22
c80138a354 Merge branch 'refs/heads/master' into fix_jigsaw 2024-04-22 14:14:48 +02:00
CrazyDev22
79a4ebcf65 woops 2024-04-19 15:29:28 +02:00
CrazyDev22
a7118aa785 fix jigsaw place command 2024-04-19 15:18:11 +02:00
RePixelatedMC
2555cd23a0 Merge branch 'VolmitSoftware:master' into 3.2.6 2024-04-19 15:17:21 +02:00
RePixelatedMC
484fbeca7b Merge branch '3.2.6' of https://github.com/RePixelatedMC/Iris into PixelatedDev
# Conflicts:
#	core/src/main/java/com/volmit/iris/core/commands/CommandIris.java
#	core/src/main/java/com/volmit/iris/core/safeguard/ServerBootSFG.java
2024-04-19 15:16:46 +02:00
RePixelatedMC
9a45e0df10 /iris support report ( gives server info )
and cleaned the main splash screen and fixed /iris import saying its loaded successfully even if it didnt
2024-04-19 15:15:08 +02:00
RePixelatedMC
9175296fc6 rev2.0 2024-04-19 12:43:57 +02:00
RePixelatedMC
5a4a86aeba - Iris Updater
Updates chunks thats it/
2024-04-19 10:14:16 +02:00
Brian Neumann-Fopiano
768fa7beb5 v+ 2024-04-19 02:47:02 -04:00
Julian Krings
6645eb9806 Merge branch 'VolmitSoftware:master' into fix_jigsaw 2024-04-18 16:04:30 +02:00
CrazyDev22
d7a283c99f fix underwater jigsaw placement 2024-04-18 16:00:47 +02:00
Brian Fopiano
8f019cd794 Merge pull request #1088 from RePixelatedMC/PixelatedDev
3.2.5 iris
2024-04-18 07:13:52 -04:00
CrazyDev22
c1d9cc62cb woops 2024-04-17 21:21:18 +02:00
Julian Krings
010a1e9e91 Merge branch 'VolmitSoftware:master' into fix_jigsaw 2024-04-17 21:16:08 +02:00
CrazyDev22
856c926cde add min distance to jigsaw structures 2024-04-17 21:15:15 +02:00
RePixelatedMC
72ed312654 wops 2024-04-16 18:09:03 +02:00
RePixelatedMC
c7fe4723f7 Merge remote-tracking branch 'origin/master' into PixelatedDev 2024-04-16 17:18:51 +02:00
RePixelatedMC
bfbea83a4a - Fixed NMS biome height.
- Improved /iris load
- Improved Vanilla height converter
- Removed WorldCreation unstable message
2024-04-16 17:18:02 +02:00
RePixelatedMC
55c58fe896 Merge pull request #1087 from RePixelatedMC/PixelatedDev
Should work
2024-04-16 16:34:12 +02:00
RePixelatedMC
72949e0950 Update IrisSettings.java 2024-04-16 16:32:52 +02:00
CrazyDev22
61c0ddb15b fix random jigsaw rotation and offset 2024-04-16 13:29:06 +02:00
Brian Neumann-Fopiano
9ac4024e4e v+ 2024-04-15 11:43:09 -04:00
RePixelatedMC
7fb2a51a33 sync 2024-04-12 17:08:13 +02:00
RePixelatedMC
5b7c0b2bc3 Merge branch 'PixelatedDev' of https://github.com/RePixelatedMC/Iris into PixelatedDev
# Conflicts:
#	core/src/main/java/com/volmit/iris/engine/object/IrisBiome.java
#	core/src/main/java/com/volmit/iris/engine/object/IrisBiomeGeneratorLink.java
2024-04-09 20:07:50 +02:00
RePixelatedMC
fc15175ff9 Improved? 2024-04-09 20:06:32 +02:00
RePixelatedMC
1eec3a09c1 now it should work 2024-04-09 18:05:27 +02:00
RePixelatedMC
60d349dd8b test 2024-04-09 17:05:43 +02:00
RePixelatedMC
0c8d144ffb Merge remote-tracking branch 'VolmitDev/smartHeight' into PixelatedDev 2024-04-09 17:04:45 +02:00
RePixelatedMC
b898f73a05 Fixed another potential mem leak
Added the base of smart320height
2024-04-09 17:04:32 +02:00
CrazyDev22
c2b9b0ba0e add smartVanillaHeight 2024-04-09 16:52:14 +02:00
RePixelatedMC
206a4e9057 Revert "sync laptop"
This reverts commit 63b8a935ae.
2024-04-06 17:07:14 +02:00
RePixelatedMC
83a0a7dd54 sync laptop 2024-04-06 17:06:06 +02:00
RePixelatedMC
63b8a935ae sync laptop 2024-04-05 18:43:30 +02:00
CrazyDev22
16affd11cc fix HMCLeaves leave decay 2024-04-04 23:46:14 +02:00
CrazyDev22
33b0dec9da fix ClassCastException when replacing to IrisBlockData 2024-04-04 23:45:25 +02:00
RePixelatedMC
c0136585e6 Merge remote-tracking branch 'origin/master' 2024-01-26 10:59:14 +01:00
RePixelatedMC
bad547356c Disabled for now 2024-01-14 16:43:39 +01:00
RePixelatedMC
1740bb0021 whoop 2024-01-14 16:35:00 +01:00
RePixelatedMC
669ede5482 remove turbo for now 2024-01-14 10:18:41 +01:00
99 changed files with 5602 additions and 2019 deletions

View File

@@ -30,14 +30,11 @@ Consider supporting our development by buying Iris on spigot! We work hard to ma
3. Add `export JAVA_HOME=$(/usr/libexec/java_home)` as a new line
4. Use `CTRL + X`, then Press `Y`, Then `ENTER`
5. Quit & Reopen Terminal and verify with `echo $JAVA_HOME`. It should print a directory
3. If this is your first time building Iris for MC 1.18+ run `gradlew setup` inside the root Iris project folder.
Otherwise, skip this step. Grab a coffee, this may take up to 5 minutes depending on your cpu & internet connection.
4. Once the project has setup, run `gradlew iris`
5. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
3. Once the project has setup, run `gradlew iris`
4. The Iris jar will be placed in `Iris/build/Iris-XXX-XXX.jar` Enjoy! Consider supporting us by buying it on spigot!
### IDE Builds (for development)
* Run `gradlew setup` any time you get dependency issues with craftbukkit
* Configure ITJ Gradle to use JDK 17 (in settings, search for gradle)
* Add a build line in the build.gradle for your own build task to directly compile Iris into your plugins folder if you
prefer.
@@ -69,7 +66,6 @@ IrisAccess access=IrisToolbelt.createWorld() // If you like builders...
.name("myWorld") // The world name
.dimension("terrifyinghands")
.seed(69133742) // The world seed
.headless(true) // Headless make gen go fast
.pregen(PregenTask // Define a pregen job to run
.builder()
.center(new Position2(0,0)) // REGION coords (1 region = 32x32 chunks)

View File

@@ -1,5 +1,3 @@
import java.util.function.Consumer
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
@@ -18,15 +16,23 @@ import java.util.function.Consumer
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
buildscript() {
repositories {
maven { url 'https://jitpack.io'}
}
dependencies {
classpath 'com.github.VolmitSoftware:NMSTools:1.0.1'
}
}
plugins {
id 'java'
id 'java-library'
id "com.github.johnrengelman.shadow" version "7.1.2"
id "io.github.goooler.shadow" version "8.1.7"
id "de.undercouch.download" version "5.0.1"
}
version '3.2.2-1.19.2-1.20.4'
def specialSourceVersion = '1.11.0' //[NMS]
version '3.4.1-1.19.2-1.21.1'
// ADD YOURSELF AS A NEW LINE IF YOU WANT YOUR OWN BUILD TASK GENERATED
// ======================== WINDOWS =============================
@@ -37,13 +43,17 @@ registerCustomOutputTask('Coco', 'D://mcsm/plugins')
registerCustomOutputTask('Strange', 'D://Servers/1.17 Test Server/plugins')
registerCustomOutputTask('Vatuu', 'D://Minecraft/Servers/1.19.4/plugins')
registerCustomOutputTask('CrazyDev22', 'C://Users/Julian/Desktop/server/plugins')
registerCustomOutputTask('Pixel', 'C://Users/repix/Iris Dimension Engine/1.20.4 - Iris Development/plugins')
registerCustomOutputTask('Pixel', 'C://Users/repix/Iris Dimension Engine/1.20.4 - Development/plugins')
// ========================== UNIX ==============================
registerCustomOutputTaskUnix('CyberpwnLT', '/Users/danielmills/development/server/plugins')
registerCustomOutputTaskUnix('PsychoLT', '/Volumes/PRO-G40/Minecraft/MinecraftDevelopment/Server/plugins')
registerCustomOutputTaskUnix('PsychoLT', '/Users/brianfopiano/Developer/RemoteGit/Server/plugins')
registerCustomOutputTaskUnix('PixelMac', '/Users/test/Desktop/mcserver/plugins')
registerCustomOutputTaskUnix('CrazyDev22LT', '/home/julian/Desktop/server/plugins')
// ==============================================================
def NMS_BINDINGS = Map.of(
"v1_21_R1", "1.21-R0.1-SNAPSHOT",
"v1_20_R4", "1.20.6-R0.1-SNAPSHOT",
"v1_20_R3", "1.20.4-R0.1-SNAPSHOT",
"v1_20_R2", "1.20.2-R0.1-SNAPSHOT",
"v1_20_R1", "1.20.1-R0.1-SNAPSHOT",
@@ -51,137 +61,31 @@ def NMS_BINDINGS = Map.of(
"v1_19_R2", "1.19.3-R0.1-SNAPSHOT",
"v1_19_R1", "1.19.2-R0.1-SNAPSHOT"
)
NMS_BINDINGS.each {
def key = it.key
def value = it.value
def nms = value.split("-")[0];
project(":nms:${key}") {
apply plugin: 'java-library'
apply plugin: 'de.undercouch.download'
def JVM_VERSION = Map.of(
"v1_21_R1", 21,
"v1_20_R4", 21,
)
NMS_BINDINGS.each { nms ->
project(":nms:${nms.key}") {
apply plugin: 'java'
apply plugin: 'com.volmit.nmstools'
nmsTools {
it.jvm = JVM_VERSION.getOrDefault(nms.key, 17)
it.version = nms.value
}
dependencies {
implementation project(":core")
compileOnly "org.spigotmc:spigot-api:${value}"
compileOnly "org.bukkit:craftbukkit:${value}:remapped-mojang" //[NMS]
}
def buildToolsJar = new File(rootProject.buildDir, "tools/BuildTools.jar")
def specialSourceJar = new File(rootProject.buildDir, "tools/SpecialSource.jar")
def buildToolsFolder = new File(buildDir, "buildtools")
def specialSourceFolder = new File(buildDir, "specialsource")
def buildToolsHint = new File(buildDir, "buildtools/craftbukkit-" + nms + ".jar")
def outputJar = new File(buildDir, "libs/${key}.jar")
def ssiJar = new File(buildDir, "specialsource/${key}.jar")
def ssobfJar = new File(buildDir, "specialsource/${key}-rmo.jar")
def ssJar = new File(buildDir, "specialsource/${key}-rma.jar")
def homePath = System.properties['user.home']
def m2 = new File(homePath + "/.m2/repository")
def m2s = m2.getAbsolutePath();
// ======================== Building Mapped Jars =============================
ext {
executeBuildTools = new Runnable() {
@Override
void run() {
//Download
if (!buildToolsJar.exists()) {
download.run {
src 'https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar'
dest buildToolsJar
}
}
//Execute
if (!buildToolsHint.exists()) {
buildToolsFolder.mkdirs()
project.javaexec {
classpath = files(buildToolsJar)
workingDir = buildToolsFolder
args = [
"--rev",
nms,
"--compile",
"craftbukkit",
"--remap"
]
}
}
}
}
}
tasks.register("executeBuildTools") {
doLast {
property("executeBuildTools").run();
}
}
tasks.build.doLast {
//Download
if (!specialSourceJar.exists()) {
download.run {
src 'https://repo.maven.apache.org/maven2/net/md-5/SpecialSource/' + specialSourceVersion + '/SpecialSource-'+specialSourceVersion+'-shaded.jar'
dest specialSourceJar
}
}
specialSourceFolder.mkdirs();
//Copy
copy {
from outputJar
into specialSourceFolder
}
//obfuscate
javaexec {
workingDir = specialSourceFolder
classpath = files(specialSourceJar,
new File(m2s + "/org/spigotmc/spigot/" + value + "/spigot-" + value + "-remapped-mojang.jar"))
mainClass = "net.md_5.specialsource.SpecialSource"
args = [
"--live",
"-i",
ssiJar.getName(),
"-o",
ssobfJar.getName(),
"-m",
m2s + "/org/spigotmc/minecraft-server/" + value + "/minecraft-server-" + value + "-maps-mojang.txt",
"--reverse",
]
}
//remap
javaexec {
workingDir = specialSourceFolder
classpath = files(specialSourceJar,
new File(m2s + "/org/spigotmc/spigot/" + value + "/spigot-" + value + "-remapped-obf.jar"))
mainClass = "net.md_5.specialsource.SpecialSource"
args = [
"--live",
"-i",
ssobfJar.getName(),
"-o",
ssJar.getName(),
"-m",
m2s + "/org/spigotmc/minecraft-server/" + value + "/minecraft-server-" + value + "-maps-spigot.csrg"
]
}
//copy
copy {
from ssJar
into outputJar.getParentFile()
rename {
outputJar.getName()
}
}
}
}
}
shadowJar {
NMS_BINDINGS.each {dependsOn(":nms:${it.key}:build")}
NMS_BINDINGS.each {
dependsOn(":nms:${it.key}:remap")
from("${project(":nms:${it.key}").layout.buildDirectory.asFile.get()}/libs/${it.key}-mapped.jar")
}
//minimize()
append("plugin.yml")
@@ -193,9 +97,6 @@ shadowJar {
dependencies {
implementation project(':core')
NMS_BINDINGS.each {
implementation project(":nms:${it.key}")
}
}
configurations.configureEach {
@@ -207,12 +108,6 @@ allprojects {
apply plugin: 'java'
repositories {
mavenLocal {
content {
includeGroup("org.bukkit")
includeGroup("org.spigotmc")
}
}
mavenCentral()
maven { url "https://repo.papermc.io/repository/maven-public/"}
maven { url "https://repo.codemc.org/repository/maven-public" }
@@ -224,6 +119,7 @@ allprojects {
maven { url "https://repo.triumphteam.dev/snapshots" }
maven { url "https://repo.mineinabyss.com/releases" }
maven { url 'https://hub.jeff-media.com/nexus/repository/jeff-media-public/' }
maven { url "https://repo.oraxen.com/releases" }
}
dependencies {
@@ -237,6 +133,8 @@ allprojects {
implementation "net.kyori:adventure-text-minimessage:4.13.1"
implementation 'net.kyori:adventure-platform-bukkit:4.3.2'
implementation 'net.kyori:adventure-api:4.13.1'
//implementation 'org.bytedeco:javacpp:1.5.10'
//implementation 'org.bytedeco:cuda-platform:12.3-8.9-1.5.10'
compileOnly 'io.lumine:Mythic-Dist:5.2.1'
// Dynamically Loaded
@@ -244,7 +142,7 @@ allprojects {
compileOnly 'it.unimi.dsi:fastutil:8.5.8'
compileOnly 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
compileOnly 'org.zeroturnaround:zt-zip:1.14'
compileOnly 'com.google.code.gson:gson:2.9.0'
compileOnly 'com.google.code.gson:gson:2.10.1'
compileOnly 'org.ow2.asm:asm:9.2'
compileOnly 'com.google.guava:guava:33.0.0-jre'
compileOnly 'bsf:bsf:2.4.0'
@@ -282,34 +180,11 @@ if (JavaVersion.current().toString() != "17") {
task iris(type: Copy) {
group "iris"
from new File(buildDir, "libs/Iris-${version}.jar")
into buildDir
from new File(layout.buildDirectory.asFile.get(), "libs/Iris-${version}.jar")
into layout.buildDirectory.asFile.get()
dependsOn(build)
}
task setup() {
group "iris"
dependsOn(clean)
NMS_BINDINGS.each {
dependsOn(":nms:${it.key}:clean");
}
doLast {
NMS_BINDINGS.each {
project(":nms:${it.key}").property("executeBuildTools").run();
}
}
}
NMS_BINDINGS.keySet().forEach {
def nms = it
tasks.register("setup-${nms}") {
group "iris"
dependsOn(":nms:${nms}:clean")
dependsOn(":nms:${nms}:executeBuildTools")
}
}
def registerCustomOutputTask(name, path) {
if (!System.properties['os.name'].toLowerCase().contains('windows')) {
return;

View File

@@ -19,7 +19,7 @@
plugins {
id 'java'
id 'java-library'
id "io.freefair.lombok" version "6.3.0"
id "io.freefair.lombok" version "8.6"
}
def apiVersion = '1.19'
@@ -35,6 +35,7 @@ compileJava {
repositories {
maven { url 'https://nexus.phoenixdevt.fr/repository/maven-public/'}
maven { url 'https://repo.auxilor.io/repository/maven-public/' }
}
/**
@@ -61,11 +62,12 @@ dependencies {
// Third Party Integrations
compileOnly 'com.ticxo.playeranimator:PlayerAnimator:R1.2.7'
compileOnly 'com.github.oraxen:oraxen:1.158.0'
compileOnly 'io.th0rgal:oraxen:1.173.0'
compileOnly 'com.github.LoneDev6:api-itemsadder:3.4.1-r4'
compileOnly 'com.github.PlaceholderAPI:placeholderapi:2.11.3'
compileOnly 'com.github.Ssomar-Developement:SCore:4.23.10.8'
compileOnly 'net.Indyuce:MMOItems-API:6.9.5-SNAPSHOT'
compileOnly 'com.willfp:EcoItems:5.44.0'
//implementation files('libs/CustomItems.jar')
}

View File

@@ -739,7 +739,7 @@ public class Iris extends VolmitPlugin implements Listener {
service(StudioSVC.class).installIntoWorld(getSender(), dim.getLoadKey(), w.worldFolder());
}
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false);
}
public void splash() {
@@ -806,9 +806,6 @@ public class Iris extends VolmitPlugin implements Listener {
} else {
splash = splashstable;
}
OperatingSystemMXBean osBean = ManagementFactory.getOperatingSystemMXBean();
String osArch = osBean.getArch();
String osName = osBean.getName();
if (!passedserversoftware) {
Iris.info("Server type & version: " + C.RED + Bukkit.getVersion());
@@ -821,37 +818,11 @@ public class Iris extends VolmitPlugin implements Listener {
Iris.info(C.YELLOW + "Purpur is recommended to use with iris.");
}
}
Iris.info("Server OS: " + osName + " (" + osArch + ")");
try {
if (warningmode){
Iris.info("Server Cpu: " + C.GOLD + getCPUModel());
} else {
if(unstablemode){
Iris.info("Server Cpu: " + C.DARK_RED + getCPUModel());
} else {
if (getCPUModel().contains("Intel")) {
Iris.info("Server Cpu: " + C.BLUE + getCPUModel());
}
if (getCPUModel().contains("Ryzen")) {
Iris.info("Server Cpu: " + C.RED + getCPUModel());
}
if (!getCPUModel().contains("Ryzen") && !getCPUModel().contains("Intel")) {
Iris.info("Server Cpu: " + C.GRAY + getCPUModel());
}
}
}
} catch (Exception e){
Iris.info("Server Cpu: " + C.DARK_RED + "Failed");
}
Iris.info("Process Threads: " + Runtime.getRuntime().availableProcessors());
Iris.info("Process Memory: " + getHardware.getProcessMemory() + " MB");
Iris.info("Free DiskSpace: " + Form.ofSize(freeSpace.getFreeSpace(), 1024));
if (getHardware.getProcessMemory() < 5999) {
Iris.warn("6GB+ Ram is recommended");
Iris.warn("Process Memory: " + getHardware.getProcessMemory() + " MB");
}
Iris.info("Bukkit version: " + Bukkit.getBukkitVersion());
Iris.info("Bukkit distro: " + Bukkit.getName());
Iris.info("Custom Biomes: " + INMS.get().countCustomBiomes());
setupChecks();
printPacks();

View File

@@ -146,7 +146,7 @@ public class IrisSettings {
@Data
public static class IrisSettingsGeneral {
public boolean ignoreBootMode = false;
public boolean DoomsdayAnnihilationSelfDestructMode = false;
public boolean commandSounds = true;
public boolean debug = false;
public boolean disableNMS = false;
@@ -177,7 +177,6 @@ public class IrisSettings {
public static class IrisSettingsGenerator {
public String defaultWorldType = "overworld";
public int maxBiomeChildDepth = 4;
// public boolean forceConvertTo320Height = false;
public boolean preventLeafDecay = true;
}

View File

@@ -21,6 +21,8 @@ package com.volmit.iris.core;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisDimension;
@@ -91,8 +93,11 @@ public class ServerConfigurator {
return worlds;
}
public static void installDataPacks(boolean fullInstall) {
installDataPacks(DataVersion.getDefault(), fullInstall);
}
public static void installDataPacks(IDataFixer fixer, boolean fullInstall) {
Iris.info("Checking Data Packs...");
File packs = new File("plugins/Iris/packs");
double ultimateMaxHeight = 0;
@@ -137,7 +142,7 @@ public class ServerConfigurator {
Iris.verbose(" Checking Dimension " + dim.getLoadFile().getPath());
for (File dpack : getDatapacksFolder()) {
dim.installDataPack(() -> data, dpack, ultimateMaxHeight, ultimateMinHeight);
dim.installDataPack(fixer, () -> data, dpack, ultimateMaxHeight, ultimateMinHeight);
}
}
}

View File

@@ -19,9 +19,12 @@
package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.IrisEngineSVC;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt;
@@ -40,7 +43,10 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.mantle.TectonicPlate;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.plugin.VolmitSender;
import io.lumine.mythic.bukkit.adapters.BukkitEntity;
import net.jpountz.lz4.LZ4BlockInputStream;
@@ -61,12 +67,14 @@ import java.net.NetworkInterface;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@Decree(name = "Developer", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"dev"})
public class CommandDeveloper implements DecreeExecutor {
private CommandTurboPregen turboPregen;
private CommandUpdater updater;
@Decree(description = "Get Loaded TectonicPlates Count", origin = DecreeOrigin.BOTH, sync = true)
public void EngineStatus() {
@@ -150,9 +158,25 @@ public class CommandDeveloper implements DecreeExecutor {
}
@Decree(description = "Upgrade to another Minecraft version")
public void upgrade(
@Param(description = "The version to upgrade to", defaultValue = "latest") DataVersion version) {
sender().sendMessage(C.GREEN + "Upgrading to " + version.getVersion() + "...");
ServerConfigurator.installDataPacks(version.get(), false);
sender().sendMessage(C.GREEN + "Done upgrading! You can now update your server version to " + version.getVersion());
}
@Decree(description = "test")
public void test() throws NoSuchFieldException, IllegalAccessException {
IrisEngineSVC.instance.engineStatus();
public void mca (
@Param(description = "String") String world) {
try {
File[] McaFiles = new File(world, "region").listFiles((dir, name) -> name.endsWith(".mca"));
for (File mca : McaFiles) {
MCAFile MCARegion = MCAUtil.read(mca);
}
} catch (Exception e) {
e.printStackTrace();
}
}

View File

@@ -20,7 +20,10 @@ package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.ServerConfigurator;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.StudioSVC;
import com.volmit.iris.core.tools.IrisBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt;
@@ -30,12 +33,14 @@ import com.volmit.iris.core.safeguard.UtilsSFG;
import com.volmit.iris.engine.object.IrisWorld;
import com.volmit.iris.engine.platform.BukkitChunkGenerator;
import com.volmit.iris.engine.platform.DummyChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.decree.specialhandlers.NullablePlayerHandler;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
import lombok.Getter;
@@ -75,9 +80,9 @@ public class CommandIris implements DecreeExecutor {
private CommandWhat what;
private CommandEdit edit;
private CommandFind find;
private CommandSupport support;
private CommandDeveloper developer;
public static boolean worldCreation = false;
String WorldToLoad;
String WorldEngine;
String worldNameToCheck = "YourWorldName";
VolmitSender sender = Iris.getSender();
@@ -89,7 +94,9 @@ public class CommandIris implements DecreeExecutor {
@Param(aliases = "dimension", description = "The dimension type to create the world with", defaultValue = "default")
IrisDimension type,
@Param(description = "The seed to generate the world with", defaultValue = "1337")
long seed
long seed,
@Param(description = "If it should convert the dimension to match the vanilla height system.", defaultValue = "false")
boolean vanillaheight
) {
if(sender() instanceof Player) {
if (incompatibilities.get("Multiverse-Core")) {
@@ -133,6 +140,7 @@ public class CommandIris implements DecreeExecutor {
.seed(seed)
.sender(sender())
.studio(false)
.smartVanillaHeight(vanillaheight)
.create();
} catch (Throwable e) {
sender().sendMessage(C.RED + "Exception raised during creation. See the console for more details.");
@@ -216,41 +224,41 @@ public class CommandIris implements DecreeExecutor {
Iris.service(StudioSVC.class).open(sender(), 1337, "overworld");
}
@Decree(description = "Check if iris has access to that specific world")
public void hasAccess(
@Param(description = "The world to access", aliases = {"world"})
World world
) {
Engine engine = IrisToolbelt.access(world).getEngine();
if (engine != null) {
sender().sendMessage("Access granted successfully.");
} else {
sender().sendMessage(C.RED + "Failed to grant access.");
}
}
@Decree(description = "Check access of all worlds.", aliases = {"accesslist"})
public void worlds() {
KList<World> IrisWorlds = new KList<>();
KList<World> BukkitWorlds = new KList<>();
@Decree(description = "All Iris Worlds on the server.", aliases = {"worlds"})
public void irisworlds() {
List<World> IrisWorlds = new ArrayList<>();
for (World world : Bukkit.getWorlds()) {
for (World w : Bukkit.getServer().getWorlds()) {
try {
if (IrisToolbelt.access(world).getEngine() != null) {
IrisWorlds.add(world);
Engine engine = IrisToolbelt.access(w).getEngine();
if (engine != null) {
IrisWorlds.add(w);
}
} catch (Exception e) {
// no
BukkitWorlds.add(w);
}
}
if (sender().isPlayer()) {
sender.sendMessage(C.IRIS + "Iris Worlds:");
for (World world : IrisWorlds) {
sender.sendMessage(C.GREEN + "- " + world.getName());
sender().sendMessage(C.BLUE + "Iris Worlds: ");
for (World IrisWorld : IrisWorlds.copy()) {
sender().sendMessage(C.IRIS + "- " +IrisWorld.getName());
}
sender().sendMessage(C.GOLD + "Bukkit Worlds: ");
for (World BukkitWorld : BukkitWorlds.copy()) {
sender().sendMessage(C.GRAY + "- " +BukkitWorld.getName());
}
} else {
Iris.info(C.IRIS + "Iris Worlds:");
for (World world : IrisWorlds) {
sender.sendMessage(C.GREEN + "- " + world.getName());
Iris.info(C.BLUE + "Iris Worlds: ");
for (World IrisWorld : IrisWorlds.copy()) {
Iris.info(C.IRIS + "- " +IrisWorld.getName());
}
Iris.info(C.GOLD + "Bukkit Worlds: ");
for (World BukkitWorld : BukkitWorlds.copy()) {
Iris.info(C.GRAY + "- " +BukkitWorld.getName());
}
}
}
@@ -314,6 +322,24 @@ public class CommandIris implements DecreeExecutor {
return dir.delete();
}
@Decree(description = "Updates all chunk in the specified world")
public void updater(
@Param(description = "World to update chunks at")
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
ChunkUpdater updater = new ChunkUpdater(world);
if (sender().isPlayer()) {
sender().sendMessage(C.GREEN + "Updating " + world.getName() + " Total chunks: " + Form.f(updater.getChunks()));
} else {
Iris.info(C.GREEN + "Updating " + world.getName() + " Total chunks: " + Form.f(updater.getChunks()));
}
updater.start();
}
@Decree(description = "Set aura spins")
public void aura(
@Param(description = "The h color value", defaultValue = "-20")
@@ -473,7 +499,7 @@ public class CommandIris implements DecreeExecutor {
sender().sendMessage(C.YELLOW + world + " Doesnt exist on the server.");
return;
}
WorldToLoad = world;
File BUKKIT_YML = new File("bukkit.yml");
String pathtodim = world + File.separator +"iris"+File.separator +"pack"+File.separator +"dimensions"+File.separator;
File directory = new File(Bukkit.getWorldContainer(), pathtodim);
@@ -509,9 +535,10 @@ public class CommandIris implements DecreeExecutor {
} catch (IOException e) {
Iris.error("Failed to update bukkit.yml!");
e.printStackTrace();
return;
}
}
checkForBukkitWorlds();
checkForBukkitWorlds(world);
sender().sendMessage(C.GREEN + world + " loaded successfully.");
}
@Decree(description = "Evacuate an iris world", origin = DecreeOrigin.PLAYER, sync = true)
@@ -532,7 +559,7 @@ public class CommandIris implements DecreeExecutor {
File worldDirectory = new File(worldContainer, worldName);
return worldDirectory.exists() && worldDirectory.isDirectory();
}
private void checkForBukkitWorlds() {
private void checkForBukkitWorlds(String world) {
FileConfiguration fc = new YamlConfiguration();
try {
fc.load(new File("bukkit.yml"));
@@ -541,9 +568,9 @@ public class CommandIris implements DecreeExecutor {
return;
}
List<String> worldsToLoad = Collections.singletonList(WorldToLoad);
List<String> worldsToLoad = Collections.singletonList(world);
for (String s : section.getKeys(false)) {
for (String s : section.getKeys(false)) {
if (!worldsToLoad.contains(s)) {
continue;
}
@@ -622,6 +649,6 @@ public class CommandIris implements DecreeExecutor {
ff.mkdirs();
service(StudioSVC.class).installIntoWorld(sender, dim.getLoadKey(), ff.getParentFile());
}
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey());
return new BukkitChunkGenerator(w, false, ff, dim.getLoadKey(), false);
}
}

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.edit.JigsawEditor;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
import com.volmit.iris.engine.jigsaw.PlannedStructure;
import com.volmit.iris.engine.object.IrisJigsawPiece;
import com.volmit.iris.engine.object.IrisJigsawStructure;
@@ -34,6 +35,7 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
import java.io.File;
@@ -55,9 +57,16 @@ public class CommandJigsaw implements DecreeExecutor {
IrisJigsawStructure structure
) {
PrecisionStopwatch p = PrecisionStopwatch.start();
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation()), new RNG());
sender().sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
ps.place(world());
try {
var world = world();
WorldObjectPlacer placer = new WorldObjectPlacer(world);
PlannedStructure ps = new PlannedStructure(structure, new IrisPosition(player().getLocation().add(0, world.getMinHeight(), 0)), new RNG());
VolmitSender sender = sender();
sender.sendMessage(C.GREEN + "Generated " + ps.getPieces().size() + " pieces in " + Form.duration(p.getMilliseconds(), 2));
ps.place(placer, failed -> sender.sendMessage(failed ? C.GREEN + "Placed the structure!" : C.RED + "Failed to place the structure!"));
} catch (IllegalArgumentException e) {
sender().sendMessage(C.RED + "Failed to place the structure: " + e.getMessage());
}
}
@Decree(description = "Create a jigsaw piece")

View File

@@ -35,6 +35,7 @@ import com.volmit.iris.util.decree.specialhandlers.ObjectHandler;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.Direction;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.scheduling.Queue;
import org.bukkit.*;
import org.bukkit.block.Block;
@@ -52,7 +53,7 @@ import java.util.*;
@Decree(name = "object", aliases = "o", origin = DecreeOrigin.PLAYER, studio = true, description = "Iris object manipulation")
public class CommandObject implements DecreeExecutor {
private static final Set<Material> skipBlocks = Set.of(Material.GRASS, Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
private static final Set<Material> skipBlocks = Set.of(E.getOrDefault(Material.class, "GRASS", "SHORT_GRASS"), Material.SNOW, Material.VINE, Material.TORCH, Material.DEAD_BUSH,
Material.POPPY, Material.DANDELION);
public static IObjectPlacer createPlacer(World world, Map<Block, BlockData> futureBlockChanges) {
@@ -197,6 +198,20 @@ public class CommandObject implements DecreeExecutor {
}
}
@Decree(description = "Shrink an object to its minimum size")
public void shrink(@Param(description = "The object to shrink", customHandler = ObjectHandler.class) String object) {
IrisObject o = IrisData.loadAnyObject(object);
sender().sendMessage("Current Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
o.shrinkwrap();
sender().sendMessage("New Object Size: " + o.getW() + " * " + o.getH() + " * " + o.getD());
try {
o.write(o.getLoadFile());
} catch (IOException e) {
sender().sendMessage("Failed to save object " + o.getLoadFile() + ": " + e.getMessage());
e.printStackTrace();
}
}
@Decree(description = "Get a powder that reveals objects", studio = true, aliases = "d")
public void dust() {
player().getInventory().addItem(WandSVC.createDust());

View File

@@ -74,6 +74,7 @@ import java.nio.file.Files;
import java.nio.file.attribute.FileTime;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
import java.util.Arrays;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
@@ -85,7 +86,7 @@ import java.util.function.Supplier;
public class CommandStudio implements DecreeExecutor {
private CommandFind find;
private CommandEdit edit;
private CommandDeepSearch deepSearch;
//private CommandDeepSearch deepSearch;
public static String hrf(Duration duration) {
return duration.toString().substring(2).replaceAll("(\\d[HMS])(?!$)", "$1 ").toLowerCase();
@@ -332,6 +333,63 @@ public class CommandStudio implements DecreeExecutor {
player().openInventory(inv);
}
@Decree(description = "Get all structures in a radius of chunks", aliases = "dist", origin = DecreeOrigin.PLAYER)
public void distances(@Param(description = "The radius") int radius) {
var engine = engine();
if (engine == null) {
sender().sendMessage(C.RED + "Only works in an Iris world!");
return;
}
var sender = sender();
int d = radius*2;
KMap<String, KList<Position2>> data = new KMap<>();
var multiBurst = new MultiBurst("Distance Sampler", Thread.MIN_PRIORITY);
var executor = multiBurst.burst(radius * radius);
sender.sendMessage(C.GRAY + "Generating data...");
var loc = player().getLocation();
new Spiraler(d, d, (x, z) -> executor.queue(() -> {
var struct = engine.getStructureAt(x, z);
if (struct != null) {
data.computeIfAbsent(struct.getLoadKey(), (k) -> new KList<>()).add(new Position2(x, z));
}
})).setOffset(loc.getBlockX(), loc.getBlockZ()).drain();
executor.complete();
multiBurst.close();
for (var key : data.keySet()) {
var list = data.get(key);
KList<Long> distances = new KList<>(list.size() - 1);
for (int i = 0; i < list.size(); i++) {
var pos = list.get(i);
double dist = Integer.MAX_VALUE;
for (var p : list) {
if (p.equals(pos)) continue;
dist = Math.min(dist, Math.sqrt(Math.pow(pos.getX() - p.getX(), 2) + Math.pow(pos.getZ() - p.getZ(), 2)));
}
if (dist == Integer.MAX_VALUE) continue;
distances.add(Math.round(dist * 16));
}
long[] array = new long[distances.size()];
for (int i = 0; i < distances.size(); i++) {
array[i] = distances.get(i);
}
Arrays.sort(array);
long min = array.length > 0 ? array[0] : 0;
long max = array.length > 0 ? array[array.length - 1] : 0;
long sum = Arrays.stream(array).sum();
long avg = array.length > 0 ? Math.round(sum / (double) array.length) : 0;
String msg = "%s: %s => min: %s/max: %s -> avg: %s".formatted(key, list.size(), min, max, avg);
sender.sendMessage(msg);
}
if (data.isEmpty()) {
sender.sendMessage(C.RED + "No data found!");
} else {
sender.sendMessage(C.GREEN + "Done!");
}
}
@Decree(description = "Render a world map (External GUI)", aliases = "render")
public void map(
@Param(name = "world", description = "The world to open the generator for", contextual = true)

View File

@@ -0,0 +1,82 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.core.commands;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.service.IrisEngineSVC;
import com.volmit.iris.core.tools.IrisPackBenchmarking;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisDimension;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.mantle.TectonicPlate;
import com.volmit.iris.util.misc.Hastebin;
import com.volmit.iris.util.misc.Platform;
import com.volmit.iris.util.misc.getHardware;
import com.volmit.iris.util.nbt.mca.MCAFile;
import com.volmit.iris.util.nbt.mca.MCAUtil;
import com.volmit.iris.util.plugin.VolmitSender;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import net.jpountz.lz4.LZ4FrameInputStream;
import net.jpountz.lz4.LZ4FrameOutputStream;
import org.apache.commons.lang.RandomStringUtils;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.World;
import oshi.SystemInfo;
import java.io.*;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
@Decree(name = "Support", origin = DecreeOrigin.BOTH, description = "Iris World Manager", aliases = {"support"})
public class CommandSupport implements DecreeExecutor {
@Decree(description = "report")
public void report() {
try {
if (sender().isPlayer()) sender().sendMessage(C.GOLD + "Creating report..");
if (!sender().isPlayer()) Iris.info(C.GOLD + "Creating report..");
Hastebin.enviornment(sender());
} catch (Exception e) {
Iris.info(C.RED + "Something went wrong: ");
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,107 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2022 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.core.commands;
import org.bukkit.World;
import com.volmit.iris.Iris;
import com.volmit.iris.core.pregenerator.ChunkUpdater;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.util.decree.DecreeExecutor;
import com.volmit.iris.util.decree.DecreeOrigin;
import com.volmit.iris.util.decree.annotations.Decree;
import com.volmit.iris.util.decree.annotations.Param;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
@Decree(name = "updater", origin = DecreeOrigin.BOTH, description = "Iris World Updater")
public class CommandUpdater implements DecreeExecutor {
private ChunkUpdater chunkUpdater;
@Decree(description = "Updates all chunk in the specified world")
public void start(
@Param(description = "World to update chunks at", contextual = true)
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
chunkUpdater = new ChunkUpdater(world);
if (sender().isPlayer()) {
sender().sendMessage(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
} else {
Iris.info(C.GREEN + "Updating " + world.getName() + C.GRAY + " Total chunks: " + Form.f(chunkUpdater.getChunks()));
}
chunkUpdater.start();
}
@Decree(description = "Pause the updater")
public void pause(
@Param(description = "World to pause the Updater at")
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
if (chunkUpdater == null) {
sender().sendMessage(C.GOLD + "You cant pause something that doesnt exist?");
return;
}
boolean status = chunkUpdater.pause();
if (sender().isPlayer()) {
if (status) {
sender().sendMessage(C.IRIS + "Paused task for: " + C.GRAY + world.getName());
} else {
sender().sendMessage(C.IRIS + "Unpause task for: " + C.GRAY + world.getName());
}
} else {
if (status) {
Iris.info(C.IRIS + "Paused task for: " + C.GRAY + world.getName());
} else {
Iris.info(C.IRIS + "Unpause task for: " + C.GRAY + world.getName());
}
}
}
@Decree(description = "Stops the updater")
public void stop(
@Param(description = "World to stop the Updater at")
World world
) {
if (!IrisToolbelt.isIrisWorld(world)) {
sender().sendMessage(C.GOLD + "This is not an Iris world");
return;
}
if (chunkUpdater == null) {
sender().sendMessage(C.GOLD + "You cant stop something that doesnt exist?");
return;
}
if (sender().isPlayer()) {
sender().sendMessage("Stopping Updater for: " + C.GRAY + world.getName());
} else {
Iris.info("Stopping Updater for: " + C.GRAY + world.getName());
}
chunkUpdater.stop();
}
}

View File

@@ -55,10 +55,10 @@ public class IrisRenderer {
IrisBiome b = renderer.getBiome((int) Math.round(x), renderer.getMaxHeight() - 1, (int) Math.round(z));
IrisBiomeGeneratorLink g = b.getGenerators().get(0);
Color c;
if (g.getMax() <= 0) {
if (g.getMax(renderer) <= 0) {
// Max is below water level, so it is most likely an ocean biome
c = Color.BLUE;
} else if (g.getMin() < 0) {
} else if (g.getMin(renderer) < 0) {
// Min is below water level, but max is not, so it is most likely a shore biome
c = Color.YELLOW;
} else {

View File

@@ -0,0 +1,72 @@
package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.reflect.WrappedField;
import com.willfp.ecoitems.items.EcoItem;
import com.willfp.ecoitems.items.EcoItems;
import org.bukkit.NamespacedKey;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
import java.util.MissingResourceException;
public class EcoItemsDataProvider extends ExternalDataProvider {
private WrappedField<EcoItem, ItemStack> itemStack;
private WrappedField<EcoItem, NamespacedKey> id;
public EcoItemsDataProvider() {
super("EcoItems");
}
@Override
public void init() {
Iris.info("Setting up EcoItems Link...");
itemStack = new WrappedField<>(EcoItem.class, "_itemStack");
if (this.itemStack.hasFailed()) {
Iris.error("Failed to set up EcoItems Link: Unable to fetch ItemStack field!");
}
id = new WrappedField<>(EcoItem.class, "id");
if (this.id.hasFailed()) {
Iris.error("Failed to set up EcoItems Link: Unable to fetch id field!");
}
}
@Override
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
}
@Override
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
EcoItem item = EcoItems.INSTANCE.getByID(itemId.key());
if (item == null) throw new MissingResourceException("Failed to find Item!", itemId.namespace(), itemId.key());
return itemStack.get(item).clone();
}
@Override
public Identifier[] getBlockTypes() {
return new Identifier[0];
}
@Override
public Identifier[] getItemTypes() {
KList<Identifier> names = new KList<>();
for (EcoItem item : EcoItems.INSTANCE.values()) {
try {
Identifier key = Identifier.fromNamespacedKey(id.get(item));
if (getItemStack(key) != null)
names.add(key);
} catch (MissingResourceException ignored) {
}
}
return names.toArray(new Identifier[0]);
}
@Override
public boolean isValidProvider(Identifier id, boolean isItem) {
return id.namespace().equalsIgnoreCase("ecoitems") && isItem;
}
}

View File

@@ -3,6 +3,7 @@ package com.volmit.iris.core.link;
import com.ssomar.score.api.executableitems.ExecutableItemsAPI;
import com.volmit.iris.Iris;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.ItemStack;
@@ -20,12 +21,12 @@ public class ExecutableItemsDataProvider extends ExternalDataProvider {
}
@Override
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
}
@Override
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
return ExecutableItemsAPI.getExecutableItemsManager().getExecutableItem(itemId.key())
.map(item -> item.buildItem(1, Optional.empty()))
.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key()));

View File

@@ -1,6 +1,7 @@
package com.volmit.iris.core.link;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KMap;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.bukkit.Bukkit;
@@ -27,10 +28,19 @@ public abstract class ExternalDataProvider {
public abstract void init();
public abstract BlockData getBlockData(Identifier blockId) throws MissingResourceException;
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
return getBlockData(blockId, new KMap<>());
}
public abstract ItemStack getItemStack(Identifier itemId) throws MissingResourceException;
public void processUpdate(Engine engine, Block block, Identifier blockId) {};
public abstract BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException;
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
return getItemStack(itemId, new KMap<>());
}
public abstract ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException;
public void processUpdate(Engine engine, Block block, Identifier blockId) {}
public abstract Identifier[] getBlockTypes();

View File

@@ -1,8 +1,11 @@
package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.service.ExternalDataSVC;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.reflect.WrappedField;
import com.volmit.iris.util.reflect.WrappedReturningMethod;
@@ -49,7 +52,7 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
}
@Override
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
Object o = blockDataMap.get(blockId.key());
if (o == null)
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
@@ -57,13 +60,13 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
if (material == null)
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
BlockData blockData = Bukkit.createBlockData(material);
if (blockData instanceof Leaves leaves)
if (IrisSettings.get().getGenerator().preventLeafDecay && blockData instanceof Leaves leaves)
leaves.setPersistent(true);
return new IrisBlockData(blockData, blockId);
return new IrisBlockData(blockData, ExternalDataSVC.buildState(blockId, state));
}
@Override
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
if (!itemDataField.containsKey(itemId.key()))
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
return itemDataField.get(itemId.key()).get();
@@ -71,9 +74,16 @@ public class HMCLeavesDataProvider extends ExternalDataProvider {
@Override
public void processUpdate(Engine engine, Block block, Identifier blockId) {
Boolean result = setCustomBlock.invoke(apiInstance, new Object[]{block.getLocation(), blockId.key(), true});
var pair = ExternalDataSVC.parseState(blockId);
blockId = pair.getA();
Boolean result = setCustomBlock.invoke(apiInstance, new Object[]{block.getLocation(), blockId.key(), false});
if (result == null || !result)
Iris.warn("Failed to set custom block! " + blockId.key() + " " + block.getX() + " " + block.getY() + " " + block.getZ());
else if (IrisSettings.get().getGenerator().preventLeafDecay) {
BlockData blockData = block.getBlockData();
if (blockData instanceof Leaves leaves)
leaves.setPersistent(true);
}
}
@Override

View File

@@ -6,6 +6,10 @@ public record Identifier(String namespace, String key) {
private static final String DEFAULT_NAMESPACE = "minecraft";
public static Identifier fromNamespacedKey(NamespacedKey key) {
return new Identifier(key.getNamespace(), key.getKey());
}
public static Identifier fromString(String id) {
String[] strings = id.split(":", 2);
if (strings.length == 1) {

View File

@@ -2,6 +2,7 @@ package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import dev.lone.itemsadder.api.CustomBlock;
import dev.lone.itemsadder.api.CustomStack;
import org.bukkit.block.data.BlockData;
@@ -32,12 +33,12 @@ public class ItemAdderDataProvider extends ExternalDataProvider {
}
@Override
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
return CustomBlock.getBaseBlockData(blockId.toString());
}
@Override
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
CustomStack stack = CustomStack.getInstance(itemId.toString());
if (stack == null) {
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());

View File

@@ -2,6 +2,7 @@ package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.scheduling.J;
import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.api.Type;
@@ -26,7 +27,7 @@ public class MMOItemsDataProvider extends ExternalDataProvider {
}
@Override
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
int id = -1;
try {
id = Integer.parseInt(blockId.key());
@@ -37,12 +38,33 @@ public class MMOItemsDataProvider extends ExternalDataProvider {
}
@Override
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
String[] parts = itemId.namespace().split("_", 2);
if (parts.length != 2)
throw new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key());
CompletableFuture<ItemStack> future = new CompletableFuture<>();
Runnable run = () -> future.complete(api().getItem(parts[1], itemId.key()));
Runnable run = () -> {
try {
var type = api().getTypes().get(parts[1]);
int level = customNbt.containsKey("level") ? (int) customNbt.get("level") : -1;
var tier = api().getTiers().get(String.valueOf(customNbt.get("tier")));
ItemStack itemStack;
if (type == null) {
future.complete(null);
return;
}
if (level != -1 && tier != null) {
itemStack = api().getItem(type, itemId.key(), level, tier);
} else {
itemStack = api().getItem(type, itemId.key());
}
future.complete(itemStack);
} catch (Throwable e) {
future.completeExceptionally(e);
}
};
if (Bukkit.isPrimaryThread()) run.run();
else J.s(run);
ItemStack item = null;

View File

@@ -19,10 +19,16 @@
package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.service.ExternalDataSVC;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.reflect.WrappedField;
import io.th0rgal.oraxen.api.OraxenItems;
import io.th0rgal.oraxen.items.ItemBuilder;
@@ -36,15 +42,22 @@ import io.th0rgal.oraxen.mechanics.provided.gameplay.furniture.FurnitureMechanic
import io.th0rgal.oraxen.mechanics.provided.gameplay.noteblock.NoteBlockMechanicFactory;
import io.th0rgal.oraxen.mechanics.provided.gameplay.stringblock.StringBlockMechanicFactory;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.MultipleFacing;
import org.bukkit.entity.Entity;
import org.bukkit.entity.ItemDisplay;
import org.bukkit.entity.ItemFrame;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.PotionMeta;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Optional;
import java.util.function.Consumer;
public class OraxenDataProvider extends ExternalDataProvider {
@@ -66,7 +79,7 @@ public class OraxenDataProvider extends ExternalDataProvider {
}
@Override
public BlockData getBlockData(Identifier blockId) throws MissingResourceException {
public BlockData getBlockData(Identifier blockId, KMap<String, String> state) throws MissingResourceException {
MechanicFactory factory = getFactory(blockId);
if (factory instanceof NoteBlockMechanicFactory f)
return f.createNoteBlockData(blockId.key());
@@ -77,22 +90,71 @@ public class OraxenDataProvider extends ExternalDataProvider {
} else if (factory instanceof StringBlockMechanicFactory f) {
return f.createTripwireData(blockId.key());
} else if (factory instanceof FurnitureFactory) {
return new IrisBlockData(B.getAir(), blockId);
return new IrisBlockData(B.getAir(), ExternalDataSVC.buildState(blockId, state));
} else
throw new MissingResourceException("Failed to find BlockData!", blockId.namespace(), blockId.key());
}
@Override
public ItemStack getItemStack(Identifier itemId) throws MissingResourceException {
public ItemStack getItemStack(Identifier itemId, KMap<String, Object> customNbt) throws MissingResourceException {
Optional<ItemBuilder> opt = OraxenItems.getOptionalItemById(itemId.key());
return opt.orElseThrow(() -> new MissingResourceException("Failed to find ItemData!", itemId.namespace(), itemId.key())).build();
}
@Override
public void processUpdate(Engine engine, Block block, Identifier blockId) {
var pair = ExternalDataSVC.parseState(blockId);
var state = pair.getB();
blockId = pair.getA();
Mechanic mechanic = getFactory(blockId).getMechanic(blockId.key());
if (mechanic instanceof FurnitureMechanic f) {
f.place(block.getLocation());
float yaw = 0;
BlockFace face = BlockFace.NORTH;
long seed = engine.getSeedManager().getSeed() + Cache.key(block.getX(), block.getZ()) + block.getY();
RNG rng = new RNG(seed);
if ("true".equals(state.get("randomYaw"))) {
yaw = rng.f(0, 360);
} else if (state.containsKey("yaw")) {
yaw = Float.parseFloat(state.get("yaw"));
}
if ("true".equals(state.get("randomFace"))) {
BlockFace[] faces = BlockFace.values();
face = faces[rng.i(0, faces.length - 1)];
} else if (state.containsKey("face")) {
face = BlockFace.valueOf(state.get("face").toUpperCase());
}
if (face == BlockFace.SELF) {
face = BlockFace.NORTH;
}
ItemStack itemStack = OraxenItems.getItemById(f.getItemID()).build();
Entity entity = f.place(block.getLocation(), itemStack, yaw, face, false);
Consumer<ItemStack> setter = null;
if (entity instanceof ItemFrame frame) {
itemStack = frame.getItem();
setter = frame::setItem;
} else if (entity instanceof ItemDisplay display) {
itemStack = display.getItemStack();
setter = display::setItemStack;
}
if (setter == null || itemStack == null) return;
BiomeColor type = null;
try {
type = BiomeColor.valueOf(state.get("matchBiome").toUpperCase());
} catch (NullPointerException | IllegalArgumentException ignored) {}
if (type != null) {
var biomeColor = INMS.get().getBiomeColor(block.getLocation(), type);
if (biomeColor == null) return;
var potionColor = Color.fromARGB(biomeColor.getAlpha(), biomeColor.getRed(), biomeColor.getGreen(), biomeColor.getBlue());
if (itemStack.getItemMeta() instanceof PotionMeta meta) {
meta.setColor(potionColor);
itemStack.setItemMeta(meta);
}
}
setter.accept(itemStack);
}
}

View File

@@ -1,12 +1,19 @@
package com.volmit.iris.core.link;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.util.data.Cuboid;
import com.volmit.iris.util.data.KCache;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.entity.Player;
import java.lang.reflect.InvocationTargetException;
import java.time.Duration;
import java.util.UUID;
public class WorldEditLink {
private static Boolean enabled = null;
private static final AtomicCache<Boolean> active = new AtomicCache<>();
public static Cuboid getSelection(Player p) {
if (!hasWorldEdit())
@@ -15,29 +22,38 @@ public class WorldEditLink {
try {
Object instance = Class.forName("com.sk89q.worldedit.WorldEdit").getDeclaredMethod("getInstance").invoke(null);
Object sessionManager = instance.getClass().getDeclaredMethod("getSessionManager").invoke(instance);
Object player = Class.forName("com.sk89q.worldedit.bukkit.BukkitAdapter").getDeclaredMethod("adapt", Player.class).invoke(null, p);
Class<?> bukkitAdapter = Class.forName("com.sk89q.worldedit.bukkit.BukkitAdapter");
Object world = bukkitAdapter.getDeclaredMethod("adapt", World.class).invoke(null, p.getWorld());
Object player = bukkitAdapter.getDeclaredMethod("adapt", Player.class).invoke(null, p);
Object localSession = sessionManager.getClass().getDeclaredMethod("getIfPresent", Class.forName("com.sk89q.worldedit.session.SessionOwner")).invoke(sessionManager, player);
Object world = Class.forName("com.sk89q.worldedit.bukkit.BukkitAdapter").getDeclaredMethod("adapt", World.class).invoke(null, p.getWorld());
Object region = localSession.getClass().getDeclaredMethod("getSelection", world.getClass()).invoke(localSession, world);
if (localSession == null) return null;
Object region = null;
try {
region = localSession.getClass().getDeclaredMethod("getSelection", Class.forName("com.sk89q.worldedit.world.World")).invoke(localSession, world);
} catch (InvocationTargetException ignored) {}
if (region == null) return null;
Object min = region.getClass().getDeclaredMethod("getMinimumPoint").invoke(region);
Object max = region.getClass().getDeclaredMethod("getMaximumPoint").invoke(region);
return new Cuboid(p.getWorld(),
(int) min.getClass().getDeclaredMethod("getX").invoke(min),
(int) min.getClass().getDeclaredMethod("getY").invoke(min),
(int) min.getClass().getDeclaredMethod("getZ").invoke(min),
(int) min.getClass().getDeclaredMethod("getX").invoke(max),
(int) min.getClass().getDeclaredMethod("getY").invoke(max),
(int) min.getClass().getDeclaredMethod("getZ").invoke(max)
(int) min.getClass().getDeclaredMethod("x").invoke(min),
(int) min.getClass().getDeclaredMethod("y").invoke(min),
(int) min.getClass().getDeclaredMethod("z").invoke(min),
(int) min.getClass().getDeclaredMethod("x").invoke(max),
(int) min.getClass().getDeclaredMethod("y").invoke(max),
(int) min.getClass().getDeclaredMethod("z").invoke(max)
);
} catch (Throwable ignored) {
} catch (Throwable e) {
Iris.error("Could not get selection");
e.printStackTrace();
active.reset();
active.aquire(() -> false);
}
return null;
}
public static boolean hasWorldEdit() {
if (enabled == null)
enabled = Bukkit.getPluginManager().isPluginEnabled("WorldEdit");
return enabled;
return active.aquire(() -> Bukkit.getPluginManager().isPluginEnabled("WorldEdit"));
}
}

View File

@@ -362,7 +362,12 @@ public class ResourceLoader<T extends IrisRegistrant> implements MeteredCache {
if (folderCache.get() == null) {
KList<File> fc = new KList<>();
for (File i : root.listFiles()) {
File[] files = root.listFiles();
if (files == null) {
throw new IllegalStateException("Failed to list files in " + root);
}
for (File i : files) {
if (i.isDirectory()) {
if (i.getName().equals(folderName)) {
fc.add(i);

View File

@@ -23,7 +23,15 @@ import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import org.bukkit.Bukkit;
import java.util.Map;
public class INMS {
private static final Map<String, String> REVISION = Map.of(
"1.20.5", "v1_20_R4",
"1.20.6", "v1_20_R4",
"1.21", "v1_21_R1",
"1.21.1", "v1_21_R1"
);
//@done
private static final INMSBinding binding = bind();
@@ -37,7 +45,12 @@ public class INMS {
}
try {
return Bukkit.getServer().getClass().getCanonicalName().split("\\Q.\\E")[3];
String name = Bukkit.getServer().getClass().getCanonicalName();
if (name.equals("org.bukkit.craftbukkit.CraftServer")) {
return REVISION.getOrDefault(Bukkit.getServer().getBukkitVersion().split("-")[0], "BUKKIT");
} else {
return name.split("\\Q.\\E")[3];
}
} catch (Throwable e) {
Iris.reportError(e);
Iris.error("Failed to determine server nms version!");

View File

@@ -18,8 +18,9 @@
package com.volmit.iris.core.nms;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisEntity;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.mantle.Mantle;
@@ -36,10 +37,11 @@ import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.event.entity.EntitySpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import java.awt.*;
public interface INMSBinding {
boolean hasTile(Location l);
@@ -112,4 +114,14 @@ public interface INMSBinding {
Vector3d getBoundingbox(org.bukkit.entity.EntityType entity);
Entity spawnEntity(Location location, EntityType type, CreatureSpawnEvent.SpawnReason reason);
Color getBiomeColor(Location location, BiomeColor type);
default DataVersion getDataVersion() {
return DataVersion.V1192;
}
default int getSpawnChunkCount(World world) {
return 441;
}
}

View File

@@ -0,0 +1,10 @@
package com.volmit.iris.core.nms.container;
public enum BiomeColor {
FOG,
WATER,
WATER_FOG,
SKY,
FOLIAGE,
GRASS
}

View File

@@ -0,0 +1,40 @@
package com.volmit.iris.core.nms.datapack;
import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.datapack.v1192.DataFixerV1192;
import com.volmit.iris.core.nms.datapack.v1206.DataFixerV1206;
import com.volmit.iris.util.collection.KMap;
import lombok.AccessLevel;
import lombok.Getter;
import java.util.function.Supplier;
//https://minecraft.wiki/w/Pack_format
@Getter
public enum DataVersion {
V1192("1.19.2", 10, DataFixerV1192::new),
V1205("1.20.6", 41, DataFixerV1206::new);
private static final KMap<DataVersion, IDataFixer> cache = new KMap<>();
@Getter(AccessLevel.NONE)
private final Supplier<IDataFixer> constructor;
private final String version;
private final int packFormat;
DataVersion(String version, int packFormat, Supplier<IDataFixer> constructor) {
this.constructor = constructor;
this.packFormat = packFormat;
this.version = version;
}
public IDataFixer get() {
return cache.computeIfAbsent(this, k -> constructor.get());
}
public static IDataFixer getDefault() {
return INMS.get().getDataVersion().get();
}
public static DataVersion getLatest() {
return values()[values().length - 1];
}
}

View File

@@ -0,0 +1,11 @@
package com.volmit.iris.core.nms.datapack;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.util.json.JSONObject;
public interface IDataFixer {
JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json);
JSONObject fixDimension(JSONObject json);
}

View File

@@ -0,0 +1,18 @@
package com.volmit.iris.core.nms.datapack.v1192;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.util.json.JSONObject;
public class DataFixerV1192 implements IDataFixer {
@Override
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
return json;
}
@Override
public JSONObject fixDimension(JSONObject json) {
return json;
}
}

View File

@@ -0,0 +1,54 @@
package com.volmit.iris.core.nms.datapack.v1206;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.engine.object.IrisBiomeCustomSpawn;
import com.volmit.iris.engine.object.IrisBiomeCustomSpawnType;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.json.JSONArray;
import com.volmit.iris.util.json.JSONObject;
import java.util.Locale;
public class DataFixerV1206 implements IDataFixer {
@Override
public JSONObject fixCustomBiome(IrisBiomeCustom biome, JSONObject json) {
int spawnRarity = biome.getSpawnRarity();
if (spawnRarity > 0) {
json.put("creature_spawn_probability", Math.min(spawnRarity/20d, 0.9999999));
}
var spawns = biome.getSpawns();
if (spawns != null && spawns.isNotEmpty()) {
JSONObject spawners = new JSONObject();
KMap<IrisBiomeCustomSpawnType, JSONArray> groups = new KMap<>();
for (IrisBiomeCustomSpawn i : spawns) {
JSONArray g = groups.computeIfAbsent(i.getGroup(), (k) -> new JSONArray());
JSONObject o = new JSONObject();
o.put("type", "minecraft:" + i.getType().name().toLowerCase());
o.put("weight", i.getWeight());
o.put("minCount", Math.min(i.getMinCount()/20d, 0));
o.put("maxCount", Math.min(i.getMaxCount()/20d, 0.9999999));
g.put(o);
}
for (IrisBiomeCustomSpawnType i : groups.k()) {
spawners.put(i.name().toLowerCase(Locale.ROOT), groups.get(i));
}
json.put("spawners", spawners);
}
return json;
}
@Override
public JSONObject fixDimension(JSONObject json) {
if (!(json.get("monster_spawn_light_level") instanceof JSONObject lightLevel))
return json;
var value = (JSONObject) lightLevel.remove("value");
lightLevel.put("max_inclusive", value.get("max_inclusive"));
lightLevel.put("min_inclusive", value.get("min_inclusive"));
return json;
}
}

View File

@@ -20,6 +20,7 @@ package com.volmit.iris.core.nms.v1X;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.container.BlockPos;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
@@ -40,6 +41,8 @@ import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import java.awt.*;
public class NMSBinding1X implements INMSBinding {
private static final boolean supportsCustomHeight = testCustomHeight();
@@ -97,6 +100,11 @@ public class NMSBinding1X implements INMSBinding {
return location.getWorld().spawnEntity(location, type);
}
@Override
public Color getBiomeColor(Location location, BiomeColor type) {
return Color.GREEN;
}
@Override
public void deserializeTile(CompoundTag s, Location newPosition) {

View File

@@ -0,0 +1,318 @@
package com.volmit.iris.core.pregenerator;
import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RollingSequence;
import com.volmit.iris.util.math.Spiraler;
import com.volmit.iris.util.scheduling.J;
import io.papermc.lib.PaperLib;
import org.bukkit.Chunk;
import org.bukkit.World;
import java.io.File;
import java.util.ArrayList;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
public class ChunkUpdater {
private AtomicBoolean paused;
private AtomicBoolean cancelled;
private KMap<Chunk, Long> lastUse;
private final RollingSequence chunksPerSecond;
private final AtomicInteger worldheightsize;
private final AtomicInteger worldwidthsize;
private final AtomicInteger totalChunks;
private final AtomicInteger totalMaxChunks;
private final AtomicInteger totalMcaregions;
private final AtomicInteger position;
private AtomicInteger chunksProcessed;
private AtomicInteger chunksUpdated;
private AtomicLong startTime;
private ExecutorService executor;
private ExecutorService chunkExecutor;
private ScheduledExecutorService scheduler;
private CompletableFuture future;
private CountDownLatch latch;
private final Object pauseLock;
private final Engine engine;
private final World world;
public ChunkUpdater(World world) {
this.engine = IrisToolbelt.access(world).getEngine();
this.chunksPerSecond = new RollingSequence(5);
this.world = world;
this.lastUse = new KMap();
this.worldheightsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 1));
this.worldwidthsize = new AtomicInteger(calculateWorldDimensions(new File(world.getWorldFolder(), "region"), 0));
int m = Math.max(worldheightsize.get(), worldwidthsize.get());
this.executor = Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors() / 3, 1));
this.chunkExecutor = Executors.newFixedThreadPool(Math.max(Runtime.getRuntime().availableProcessors() / 3, 1));
this.scheduler = Executors.newScheduledThreadPool(1);
this.future = new CompletableFuture<>();
this.startTime = new AtomicLong();
this.worldheightsize.set(m);
this.worldwidthsize.set(m);
this.totalMaxChunks = new AtomicInteger((worldheightsize.get() / 16) * (worldwidthsize.get() / 16));
this.chunksProcessed = new AtomicInteger();
this.chunksUpdated = new AtomicInteger();
this.position = new AtomicInteger(0);
this.latch = new CountDownLatch(totalMaxChunks.get());
this.paused = new AtomicBoolean(false);
this.pauseLock = new Object();
this.cancelled = new AtomicBoolean(false);
this.totalChunks = new AtomicInteger(0);
this.totalMcaregions = new AtomicInteger(0);
}
public int getChunks() {
return totalMaxChunks.get();
}
public void start() {
unloadAndSaveAllChunks();
update();
}
public boolean pause() {
unloadAndSaveAllChunks();
if (paused.get()) {
paused.set(false);
return false;
} else {
paused.set(true);
return true;
}
}
public void stop() {
unloadAndSaveAllChunks();
cancelled.set(true);
}
private void update() {
Iris.info("Updating..");
try {
startTime.set(System.currentTimeMillis());
scheduler.scheduleAtFixedRate(() -> {
try {
if (!paused.get()) {
long eta = computeETA();
long elapsedSeconds = (System.currentTimeMillis() - startTime.get()) / 1000;
int processed = chunksProcessed.get();
double cps = elapsedSeconds > 0 ? processed / (double) elapsedSeconds : 0;
chunksPerSecond.put(cps);
double percentage = ((double) chunksProcessed.get() / (double) totalMaxChunks.get()) * 100;
if (!cancelled.get()) {
Iris.info("Updated: " + Form.f(processed) + " of " + Form.f(totalMaxChunks.get()) + " (%.0f%%) " + Form.f(chunksPerSecond.getAverage()) + "/s, ETA: " + Form.duration(eta,
2), percentage);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}, 0, 3, TimeUnit.SECONDS);
CompletableFuture.runAsync(() -> {
for (int i = 0; i < totalMaxChunks.get(); i++) {
if (paused.get()) {
synchronized (pauseLock) {
try {
pauseLock.wait();
} catch (InterruptedException e) {
Iris.error("Interrupted while waiting for executor: ");
e.printStackTrace();
break;
}
}
}
executor.submit(() -> {
if (!cancelled.get()) {
processNextChunk();
}
latch.countDown();
});
}
}).thenRun(() -> {
try {
latch.await();
close();
} catch (Exception e) {
Thread.currentThread().interrupt();
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
public void close() {
try {
unloadAndSaveAllChunks();
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
chunkExecutor.shutdown();
chunkExecutor.awaitTermination(5, TimeUnit.SECONDS);
scheduler.shutdownNow();
} catch (Exception ignored) {
}
if (cancelled.get()) {
Iris.info("Updated: " + Form.f(chunksUpdated.get()) + " Chunks");
Iris.info("Irritated: " + Form.f(chunksProcessed.get()) + " of " + Form.f(totalMaxChunks.get()));
Iris.info("Stopped updater.");
} else {
Iris.info("Processed: " + Form.f(chunksProcessed.get()) + " Chunks");
Iris.info("Finished Updating: " + Form.f(chunksUpdated.get()) + " Chunks");
}
}
private void processNextChunk() {
int pos = position.getAndIncrement();
int[] coords = getChunk(pos);
if (loadChunksIfGenerated(coords[0], coords[1])) {
Chunk c = world.getChunkAt(coords[0], coords[1]);
engine.updateChunk(c);
chunksUpdated.incrementAndGet();
}
chunksProcessed.getAndIncrement();
}
private boolean loadChunksIfGenerated(int x, int z) {
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
if (!PaperLib.isChunkGenerated(world, x + dx, z + dz)) {
return false;
}
}
}
AtomicBoolean generated = new AtomicBoolean(true);
KList<Future<?>> futures = new KList<>(9);
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
int xx = x + dx;
int zz = z + dz;
futures.add(chunkExecutor.submit(() -> {
Chunk c;
try {
c = PaperLib.getChunkAtAsync(world, xx, zz, false).get();
} catch (InterruptedException | ExecutionException e) {
generated.set(false);
return;
}
if (!c.isLoaded()) {
CountDownLatch latch = new CountDownLatch(1);
J.s(() -> {
c.load(false);
latch.countDown();
});
try {
latch.await();
} catch (InterruptedException ignored) {}
}
if (!c.isGenerated()) {
generated.set(false);
}
lastUse.put(c, M.ms());
}));
}
}
while (!futures.isEmpty()) {
futures.removeIf(Future::isDone);
try {
Thread.sleep(50);
} catch (InterruptedException ignored) {}
}
return generated.get();
}
private void unloadAndSaveAllChunks() {
try {
J.sfut(() -> {
if (world == null) {
Iris.warn("World was null somehow...");
return;
}
for (Chunk i : new ArrayList<>(lastUse.keySet())) {
Long lastUseTime = lastUse.get(i);
if (lastUseTime != null && M.ms() - lastUseTime >= 5000) {
i.unload();
lastUse.remove(i);
}
}
world.save();
}).get();
} catch (Throwable e) {
e.printStackTrace();
}
}
private long computeETA() {
return (long) (totalMaxChunks.get() > 1024 ? // Generated chunks exceed 1/8th of total?
// If yes, use smooth function (which gets more accurate over time since its less sensitive to outliers)
((totalMaxChunks.get() - chunksProcessed.get()) * ((double) (M.ms() - startTime.get()) / (double) chunksProcessed.get())) :
// If no, use quick function (which is less accurate over time but responds better to the initial delay)
((totalMaxChunks.get() - chunksProcessed.get()) / chunksPerSecond.getAverage()) * 1000
);
}
public int calculateWorldDimensions(File regionDir, Integer o) {
File[] files = regionDir.listFiles((dir, name) -> name.endsWith(".mca"));
int minX = Integer.MAX_VALUE;
int maxX = Integer.MIN_VALUE;
int minZ = Integer.MAX_VALUE;
int maxZ = Integer.MIN_VALUE;
for (File file : files) {
String[] parts = file.getName().split("\\.");
int x = Integer.parseInt(parts[1]);
int z = Integer.parseInt(parts[2]);
if (x < minX) minX = x;
if (x > maxX) maxX = x;
if (z < minZ) minZ = z;
if (z > maxZ) maxZ = z;
}
int height = (maxX - minX + 1) * 32 * 16;
int width = (maxZ - minZ + 1) * 32 * 16;
if (o == 1) {
return height;
}
if (o == 0) {
return width;
}
return 0;
}
public int[] getChunk(int position) {
int p = -1;
AtomicInteger xx = new AtomicInteger();
AtomicInteger zz = new AtomicInteger();
Spiraler s = new Spiraler(worldheightsize.get() * 2, worldwidthsize.get() * 2, (x, z) -> {
xx.set(x);
zz.set(z);
});
while (s.hasNext() && p++ < position) {
s.next();
}
int[] coords = new int[2];
coords[0] = xx.get();
coords[1] = zz.get();
return coords;
}
}

View File

@@ -44,13 +44,13 @@ public class ModesSFG {
Iris.info(C.DARK_RED + "ATTENTION: " + C.RED + "While running Iris in unstable mode, you won't be eligible for support.");
Iris.info(C.DARK_RED + "CAUSE: " + C.RED + UtilsSFG.MSGIncompatibleWarnings());
if (IrisSettings.get().getGeneral().ignoreBootMode) {
if (IrisSettings.get().getGeneral().DoomsdayAnnihilationSelfDestructMode) {
Iris.info(C.DARK_RED + "Boot Unstable is set to true, continuing with the startup process.");
} else {
Iris.info(C.DARK_RED + "Go to plugins/iris/settings.json and set ignoreBootMode to true if you wish to proceed.");
Iris.info(C.DARK_RED + "Go to plugins/iris/settings.json and set DoomsdayAnnihilationSelfDestructMode to true if you wish to proceed.");
while (true) {
try {
Thread.sleep(1000);
Thread.sleep(Long.MAX_VALUE);
} catch (InterruptedException e) {
// no
}

View File

@@ -5,7 +5,7 @@ import com.volmit.iris.core.nms.INMS;
import com.volmit.iris.core.nms.v1X.NMSBinding1X;
import org.bukkit.Bukkit;
import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginManager;
import javax.tools.JavaCompiler;
import javax.tools.ToolProvider;
import java.io.File;
@@ -15,6 +15,7 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringJoiner;
@@ -39,7 +40,7 @@ public class ServerBootSFG {
public static void BootCheck() {
Iris.info("Checking for possible conflicts..");
org.bukkit.plugin.PluginManager pluginManager = Bukkit.getPluginManager();
PluginManager pluginManager = Bukkit.getPluginManager();
Plugin[] plugins = pluginManager.getPlugins();
incompatibilities.clear();
@@ -64,24 +65,29 @@ public class ServerBootSFG {
joiner.add(entry.getKey());
}
}
// Legacy ServerInfo
String distro = Bukkit.getName().toLowerCase();
if (
!instance.getServer().getVersion().contains("Purpur") &&
!instance.getServer().getVersion().contains("Paper") &&
!instance.getServer().getVersion().contains("Spigot") &&
!instance.getServer().getVersion().contains("Pufferfish") &&
!instance.getServer().getVersion().contains("Bukkit")) {
!distro.contains("purpur") &&
!distro.contains("paper") &&
!distro.contains("spigot") &&
!distro.contains("pufferfish") &&
!distro.contains("bukkit")) {
passedserversoftware = false;
joiner.add("Server Software");
severityHigh++;
severityMedium++;
}
if (INMS.get() instanceof NMSBinding1X) {
unsuportedversion = true;
joiner.add("Unsupported Minecraft Version");
severityHigh++;
}
if (getJavaVersion() != 17) {
if (!List.of(17, 21).contains(getJavaVersion())) {
isJDK17 = false;
joiner.add("Unsupported Java version");
severityMedium++;

View File

@@ -37,7 +37,7 @@ public class UtilsSFG {
}
if (ServerBootSFG.unsuportedversion) {
Iris.safeguard(C.RED + "Server Version");
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.20.4");
Iris.safeguard(C.RED + "- Iris only supports 1.19.2 > 1.21.1");
}
if (!ServerBootSFG.passedserversoftware) {
Iris.safeguard(C.YELLOW + "Unsupported Server Software");
@@ -53,11 +53,11 @@ public class UtilsSFG {
}
if (!ServerBootSFG.isJDK17) {
Iris.safeguard(C.YELLOW + "Unsupported java version");
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 Instead of JDK " + Iris.getJavaVersion());
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 (or 21 for 1.20.6) Instead of JDK " + Iris.getJavaVersion());
}
if (ServerBootSFG.isJRE) {
Iris.safeguard(C.YELLOW + "Unsupported Server JDK");
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 Instead of JRE " + Iris.getJavaVersion());
Iris.safeguard(C.YELLOW + "- Please consider using JDK 17 (or 21 for 1.20.6) Instead of JRE " + Iris.getJavaVersion());
}
}
}

View File

@@ -20,8 +20,10 @@ package com.volmit.iris.core.service;
import com.volmit.iris.Iris;
import com.volmit.iris.core.link.*;
import com.volmit.iris.core.nms.container.Pair;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.plugin.IrisService;
import lombok.Data;
import org.bukkit.Bukkit;
@@ -31,8 +33,8 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.server.PluginEnableEvent;
import org.bukkit.inventory.ItemStack;
import java.util.MissingResourceException;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;
@Data
public class ExternalDataSVC implements IrisService {
@@ -64,6 +66,10 @@ public class ExternalDataSVC implements IrisService {
if (Bukkit.getPluginManager().getPlugin("MMOItems") != null) {
Iris.info("MMOItems found, loading MMOItemsDataProvider...");
}
providers.add(new EcoItemsDataProvider());
if (Bukkit.getPluginManager().getPlugin("EcoItems") != null) {
Iris.info("EcoItems found, loading EcoItemsDataProvider...");
}
for (ExternalDataProvider p : providers) {
if (p.isReady()) {
@@ -89,26 +95,29 @@ public class ExternalDataSVC implements IrisService {
}
}
public Optional<BlockData> getBlockData(Identifier key) {
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, false)).findFirst();
public Optional<BlockData> getBlockData(final Identifier key) {
var pair = parseState(key);
Identifier mod = pair.getA();
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(mod, false)).findFirst();
if (provider.isEmpty())
return Optional.empty();
try {
return Optional.of(provider.get().getBlockData(key));
return Optional.of(provider.get().getBlockData(mod, pair.getB()));
} catch (MissingResourceException e) {
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
return Optional.empty();
}
}
public Optional<ItemStack> getItemStack(Identifier key) {
public Optional<ItemStack> getItemStack(Identifier key, KMap<String, Object> customNbt) {
Optional<ExternalDataProvider> provider = activeProviders.stream().filter(p -> p.isValidProvider(key, true)).findFirst();
if (provider.isEmpty()) {
Iris.warn("No matching Provider found for modded material \"%s\"!", key);
return Optional.empty();
}
try {
return Optional.of(provider.get().getItemStack(key));
return Optional.of(provider.get().getItemStack(key, customNbt));
} catch (MissingResourceException e) {
Iris.error(e.getMessage() + " - [" + e.getClassName() + ":" + e.getKey() + "]");
return Optional.empty();
@@ -135,4 +144,27 @@ public class ExternalDataSVC implements IrisService {
activeProviders.forEach(p -> names.add(p.getItemTypes()));
return names.toArray(new Identifier[0]);
}
public static Pair<Identifier, KMap<String, String>> parseState(Identifier key) {
if (!key.key().contains("[") || !key.key().contains("]")) {
return new Pair<>(key, new KMap<>());
}
String state = key.key().split("\\Q[\\E")[1].split("\\Q]\\E")[0];
KMap<String, String> stateMap = new KMap<>();
if (!state.isEmpty()) {
Arrays.stream(state.split(",")).forEach(s -> stateMap.put(s.split("=")[0], s.split("=")[1]));
}
return new Pair<>(new Identifier(key.namespace(), key.key().split("\\Q[\\E")[0]), stateMap);
}
public static Identifier buildState(Identifier key, KMap<String, String> state) {
if (state.isEmpty()) {
return key;
}
String path = state.entrySet()
.stream()
.map(e -> e.getKey() + "=" + e.getValue())
.collect(Collectors.joining(",", key.key() + "[", "]"));
return new Identifier(key.namespace(), path);
}
}

View File

@@ -78,6 +78,9 @@ public class IrisEngineSVC implements IrisService {
t = t - 200;
}
this.setup();
this.TrimLogic();
this.UnloadLogic();
trimAlive.begin();
unloadAlive.begin();
trimActiveAlive.begin();
@@ -85,8 +88,8 @@ public class IrisEngineSVC implements IrisService {
updateTicker.start();
cacheTicker.start();
trimTicker.start();
unloadTicker.start();
//trimTicker.start();
//unloadTicker.start();
instance = this;
}
@@ -104,10 +107,6 @@ public class IrisEngineSVC implements IrisService {
return tectonicLimit.get();
}
public void EngineReport() {
Iris.info(C.RED + "CRITICAL ENGINE FAILURE! The Tectonic Trim subsystem has not responded for: " + Form.duration(trimAlive.getMillis()) + ".");
}
@EventHandler
public void onWorldUnload(WorldUnloadEvent event) {
updateWorlds();
@@ -179,9 +178,9 @@ public class IrisEngineSVC implements IrisService {
}
if (!isServerShuttingDown && isServerLoaded) {
if (!trimTicker.isAlive()) {
Iris.info(C.IRIS + "TrimTicker found dead! Booting it up!");
Iris.info(C.RED + "TrimTicker found dead! Booting it up!");
try {
trimTicker.start();
TrimLogic();
} catch (Exception e) {
Iris.error("What happened?");
e.printStackTrace();
@@ -189,9 +188,9 @@ public class IrisEngineSVC implements IrisService {
}
if (!unloadTicker.isAlive()) {
Iris.info(C.IRIS + "UnloadTicker found dead! Booting it up!");
Iris.info(C.RED + "UnloadTicker found dead! Booting it up!");
try {
unloadTicker.start();
UnloadLogic();
} catch (Exception e) {
Iris.error("What happened?");
e.printStackTrace();
@@ -205,63 +204,72 @@ public class IrisEngineSVC implements IrisService {
return 1000;
}
};
}
public void TrimLogic() {
if (trimTicker == null || !trimTicker.isAlive()) {
trimTicker = new Looper() {
private final Supplier<Engine> supplier = createSupplier();
trimTicker = new Looper() {
private final Supplier<Engine> supplier = createSupplier();
@Override
protected long loop() {
long start = System.currentTimeMillis();
trimAlive.reset();
try {
Engine engine = supplier.get();
if (engine != null) {
engine.getMantle().trim(tectonicLimit.get() / lastUse.size());
}
} catch (Throwable e) {
Iris.reportError(e);
Iris.info(C.RED + "EngineSVC: Failed to trim. Please contact support!");
e.printStackTrace();
return -1;
}
int size = lastUse.size();
long time = (size > 0 ? 1000/size : 1000) - (System.currentTimeMillis() - start);
if (time <= 0)
return 0;
return time;
}
};
unloadTicker = new Looper() {
private final Supplier<Engine> supplier = createSupplier();
@Override
protected long loop() {
long start = System.currentTimeMillis();
unloadAlive.reset();
try {
Engine engine = supplier.get();
if (engine != null) {
long unloadStart = System.currentTimeMillis();
int count = engine.getMantle().unloadTectonicPlate(tectonicLimit.get() / lastUse.size());
if (count > 0) {
Iris.debug(C.GOLD + "Unloaded " + C.YELLOW + count + " TectonicPlates in " + C.RED + Form.duration(System.currentTimeMillis() - unloadStart, 2));
@Override
protected long loop() {
long start = System.currentTimeMillis();
trimAlive.reset();
try {
Engine engine = supplier.get();
if (engine != null) {
engine.getMantle().trim(tectonicLimit.get() / lastUse.size());
}
} catch (Throwable e) {
Iris.reportError(e);
Iris.info(C.RED + "EngineSVC: Failed to trim.");
e.printStackTrace();
return -1;
}
} catch (Throwable e) {
Iris.reportError(e);
Iris.info(C.RED + "EngineSVC: Failed to unload.");
e.printStackTrace();
return -1;
}
int size = lastUse.size();
long time = (size > 0 ? 1000/size : 1000) - (System.currentTimeMillis() - start);
if (time <= 0)
return 0;
return time;
}
};
int size = lastUse.size();
long time = (size > 0 ? 1000 / size : 1000) - (System.currentTimeMillis() - start);
if (time <= 0)
return 0;
return time;
}
};
trimTicker.start();
}
}
public void UnloadLogic() {
if (unloadTicker == null || !unloadTicker.isAlive()) {
unloadTicker = new Looper() {
private final Supplier<Engine> supplier = createSupplier();
@Override
protected long loop() {
long start = System.currentTimeMillis();
unloadAlive.reset();
try {
Engine engine = supplier.get();
if (engine != null) {
long unloadStart = System.currentTimeMillis();
int count = engine.getMantle().unloadTectonicPlate(tectonicLimit.get() / lastUse.size());
if (count > 0) {
Iris.debug(C.GOLD + "Unloaded " + C.YELLOW + count + " TectonicPlates in " + C.RED + Form.duration(System.currentTimeMillis() - unloadStart, 2));
}
}
} catch (Throwable e) {
Iris.reportError(e);
Iris.info(C.RED + "EngineSVC: Failed to unload.");
e.printStackTrace();
return -1;
}
int size = lastUse.size();
long time = (size > 0 ? 1000 / size : 1000) - (System.currentTimeMillis() - start);
if (time <= 0)
return 0;
return time;
}
};
unloadTicker.start();
}
}
private Supplier<Engine> createSupplier() {
@@ -281,7 +289,8 @@ public class IrisEngineSVC implements IrisService {
if (generator != null) {
Engine engine = generator.getEngine();
if (engine != null && !engine.isStudio()) {
boolean closed = engine.getMantle().getData().isClosed();
if (engine != null && !engine.isStudio() && !closed) {
lastUseLock.lock();
lastUse.put(world, System.currentTimeMillis());
lastUseLock.unlock();

View File

@@ -232,7 +232,7 @@ public class StudioSVC implements IrisService {
}
try {
dir = zipFiles.length == 1 && zipFiles[0].isDirectory() ? zipFiles[0] : null;
dir = zipFiles.length > 1 ? work : zipFiles[0].isDirectory() ? zipFiles[0] : null;
} catch (NullPointerException e) {
Iris.reportError(e);
sender.sendMessage("Error when finding home directory. Are there any non-text characters in the file name?");

View File

@@ -240,7 +240,7 @@ public class TreeSVC implements IrisService {
boolean isUseAll = worldAccess.getEngine().getDimension().getTreeSettings().getMode().equals(IrisTreeModes.ALL);
// Retrieve objectPlacements of type `species` from biome
IrisBiome biome = worldAccess.getEngine().getBiome(location.getBlockX(), location.getBlockY(), location.getBlockZ());
IrisBiome biome = worldAccess.getEngine().getBiome(location.getBlockX(), location.getBlockY()-worldAccess.getTarget().getWorld().minHeight(), location.getBlockZ());
placements.addAll(matchObjectPlacements(biome.getObjects(), size, type));
// Add more or find any in the region

View File

@@ -30,9 +30,11 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.matter.Matter;
import com.volmit.iris.util.matter.WorldMatter;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.plugin.IrisService;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
import com.volmit.iris.util.scheduling.S;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.enchantments.Enchantment;
@@ -53,6 +55,9 @@ import java.util.ArrayList;
import java.util.Objects;
public class WandSVC implements IrisService {
private static final Particle CRIT_MAGIC = E.getOrDefault(Particle.class, "CRIT_MAGIC", "CRIT");
private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST");
private static ItemStack dust;
private static ItemStack wand;
@@ -162,11 +167,11 @@ public class WandSVC implements IrisService {
*/
public static ItemStack createDust() {
ItemStack is = new ItemStack(Material.GLOWSTONE_DUST);
is.addUnsafeEnchantment(Enchantment.ARROW_INFINITE, 1);
is.addUnsafeEnchantment(Enchantment.FIRE_ASPECT, 1);
ItemMeta im = is.getItemMeta();
im.setDisplayName(C.BOLD + "" + C.YELLOW + "Dust of Revealing");
im.setUnbreakable(true);
im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_PLACED_ON, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_DESTROYS, ItemFlag.HIDE_ENCHANTS);
im.addItemFlags(ItemFlag.values());
im.setLore(new KList<String>().qadd("Right click on a block to reveal it's placement structure!"));
is.setItemMeta(im);
@@ -206,11 +211,11 @@ public class WandSVC implements IrisService {
*/
public static ItemStack createWand(Location a, Location b) {
ItemStack is = new ItemStack(Material.BLAZE_ROD);
is.addUnsafeEnchantment(Enchantment.ARROW_INFINITE, 1);
is.addUnsafeEnchantment(Enchantment.FIRE_ASPECT, 1);
ItemMeta im = is.getItemMeta();
im.setDisplayName(C.BOLD + "" + C.GOLD + "Wand of Iris");
im.setUnbreakable(true);
im.addItemFlags(ItemFlag.HIDE_ATTRIBUTES, ItemFlag.HIDE_PLACED_ON, ItemFlag.HIDE_POTION_EFFECTS, ItemFlag.HIDE_DESTROYS, ItemFlag.HIDE_ENCHANTS);
im.addItemFlags(ItemFlag.values());
im.setLore(new KList<String>().add(locationToString(a), locationToString(b)));
is.setItemMeta(im);
@@ -311,9 +316,9 @@ public class WandSVC implements IrisService {
*/
public void draw(Location[] d, Player p) {
Vector gx = Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65);
d[0].getWorld().spawnParticle(Particle.CRIT_MAGIC, d[0], 1, 0.5 + gx.getX(), 0.5 + gx.getY(), 0.5 + gx.getZ(), 0, null, false);
d[0].getWorld().spawnParticle(CRIT_MAGIC, d[0], 1, 0.5 + gx.getX(), 0.5 + gx.getY(), 0.5 + gx.getZ(), 0, null, false);
Vector gxx = Vector.getRandom().subtract(Vector.getRandom()).normalize().clone().multiply(0.65);
d[1].getWorld().spawnParticle(Particle.CRIT, d[1], 1, 0.5 + gxx.getX(), 0.5 + gxx.getY(), 0.5 + gxx.getZ(), 0, null, false);
d[1].getWorld().spawnParticle(CRIT_MAGIC, d[1], 1, 0.5 + gxx.getX(), 0.5 + gxx.getY(), 0.5 + gxx.getZ(), 0, null, false);
if (!d[0].getWorld().equals(d[1].getWorld())) {
return;
@@ -370,7 +375,7 @@ public class WandSVC implements IrisService {
int r = color.getRed();
int g = color.getGreen();
int b = color.getBlue();
p.spawnParticle(Particle.REDSTONE, lv.getX(), lv.getY(), lv.getZ(), 1, 0, 0, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(r, g, b), 0.75f));
p.spawnParticle(REDSTONE, lv.getX(), lv.getY(), lv.getZ(), 1, 0, 0, 0, 0, new Particle.DustOptions(org.bukkit.Color.fromRGB(r, g, b), 0.75f));
}
}
}
@@ -383,7 +388,7 @@ public class WandSVC implements IrisService {
if (e.getHand() != EquipmentSlot.HAND)
return;
try {
if (isHoldingWand(e.getPlayer())) {
if (isHoldingIrisWand(e.getPlayer())) {
if (e.getAction().equals(Action.LEFT_CLICK_BLOCK)) {
e.setCancelled(true);
e.getPlayer().getInventory().setItemInMainHand(update(true, Objects.requireNonNull(e.getClickedBlock()).getLocation(), e.getPlayer().getInventory().getItemInMainHand()));

View File

@@ -28,7 +28,6 @@ import java.io.InputStreamReader;
import static com.google.common.math.LongMath.isPrime;
import static com.volmit.iris.util.misc.getHardware.getCPUModel;
import static com.volmit.iris.util.misc.getHardware.getDiskModel;
public class IrisBenchmarking {
static String ServerOS;
static String filePath = "benchmark.dat";
@@ -180,12 +179,12 @@ public class IrisBenchmarking {
Iris.info("- Data Compression: " + formatDouble(calculateDataCompression) + " MBytes/Sec");
if (WindowsDiskSpeed) {
Iris.info("Disk Model: " + getDiskModel());
//Iris.info("Disk Model: " + getDiskModel());
Iris.info(C.BLUE + "- Running with Windows System Assessment Tool");
Iris.info("- Sequential 64.0 Write: " + C.BLUE + formatDouble(avgWriteSpeedMBps) + " Mbps");
Iris.info("- Sequential 64.0 Read: " + C.BLUE + formatDouble(avgReadSpeedMBps) + " Mbps");
} else {
Iris.info("Disk Model: " + getDiskModel());
// Iris.info("Disk Model: " + getDiskModel());
Iris.info(C.GREEN + "- Running in Native Mode");
Iris.info("- Average Write Speed: " + C.GREEN + formatDouble(avgWriteSpeedMBps) + " Mbps");
Iris.info("- Average Read Speed: " + C.GREEN + formatDouble(avgReadSpeedMBps) + " Mbps");

View File

@@ -86,6 +86,7 @@ public class IrisCreator {
* Benchmark mode
*/
private boolean benchmark = false;
private boolean smartVanillaHeight = false;
public static boolean removeFromBukkitYml(String name) throws IOException {
YamlConfiguration yml = YamlConfiguration.loadConfiguration(BUKKIT_YML);
@@ -112,13 +113,6 @@ public class IrisCreator {
*/
public World create() throws IrisException {
if (unstablemode){
Iris.info(C.RED + "Your server is experiencing an incompatibility with the Iris plugin. Please rectify this problem to avoid further complications.");
Iris.info(C.RED + "----------------------------------------------------------------");
Iris.info(C.RED + "Operation ran: Loading Iris World..");
UtilsSFG.printIncompatibleWarnings();
Iris.info(C.RED + "----------------------------------------------------------------");
}
if (Bukkit.isPrimaryThread()) {
throw new IrisException("You cannot invoke create() on the main thread.");
}
@@ -149,6 +143,7 @@ public class IrisCreator {
.name(name)
.seed(seed)
.studio(studio)
.smartVanillaHeight(smartVanillaHeight)
.create();
ServerConfigurator.installDataPacks(false);
@@ -157,7 +152,6 @@ public class IrisCreator {
J.a(() ->
{
int req = 441;
Supplier<Integer> g = () -> {
if (finalAccess1 == null || finalAccess1.getEngine() == null) {
return 0;
@@ -165,6 +159,9 @@ public class IrisCreator {
return finalAccess1.getEngine().getGenerated();
};
if(!benchmark) {
if (finalAccess1 == null) return;
int req = finalAccess1.getSpawnChunks().join();
while (g.get() < req) {
double v = (double) g.get() / (double) req;
if (sender.isPlayer()) {

View File

@@ -32,6 +32,7 @@ public class IrisWorldCreator {
private String name;
private boolean studio = false;
private String dimensionName = null;
private boolean smartVanillaHeight = false;
private long seed = 1337;
public IrisWorldCreator() {
@@ -63,6 +64,11 @@ public class IrisWorldCreator {
return this;
}
public IrisWorldCreator smartVanillaHeight(boolean smartVanillaHeight) {
this.smartVanillaHeight = smartVanillaHeight;
return this;
}
public WorldCreator create() {
IrisDimension dim = IrisData.loadAnyDimension(dimensionName);
@@ -76,7 +82,7 @@ public class IrisWorldCreator {
.build();
ChunkGenerator g = new BukkitChunkGenerator(w, studio, studio
? dim.getLoader().getDataFolder() :
new File(w.worldFolder(), "iris/pack"), dimensionName);
new File(w.worldFolder(), "iris/pack"), dimensionName, smartVanillaHeight);
return new WorldCreator(name)

View File

@@ -21,6 +21,7 @@ package com.volmit.iris.core.wand;
import com.volmit.iris.util.data.Cuboid;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.E;
import org.bukkit.Location;
import org.bukkit.Particle;
import org.bukkit.entity.Player;
@@ -29,6 +30,7 @@ import org.bukkit.util.Vector;
import java.awt.*;
public class WandSelection {
private static final Particle REDSTONE = E.getOrDefault(Particle.class, "REDSTONE", "DUST");
private final Cuboid c;
private final Player p;
@@ -101,7 +103,7 @@ public class WandSelection {
int g = color.getGreen();
int b = color.getBlue();
p.spawnParticle(Particle.REDSTONE, a.getX(), a.getY(), a.getZ(),
p.spawnParticle(REDSTONE, a.getX(), a.getY(), a.getZ(),
1, 0, 0, 0, 0,
new Particle.DustOptions(org.bukkit.Color.fromRGB(r, g, b),
(float) dist * 3f));

View File

@@ -131,6 +131,7 @@ public class IrisComplex implements DataProvider {
caveBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
.convert((r)
-> engine.getDimension().getCaveBiomeStyle().create(rng.nextParallelRNG(InferredType.CAVE.ordinal()), getData()).stream()
.zoom(engine.getDimension().getBiomeZoom())
.zoom(r.getCaveBiomeZoom())
.selectRarity(data.getBiomeLoader().loadAll(r.getCaveBiomes()))
.onNull(emptyBiome)
@@ -139,6 +140,8 @@ public class IrisComplex implements DataProvider {
landBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
.convert((r)
-> engine.getDimension().getLandBiomeStyle().create(rng.nextParallelRNG(InferredType.LAND.ordinal()), getData()).stream()
.zoom(engine.getDimension().getBiomeZoom())
.zoom(engine.getDimension().getLandZoom())
.zoom(r.getLandBiomeZoom())
.selectRarity(data.getBiomeLoader().loadAll(r.getLandBiomes(), (t) -> t.setInferredType(InferredType.LAND)))
).convertAware2D(ProceduralStream::get)
@@ -147,6 +150,8 @@ public class IrisComplex implements DataProvider {
seaBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
.convert((r)
-> engine.getDimension().getSeaBiomeStyle().create(rng.nextParallelRNG(InferredType.SEA.ordinal()), getData()).stream()
.zoom(engine.getDimension().getBiomeZoom())
.zoom(engine.getDimension().getSeaZoom())
.zoom(r.getSeaBiomeZoom())
.selectRarity(data.getBiomeLoader().loadAll(r.getSeaBiomes(), (t) -> t.setInferredType(InferredType.SEA)))
).convertAware2D(ProceduralStream::get)
@@ -155,6 +160,7 @@ public class IrisComplex implements DataProvider {
shoreBiomeStream = regionStream.contextInjecting((c, x, z) -> IrisContext.getOr(engine).getChunkContext().getRegion().get(x, z))
.convert((r)
-> engine.getDimension().getShoreBiomeStyle().create(rng.nextParallelRNG(InferredType.SHORE.ordinal()), getData()).stream()
.zoom(engine.getDimension().getBiomeZoom())
.zoom(r.getShoreBiomeZoom())
.selectRarity(data.getBiomeLoader().loadAll(r.getShoreBiomes(), (t) -> t.setInferredType(InferredType.SHORE)))
).convertAware2D(ProceduralStream::get).cache2D("shoreBiomeStream", engine, cacheSize).waste("Shore Biome Stream");
@@ -292,7 +298,7 @@ public class IrisComplex implements DataProvider {
double b = 0;
for (IrisGenerator gen : generators) {
b += bx.getGenLinkMax(gen.getLoadKey());
b += bx.getGenLinkMax(gen.getLoadKey(), engine);
}
return b;
@@ -311,7 +317,7 @@ public class IrisComplex implements DataProvider {
double b = 0;
for (IrisGenerator gen : generators) {
b += bx.getGenLinkMin(gen.getLoadKey());
b += bx.getGenLinkMin(gen.getLoadKey(), engine);
}
return b;

View File

@@ -254,30 +254,40 @@ public class IrisEngine implements Engine {
return engineData.aquire(() -> {
//TODO: Method this file
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + ".json");
IrisEngineData data = null;
if (!f.exists()) {
if (f.exists()) {
try {
f.getParentFile().mkdirs();
IrisEngineData data = new IrisEngineData();
data.getStatistics().setVersion(Iris.instance.getIrisVersion());
data.getStatistics().setMCVersion(Iris.instance.getMCVersion());
data.getStatistics().setUpgradedVersion(Iris.instance.getIrisVersion());
if (data.getStatistics().getVersion() == -1 || data.getStatistics().getMCVersion() == -1 ) {
Iris.error("Failed to setup Engine Data!");
data = new Gson().fromJson(IO.readAll(f), IrisEngineData.class);
if (data == null) {
Iris.error("Failed to read Engine Data! Corrupted File? recreating...");
}
IO.writeAll(f, new Gson().toJson(data));
} catch (IOException e) {
e.printStackTrace();
}
}
try {
return new Gson().fromJson(IO.readAll(f), IrisEngineData.class);
} catch (Throwable e) {
e.printStackTrace();
if (data == null) {
data = new IrisEngineData();
data.getStatistics().setVersion(Iris.instance.getIrisVersion());
data.getStatistics().setMCVersion(Iris.instance.getMCVersion());
data.getStatistics().setUpgradedVersion(Iris.instance.getIrisVersion());
if (data.getStatistics().getVersion() == -1 || data.getStatistics().getMCVersion() == -1 ) {
Iris.error("Failed to setup Engine Data!");
}
if (f.getParentFile().exists() || f.getParentFile().mkdirs()) {
try {
IO.writeAll(f, new Gson().toJson(data));
} catch (IOException e) {
e.printStackTrace();
}
} else {
Iris.error("Failed to setup Engine Data!");
}
}
return new IrisEngineData();
return data;
});
}

View File

@@ -39,11 +39,17 @@ public class IrisSeaFloorDecorator extends IrisEngineDecorator {
if (decorator != null) {
if (!decorator.isStacking()) {
if (!decorator.isForcePlace() && !decorator.getSlopeCondition().isDefault()
&& !decorator.getSlopeCondition().isValid(getComplex().getSlopeStream().get(realX, realZ))) {
return;
}
if (height >= 0 || height < getEngine().getHeight()) {
if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) {
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
height++;
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
if (height == getDimension().getFluidHeight() - 1) {
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
height++;
data.set(x, height, z, decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData()));
}
} else {
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));
}

View File

@@ -45,6 +45,11 @@ public class IrisShoreLineDecorator extends IrisEngineDecorator {
IrisDecorator decorator = getDecorator(biome, realX, realZ);
if (decorator != null) {
if (!decorator.isForcePlace() && !decorator.getSlopeCondition().isDefault()
&& !decorator.getSlopeCondition().isValid(getComplex().getSlopeStream().get(realX, realZ))) {
return;
}
if (!decorator.isStacking()) {
if (null != decorator.getBlockDataForTop(biome, getRng(), realX, height, realZ, getData())) {
data.set(x, height, z, decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData()));

View File

@@ -53,6 +53,11 @@ public class IrisSurfaceDecorator extends IrisEngineDecorator {
boolean underwater = height < getDimension().getFluidHeight();
if (decorator != null) {
if (!decorator.isForcePlace() && !decorator.getSlopeCondition().isDefault()
&& !decorator.getSlopeCondition().isValid(getComplex().getSlopeStream().get(realX, realZ))) {
return;
}
if (!decorator.isStacking()) {
bd = decorator.getBlockData100(biome, getRng(), realX, height, realZ, getData());

View File

@@ -269,77 +269,80 @@ public interface Engine extends DataProvider, Fallible, LootProvider, BlockUpdat
@ChunkCoordinates
@Override
default void updateChunk(Chunk c) {
if (c.getWorld().isChunkLoaded(c.getX() + 1, c.getZ() + 1)
&& c.getWorld().isChunkLoaded(c.getX(), c.getZ() + 1)
&& c.getWorld().isChunkLoaded(c.getX() + 1, c.getZ())
&& c.getWorld().isChunkLoaded(c.getX() - 1, c.getZ() - 1)
&& c.getWorld().isChunkLoaded(c.getX(), c.getZ() - 1)
&& c.getWorld().isChunkLoaded(c.getX() - 1, c.getZ())
&& c.getWorld().isChunkLoaded(c.getX() + 1, c.getZ() - 1)
&& c.getWorld().isChunkLoaded(c.getX() - 1, c.getZ() + 1) && getMantle().getMantle().isLoaded(c)) {
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.TILE, () -> J.s(() -> {
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), TileWrapper.class, (x, y, z, tile) -> {
int betterY = y + getWorld().minHeight();
if (!TileData.setTileState(c.getBlock(x, betterY, z), tile.getData()))
Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", x, betterY, z, c.getBlock(x, betterY, z).getBlockData().getMaterial().getKey(), tile.getData().getTileId());
});
}));
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.CUSTOM, () -> J.s(() -> {
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), Identifier.class, (x, y, z, v) -> {
Iris.service(ExternalDataSVC.class).processUpdate(this, c.getBlock(x & 15, y + getWorld().minHeight(), z & 15), v);
});
}));
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.UPDATE, () -> J.s(() -> {
PrecisionStopwatch p = PrecisionStopwatch.start();
KMap<Long, Integer> updates = new KMap<>();
RNG r = new RNG(Cache.key(c.getX(), c.getZ()));
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), MatterCavern.class, (x, yf, z, v) -> {
int y = yf + getWorld().minHeight();
if (!B.isFluid(c.getBlock(x & 15, y, z & 15).getBlockData())) {
return;
}
boolean u = false;
if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.DOWN).getBlockData())) {
u = true;
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.WEST).getBlockData())) {
u = true;
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.EAST).getBlockData())) {
u = true;
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.SOUTH).getBlockData())) {
u = true;
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.NORTH).getBlockData())) {
u = true;
}
if (u) {
updates.compute(Cache.key(x & 15, z & 15), (k, vv) -> {
if (vv != null) {
return Math.max(vv, y);
}
return y;
});
}
});
updates.forEach((k, v) -> update(Cache.keyX(k), v, Cache.keyZ(k), c, r));
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), MatterUpdate.class, (x, yf, z, v) -> {
int y = yf + getWorld().minHeight();
if (v != null && v.isUpdate()) {
int vx = x & 15;
int vz = z & 15;
update(x, y, z, c, new RNG(Cache.key(c.getX(), c.getZ())));
if (vx > 0 && vx < 15 && vz > 0 && vz < 15) {
updateLighting(x, y, z, c);
}
}
});
getMantle().getMantle().deleteChunkSlice(c.getX(), c.getZ(), MatterUpdate.class);
getMetrics().getUpdates().put(p.getMilliseconds());
}, RNG.r.i(0, 20)));
for (int x = -1; x <= 1; x++) {
for (int z = -1; z <= 1; z++) {
if (c.getWorld().isChunkLoaded(c.getX() + x, c.getZ() + z))
continue;
Iris.debug("Chunk %s, %s [%s, %s] is not loaded".formatted(c.getX() + x, c.getZ() + z, x, z));
return;
}
}
if (!getMantle().getMantle().isLoaded(c)) {
Iris.debug("Mantle Chunk " + c.getX() + c.getX() + " is not loaded");
return;
}
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.TILE, () -> J.s(() -> {
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), TileWrapper.class, (x, y, z, tile) -> {
int betterY = y + getWorld().minHeight();
if (!TileData.setTileState(c.getBlock(x, betterY, z), tile.getData()))
Iris.warn("Failed to set tile entity data at [%d %d %d | %s] for tile %s!", x, betterY, z, c.getBlock(x, betterY, z).getBlockData().getMaterial().getKey(), tile.getData().getTileId());
});
}));
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.CUSTOM, () -> J.s(() -> {
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), Identifier.class, (x, y, z, v) -> {
Iris.service(ExternalDataSVC.class).processUpdate(this, c.getBlock(x & 15, y + getWorld().minHeight(), z & 15), v);
});
}));
getMantle().getMantle().raiseFlag(c.getX(), c.getZ(), MantleFlag.UPDATE, () -> J.s(() -> {
PrecisionStopwatch p = PrecisionStopwatch.start();
KMap<Long, Integer> updates = new KMap<>();
RNG r = new RNG(Cache.key(c.getX(), c.getZ()));
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), MatterCavern.class, (x, yf, z, v) -> {
int y = yf + getWorld().minHeight();
if (!B.isFluid(c.getBlock(x & 15, y, z & 15).getBlockData())) {
return;
}
boolean u = false;
if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.DOWN).getBlockData())) {
u = true;
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.WEST).getBlockData())) {
u = true;
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.EAST).getBlockData())) {
u = true;
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.SOUTH).getBlockData())) {
u = true;
} else if (B.isAir(c.getBlock(x & 15, y, z & 15).getRelative(BlockFace.NORTH).getBlockData())) {
u = true;
}
if (u) {
updates.compute(Cache.key(x & 15, z & 15), (k, vv) -> {
if (vv != null) {
return Math.max(vv, y);
}
return y;
});
}
});
updates.forEach((k, v) -> update(Cache.keyX(k), v, Cache.keyZ(k), c, r));
getMantle().getMantle().iterateChunk(c.getX(), c.getZ(), MatterUpdate.class, (x, yf, z, v) -> {
int y = yf + getWorld().minHeight();
if (v != null && v.isUpdate()) {
int vx = x & 15;
int vz = z & 15;
update(x, y, z, c, new RNG(Cache.key(c.getX(), c.getZ())));
if (vx > 0 && vx < 15 && vz > 0 && vz < 15) {
updateLighting(x, y, z, c);
}
}
});
getMantle().getMantle().deleteChunkSlice(c.getX(), c.getZ(), MatterUpdate.class);
getMetrics().getUpdates().put(p.getMilliseconds());
}, RNG.r.i(0, 20)));
}
@BlockCoordinates

View File

@@ -0,0 +1,127 @@
package com.volmit.iris.engine.framework.placer;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.framework.IrisLootEvent;
import com.volmit.iris.engine.mantle.EngineMantle;
import com.volmit.iris.engine.object.IObjectPlacer;
import com.volmit.iris.engine.object.InventorySlotType;
import com.volmit.iris.engine.object.IrisLootTable;
import com.volmit.iris.engine.object.TileData;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.math.RNG;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.InventoryHolder;
@Getter
@EqualsAndHashCode(exclude = {"engine", "mantle"})
public class WorldObjectPlacer implements IObjectPlacer {
private final World world;
private final Engine engine;
private final EngineMantle mantle;
public WorldObjectPlacer(World world) {
var a = IrisToolbelt.access(world);
if (a == null || a.getEngine() == null) throw new IllegalStateException(world.getName() + " is not an Iris World!");
this.world = world;
this.engine = a.getEngine();
this.mantle = engine.getMantle();
}
@Override
public int getHighest(int x, int z, IrisData data) {
return mantle.getHighest(x, z, data);
}
@Override
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
return mantle.getHighest(x, z, data, ignoreFluid);
}
@Override
public void set(int x, int y, int z, BlockData d) {
Block block = world.getBlockAt(x, y + world.getMinHeight(), z);
if (y <= world.getMinHeight() || block.getType() == Material.BEDROCK) return;
InventorySlotType slot = null;
if (B.isStorageChest(d)) {
slot = InventorySlotType.STORAGE;
}
if (slot != null) {
RNG rx = new RNG(Cache.key(x, z));
KList<IrisLootTable> tables = engine.getLootTables(rx, block);
try {
Bukkit.getPluginManager().callEvent(new IrisLootEvent(engine, block, slot, tables));
if (!tables.isEmpty()){
Iris.debug("IrisLootEvent has been accessed");
}
if (tables.isEmpty())
return;
InventoryHolder m = (InventoryHolder) block.getState();
engine.addItems(false, m.getInventory(), rx, tables, slot, x, y, z, 15);
} catch (Throwable e) {
Iris.reportError(e);
}
}
block.setBlockData(d);
}
@Override
public BlockData get(int x, int y, int z) {
return world.getBlockAt(x, y + world.getMinHeight(), z).getBlockData();
}
@Override
public boolean isPreventingDecay() {
return mantle.isPreventingDecay();
}
@Override
public boolean isCarved(int x, int y, int z) {
return mantle.isCarved(x, y, z);
}
@Override
public boolean isSolid(int x, int y, int z) {
return world.getBlockAt(x, y + world.getMinHeight(), z).getType().isSolid();
}
@Override
public boolean isUnderwater(int x, int z) {
return mantle.isUnderwater(x, z);
}
@Override
public int getFluidHeight() {
return mantle.getFluidHeight();
}
@Override
public boolean isDebugSmartBore() {
return mantle.isDebugSmartBore();
}
@Override
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
BlockState state = world.getBlockAt(xx, yy + world.getMinHeight(), zz).getState();
tile.toBukkitTry(state);
state.update();
}
}

View File

@@ -20,29 +20,19 @@ package com.volmit.iris.engine.jigsaw;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.engine.platform.PlatformChunkGenerator;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.context.IrisContext;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.math.AxisAlignedBB;
import com.volmit.iris.util.math.BlockPosition;
import com.volmit.iris.util.math.RNG;
import lombok.AccessLevel;
import lombok.Data;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.block.Block;
import org.bukkit.block.BlockState;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import org.bukkit.inventory.InventoryHolder;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import org.bukkit.util.BlockVector;
import java.util.ArrayList;
import java.util.List;
@SuppressWarnings("ALL")
@Data
public class PlannedPiece {
private IrisPosition position;
@@ -50,11 +40,19 @@ public class PlannedPiece {
private IrisObject ogObject;
private IrisJigsawPiece piece;
private IrisObjectRotation rotation;
@EqualsAndHashCode.Exclude
private IrisData data;
private KList<IrisJigsawPieceConnector> connected;
private boolean dead = false;
private AxisAlignedBB box;
@EqualsAndHashCode.Exclude
private PlannedStructure structure;
@EqualsAndHashCode.Exclude
@Setter(AccessLevel.NONE)
private ParentConnection parent = null;
@EqualsAndHashCode.Exclude
@Setter(AccessLevel.NONE)
private KMap<IrisJigsawPieceConnector, IrisPosition> realPositions;
public PlannedPiece(PlannedStructure structure, IrisPosition position, IrisJigsawPiece piece) {
this(structure, position, piece, 0, 0, 0);
@@ -76,6 +74,7 @@ public class PlannedPiece {
this.object.setLoadKey(piece.getObject());
this.ogObject.setLoadKey(piece.getObject());
this.connected = new KList<>();
this.realPositions = new KMap<>();
}
@@ -94,7 +93,15 @@ public class PlannedPiece {
}
BlockVector v = getObject().getCenter();
box = object.getAABB().shifted(position.add(new IrisPosition(object.getCenter())));
IrisPosition pos = new IrisPosition();
IrisObjectPlacement options = piece.getPlacementOptions();
if (options != null && options.getTranslate() != null) {
IrisObjectTranslate translate = options.getTranslate();
pos.setX(translate.getX());
pos.setY(translate.getY());
pos.setZ(translate.getZ());
}
box = object.getAABB().shifted(position.add(new IrisPosition(object.getCenter())).add(pos));
return box;
}
@@ -126,11 +133,21 @@ public class PlannedPiece {
return c;
}
public boolean connect(IrisJigsawPieceConnector c) {
if (piece.getConnectors().contains(c)) {
return connected.addIfMissing(c);
}
public KList<IrisJigsawPieceConnector> getChildConnectors() {
ParentConnection pc = getParent();
KList<IrisJigsawPieceConnector> c = getConnected().copy();
if (pc != null) c.removeIf(i -> i.equals(pc.connector));
return c;
}
public boolean connect(IrisJigsawPieceConnector c, PlannedPiece p, IrisJigsawPieceConnector pc) {
if (piece.getConnectors().contains(c) && p.getPiece().getConnectors().contains(pc)) {
if (connected.contains(c) || p.connected.contains(pc)) return false;
connected.add(c);
p.connected.add(pc);
p.parent = new ParentConnection(this, c, p, pc);
return true;
}
return false;
}
@@ -162,108 +179,29 @@ public class PlannedPiece {
}
public boolean isFull() {
return connected.size() >= piece.getConnectors().size() || isDead();
return connected.size() >= piece.getConnectors().size();
}
public void place(World world) {
PlatformChunkGenerator a = IrisToolbelt.access(world);
int minY = 0;
if (a != null) {
minY = a.getEngine().getMinHeight();
if (!a.getEngine().getDimension().isBedrock())
minY--; //If the dimension has no bedrock, allow it to go a block lower
public void setRealPositions(int x, int y, int z, IObjectPlacer placer) {
boolean isUnderwater = piece.getPlacementOptions().isUnderwater();
for (IrisJigsawPieceConnector c : piece.getConnectors()) {
var pos = c.getPosition().add(new IrisPosition(x, 0, z));
if (y < 0) {
pos.setY(pos.getY() + placer.getHighest(pos.getX(), pos.getZ(), getData(), isUnderwater) + (object.getH() / 2));
} else {
pos.setY(pos.getY() + y);
}
realPositions.put(c, pos);
}
}
getPiece().getPlacementOptions().setTranslate(new IrisObjectTranslate());
getPiece().getPlacementOptions().setRotation(rotation);
int finalMinY = minY;
RNG rng = getStructure().getRng().nextParallelRNG(37555);
// TODO: REAL CLASSES!!!!!!!
getOgObject().place(position.getX() + getObject().getCenter().getBlockX(), position.getY() + getObject().getCenter().getBlockY(), position.getZ() + getObject().getCenter().getBlockZ(), new IObjectPlacer() {
@Override
public int getHighest(int x, int z, IrisData data) {
return position.getY();
}
@Override
public int getHighest(int x, int z, IrisData data, boolean ignoreFluid) {
return position.getY();
}
@Override
public void set(int x, int y, int z, BlockData d) {
Block block = world.getBlockAt(x, y, z);
//Prevent blocks being set in or bellow bedrock
if (y <= finalMinY || block.getType() == Material.BEDROCK) return;
block.setBlockData(d);
if (a != null && getPiece().getPlacementOptions().getLoot().isNotEmpty() &&
block.getState() instanceof InventoryHolder) {
IrisLootTable table = getPiece().getPlacementOptions().getTable(block.getBlockData(), getData());
if (table == null) return;
Engine engine = a.getEngine();
engine.addItems(false, ((InventoryHolder) block.getState()).getInventory(),
rng.nextParallelRNG(BlockPosition.toLong(x, y, z)),
new KList<>(table), InventorySlotType.STORAGE, x, y, z, 15);
}
}
@Override
public BlockData get(int x, int y, int z) {
return world.getBlockAt(x, y, z).getBlockData();
}
@Override
public boolean isPreventingDecay() {
return false;
}
@Override
public boolean isCarved(int x, int y, int z) {
return false;
}
@Override
public boolean isSolid(int x, int y, int z) {
return world.getBlockAt(x, y, z).getType().isSolid();
}
@Override
public boolean isUnderwater(int x, int z) {
return false;
}
@Override
public int getFluidHeight() {
return 0;
}
@Override
public boolean isDebugSmartBore() {
return false;
}
@Override
public void setTile(int xx, int yy, int zz, TileData<? extends TileState> tile) {
BlockState state = world.getBlockAt(xx, yy, zz).getState();
tile.toBukkitTry(state);
state.update();
}
@Override
public Engine getEngine() {
if (IrisToolbelt.isIrisWorld(world)) {
return IrisToolbelt.access(world).getEngine();
}
return IrisContext.get().getEngine();
}
}, piece.getPlacementOptions(), rng, getData());
public record ParentConnection(PlannedPiece parent, IrisJigsawPieceConnector parentConnector, PlannedPiece self, IrisJigsawPieceConnector connector) {
public IrisPosition getTargetPosition() {
var pos = parent.realPositions.get(parentConnector);
if (pos == null) return null;
return pos.add(new IrisPosition(parentConnector.getDirection().toVector()))
.sub(connector.getPosition())
.sub(new IrisPosition(self.object.getCenter()));
}
}
}

View File

@@ -21,19 +21,21 @@ package com.volmit.iris.engine.jigsaw;
import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.engine.data.cache.Cache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.framework.placer.WorldObjectPlacer;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.slices.container.JigsawPieceContainer;
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
import com.volmit.iris.util.scheduling.J;
import lombok.Data;
import org.bukkit.Axis;
import org.bukkit.World;
import org.bukkit.block.TileState;
import org.bukkit.block.data.BlockData;
import java.util.function.Consumer;
@Data
public class PlannedStructure {
@@ -74,33 +76,44 @@ public class PlannedStructure {
}
}
public void place(IObjectPlacer placer, Mantle e, Engine eng) {
public boolean place(IObjectPlacer placer, Mantle e, Engine eng) {
IrisObjectPlacement options = new IrisObjectPlacement();
options.getRotation().setEnabled(false);
options.setRotation(IrisObjectRotation.of(0,0,0));
int startHeight = pieces.get(0).getPosition().getY();
boolean placed = false;
for (PlannedPiece i : pieces) {
place(i, startHeight, options, placer, e, eng);
if (place(i, startHeight, options, placer, e, eng))
placed = true;
}
if (placed) {
Position2 chunkPos = new Position2(position.getX() >> 4, position.getZ() >> 4);
Position2 regionPos = new Position2(chunkPos.getX() >> 5, chunkPos.getZ() >> 5);
JigsawStructuresContainer slice = e.get(regionPos.getX(), 0, regionPos.getZ(), JigsawStructuresContainer.class);
if (slice == null) slice = new JigsawStructuresContainer();
slice.add(structure, chunkPos);
e.set(regionPos.getX(), 0, regionPos.getZ(), slice);
}
return placed;
}
public void place(PlannedPiece i, int startHeight, IrisObjectPlacement o, IObjectPlacer placer, Mantle e, Engine eng) {
public boolean place(PlannedPiece i, int startHeight, IrisObjectPlacement o, IObjectPlacer placer, Mantle e, Engine eng) {
IrisObjectPlacement options = o;
if (i.getPiece().getPlacementOptions() != null) {
options = i.getPiece().getPlacementOptions();
options.getRotation().setEnabled(false);
options.setRotateTowardsSlope(false);
options.setWarp(new IrisGeneratorStyle(NoiseStyle.FLAT));
} else {
options.setMode(i.getPiece().getPlaceMode());
}
IrisObject vo = i.getOgObject();
IrisObject v = i.getObject();
int sx = (v.getW() / 2);
int sz = (v.getD() / 2);
int xx = i.getPosition().getX() + sx;
int zz = i.getPosition().getZ() + sz;
RNG rngf = new RNG(Cache.key(xx, zz));
int offset = i.getPosition().getY() - startHeight;
int height;
@@ -108,12 +121,23 @@ public class PlannedStructure {
if (i.getStructure().getStructure().getOverrideYRange() != null) {
height = (int) i.getStructure().getStructure().getOverrideYRange().get(rng, xx, zz, getData());
} else {
height = placer.getHighest(xx, zz, getData());
height = placer.getHighest(xx, zz, getData(), options.isUnderwater());
}
} else {
height = i.getStructure().getStructure().getLockY();
}
PlannedPiece.ParentConnection connection = i.getParent();
if (connection != null && connection.connector().isLockY()) {
var pos = connection.getTargetPosition();
if (pos != null) {
height = pos.getY();
offset = 0;
} else {
Iris.warn("Failed to get target position for " + v.getLoadKey());
}
}
height += offset + (v.getH() / 2);
if (options.getMode().equals(ObjectPlaceMode.PAINT)) {
@@ -122,16 +146,18 @@ public class PlannedStructure {
int id = rng.i(0, Integer.MAX_VALUE);
JigsawPieceContainer container = JigsawPieceContainer.toContainer(i.getPiece());
vo.place(xx, height, zz, placer, options, rng, (b, data) -> {
i.setRealPositions(xx, height, zz, placer);
return v.place(xx, height, zz, placer, options, rng, (b, data) -> {
e.set(b.getX(), b.getY(), b.getZ(), v.getLoadKey() + "@" + id);
e.set(b.getX(), b.getY(), b.getZ(), container);
}, null, getData());
if (data instanceof IrisBlockData d) {
e.set(b.getX(), b.getY(), b.getZ(), d.getCustom());
}
}, null, getData().getEngine() != null ? getData() : eng.getData()) != -1;
}
public void place(World world) {
for (PlannedPiece i : pieces) {
Iris.sq(() -> i.place(world));
}
public void place(WorldObjectPlacer placer, Consumer<Boolean> consumer) {
J.s(() -> consumer.accept(place(placer, placer.getMantle().getMantle(), placer.getEngine())));
}
private void generateOutwards() {
@@ -167,9 +193,7 @@ public class PlannedStructure {
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea) {
if (!piece.getPiece().getPlacementOptions().getRotation().isEnabled()) {
if (generateRotatedPiece(piece, pieceConnector, idea, 0, 0, 0)) {
return true;
}
return generateRotatedPiece(piece, pieceConnector, idea, 0, 0, 0);
}
KList<Integer> forder1 = new KList<Integer>().qadd(0).qadd(1).qadd(2).qadd(3).shuffle(rng);
@@ -216,7 +240,7 @@ public class PlannedStructure {
}
private boolean generateRotatedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, IrisJigsawPiece idea, int x, int y, int z) {
return generateRotatedPiece(piece, pieceConnector, idea, IrisObjectRotation.of(x, y, z));
return generateRotatedPiece(piece, pieceConnector, idea, IrisObjectRotation.of(x * 90D, y * 90D, z * 90D));
}
private boolean generatePositionedPiece(PlannedPiece piece, IrisJigsawPieceConnector pieceConnector, PlannedPiece test, IrisJigsawPieceConnector testConnector) {
@@ -240,8 +264,7 @@ public class PlannedStructure {
return false;
}
piece.connect(pieceConnector);
test.connect(testConnector);
piece.connect(pieceConnector, test, testConnector);
pieces.add(test);
return true;
@@ -250,7 +273,8 @@ public class PlannedStructure {
private KList<IrisJigsawPiece> getShuffledPiecesFor(IrisJigsawPieceConnector c) {
KList<IrisJigsawPiece> p = new KList<>();
for (String i : c.getPools().shuffleCopy(rng)) {
KList<String> pools = terminating && getStructure().getTerminatePool() != null ? new KList<>(getStructure().getTerminatePool()) : c.getPools().shuffleCopy(rng);
for (String i : pools) {
for (String j : getData().getJigsawPoolLoader().load(i).getPieces().shuffleCopy(rng)) {
IrisJigsawPiece pi = getData().getJigsawPieceLoader().load(j);
@@ -276,7 +300,9 @@ public class PlannedStructure {
}
public KList<PlannedPiece> getPiecesWithAvailableConnectors() {
return pieces.copy().removeWhere(PlannedPiece::isFull);
KList<PlannedPiece> available = pieces.copy().removeWhere(PlannedPiece::isFull);
if (!terminating) available.removeIf(PlannedPiece::isDead);
return available;
}
public int getVolume() {
@@ -301,6 +327,10 @@ public class PlannedStructure {
public boolean collidesWith(PlannedPiece piece, PlannedPiece ignore) {
for (PlannedPiece i : pieces) {
if (i.equals(ignore)) {
continue;
}
if (i.collidesWith(piece)) {
return true;
}

View File

@@ -24,13 +24,17 @@ import com.volmit.iris.engine.mantle.IrisMantleComponent;
import com.volmit.iris.engine.mantle.MantleWriter;
import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.mantle.MantleFlag;
import com.volmit.iris.util.math.Position2;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
import com.volmit.iris.util.noise.CNG;
import org.jetbrains.annotations.Nullable;
import java.util.List;
@@ -39,21 +43,22 @@ public class MantleJigsawComponent extends IrisMantleComponent {
public MantleJigsawComponent(EngineMantle engineMantle) {
super(engineMantle, MantleFlag.JIGSAW);
cng = NoiseStyle.STATIC.create(new RNG(engineMantle.getEngine().getSeedManager().getJigsaw()));
cng = NoiseStyle.STATIC.create(new RNG(jigsaw()));
}
@Override
public void generateLayer(MantleWriter writer, int x, int z, ChunkContext context) {
RNG rng = new RNG(cng.fit(-Integer.MAX_VALUE, Integer.MAX_VALUE, x, z));
int xxx = 8 + (x << 4);
int zzz = 8 + (z << 4);
IrisRegion region = getComplex().getRegionStream().get(xxx, zzz);
IrisBiome biome = getComplex().getTrueBiomeStream().get(xxx, zzz);
generateJigsaw(writer, rng, x, z, biome, region);
generateJigsaw(writer, x, z, biome, region);
}
@ChunkCoordinates
private void generateJigsaw(MantleWriter writer, RNG rng, int x, int z, IrisBiome biome, IrisRegion region) {
private void generateJigsaw(MantleWriter writer, int x, int z, IrisBiome biome, IrisRegion region) {
long seed = cng.fit(Integer.MIN_VALUE, Integer.MIN_VALUE, x, z);
if (getDimension().getStronghold() != null) {
List<Position2> poss = getDimension().getStrongholds(seed());
@@ -61,28 +66,61 @@ public class MantleJigsawComponent extends IrisMantleComponent {
for (Position2 pos : poss) {
if (x == pos.getX() >> 4 && z == pos.getZ() >> 4) {
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(getDimension().getStronghold());
place(writer, pos.toIris(), structure, rng);
place(writer, pos.toIris(), structure, new RNG(seed));
return;
}
}
}
}
boolean placed = placeStructures(writer, rng, x, z, biome.getJigsawStructures());
KSet<Position2> cachedRegions = new KSet<>();
KMap<String, KSet<Position2>> cache = new KMap<>();
KMap<Position2, Double> distanceCache = new KMap<>();
boolean placed = placeStructures(writer, seed, x, z, biome.getJigsawStructures(), cachedRegions, cache, distanceCache);
if (!placed)
placed = placeStructures(writer, rng, x, z, region.getJigsawStructures());
placed = placeStructures(writer, seed, x, z, region.getJigsawStructures(), cachedRegions, cache, distanceCache);
if (!placed)
placeStructures(writer, rng, x, z, getDimension().getJigsawStructures());
placeStructures(writer, seed, x, z, getDimension().getJigsawStructures(), cachedRegions, cache, distanceCache);
}
@ChunkCoordinates
private boolean placeStructures(MantleWriter writer, RNG rng, int x, int z, KList<IrisJigsawStructurePlacement> structures) {
for (IrisJigsawStructurePlacement i : structures) {
if (rng.nextInt(i.getRarity()) == 0) {
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
place(writer, position, structure, rng);
return true;
private boolean placeStructures(MantleWriter writer, long seed, int x, int z, KList<IrisJigsawStructurePlacement> structures,
KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
IrisJigsawStructurePlacement i = pick(structures, seed, x, z);
if (i == null || checkMinDistances(i.collectMinDistances(), x, z, cachedRegions, cache, distanceCache))
return false;
RNG rng = new RNG(seed);
IrisPosition position = new IrisPosition((x << 4) + rng.nextInt(15), 0, (z << 4) + rng.nextInt(15));
IrisJigsawStructure structure = getData().getJigsawStructureLoader().load(i.getStructure());
return place(writer, position, structure, rng);
}
@ChunkCoordinates
private boolean checkMinDistances(KMap<String, Integer> minDistances, int x, int z, KSet<Position2> cachedRegions, KMap<String, KSet<Position2>> cache, KMap<Position2, Double> distanceCache) {
int range = 0;
for (int d : minDistances.values())
range = Math.max(range, d);
for (int xx = -range; xx <= range; xx++) {
for (int zz = -range; zz <= range; zz++) {
Position2 pos = new Position2((xx + x) >> 5, (zz + z) >> 5);
if (cachedRegions.contains(pos)) continue;
cachedRegions.add(pos);
JigsawStructuresContainer container = getMantle().get(pos.getX(), 0, pos.getZ(), JigsawStructuresContainer.class);
if (container == null) continue;
for (String key : container.getStructures()) {
cache.computeIfAbsent(key, k -> new KSet<>()).addAll(container.getPositions(key));
}
}
}
Position2 pos = new Position2(x, z);
for (String structure : minDistances.keySet()) {
if (!cache.containsKey(structure)) continue;
double minDist = minDistances.get(structure);
minDist = minDist * minDist;
for (Position2 sPos : cache.get(structure)) {
double dist = distanceCache.computeIfAbsent(sPos, position2 -> position2.distance(pos));
if (minDist > dist) return true;
}
}
return false;
@@ -91,8 +129,8 @@ public class MantleJigsawComponent extends IrisMantleComponent {
@ChunkCoordinates
public IrisJigsawStructure guess(int x, int z) {
// todo The guess doesnt bring into account that the placer may return -1
boolean t = false;
RNG rng = new RNG(cng.fit(-Integer.MAX_VALUE, Integer.MAX_VALUE, x, z));
// todo doesnt bring skipped placements into account
long seed = cng.fit(Integer.MIN_VALUE, Integer.MIN_VALUE, x, z);
IrisBiome biome = getEngineMantle().getEngine().getSurfaceBiome((x << 4) + 8, (z << 4) + 8);
IrisRegion region = getEngineMantle().getEngine().getRegion((x << 4) + 8, (z << 4) + 8);
@@ -108,29 +146,26 @@ public class MantleJigsawComponent extends IrisMantleComponent {
}
}
for (IrisJigsawStructurePlacement i : biome.getJigsawStructures()) {
if (rng.nextInt(i.getRarity()) == 0) {
return getData().getJigsawStructureLoader().load(i.getStructure());
}
}
IrisJigsawStructurePlacement i = pick(biome.getJigsawStructures(), seed, x, z);
if (i == null) i = pick(region.getJigsawStructures(), seed, x, z);
if (i == null) i = pick(getDimension().getJigsawStructures(), seed, x, z);
return i != null ? getData().getJigsawStructureLoader().load(i.getStructure()) : null;
}
for (IrisJigsawStructurePlacement i : region.getJigsawStructures()) {
if (rng.nextInt(i.getRarity()) == 0) {
return getData().getJigsawStructureLoader().load(i.getStructure());
}
}
for (IrisJigsawStructurePlacement i : getDimension().getJigsawStructures()) {
if (rng.nextInt(i.getRarity()) == 0) {
return getData().getJigsawStructureLoader().load(i.getStructure());
}
}
return null;
@Nullable
@ChunkCoordinates
private IrisJigsawStructurePlacement pick(List<IrisJigsawStructurePlacement> structures, long seed, int x, int z) {
return IRare.pick(structures.stream()
.filter(p -> p.shouldPlace(getDimension().getJigsawStructureDivisor(), jigsaw(), x, z))
.toList(), new RNG(seed).nextDouble());
}
@BlockCoordinates
private void place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
private boolean place(MantleWriter writer, IrisPosition position, IrisJigsawStructure structure, RNG rng) {
return new PlannedStructure(structure, position, rng).place(writer, getMantle(), writer.getEngine());
}
private long jigsaw() {
return getEngineMantle().getEngine().getSeedManager().getJigsaw();
}
}

View File

@@ -27,6 +27,7 @@ import com.volmit.iris.engine.object.*;
import com.volmit.iris.util.collection.KSet;
import com.volmit.iris.util.context.ChunkContext;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.data.IrisBlockData;
import com.volmit.iris.util.documentation.BlockCoordinates;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.mantle.MantleFlag;
@@ -103,6 +104,9 @@ public class MantleObjectComponent extends IrisMantleComponent {
if (objectPlacement.isDolphinTarget() && objectPlacement.isUnderwater() && B.isStorageChest(data)) {
writer.setData(b.getX(), b.getY(), b.getZ(), MatterStructurePOI.BURIED_TREASURE);
}
if (data instanceof IrisBlockData d) {
writer.setData(b.getX(), b.getY(), b.getZ(), d.getCustom());
}
}, null, getData());
}
}

View File

@@ -194,13 +194,14 @@ public class IrisBiome extends IrisRegistrant implements IRare {
return getCustomDerivitives() != null && getCustomDerivitives().isNotEmpty();
}
public double getGenLinkMax(String loadKey) {
public double getGenLinkMax(String loadKey, Engine engine) {
Integer v = genCacheMax.aquire(() ->
{
KMap<String, Integer> l = new KMap<>();
for (IrisBiomeGeneratorLink i : getGenerators()) {
l.put(i.getGenerator(), i.getMax());
l.put(i.getGenerator(), i.getMax(engine));
}
return l;
@@ -209,13 +210,13 @@ public class IrisBiome extends IrisRegistrant implements IRare {
return v == null ? 0 : v;
}
public double getGenLinkMin(String loadKey) {
public double getGenLinkMin(String loadKey, Engine engine) {
Integer v = genCacheMin.aquire(() ->
{
KMap<String, Integer> l = new KMap<>();
for (IrisBiomeGeneratorLink i : getGenerators()) {
l.put(i.getGenerator(), i.getMin());
l.put(i.getGenerator(), i.getMin(engine));
}
return l;
@@ -450,26 +451,26 @@ public class IrisBiome extends IrisRegistrant implements IRare {
return real;
}
public int getMaxHeight() {
public int getMaxHeight(Engine engine) {
return maxHeight.aquire(() ->
{
int maxHeight = 0;
for (IrisBiomeGeneratorLink i : getGenerators()) {
maxHeight += i.getMax();
maxHeight += i.getMax(engine);
}
return maxHeight;
});
}
public int getMaxWithObjectHeight(IrisData data) {
public int getMaxWithObjectHeight(IrisData data, Engine engine) {
return maxWithObjectHeight.aquire(() ->
{
int maxHeight = 0;
for (IrisBiomeGeneratorLink i : getGenerators()) {
maxHeight += i.getMax();
maxHeight += i.getMax(engine);
}
int gg = 0;

View File

@@ -19,6 +19,7 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
@@ -68,8 +69,10 @@ public class IrisBiomeCustom {
@Desc("The biome's category type")
private IrisBiomeCustomCategory category = IrisBiomeCustomCategory.plains;
@MinNumber(0)
@MaxNumber(20)
@Desc("The spawn rarity of any defined spawners")
private int spawnRarity = -1;
private int spawnRarity = 0;
@Desc("The color of the sky, top half of sky. (hex format)")
private String skyColor = "#79a8e1";
@@ -89,7 +92,7 @@ public class IrisBiomeCustom {
@Desc("The color of foliage (hex format). Leave blank / don't define to not change")
private String foliageColor = "";
public String generateJson() {
public String generateJson(IDataFixer fixer) {
JSONObject effects = new JSONObject();
effects.put("sky_color", parseColor(getSkyColor()));
effects.put("fog_color", parseColor(getFogColor()));
@@ -155,7 +158,7 @@ public class IrisBiomeCustom {
j.put("spawners", spawners);
}
return j.toString(4);
return fixer.fixCustomBiome(this, j).toString(4);
}
private int parseColor(String c) {

View File

@@ -18,14 +18,13 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.core.IrisSettings;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.data.DataProvider;
import com.volmit.iris.util.interpolation.IrisInterpolation;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.*;
import lombok.experimental.Accessors;
@Snippet("generator-layer")
@@ -40,22 +39,23 @@ public class IrisBiomeGeneratorLink {
@RegistryListResource(IrisGenerator.class)
@Desc("The generator id")
private String generator = "default";
@DependsOn({"min", "max"})
@DependsOn({ "min", "max" })
@Required
@MinNumber(-2032) // TODO: WARNING HEIGHT
@MaxNumber(2032) // TODO: WARNING HEIGHT
@Desc("The min block value (value + fluidHeight)")
@Getter(AccessLevel.NONE)
private int min = 0;
@DependsOn({"min", "max"})
@DependsOn({ "min", "max" })
@Required
@MinNumber(-2032) // TODO: WARNING HEIGHT
@MaxNumber(2032) // TODO: WARNING HEIGHT
@Getter(AccessLevel.NONE)
@Desc("The max block value (value + fluidHeight)")
private int max = 0;
public IrisGenerator getCachedGenerator(DataProvider g) {
return gen.aquire(() ->
{
return gen.aquire(() -> {
IrisGenerator gen = g.getData().getGeneratorLoader().load(getGenerator());
if (gen == null) {
@@ -66,21 +66,74 @@ public class IrisBiomeGeneratorLink {
});
}
private int[] getBiomeGeneratorsRaw(Engine engine) {
int max = engine.getDimension().getMinHeight();
int min = engine.getDimension().getMaxHeight();
for (IrisBiome biome : engine.getAllBiomes()) {
for (IrisBiomeGeneratorLink i : biome.getGenerators()) {
int biomeRawMax = i.getMaxRaw();
int biomeRawMin = i.getMinRaw();
if (max < biomeRawMax)
max = biomeRawMax;
if (min > biomeRawMin)
min = biomeRawMin;
}
}
return new int[] { min, max };
}
private int calculateHeight(Engine engine, int option) {
int dmx = engine.getDimension().getMaxHeight();
int dmn = engine.getDimension().getMinHeight();
int[] heights = getBiomeGeneratorsRaw(engine);
int gmx = heights[1];
int gmn = heights[0];
int mx = getMaxRaw();
int mn = getMinRaw();
if (engine.getDimension().isSmartVanillaHeight()) {
if (mx > 0)
mx = Math.min((int) (((float) mx / (float) gmx) * 300.0f), 300);
if (mx < 0)
mx = Math.min((int) (((float) mx / (float) gmn) * 300.0f), 56);
if (mn > 0)
mn = Math.min((int) (((float) mn / (float) gmx) * 300.0f), 300);
if (mn < 0)
mn = Math.min((int) (((float) mn / (float) gmn) * 300.0f), 56);
}
if (option == 1) {
return mx;
}
if (option == 0) {
return mn;
}
Iris.error("Fatal Generator error!");
return 0;
}
public int getMax(Engine engine) {
return calculateHeight(engine, 1);
}
public int getMin(Engine engine) {
return calculateHeight(engine, 0);
}
private int getMaxRaw() {
return max;
}
private int getMinRaw() {
return min;
}
public double getHeight(DataProvider xg, double x, double z, long seed) {
double g = getCachedGenerator(xg).getHeight(x, z, seed);
g = g < 0 ? 0 : g;
g = g > 1 ? 1 : g;
// if (IrisSettings.get().getGenerator().forceConvertTo320Height) {
// if (max > 320 || min > 320) {
// double scaleFactor = 320.0 / Math.max(max, min);
// min *= (int) scaleFactor;
// max *= (int) scaleFactor;
// if (min < 0) {
//
// }
// }
// }
// todo This
return IrisInterpolation.lerp(min, max, g);
}

View File

@@ -55,6 +55,8 @@ public class IrisDecorator {
@ArrayType(min = 1, type = IrisBlockData.class)
@Desc("When set, the decorator will never place onto any of these blocks.")
private KList<IrisBlockData> blacklist;
@Desc("The slope at which this decorator can be placed. Range from 0 to 10 by default. Calculated from a 3-block radius from the center of the decorator placement.")
private IrisSlopeClip slopeCondition = new IrisSlopeClip();
@DependsOn({"scaleStack", "stackMin", "stackMax"})
@Desc("If stackMax is set to true, use this to limit its max height for large caverns")
private int absoluteMaxStack = 30;

View File

@@ -21,12 +21,11 @@ package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.core.loader.IrisData;
import com.volmit.iris.core.loader.IrisRegistrant;
import com.volmit.iris.core.nms.datapack.IDataFixer;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.annotations.*;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.data.DataProvider;
import com.volmit.iris.util.data.Dimension;
import com.volmit.iris.util.io.IO;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.math.Position2;
@@ -42,7 +41,6 @@ import org.bukkit.Material;
import org.bukkit.World.Environment;
import org.bukkit.block.data.BlockData;
import java.io.DataInput;
import java.io.File;
import java.io.IOException;
@@ -210,6 +208,8 @@ public class IrisDimension extends IrisRegistrant {
private IrisCarving carving = new IrisCarving();
@Desc("Configuration of fluid bodies such as rivers & lakes")
private IrisFluidBodies fluidBodies = new IrisFluidBodies();
@Desc("forceConvertTo320Height")
private Boolean forceConvertTo320Height = false;
@Desc("The world environment")
private Environment environment = Environment.NORMAL;
@RegistryListResource(IrisRegion.class)
@@ -220,6 +220,8 @@ public class IrisDimension extends IrisRegistrant {
@ArrayType(min = 1, type = IrisJigsawStructurePlacement.class)
@Desc("Jigsaw structures")
private KList<IrisJigsawStructurePlacement> jigsawStructures = new KList<>();
@Desc("The jigsaw structure divisor to use when generating missing jigsaw placement values")
private double jigsawStructureDivisor = 18;
@Required
@MinNumber(0)
@MaxNumber(1024)
@@ -231,6 +233,8 @@ public class IrisDimension extends IrisRegistrant {
private IrisRange dimensionHeightEnd = new IrisRange(-64, 320);
@Desc("Define the min and max Y bounds of this dimension. Please keep in mind that Iris internally generates from 0 to (max - min). \n\nFor example at -64 to 320, Iris is internally generating to 0 to 384, then on outputting chunks, it shifts it down by the min height (64 blocks). The default is -64 to 320. \n\nThe fluid height is placed at (fluid height + min height). So a fluid height of 63 would actually show up in the world at 1.")
private IrisRange dimensionHeightNether = new IrisRange(-64, 320);
@Desc("Enable smart vanilla height")
private boolean smartVanillaHeight = false;
@RegistryListResource(IrisBiome.class)
@Desc("Keep this either undefined or empty. Setting any biome name into this will force iris to only generate the specified biome. Great for testing.")
private String focus = "";
@@ -240,7 +244,7 @@ public class IrisDimension extends IrisRegistrant {
@MinNumber(0.0001)
@MaxNumber(512)
@Desc("Zoom in or out the biome size. Higher = bigger biomes")
private double biomeZoom = 5D;
private double biomeZoom = 1D;
@MinNumber(0)
@MaxNumber(360)
@Desc("You can rotate the input coordinates by an angle. This can make terrain appear more natural (less sharp corners and lines). This literally rotates the entire dimension by an angle. Hint: Try 12 degrees or something not on a 90 or 45 degree angle.")
@@ -442,7 +446,7 @@ public class IrisDimension extends IrisRegistrant {
return landBiomeStyle;
}
public boolean installDataPack(DataProvider data, File datapacks, double ultimateMaxHeight, double ultimateMinHeight) {
public boolean installDataPack(IDataFixer fixer, DataProvider data, File datapacks, double ultimateMaxHeight, double ultimateMinHeight) {
boolean write = false;
boolean changed = false;
@@ -462,7 +466,7 @@ public class IrisDimension extends IrisRegistrant {
Iris.verbose(" Installing Data Pack Biome: " + output.getPath());
output.getParentFile().mkdirs();
try {
IO.writeAll(output, j.generateJson());
IO.writeAll(output, j.generateJson(fixer));
} catch (IOException e) {
Iris.reportError(e);
e.printStackTrace();
@@ -475,7 +479,7 @@ public class IrisDimension extends IrisRegistrant {
Iris.verbose(" Installing Data Pack Dimension Types: \"minecraft:overworld\", \"minecraft:the_nether\", \"minecraft:the_end\"");
dimensionHeight.setMax(ultimateMaxHeight);
dimensionHeight.setMin(ultimateMinHeight);
changed = writeDimensionType(changed, datapacks);
changed = writeDimensionType(fixer, changed, datapacks);
}
if (write) {
@@ -514,13 +518,13 @@ public class IrisDimension extends IrisRegistrant {
}
public boolean writeDimensionType(boolean changed, File datapacks) {
public boolean writeDimensionType(IDataFixer fixer, boolean changed, File datapacks) {
File dimTypeOverworld = new File(datapacks, "iris/data/minecraft/dimension_type/overworld.json");
if (!dimTypeOverworld.exists())
changed = true;
dimTypeOverworld.getParentFile().mkdirs();
try {
IO.writeAll(dimTypeOverworld, generateDatapackJsonOverworld());
IO.writeAll(dimTypeOverworld, generateDatapackJsonOverworld(fixer));
} catch (IOException e) {
Iris.reportError(e);
e.printStackTrace();
@@ -532,7 +536,7 @@ public class IrisDimension extends IrisRegistrant {
changed = true;
dimTypeNether.getParentFile().mkdirs();
try {
IO.writeAll(dimTypeNether, generateDatapackJsonNether());
IO.writeAll(dimTypeNether, generateDatapackJsonNether(fixer));
} catch (IOException e) {
Iris.reportError(e);
e.printStackTrace();
@@ -544,7 +548,7 @@ public class IrisDimension extends IrisRegistrant {
changed = true;
dimTypeEnd.getParentFile().mkdirs();
try {
IO.writeAll(dimTypeEnd, generateDatapackJsonEnd());
IO.writeAll(dimTypeEnd, generateDatapackJsonEnd(fixer));
} catch (IOException e) {
Iris.reportError(e);
e.printStackTrace();
@@ -553,27 +557,27 @@ public class IrisDimension extends IrisRegistrant {
return changed;
}
private String generateDatapackJsonOverworld() {
private String generateDatapackJsonOverworld(IDataFixer fixer) {
JSONObject obj = new JSONObject(DP_OVERWORLD_DEFAULT);
obj.put("min_y", dimensionHeight.getMin());
obj.put("height", dimensionHeight.getMax() - dimensionHeight.getMin());
obj.put("logical_height", logicalHeight);
return obj.toString(4);
return fixer.fixDimension(obj).toString(4);
}
private String generateDatapackJsonNether() {
private String generateDatapackJsonNether(IDataFixer fixer) {
JSONObject obj = new JSONObject(DP_NETHER_DEFAULT);
obj.put("min_y", dimensionHeightNether.getMin());
obj.put("height", dimensionHeightNether.getMax() - dimensionHeightNether.getMin());
obj.put("logical_height", logicalHeightNether);
return obj.toString(4);
return fixer.fixDimension(obj).toString(4);
}
private String generateDatapackJsonEnd() {
private String generateDatapackJsonEnd(IDataFixer fixer) {
JSONObject obj = new JSONObject(DP_END_DEFAULT);
obj.put("min_y", dimensionHeightEnd.getMin());
obj.put("height", dimensionHeightEnd.getMax() - dimensionHeightEnd.getMin());
obj.put("logical_height", logicalHeightEnd);
return obj.toString(4);
return fixer.fixDimension(obj).toString(4);
}
}

View File

@@ -29,6 +29,7 @@ import com.volmit.iris.util.format.C;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.math.M;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.plugin.Chunks;
import com.volmit.iris.util.plugin.VolmitSender;
import com.volmit.iris.util.scheduling.J;
@@ -65,6 +66,7 @@ import java.util.concurrent.atomic.AtomicReference;
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisEntity extends IrisRegistrant {
private static final Particle ITEM = E.getOrDefault(Particle.class, "ITEM_CRACK", "ITEM");
@Required
@Desc("The type of entity to spawn. To spawn a mythic mob, set this type to unknown and define mythic type.")
private EntityType type = EntityType.UNKNOWN;
@@ -386,7 +388,7 @@ public class IrisEntity extends IrisRegistrant {
if (e.getLocation().getBlock().getType().isSolid() || ((LivingEntity) e).getEyeLocation().getBlock().getType().isSolid()) {
e.teleport(start.add(new Vector(0, 0.1, 0)));
ItemStack itemCrackData = new ItemStack(((LivingEntity) e).getEyeLocation().clone().subtract(0, 2, 0).getBlock().getBlockData().getMaterial());
e.getWorld().spawnParticle(Particle.ITEM_CRACK, ((LivingEntity) e).getEyeLocation(), 6, 0.2, 0.4, 0.2, 0.06f, itemCrackData);
e.getWorld().spawnParticle(ITEM, ((LivingEntity) e).getEyeLocation(), 6, 0.2, 0.4, 0.2, 0.06f, itemCrackData);
if (M.r(0.2)) {
e.getWorld().playSound(e.getLocation(), Sound.BLOCK_CHORUS_FLOWER_GROW, 0.8f, 0.1f);
}

View File

@@ -0,0 +1,29 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.MinNumber;
import com.volmit.iris.engine.object.annotations.RegistryListResource;
import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.engine.object.annotations.Snippet;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Snippet("jigsaw-structure-min-distance")
@Accessors(chain = true)
@NoArgsConstructor
@AllArgsConstructor
@Desc("Represents the min distance between jigsaw structure placements")
@Data
public class IrisJigsawMinDistance {
@Required
@RegistryListResource(IrisJigsawStructure.class)
@Desc("The structure to check against")
private String structure;
@Required
@MinNumber(0)
@Desc("The min distance in blocks to a placed structure\nWARNING: The performance impact scales exponentially!")
private int distance;
}

View File

@@ -101,19 +101,12 @@ public class IrisJigsawPiece extends IrisRegistrant {
}
public IrisJigsawPiece copy() {
IrisJigsawPiece p = new IrisJigsawPiece();
p.setObject(getObject());
p.setLoader(getLoader());
p.setLoadKey(getLoadKey());
p.setLoadFile(getLoadFile());
p.setConnectors(new KList<>());
p.setPlacementOptions(getPlacementOptions());
for (IrisJigsawPieceConnector i : getConnectors()) {
p.getConnectors().add(i.copy());
}
return p;
var gson = getLoader().getGson();
IrisJigsawPiece copy = gson.fromJson(gson.toJson(this), IrisJigsawPiece.class);
copy.setLoader(getLoader());
copy.setLoadKey(getLoadKey());
copy.setLoadFile(getLoadFile());
return copy;
}
public boolean isTerminal() {

View File

@@ -79,6 +79,9 @@ public class IrisJigsawPieceConnector {
@Required
private IrisDirection direction = IrisDirection.UP_POSITIVE_Y;
@Desc("Lock the Y position of this connector")
private boolean lockY = false;
public String toString() {
return direction.getFace().name() + "@(" + position.getX() + "," + position.getY() + "," + position.getZ() + ")";
}

View File

@@ -56,6 +56,10 @@ public class IrisJigsawStructure extends IrisRegistrant {
@Desc("If set to true, iris will look for any pieces with only one connector in valid pools for edge connectors and attach them to 'terminate' the paths/piece connectors. Essentially it caps off ends. For example in a village, Iris would add houses to the ends of roads where possible. For terminators to be selected, they can only have one connector or they wont be chosen.")
private boolean terminate = true;
@RegistryListResource(IrisJigsawPool.class)
@Desc("The pool to use when terminating pieces")
private String terminatePool = null;
@Desc("Override the y range instead of placing on the height map")
private IrisStyledRange overrideYRange = null;

View File

@@ -18,17 +18,24 @@
package com.volmit.iris.engine.object;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.object.annotations.ArrayType;
import com.volmit.iris.engine.object.annotations.Desc;
import com.volmit.iris.engine.object.annotations.MaxNumber;
import com.volmit.iris.engine.object.annotations.MinNumber;
import com.volmit.iris.engine.object.annotations.RegistryListResource;
import com.volmit.iris.engine.object.annotations.Required;
import com.volmit.iris.engine.object.annotations.Snippet;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.math.RNG;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
@Snippet("jigsaw-structure-placement")
@Accessors(chain = true)
@NoArgsConstructor
@@ -36,13 +43,99 @@ import lombok.experimental.Accessors;
@Desc("Represents a jigsaw structure placer")
@Data
@EqualsAndHashCode(callSuper = false)
public class IrisJigsawStructurePlacement {
public class IrisJigsawStructurePlacement implements IRare {
@RegistryListResource(IrisJigsawStructure.class)
@Required
@Desc("The structure to place")
private String structure;
@Required
@Desc("The 1 in X chance rarity")
@Desc("The 1 in X chance rarity applies when generating multiple structures at once")
private int rarity = 100;
@Required
@Desc("The salt to use when generating the structure (to differentiate structures)")
@MinNumber(Long.MIN_VALUE)
@MaxNumber(Long.MAX_VALUE)
private long salt = 0;
@Required
@MinNumber(0)
@Desc("Average distance in chunks between two neighboring generation attempts")
private int spacing = -1;
@Required
@MinNumber(0)
@Desc("Minimum distance in chunks between two neighboring generation attempts\nThe maximum distance of two neighboring generation attempts is 2*spacing - separation")
private int separation = -1;
@Desc("The method used to spread the structure")
private SpreadType spreadType = SpreadType.TRIANGULAR;
@ArrayType(type = IrisJigsawMinDistance.class)
@Desc("List of minimum distances to check for")
private KList<IrisJigsawMinDistance> minDistances = new KList<>();
public KMap<String, Integer> collectMinDistances() {
KMap<String, Integer> map = new KMap<>();
for (IrisJigsawMinDistance d : minDistances) {
map.compute(d.getStructure(), (k, v) -> v != null ? Math.min(toChunks(d.getDistance()), v) : toChunks(d.getDistance()));
}
return map;
}
private int toChunks(int blocks) {
return (int) Math.ceil(blocks / 16d);
}
private void calculateMissing(double divisor, long seed) {
seed = seed + hashCode();
if (salt == 0) {
salt = new RNG(seed).nextLong(Integer.MIN_VALUE, Integer.MAX_VALUE);
}
if (separation == -1 || spacing == -1) {
separation = (int) Math.round(rarity / divisor);
spacing = new RNG(seed).nextInt(separation, separation * 2);
}
}
@ChunkCoordinates
public boolean shouldPlace(double divisor, long seed, int x, int z) {
calculateMissing(divisor, seed);
if (separation > spacing) {
separation = spacing;
Iris.warn("JigsawStructurePlacement: separation must be less than or equal to spacing");
}
int i = Math.floorDiv(x, spacing);
int j = Math.floorDiv(z, spacing);
RNG rng = new RNG(i * 341873128712L + j * 132897987541L + seed + salt);
int k = spacing - separation;
int l = spreadType.apply(rng, k);
int m = spreadType.apply(rng, k);
return i * spacing + l == x && j * spacing + m == z;
}
@Desc("Spread type")
public enum SpreadType {
@Desc("Linear spread")
LINEAR(RNG::i),
@Desc("Triangular spread")
TRIANGULAR((rng, bound) -> (rng.i(bound) + rng.i(bound)) / 2);
private final SpreadMethod method;
SpreadType(SpreadMethod method) {
this.method = method;
}
public int apply(RNG rng, int bound) {
return method.apply(rng, bound);
}
}
private interface SpreadMethod {
int apply(RNG rng, int bound);
}
}

View File

@@ -29,7 +29,6 @@ import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.data.B;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.math.RNG;
import com.volmit.iris.util.noise.CNG;
import lombok.AllArgsConstructor;
@@ -146,7 +145,7 @@ public class IrisLoot {
// TODO Better Third Party Item Acquisition
private ItemStack getItemStack(RNG rng) {
if (!type.startsWith("minecraft:") && type.contains(":")) {
Optional<ItemStack> opt = Iris.service(ExternalDataSVC.class).getItemStack(Identifier.fromString(type));
Optional<ItemStack> opt = Iris.service(ExternalDataSVC.class).getItemStack(Identifier.fromString(type), customNbt);
if (opt.isEmpty()) {
Iris.warn("Unknown Material: " + type);
return new ItemStack(Material.AIR);

View File

@@ -59,6 +59,10 @@ public class IrisLootTable extends IrisRegistrant {
@Desc("The minimum amount of loot that can be picked in this table at a time.")
private int minPicked = 1;
@MinNumber(1)
@Desc("The maximum amount of tries to generate loot")
private int maxTries = 10;
@Desc("The loot in this table")
@ArrayType(min = 1, type = IrisLoot.class)
private KList<IrisLoot> loot = new KList<>();
@@ -67,9 +71,10 @@ public class IrisLootTable extends IrisRegistrant {
KList<ItemStack> lootf = new KList<>();
int m = 0;
int c = 0;
int mx = rng.i(getMinPicked(), getMaxPicked());
while (m < mx) {
while (m < mx && c++ < getMaxTries()) {
int num = rng.i(loot.size());
IrisLoot l = loot.get(num);

View File

@@ -136,6 +136,8 @@ public class IrisObjectPlacement {
@ArrayType(type = String.class)
@Desc("List of objects to this object is forbidden to collied with")
private KList<String> forbiddenCollisions = new KList<>();
@Desc("Ignore any placement restrictions for this object")
private boolean forcePlace = false;
private transient AtomicCache<TableCache> cache = new AtomicCache<>();
public IrisObjectPlacement toPlacement(String... place) {

View File

@@ -101,6 +101,11 @@ public class IrisObjectRotation {
i.setPosition(rotate(i.getPosition()));
i.setDirection(rotate(i.getDirection()));
}
try {
var translate = piece.getPlacementOptions().getTranslate();
var pos = rotate(new IrisPosition(translate.getX(), translate.getY(), translate.getZ()));
translate.setX(pos.getX()).setY(pos.getY()).setZ(pos.getZ());
} catch (NullPointerException ignored) {}
return piece;
}

View File

@@ -58,9 +58,12 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -82,6 +85,8 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
private final AtomicBoolean setup;
private final boolean studio;
private final AtomicInteger a = new AtomicInteger(0);
private final CompletableFuture<Integer> spawnChunks = new CompletableFuture<>();
private final boolean smartVanillaHeight;
private Engine engine;
private Looper hotloader;
private StudioMode lastMode;
@@ -91,7 +96,7 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
private boolean initialized = false;
public BukkitChunkGenerator(IrisWorld world, boolean studio, File dataLocation, String dimensionKey) {
public BukkitChunkGenerator(IrisWorld world, boolean studio, File dataLocation, String dimensionKey, boolean smartVanillaHeight) {
setup = new AtomicBoolean(false);
studioGenerator = null;
dummyBiomeProvider = new DummyBiomeProvider();
@@ -103,6 +108,7 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
this.dataLocation = dataLocation;
this.dimensionKey = dimensionKey;
this.folder = new ReactiveFolder(dataLocation, (_a, _b, _c) -> hotload());
this.smartVanillaHeight = smartVanillaHeight;
Bukkit.getServer().getPluginManager().registerEvents(this, Iris.instance);
}
@@ -144,6 +150,7 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
} else {
INMS.get().inject(event.getWorld().getSeed(), engine, event.getWorld());
Iris.info("Injected Iris Biome Source into " + event.getWorld().getName());
spawnChunks.complete(INMS.get().getSpawnChunkCount(event.getWorld()));
initialized = true;
}
}
@@ -181,6 +188,14 @@ public class BukkitChunkGenerator extends ChunkGenerator implements PlatformChun
throw new RuntimeException("Missing Dimension: " + dimensionKey);
}
}
if (smartVanillaHeight) {
dimension.setSmartVanillaHeight(true);
try (FileWriter writer = new FileWriter(data.getDimensionLoader().fileFor(dimension))) {
writer.write(data.getGson().toJson(dimension));
} catch (IOException e) {
e.printStackTrace();
}
}
lastMode = StudioMode.NORMAL;
engine = new IrisEngine(new EngineTarget(world, dimension, data), studio);

View File

@@ -25,6 +25,7 @@ import com.volmit.iris.engine.framework.Hotloadable;
import com.volmit.iris.util.data.DataProvider;
import org.bukkit.World;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
public interface PlatformChunkGenerator extends Hotloadable, DataProvider {
@@ -46,4 +47,6 @@ public interface PlatformChunkGenerator extends Hotloadable, DataProvider {
boolean isStudio();
void touch(World world);
CompletableFuture<Integer> getSpawnChunks();
}

View File

@@ -25,6 +25,7 @@ import com.volmit.iris.core.service.ExternalDataSVC;
import com.volmit.iris.engine.object.IrisCompat;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.misc.E;
import com.volmit.iris.util.scheduling.ChronoLatch;
import it.unimi.dsi.fastutil.ints.*;
import org.bukkit.Bukkit;
@@ -46,6 +47,7 @@ public class B {
private static final KMap<String, BlockData> custom = new KMap<>();
private static final Material AIR_MATERIAL = Material.AIR;
private static final Material SHORT_GRASS = E.getOrDefault(Material.class, "GRASS", "SHORT_GRASS");
private static final BlockData AIR = AIR_MATERIAL.createBlockData();
private static final IntSet foliageCache = buildFoliageCache();
private static final IntSet deepslateCache = buildDeepslateCache();
@@ -85,7 +87,7 @@ public class B {
WHITE_TULIP,
FERN,
LARGE_FERN,
GRASS,
SHORT_GRASS,
TALL_GRASS
}).forEach((i) -> b.add(i.ordinal()));
@@ -143,7 +145,7 @@ public class B {
private static IntSet buildDecorantCache() {
IntSet b = new IntOpenHashSet();
Arrays.stream(new Material[]{
GRASS,
SHORT_GRASS,
TALL_GRASS,
TALL_SEAGRASS,
FERN,

View File

@@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@Data
public class IrisBlockData implements BlockData{
public class IrisBlockData implements BlockData {
private final @NonNull BlockData base;
private final @NotNull Identifier custom;

View File

@@ -0,0 +1,36 @@
package com.volmit.iris.util.decree.handlers;
import com.volmit.iris.core.nms.datapack.DataVersion;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.decree.DecreeParameterHandler;
import com.volmit.iris.util.decree.exceptions.DecreeParsingException;
public class DataVersionHandler implements DecreeParameterHandler<DataVersion> {
@Override
public KList<DataVersion> getPossibilities() {
return new KList<>(DataVersion.values());
}
@Override
public String toString(DataVersion version) {
return version.getVersion();
}
@Override
public DataVersion parse(String in, boolean force) throws DecreeParsingException {
if (in.equalsIgnoreCase("latest")) {
return DataVersion.getLatest();
}
for (DataVersion v : DataVersion.values()) {
if (v.getVersion().equalsIgnoreCase(in)) {
return v;
}
}
throw new DecreeParsingException("Unable to parse data version \"" + in + "\"");
}
@Override
public boolean supports(Class<?> type) {
return DataVersion.class.equals(type);
}
}

View File

@@ -212,7 +212,7 @@ public class UIElement implements Element {
im.setLore(getLore().copy());
if (isEnchanted()) {
im.addEnchant(Enchantment.DURABILITY, 1, true);
im.addEnchant(Enchantment.FIRE_ASPECT, 1, true);
}
is.setItemMeta(im);

View File

@@ -0,0 +1,35 @@
package com.volmit.iris.util.matter.slices;
import com.volmit.iris.util.data.palette.Palette;
import com.volmit.iris.util.matter.Sliced;
import com.volmit.iris.util.matter.slices.container.JigsawStructuresContainer;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
@Sliced
public class JigsawStructuresMatter extends RawMatter<JigsawStructuresContainer> {
public JigsawStructuresMatter() {
this(1, 1, 1);
}
public JigsawStructuresMatter(int width, int height, int depth) {
super(width, height, depth, JigsawStructuresContainer.class);
}
@Override
public Palette<JigsawStructuresContainer> getGlobalPalette() {
return null;
}
@Override
public void writeNode(JigsawStructuresContainer b, DataOutputStream dos) throws IOException {
b.write(dos);
}
@Override
public JigsawStructuresContainer readNode(DataInputStream din) throws IOException {
return new JigsawStructuresContainer(din);
}
}

View File

@@ -0,0 +1,62 @@
package com.volmit.iris.util.matter.slices.container;
import com.volmit.iris.engine.object.IrisJigsawStructure;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.documentation.ChunkCoordinates;
import com.volmit.iris.util.math.Position2;
import org.jetbrains.annotations.Unmodifiable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class JigsawStructuresContainer {
private final Map<String, List<Position2>> map = new KMap<>();
public JigsawStructuresContainer() {}
public JigsawStructuresContainer(DataInputStream din) throws IOException {
int s0 = din.readInt();
for (int i = 0; i < s0; i++) {
int s1 = din.readInt();
KList<Position2> list = new KList<>(s1);
for (int j = 0; j < s1; j++) {
list.add(new Position2(din.readInt(), din.readInt()));
}
map.put(din.readUTF(), list);
}
}
public void write(DataOutputStream dos) throws IOException {
dos.writeInt(map.size());
for (String key : map.keySet()) {
List<Position2> list = map.get(key);
dos.writeInt(list.size());
for (Position2 pos : list) {
dos.writeInt(pos.getX());
dos.writeInt(pos.getZ());
}
dos.writeUTF(key);
}
}
@Unmodifiable
public Set<String> getStructures() {
return Collections.unmodifiableSet(map.keySet());
}
@Unmodifiable
public List<Position2> getPositions(String structure) {
return Collections.unmodifiableList(map.get(structure));
}
@ChunkCoordinates
public void add(IrisJigsawStructure structure, Position2 pos) {
map.computeIfAbsent(structure.getLoadKey(), k -> new KList<>()).add(pos);
}
}

View File

@@ -0,0 +1,12 @@
package com.volmit.iris.util.misc;
public class E {
public static <T extends Enum<T>> T getOrDefault(Class<T> enumClass, String name, String fallback) {
try {
return Enum.valueOf(enumClass, name);
} catch (Throwable e) {
return Enum.valueOf(enumClass, fallback);
}
}
}

View File

@@ -0,0 +1,135 @@
package com.volmit.iris.util.misc;
import com.volmit.iris.Iris;
import com.volmit.iris.core.tools.IrisToolbelt;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import net.md_5.bungee.api.chat.ClickEvent;
import net.md_5.bungee.api.chat.TextComponent;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.command.CommandSender;
import oshi.SystemInfo;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.file.Files;
import java.util.List;
public class Hastebin {
public static void enviornment(CommandSender sender) {
// Construct the server information
StringBuilder sb = new StringBuilder();
SystemInfo systemInfo = new SystemInfo();
KList<String> disks = new KList<>(getHardware.getDisk());
KList<String> interfaces = new KList<>(getHardware.getInterfaces());
KList<String> displays = new KList<>(getHardware.getEDID());
KList<String> sensors = new KList<>(getHardware.getSensors());
KList<String> gpus = new KList<>(getHardware.getGraphicsCards());
KList<String> powersources = new KList<>(getHardware.getPowerSources());
KList<World> IrisWorlds = new KList<>();
KList<World> BukkitWorlds = new KList<>();
for (World w : Bukkit.getServer().getWorlds()) {
try {
Engine engine = IrisToolbelt.access(w).getEngine();
if (engine != null) {
IrisWorlds.add(w);
}
} catch (Exception e) {
BukkitWorlds.add(w);
}
}
sb.append(" -- == Iris Info == -- \n");
sb.append("Iris Version Version: ").append(Iris.instance.getDescription().getVersion()).append("\n");
sb.append("- Iris Worlds");
for (World w : IrisWorlds.copy()) {
sb.append(" - ").append(w.getName());
}
sb.append("- Bukkit Worlds");
for (World w : BukkitWorlds.copy()) {
sb.append(" - ").append(w.getName());
}
sb.append(" -- == Platform Overview == -- " + "\n");
sb.append("Server Type: ").append(Bukkit.getVersion()).append("\n");
sb.append("Server Uptime: ").append(Form.stampTime(systemInfo.getOperatingSystem().getSystemUptime())).append("\n");
sb.append("Version: ").append(Platform.getVersion()).append(" - Platform: ").append(Platform.getName()).append("\n");
sb.append("Java Vendor: ").append(Platform.ENVIRONMENT.getJavaVendor()).append(" - Java Version: ").append(Platform.ENVIRONMENT.getJavaVersion()).append("\n");
sb.append(" -- == Processor Overview == -- " + "\n");
sb.append("CPU Model: ").append(getHardware.getCPUModel());
sb.append("CPU Architecture: ").append(Platform.CPU.getArchitecture()).append(" Available Processors: ").append(Platform.CPU.getAvailableProcessors()).append("\n");
sb.append("CPU Load: ").append(Form.pc(Platform.CPU.getCPULoad())).append(" CPU Live Process Load: ").append(Form.pc(Platform.CPU.getLiveProcessCPULoad())).append("\n");
sb.append("-=" + " Graphics " + "=- " + "\n");
for (String gpu : gpus) {
sb.append(" ").append(gpu).append("\n");
}
sb.append(" -- == Memory Information == -- " + "\n");
sb.append("Physical Memory - Total: ").append(Form.memSize(Platform.MEMORY.PHYSICAL.getTotalMemory())).append(" Free: ").append(Form.memSize(Platform.MEMORY.PHYSICAL.getFreeMemory())).append(" Used: ").append(Form.memSize(Platform.MEMORY.PHYSICAL.getUsedMemory())).append("\n");
sb.append("Virtual Memory - Total: ").append(Form.memSize(Platform.MEMORY.VIRTUAL.getTotalMemory())).append(" Free: ").append(Form.memSize(Platform.MEMORY.VIRTUAL.getFreeMemory())).append(" Used: ").append(Form.memSize(Platform.MEMORY.VIRTUAL.getUsedMemory())).append("\n");
sb.append(" -- == Storage Information == -- " + "\n");
for (String disk : disks) {
sb.append(" ").append(sb.append(disk)).append("\n");
}
sb.append(" -- == Interface Information == -- "+ "\n" );
for (String inter : interfaces) {
sb.append(" ").append(inter).append("\n");
}
sb.append(" -- == Display Information == -- "+ "\n" );
for (String display : displays) {
sb.append(display).append("\n");
}
sb.append(" -- == Sensor Information == -- " + "\n");
for (String sensor : sensors) {
sb.append(" ").append(sensor).append("\n");
}
sb.append(" -- == Power Information == -- " + "\n");
for (String power : powersources) {
sb.append(" ").append(power).append("\n");
}
try {
String hastebinUrl = uploadToHastebin(sb.toString());
// Create the clickable message
TextComponent message = new TextComponent("[Link]");
TextComponent link = new TextComponent(hastebinUrl);
link.setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, hastebinUrl));
message.addExtra(link);
// Send the clickable message to the player
sender.spigot().sendMessage(message);
} catch (Exception e) {
sender.sendMessage(C.DARK_RED + "Failed to upload server information to Hastebin.");
}
}
private static String uploadToHastebin(String content) throws Exception {
URL url = new URL("https://paste.bytecode.ninja/documents");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "text/plain");
conn.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(content);
wr.flush();
wr.close();
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String response = br.readLine();
br.close();
return "https://paste.bytecode.ninja/" + response.split("\"")[3];
}
}

View File

@@ -0,0 +1,145 @@
package com.volmit.iris.util.misc;
import com.sun.management.OperatingSystemMXBean;
import java.io.File;
import java.lang.management.ManagementFactory;
@SuppressWarnings("restriction")
public class Platform {
public static String getVersion() {
return getSystem().getVersion();
}
public static String getName() {
return getSystem().getName();
}
private static OperatingSystemMXBean getSystem() {
return (OperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean();
}
public static class ENVIRONMENT {
public static boolean canRunBatch() {
return getSystem().getName().toLowerCase().contains("windows");
}
public static String getJavaHome() {
return System.getProperty("java.home");
}
public static String getJavaVendor() {
return System.getProperty("java.vendor");
}
public static String getJavaVersion() {
return System.getProperty("java.version");
}
}
public static class STORAGE {
public static long getAbsoluteTotalSpace() {
long t = 0;
for (File i : getRoots()) {
t += getTotalSpace(i);
}
return t;
}
public static long getTotalSpace() {
return getTotalSpace(new File("."));
}
public static long getTotalSpace(File root) {
return root.getTotalSpace();
}
public static long getAbsoluteFreeSpace() {
long t = 0;
for (File i : getRoots()) {
t += getFreeSpace(i);
}
return t;
}
public static long getFreeSpace() {
return getFreeSpace(new File("."));
}
public static long getFreeSpace(File root) {
return root.getFreeSpace();
}
public static long getUsedSpace() {
return getTotalSpace() - getFreeSpace();
}
public static long getUsedSpace(File root) {
return getTotalSpace(root) - getFreeSpace(root);
}
public static long getAbsoluteUsedSpace() {
return getAbsoluteTotalSpace() - getAbsoluteFreeSpace();
}
public static File[] getRoots() {
return File.listRoots();
}
}
public static class MEMORY {
public static class PHYSICAL {
public static long getTotalMemory() {
return getSystem().getTotalPhysicalMemorySize();
}
public static long getFreeMemory() {
return getSystem().getFreePhysicalMemorySize();
}
public static long getUsedMemory() {
return getTotalMemory() - getFreeMemory();
}
}
public static class VIRTUAL {
public static long getTotalMemory() {
return getSystem().getTotalSwapSpaceSize();
}
public static long getFreeMemory() {
return getSystem().getFreeSwapSpaceSize();
}
public static long getUsedMemory() {
return getTotalMemory() - getFreeMemory();
}
public static long getCommittedVirtualMemory() {
return getSystem().getCommittedVirtualMemorySize();
}
}
}
public static class CPU {
public static int getAvailableProcessors() {
return getSystem().getAvailableProcessors();
}
public static double getCPULoad() {
return getSystem().getSystemCpuLoad();
}
public static double getLiveProcessCPULoad() {
return getSystem().getProcessCpuLoad();
}
public static String getArchitecture() {
return getSystem().getArch();
}
}
}

View File

@@ -1,11 +1,24 @@
package com.volmit.iris.util.misc;
import oshi.SystemInfo;
import oshi.hardware.CentralProcessor;
import oshi.hardware.HWDiskStore;
import oshi.software.os.OperatingSystem;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.format.C;
import com.volmit.iris.util.format.Form;
import org.jetbrains.annotations.Nullable;
import oshi.SystemInfo;
import oshi.hardware.*;
import oshi.software.os.FileSystem;
import oshi.software.os.OSFileStore;
import oshi.software.os.OperatingSystem;
import oshi.util.EdidUtil;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.stream.Collectors;
public class getHardware {
public static String getServerOS() {
@@ -44,14 +57,127 @@ public class getHardware {
}
}
public static String getDiskModel() {
SystemInfo systemInfo = new SystemInfo();
List<HWDiskStore> diskStores = systemInfo.getHardware().getDiskStores();
if (!diskStores.isEmpty()) {
HWDiskStore firstDisk = diskStores.get(0);
return firstDisk.getModel();
} else {
return "Unknown Disk Model";
public static KList<String> getSensors() {
try {
KList<String> temps = new KList<>();
SystemInfo systemInfo = new SystemInfo();
temps.add("CPU Temperature: " + systemInfo.getHardware().getSensors().getCpuTemperature());
temps.add("CPU Voltage: " + systemInfo.getHardware().getSensors().getCpuTemperature());
temps.add("Fan Speeds: " + Arrays.toString(systemInfo.getHardware().getSensors().getFanSpeeds()));
return temps.copy();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
public static KList<String> getGraphicsCards() {
try {
KList<String> gpus = new KList<>();
SystemInfo systemInfo = new SystemInfo();
for (GraphicsCard gpu : systemInfo.getHardware().getGraphicsCards()) {
gpus.add(C.BLUE + "Gpu Model: " + C.GRAY + gpu.getName());
gpus.add("- vRam Size: " + C.GRAY + Form.memSize(gpu.getVRam()));
gpus.add("- Vendor: " + C.GRAY + gpu.getVendor());
}
return gpus.copy();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static KList<String> getDisk() {
try {
KList<String> systemDisks = new KList<>();
SystemInfo systemInfo = new SystemInfo();
List<HWDiskStore> diskStores = systemInfo.getHardware().getDiskStores();
OperatingSystem operatingSystem = systemInfo.getOperatingSystem();
List<OSFileStore> fileStores = operatingSystem.getFileSystem().getFileStores();
for (HWDiskStore disk : diskStores) {
systemDisks.add(C.BLUE + "Disk: " + disk.getName());
systemDisks.add("- Model: " + disk.getModel());
systemDisks.add("Partitions: " + disk.getPartitions());
for (OSFileStore partition : fileStores) {
systemDisks.add(C.BLUE + "- Name: " + partition.getName());
systemDisks.add(" - Description: " + partition.getDescription());
systemDisks.add(" - Total Space: " + Form.memSize(partition.getTotalSpace()));
systemDisks.add(" - Free Space: " + Form.memSize(partition.getFreeSpace()));
systemDisks.add(" - Mount: " + partition.getMount());
systemDisks.add(" - Label: " + partition.getLabel());
}
systemDisks.add(C.DARK_GRAY + "-=" + C.BLUE +" Since Boot " + C.DARK_GRAY + "=- ");
systemDisks.add("- Total Reads: " + Form.memSize(disk.getReadBytes()));
systemDisks.add("- Total Writes: " + Form.memSize(disk.getWriteBytes()));
}
if (systemDisks.isEmpty()) {
systemDisks.add("Failed to get disks.");
}
return systemDisks.copy();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static KList<String> getPowerSources() {
try {
KList<String> systemPowerSources = new KList<>();
SystemInfo systemInfo = new SystemInfo();
List<PowerSource> powerSources = systemInfo.getHardware().getPowerSources();
for (PowerSource powersource : powerSources) {
systemPowerSources.add(C.BLUE + "- Name: " + powersource.getName());
systemPowerSources.add("- RemainingCapacityPercent: " + powersource.getRemainingCapacityPercent());
systemPowerSources.add("- Power Usage Rate: " + powersource.getPowerUsageRate());
systemPowerSources.add("- Power OnLine: " + powersource.isPowerOnLine());
systemPowerSources.add("- Capacity Units: " + powersource.getCapacityUnits());
systemPowerSources.add("- Cycle Count: " + powersource.getCycleCount());
}
if (systemPowerSources.isEmpty()) {
systemPowerSources.add("No PowerSources.");
}
return systemPowerSources.copy();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static KList<String> getEDID() {
try {
KList<String> systemEDID = new KList<>();
SystemInfo systemInfo = new SystemInfo();
HardwareAbstractionLayer hardware = systemInfo.getHardware();
List<Display> displays = hardware.getDisplays();
for (Display display : displays) {
systemEDID.add("Display: " + display.getEdid());
}
if (!systemEDID.isEmpty()) {
systemEDID.add("No displays");
}
return systemEDID.copy();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static KList<String> getInterfaces() {
try {
KList<String> interfaces = new KList<>();
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface ni : Collections.list(networkInterfaces)) {
interfaces.add(C.BLUE + "Display Name: %s", ni.getDisplayName());
Enumeration<InetAddress> inetAddresses = ni.getInetAddresses();
for (InetAddress ia : Collections.list(inetAddresses)) {
interfaces.add("IP: %s", ia.getHostAddress());
}
return interfaces.copy();
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@@ -27,10 +27,12 @@ import com.volmit.iris.util.nbt.io.NamedTag;
import com.volmit.iris.util.nbt.mca.palette.MCABiomeContainer;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import com.volmit.iris.util.nbt.tag.ListTag;
import org.bukkit.World;
import java.io.*;
import static com.volmit.iris.util.nbt.mca.LoadFlags.*;
import static org.bukkit.Bukkit.getServer;
public class Chunk {
public static final int DEFAULT_DATA_VERSION = 2730;
@@ -39,6 +41,7 @@ public class Chunk {
private int lastMCAUpdate;
private CompoundTag data;
private int dataVersion;
private int nativeIrisVersion;
private long lastUpdate;
private long inhabitedTime;
private MCABiomeContainer biomes;
@@ -71,15 +74,21 @@ public class Chunk {
}
public static Chunk newChunk() {
World mainWorld = getServer().getWorlds().get(0);
Chunk c = new Chunk(0);
c.dataVersion = DEFAULT_DATA_VERSION;
c.data = new CompoundTag();
c.biomes = INMS.get().newBiomeContainer(0, 256);
c.biomes = INMS.get().newBiomeContainer(mainWorld.getMinHeight(), mainWorld.getMaxHeight());
c.data.put("Level", defaultLevel());
c.status = "full";
return c;
}
public static void injectIrisData(Chunk c) {
World mainWorld = getServer().getWorlds().get(0);
c.data.put("Iris", nativeIrisVersion());
}
private static CompoundTag defaultLevel() {
CompoundTag level = new CompoundTag();
level.putString("Status", "full");
@@ -87,19 +96,25 @@ public class Chunk {
return level;
}
private static CompoundTag nativeIrisVersion() {
CompoundTag level = new CompoundTag();
level.putString("Generator", "Iris " + Iris.instance.getDescription().getVersion());
return level;
}
private void initReferences(long loadFlags) {
if (data == null) {
throw new NullPointerException("data cannot be null");
}
CompoundTag level;
if ((level = data.getCompoundTag("Level")) == null) {
throw new IllegalArgumentException("data does not contain \"Level\" tag");
}
CompoundTag level = data;
World mainWorld = getServer().getWorlds().get(0);
dataVersion = data.getInt("DataVersion");
inhabitedTime = level.getLong("InhabitedTime");
lastUpdate = level.getLong("LastUpdate");
if ((loadFlags & BIOMES) != 0) {
biomes = INMS.get().newBiomeContainer(0, 256, level.getIntArray("Biomes"));
biomes = INMS.get().newBiomeContainer(mainWorld.getMinHeight(), mainWorld.getMaxHeight(), level.getIntArray("Biomes"));
}
if ((loadFlags & HEIGHTMAPS) != 0) {
heightMaps = level.getCompoundTag("Heightmaps");

View File

@@ -12,7 +12,7 @@ libraries:
- commons-io:commons-io:2.13.0
- io.timeandspace:smoothie-map:2.0.2
- com.google.guava:guava:31.0.1-jre
- com.google.code.gson:gson:2.8.9
- com.google.code.gson:gson:2.10.1
- org.zeroturnaround:zt-zip:1.14
- it.unimi.dsi:fastutil:8.5.6
- org.ow2.asm:asm:9.2

View File

@@ -19,4 +19,8 @@ org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.jvmargs=-Xmx3072m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
org.gradle.caching=true
org.gradle.configureondemand=false
org.gradle.configureondemand=false
nmsTools.useBuildTools=false
nmsTools.repo-url=https://repo.codemc.org/repository/nms/
nmsTools.specialSourceVersion=1.11.4

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -1,5 +1,6 @@
package com.volmit.iris.core.nms.v1_19_R1;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -12,6 +13,8 @@ import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import net.minecraft.world.level.LevelReader;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -517,6 +520,30 @@ public class NMSBinding implements INMSBinding {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
@Override
public Color getBiomeColor(Location location, BiomeColor type) {
LevelReader reader = ((CraftWorld) location.getWorld()).getHandle();
var holder = reader.getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
var biome = holder.value();
if (biome == null) throw new IllegalArgumentException("Invalid biome: " + holder.unwrapKey().orElse(null));
int rgba = switch (type) {
case FOG -> biome.getFogColor();
case WATER -> biome.getWaterColor();
case WATER_FOG -> biome.getWaterFogColor();
case SKY -> biome.getSkyColor();
case FOLIAGE -> biome.getFoliageColor();
case GRASS -> biome.getGrassColor(location.getBlockX(), location.getBlockZ());
};
if (rgba == 0) {
if (BiomeColor.FOLIAGE == type && biome.getSpecialEffects().getFoliageColorOverride().isEmpty())
return null;
if (BiomeColor.GRASS == type && biome.getSpecialEffects().getGrassColorOverride().isEmpty())
return null;
}
return new Color(rgba, true);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -1,5 +1,6 @@
package com.volmit.iris.core.nms.v1_19_R2;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -12,6 +13,8 @@ import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import net.minecraft.world.level.LevelReader;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -519,6 +522,30 @@ public class NMSBinding implements INMSBinding {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
@Override
public Color getBiomeColor(Location location, BiomeColor type) {
LevelReader reader = ((CraftWorld) location.getWorld()).getHandle();
var holder = reader.getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
var biome = holder.value();
if (biome == null) throw new IllegalArgumentException("Invalid biome: " + holder.unwrapKey().orElse(null));
int rgba = switch (type) {
case FOG -> biome.getFogColor();
case WATER -> biome.getWaterColor();
case WATER_FOG -> biome.getWaterFogColor();
case SKY -> biome.getSkyColor();
case FOLIAGE -> biome.getFoliageColor();
case GRASS -> biome.getGrassColor(location.getBlockX(), location.getBlockZ());
};
if (rgba == 0) {
if (BiomeColor.FOLIAGE == type && biome.getSpecialEffects().getFoliageColorOverride().isEmpty())
return null;
if (BiomeColor.GRASS == type && biome.getSpecialEffects().getGrassColorOverride().isEmpty())
return null;
}
return new Color(rgba, true);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -1,5 +1,6 @@
package com.volmit.iris.core.nms.v1_19_R3;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -12,6 +13,8 @@ import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import net.minecraft.world.level.LevelReader;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -523,6 +526,30 @@ public class NMSBinding implements INMSBinding {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
@Override
public Color getBiomeColor(Location location, BiomeColor type) {
LevelReader reader = ((CraftWorld) location.getWorld()).getHandle();
var holder = reader.getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
var biome = holder.value();
if (biome == null) throw new IllegalArgumentException("Invalid biome: " + holder.unwrapKey().orElse(null));
int rgba = switch (type) {
case FOG -> biome.getFogColor();
case WATER -> biome.getWaterColor();
case WATER_FOG -> biome.getWaterFogColor();
case SKY -> biome.getSkyColor();
case FOLIAGE -> biome.getFoliageColor();
case GRASS -> biome.getGrassColor(location.getBlockX(), location.getBlockZ());
};
if (rgba == 0) {
if (BiomeColor.FOLIAGE == type && biome.getSpecialEffects().getFoliageColorOverride().isEmpty())
return null;
if (BiomeColor.GRASS == type && biome.getSpecialEffects().getGrassColorOverride().isEmpty())
return null;
}
return new Color(rgba, true);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -3,6 +3,7 @@ package com.volmit.iris.core.nms.v1_20_R1;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
@@ -27,6 +28,7 @@ import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityDimensions;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
@@ -55,6 +57,7 @@ import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import sun.misc.Unsafe;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -522,6 +525,30 @@ public class NMSBinding implements INMSBinding {
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
}
@Override
public Color getBiomeColor(Location location, BiomeColor type) {
LevelReader reader = ((CraftWorld) location.getWorld()).getHandle();
var holder = reader.getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
var biome = holder.value();
if (biome == null) throw new IllegalArgumentException("Invalid biome: " + holder.unwrapKey().orElse(null));
int rgba = switch (type) {
case FOG -> biome.getFogColor();
case WATER -> biome.getWaterColor();
case WATER_FOG -> biome.getWaterFogColor();
case SKY -> biome.getSkyColor();
case FOLIAGE -> biome.getFoliageColor();
case GRASS -> biome.getGrassColor(location.getBlockX(), location.getBlockZ());
};
if (rgba == 0) {
if (BiomeColor.FOLIAGE == type && biome.getSpecialEffects().getFoliageColorOverride().isEmpty())
return null;
if (BiomeColor.GRASS == type && biome.getSpecialEffects().getGrassColorOverride().isEmpty())
return null;
}
return new Color(rgba, true);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -1,5 +1,6 @@
package com.volmit.iris.core.nms.v1_20_R2;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -12,6 +13,8 @@ import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import net.minecraft.world.level.LevelReader;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -520,6 +523,30 @@ public class NMSBinding implements INMSBinding {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
@Override
public Color getBiomeColor(Location location, BiomeColor type) {
LevelReader reader = ((CraftWorld) location.getWorld()).getHandle();
var holder = reader.getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
var biome = holder.value();
if (biome == null) throw new IllegalArgumentException("Invalid biome: " + holder.unwrapKey().orElse(null));
int rgba = switch (type) {
case FOG -> biome.getFogColor();
case WATER -> biome.getWaterColor();
case WATER_FOG -> biome.getWaterFogColor();
case SKY -> biome.getSkyColor();
case FOLIAGE -> biome.getFoliageColor();
case GRASS -> biome.getGrassColor(location.getBlockX(), location.getBlockZ());
};
if (rgba == 0) {
if (BiomeColor.FOLIAGE == type && biome.getSpecialEffects().getFoliageColorOverride().isEmpty())
return null;
if (BiomeColor.GRASS == type && biome.getSpecialEffects().getGrassColorOverride().isEmpty())
return null;
}
return new Color(rgba, true);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -1,5 +1,6 @@
package com.volmit.iris.core.nms.v1_20_R3;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
@@ -12,6 +13,8 @@ import java.util.List;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import net.minecraft.world.level.LevelReader;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
@@ -521,6 +524,30 @@ public class NMSBinding implements INMSBinding {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
@Override
public Color getBiomeColor(Location location, BiomeColor type) {
LevelReader reader = ((CraftWorld) location.getWorld()).getHandle();
var holder = reader.getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
var biome = holder.value();
if (biome == null) throw new IllegalArgumentException("Invalid biome: " + holder.unwrapKey().orElse(null));
int rgba = switch (type) {
case FOG -> biome.getFogColor();
case WATER -> biome.getWaterColor();
case WATER_FOG -> biome.getWaterFogColor();
case SKY -> biome.getSkyColor();
case FOLIAGE -> biome.getFoliageColor();
case GRASS -> biome.getGrassColor(location.getBlockX(), location.getBlockZ());
};
if (rgba == 0) {
if (BiomeColor.FOLIAGE == type && biome.getSpecialEffects().getFoliageColorOverride().isEmpty())
return null;
if (BiomeColor.GRASS == type && biome.getSpecialEffects().getGrassColorOverride().isEmpty())
return null;
}
return new Color(rgba, true);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {

View File

@@ -0,0 +1,168 @@
package com.volmit.iris.core.nms.v1_20_R4;
import com.mojang.serialization.MapCodec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.math.RNG;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Climate;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_20_R4.CraftServer;
import org.bukkit.craftbukkit.v1_20_R4.CraftWorld;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class CustomBiomeSource extends BiomeSource {
private final long seed;
private final Engine engine;
private final Registry<Biome> biomeCustomRegistry;
private final Registry<Biome> biomeRegistry;
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
private final RNG rng;
private final KMap<String, Holder<Biome>> customBiomes;
public CustomBiomeSource(long seed, Engine engine, World world) {
this.engine = engine;
this.seed = seed;
this.biomeCustomRegistry = registry().registry(Registries.BIOME).orElse(null);
this.biomeRegistry = ((RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer())).registry(Registries.BIOME).orElse(null);
this.rng = new RNG(engine.getSeedManager().getBiome());
this.customBiomes = fillCustomBiomes(biomeCustomRegistry, engine);
}
private static List<Holder<Biome>> getAllBiomes(Registry<Biome> customRegistry, Registry<Biome> registry, Engine engine) {
List<Holder<Biome>> b = new ArrayList<>();
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
b.add(customRegistry.getHolder(customRegistry.getResourceKey(customRegistry
.get(new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId()))).get()).get());
}
} else {
b.add(NMSBinding.biomeToBiomeBase(registry, i.getVanillaDerivative()));
}
}
return b;
}
private static Object getFor(Class<?> type, Object source) {
Object o = fieldFor(type, source);
if (o != null) {
return o;
}
return invokeFor(type, source);
}
private static Object fieldFor(Class<?> returns, Object in) {
return fieldForClass(returns, in.getClass(), in);
}
private static Object invokeFor(Class<?> returns, Object in) {
for (Method i : in.getClass().getMethods()) {
if (i.getReturnType().equals(returns)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()");
return i.invoke(in);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
return null;
}
@SuppressWarnings("unchecked")
private static <T> T fieldForClass(Class<T> returnType, Class<?> sourceType, Object in) {
for (Field i : sourceType.getDeclaredFields()) {
if (i.getType().equals(returnType)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName());
return (T) i.get(in);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
protected Stream<Holder<Biome>> collectPossibleBiomes() {
return getAllBiomes(
((RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()))
.registry(Registries.BIOME).orElse(null),
((CraftWorld) engine.getWorld().realWorld()).getHandle().registryAccess().registry(Registries.BIOME).orElse(null),
engine).stream();
}
private KMap<String, Holder<Biome>> fillCustomBiomes(Registry<Biome> customRegistry, Engine engine) {
KMap<String, Holder<Biome>> m = new KMap<>();
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
ResourceLocation resourceLocation = new ResourceLocation(engine.getDimension().getLoadKey() + ":" + j.getId());
Biome biome = customRegistry.get(resourceLocation);
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
if (optionalBiomeKey.isEmpty()) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
ResourceKey<Biome> biomeKey = optionalBiomeKey.get();
Optional<Holder.Reference<Biome>> optionalReferenceHolder = customRegistry.getHolder(biomeKey);
if (optionalReferenceHolder.isEmpty()) {
Iris.error("Cannot find reference to biome " + biomeKey + " for engine " + engine.getName());
continue;
}
m.put(j.getId(), optionalReferenceHolder.get());
}
}
}
return m;
}
private RegistryAccess registry() {
return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
}
@Override
protected MapCodec<? extends BiomeSource> codec() {
throw new UnsupportedOperationException("Not supported");
}
@Override
public Holder<Biome> getNoiseBiome(int x, int y, int z, Climate.Sampler sampler) {
int m = (y - engine.getMinHeight()) << 2;
IrisBiome ib = engine.getComplex().getTrueBiomeStream().get(x << 2, z << 2);
if (ib.isCustom()) {
return customBiomes.get(ib.getCustomBiome(rng, x << 2, m, z << 2).getId());
} else {
org.bukkit.block.Biome v = ib.getSkyBiome(rng, x << 2, m, z << 2);
return NMSBinding.biomeToBiomeBase(biomeRegistry, v);
}
}
}

View File

@@ -0,0 +1,588 @@
package com.volmit.iris.core.nms.v1_20_R4;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.datapack.DataVersion;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_20_R4.CraftChunk;
import org.bukkit.craftbukkit.v1_20_R4.CraftServer;
import org.bukkit.craftbukkit.v1_20_R4.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R4.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_20_R4.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_20_R4.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_20_R4.util.CraftNamespacedKey;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import sun.misc.Unsafe;
public class NMSBinding implements INMSBinding {
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
private final BlockData AIR = Material.AIR.createBlockData();
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
private Field biomeStorageCache = null;
private static Object getFor(Class<?> type, Object source) {
Object o = fieldFor(type, source);
if (o != null) {
return o;
}
return invokeFor(type, source);
}
private static Object invokeFor(Class<?> returns, Object in) {
for (Method i : in.getClass().getMethods()) {
if (i.getReturnType().equals(returns)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()");
return i.invoke(in);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
return null;
}
private static Object fieldFor(Class<?> returns, Object in) {
return fieldForClass(returns, in.getClass(), in);
}
@SuppressWarnings("unchecked")
private static <T> T fieldForClass(Class<T> returnType, Class<?> sourceType, Object in) {
for (Field i : sourceType.getDeclaredFields()) {
if (i.getType().equals(returnType)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName());
return (T) i.get(in);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return null;
}
private static Class<?> getClassType(Class<?> type, int ordinal) {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata(registry());
return convert(tag);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
}
return null;
}
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
}
@Override
public CompoundTag serializeEntity(Entity location) {
return null;// TODO:
}
@Override
public Entity deserializeEntity(CompoundTag s, Location newPosition) {
return null;// TODO:
}
@Override
public boolean supportsCustomHeight() {
return true;
}
private RegistryAccess registry() {
return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
}
private Registry<net.minecraft.world.level.biome.Biome> getCustomBiomeRegistry() {
return registry().registry(Registries.BIOME).orElse(null);
}
private Registry<Block> getBlockRegistry() {
return registry().registry(Registries.BLOCK).orElse(null);
}
@Override
public Object getBiomeBaseFromId(int id) {
return getCustomBiomeRegistry().getHolder(id);
}
@Override
public int getMinHeight(World world) {
return world.getMinHeight();
}
@Override
public boolean supportsCustomBiomes() {
return true;
}
@Override
public int getTrueBiomeBaseId(Object biomeBase) {
return getCustomBiomeRegistry().getId(((Holder<net.minecraft.world.level.biome.Biome>) biomeBase).value());
}
@Override
public Object getTrueBiomeBase(Location location) {
return ((CraftWorld) location.getWorld()).getHandle().getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
}
@Override
public String getTrueBiomeBaseKey(Location location) {
return getKeyForBiomeBase(getTrueBiomeBase(location));
}
@Override
public Object getCustomBiomeBaseFor(String mckey) {
return getCustomBiomeRegistry().get(new ResourceLocation(mckey));
}
@Override
public Object getCustomBiomeBaseHolderFor(String mckey) {
return getCustomBiomeRegistry().getHolder(getTrueBiomeBaseId(getCustomBiomeRegistry().get(new ResourceLocation(mckey)))).get();
}
public int getBiomeBaseIdForKey(String key) {
return getCustomBiomeRegistry().getId(getCustomBiomeRegistry().get(new ResourceLocation(key)));
}
@Override
public String getKeyForBiomeBase(Object biomeBase) {
return getCustomBiomeRegistry().getKey((net.minecraft.world.level.biome.Biome) biomeBase).getPath(); // something, not something:something
}
@Override
public Object getBiomeBase(World world, Biome biome) {
return biomeToBiomeBase(((CraftWorld) world).getHandle()
.registryAccess().registry(Registries.BIOME).orElse(null), biome);
}
@Override
public Object getBiomeBase(Object registry, Biome biome) {
Object v = baseBiomeCache.get(biome);
if (v != null) {
return v;
}
//noinspection unchecked
v = biomeToBiomeBase((Registry<net.minecraft.world.level.biome.Biome>) registry, biome);
if (v == null) {
// Ok so there is this new biome name called "CUSTOM" in Paper's new releases.
// But, this does NOT exist within CraftBukkit which makes it return an error.
// So, we will just return the ID that the plains biome returns instead.
//noinspection unchecked
return biomeToBiomeBase((Registry<net.minecraft.world.level.biome.Biome>) registry, Biome.PLAINS);
}
baseBiomeCache.put(biome, v);
return v;
}
@Override
public KList<Biome> getBiomes() {
return new KList<>(Biome.values()).qadd(Biome.CHERRY_GROVE).qdel(Biome.CUSTOM);
}
@Override
public boolean isBukkit() {
return true;
}
@Override
public int getBiomeId(Biome biome) {
for (World i : Bukkit.getWorlds()) {
if (i.getEnvironment().equals(World.Environment.NORMAL)) {
Registry<net.minecraft.world.level.biome.Biome> registry = ((CraftWorld) i).getHandle().registryAccess().registry(Registries.BIOME).orElse(null);
return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome));
}
}
return biome.ordinal();
}
private MCAIdMap<net.minecraft.world.level.biome.Biome> getBiomeMapping() {
return biomeMapCache.aquire(() -> new MCAIdMap<>() {
@NotNull
@Override
public Iterator<net.minecraft.world.level.biome.Biome> iterator() {
return getCustomBiomeRegistry().iterator();
}
@Override
public int getId(net.minecraft.world.level.biome.Biome paramT) {
return getCustomBiomeRegistry().getId(paramT);
}
@Override
public net.minecraft.world.level.biome.Biome byId(int paramInt) {
return (net.minecraft.world.level.biome.Biome) getBiomeBaseFromId(paramInt);
}
});
}
@NotNull
private MCABiomeContainer getBiomeContainerInterface(MCAIdMap<net.minecraft.world.level.biome.Biome> biomeMapping, MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base) {
return new MCABiomeContainer() {
@Override
public int[] getData() {
return base.writeBiomes();
}
@Override
public void setBiome(int x, int y, int z, int id) {
base.setBiome(x, y, z, biomeMapping.byId(id));
}
@Override
public int getBiome(int x, int y, int z) {
return biomeMapping.getId(base.getBiome(x, y, z));
}
};
}
@Override
public MCABiomeContainer newBiomeContainer(int min, int max) {
MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base = new MCAChunkBiomeContainer<>(getBiomeMapping(), min, max);
return getBiomeContainerInterface(getBiomeMapping(), base);
}
@Override
public MCABiomeContainer newBiomeContainer(int min, int max, int[] data) {
MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base = new MCAChunkBiomeContainer<>(getBiomeMapping(), min, max, data);
return getBiomeContainerInterface(getBiomeMapping(), base);
}
@Override
public int countCustomBiomes() {
AtomicInteger a = new AtomicInteger(0);
getCustomBiomeRegistry().keySet().forEach((i) -> {
if (i.getNamespace().equals("minecraft")) {
return;
}
a.incrementAndGet();
Iris.debug("Custom Biome: " + i);
});
return a.get();
}
public boolean supportsDataPacks() {
return true;
}
public void setBiomes(int cx, int cz, World world, Hunk<Object> biomes) {
LevelChunk c = ((CraftWorld) world).getHandle().getChunk(cx, cz);
biomes.iterateSync((x, y, z, b) -> c.setBiome(x, y, z, (Holder<net.minecraft.world.level.biome.Biome>) b));
c.setUnsaved(true);
}
@Override
public void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk) {
try {
ChunkAccess s = (ChunkAccess) getFieldForBiomeStorage(chunk).get(chunk);
Holder<net.minecraft.world.level.biome.Biome> biome = (Holder<net.minecraft.world.level.biome.Biome>) somethingVeryDirty;
s.setBiome(x, y, z, biome);
} catch (IllegalAccessException e) {
Iris.reportError(e);
e.printStackTrace();
}
}
private Field getFieldForBiomeStorage(Object storage) {
Field f = biomeStorageCache;
if (f != null) {
return f;
}
try {
f = storage.getClass().getDeclaredField("biome");
f.setAccessible(true);
return f;
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
Iris.error(storage.getClass().getCanonicalName());
}
biomeStorageCache = f;
return null;
}
@Override
public MCAPaletteAccess createPalette() {
MCAIdMapper<BlockState> registry = registryCache.aquireNasty(() -> {
Field cf = net.minecraft.core.IdMapper.class.getDeclaredField("tToId");
Field df = net.minecraft.core.IdMapper.class.getDeclaredField("idToT");
Field bf = net.minecraft.core.IdMapper.class.getDeclaredField("nextId");
cf.setAccessible(true);
df.setAccessible(true);
bf.setAccessible(true);
net.minecraft.core.IdMapper<BlockState> blockData = Block.BLOCK_STATE_REGISTRY;
int b = bf.getInt(blockData);
Object2IntMap<BlockState> c = (Object2IntMap<BlockState>) cf.get(blockData);
List<BlockState> d = (List<BlockState>) df.get(blockData);
return new MCAIdMapper<BlockState>(c, d, b);
});
MCAPalette<BlockState> global = globalCache.aquireNasty(() -> new MCAGlobalPalette<>(registry, ((CraftBlockData) AIR).getState()));
MCAPalettedContainer<BlockState> container = new MCAPalettedContainer<>(global, registry,
i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState(),
i -> NBTWorld.getCompound(CraftBlockData.fromData(i)),
((CraftBlockData) AIR).getState());
return new MCAWrappedPalettedContainer<>(container,
i -> NBTWorld.getCompound(CraftBlockData.fromData(i)),
i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState());
}
@Override
public void injectBiomesFromMantle(Chunk e, Mantle mantle) {
ChunkAccess chunk = ((CraftChunk) e).getHandle(ChunkStatus.FULL);
AtomicInteger c = new AtomicInteger();
AtomicInteger r = new AtomicInteger();
mantle.iterateChunk(e.getX(), e.getZ(), MatterBiomeInject.class, (x, y, z, b) -> {
if (b != null) {
if (b.isCustom()) {
chunk.setBiome(x, y, z, getCustomBiomeRegistry().getHolder(b.getBiomeId()).get());
c.getAndIncrement();
} else {
chunk.setBiome(x, y, z, (Holder<net.minecraft.world.level.biome.Biome>) getBiomeBase(e.getWorld(), b.getBiome()));
r.getAndIncrement();
}
}
});
}
public ItemStack applyCustomNbt(ItemStack itemStack, KMap<String, Object> customNbt) throws IllegalArgumentException {
if (customNbt != null && !customNbt.isEmpty()) {
net.minecraft.world.item.ItemStack s = CraftItemStack.asNMSCopy(itemStack);
try {
net.minecraft.nbt.CompoundTag tag = TagParser.parseTag((new JSONObject(customNbt)).toString());
tag.merge(s.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).getUnsafe());
s.set(DataComponents.CUSTOM_DATA, CustomData.of(tag));
} catch (CommandSyntaxException var5) {
throw new IllegalArgumentException(var5);
}
return CraftItemStack.asBukkitCopy(s);
} else {
return itemStack;
}
}
public void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos) {
CraftDolphin cd = (CraftDolphin)dolphin;
cd.getHandle().setTreasurePos(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
cd.getHandle().setGotFish(true);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
ServerLevel serverLevel = ((CraftWorld)world).getHandle();
Class<?> clazz = serverLevel.getChunkSource().chunkMap.generator.getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(serverLevel.getChunkSource().chunkMap.generator), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(serverLevel.getChunkSource().chunkMap.generator, customBiomeSource);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
Field[] fields = EntityType.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().equals(EntityType.class)) {
try {
EntityType entityType = (EntityType) field.get(null);
if (entityType.getDescriptionId().equals("entity.minecraft." + entity.name().toLowerCase())) {
Vector<Float> v1 = new Vector<>();
v1.add(entityType.getHeight());
entityType.getDimensions();
Vector3d box = new Vector3d( entityType.getWidth(), entityType.getHeight(), entityType.getWidth());
//System.out.println("Entity Type: " + entityType.getDescriptionId() + ", " + "Height: " + height + ", Width: " + width);
return box;
}
} catch (IllegalAccessException e) {
Iris.error("Unable to get entity dimensions!");
e.printStackTrace();
}
}
}
return null;
}
@Override
public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
@Override
public Color getBiomeColor(Location location, BiomeColor type) {
LevelReader reader = ((CraftWorld) location.getWorld()).getHandle();
var holder = reader.getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
var biome = holder.value();
if (biome == null) throw new IllegalArgumentException("Invalid biome: " + holder.unwrapKey().orElse(null));
int rgba = switch (type) {
case FOG -> biome.getFogColor();
case WATER -> biome.getWaterColor();
case WATER_FOG -> biome.getWaterFogColor();
case SKY -> biome.getSkyColor();
case FOLIAGE -> biome.getFoliageColor();
case GRASS -> biome.getGrassColor(location.getBlockX(), location.getBlockZ());
};
if (rgba == 0) {
if (BiomeColor.FOLIAGE == type && biome.getSpecialEffects().getFoliageColorOverride().isEmpty())
return null;
if (BiomeColor.GRASS == type && biome.getSpecialEffects().getGrassColorOverride().isEmpty())
return null;
}
return new Color(rgba, true);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(fieldType))
return f;
}
throw new NoSuchFieldException(fieldType.getName());
} catch (NoSuchFieldException var4) {
Class<?> superClass = clazz.getSuperclass();
if (superClass == null) {
throw var4;
} else {
return getField(superClass, fieldType);
}
}
}
public static Holder<net.minecraft.world.level.biome.Biome> biomeToBiomeBase(Registry<net.minecraft.world.level.biome.Biome> registry, Biome biome) {
return registry.getHolderOrThrow(ResourceKey.create(Registries.BIOME, CraftNamespacedKey.toMinecraft(biome.getKey())));
}
@Override
public DataVersion getDataVersion() {
return DataVersion.V1205;
}
@Override
public int getSpawnChunkCount(World world) {
var radius = Optional.ofNullable(world.getGameRuleValue(GameRule.SPAWN_CHUNK_RADIUS))
.orElseGet(() -> world.getGameRuleDefault(GameRule.SPAWN_CHUNK_RADIUS));
if (radius == null) throw new IllegalStateException("GameRule.SPAWN_CHUNK_RADIUS is null!");
return (int) Math.pow(2 * radius + 1, 2);
}
}

View File

@@ -0,0 +1,168 @@
package com.volmit.iris.core.nms.v1_21_R1;
import com.mojang.serialization.MapCodec;
import com.volmit.iris.Iris;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.object.IrisBiome;
import com.volmit.iris.engine.object.IrisBiomeCustom;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.math.RNG;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.biome.Climate;
import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.craftbukkit.v1_21_R1.CraftServer;
import org.bukkit.craftbukkit.v1_21_R1.CraftWorld;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
public class CustomBiomeSource extends BiomeSource {
private final long seed;
private final Engine engine;
private final Registry<Biome> biomeCustomRegistry;
private final Registry<Biome> biomeRegistry;
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
private final RNG rng;
private final KMap<String, Holder<Biome>> customBiomes;
public CustomBiomeSource(long seed, Engine engine, World world) {
this.engine = engine;
this.seed = seed;
this.biomeCustomRegistry = registry().registry(Registries.BIOME).orElse(null);
this.biomeRegistry = ((RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer())).registry(Registries.BIOME).orElse(null);
this.rng = new RNG(engine.getSeedManager().getBiome());
this.customBiomes = fillCustomBiomes(biomeCustomRegistry, engine);
}
private static List<Holder<Biome>> getAllBiomes(Registry<Biome> customRegistry, Registry<Biome> registry, Engine engine) {
List<Holder<Biome>> b = new ArrayList<>();
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
b.add(customRegistry.getHolder(customRegistry.getResourceKey(customRegistry
.get(ResourceLocation.fromNamespaceAndPath(engine.getDimension().getLoadKey(), j.getId()))).get()).get());
}
} else {
b.add(NMSBinding.biomeToBiomeBase(registry, i.getVanillaDerivative()));
}
}
return b;
}
private static Object getFor(Class<?> type, Object source) {
Object o = fieldFor(type, source);
if (o != null) {
return o;
}
return invokeFor(type, source);
}
private static Object fieldFor(Class<?> returns, Object in) {
return fieldForClass(returns, in.getClass(), in);
}
private static Object invokeFor(Class<?> returns, Object in) {
for (Method i : in.getClass().getMethods()) {
if (i.getReturnType().equals(returns)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()");
return i.invoke(in);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
return null;
}
@SuppressWarnings("unchecked")
private static <T> T fieldForClass(Class<T> returnType, Class<?> sourceType, Object in) {
for (Field i : sourceType.getDeclaredFields()) {
if (i.getType().equals(returnType)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName());
return (T) i.get(in);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return null;
}
@Override
protected Stream<Holder<Biome>> collectPossibleBiomes() {
return getAllBiomes(
((RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()))
.registry(Registries.BIOME).orElse(null),
((CraftWorld) engine.getWorld().realWorld()).getHandle().registryAccess().registry(Registries.BIOME).orElse(null),
engine).stream();
}
private KMap<String, Holder<Biome>> fillCustomBiomes(Registry<Biome> customRegistry, Engine engine) {
KMap<String, Holder<Biome>> m = new KMap<>();
for (IrisBiome i : engine.getAllBiomes()) {
if (i.isCustom()) {
for (IrisBiomeCustom j : i.getCustomDerivitives()) {
ResourceLocation resourceLocation = ResourceLocation.fromNamespaceAndPath(engine.getDimension().getLoadKey(), j.getId());
Biome biome = customRegistry.get(resourceLocation);
Optional<ResourceKey<Biome>> optionalBiomeKey = customRegistry.getResourceKey(biome);
if (optionalBiomeKey.isEmpty()) {
Iris.error("Cannot find biome for IrisBiomeCustom " + j.getId() + " from engine " + engine.getName());
continue;
}
ResourceKey<Biome> biomeKey = optionalBiomeKey.get();
Optional<Holder.Reference<Biome>> optionalReferenceHolder = customRegistry.getHolder(biomeKey);
if (optionalReferenceHolder.isEmpty()) {
Iris.error("Cannot find reference to biome " + biomeKey + " for engine " + engine.getName());
continue;
}
m.put(j.getId(), optionalReferenceHolder.get());
}
}
}
return m;
}
private RegistryAccess registry() {
return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
}
@Override
protected MapCodec<? extends BiomeSource> codec() {
throw new UnsupportedOperationException("Not supported");
}
@Override
public Holder<Biome> getNoiseBiome(int x, int y, int z, Climate.Sampler sampler) {
int m = (y - engine.getMinHeight()) << 2;
IrisBiome ib = engine.getComplex().getTrueBiomeStream().get(x << 2, z << 2);
if (ib.isCustom()) {
return customBiomes.get(ib.getCustomBiome(rng, x << 2, m, z << 2).getId());
} else {
org.bukkit.block.Biome v = ib.getSkyBiome(rng, x << 2, m, z << 2);
return NMSBinding.biomeToBiomeBase(biomeRegistry, v);
}
}
}

View File

@@ -0,0 +1,593 @@
package com.volmit.iris.core.nms.v1_21_R1;
import java.awt.Color;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Vector;
import java.util.concurrent.atomic.AtomicInteger;
import com.volmit.iris.core.nms.container.BiomeColor;
import com.volmit.iris.core.nms.datapack.DataVersion;
import net.minecraft.core.component.DataComponents;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.world.item.component.CustomData;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.status.WorldGenContext;
import org.bukkit.*;
import org.bukkit.block.Biome;
import org.bukkit.block.data.BlockData;
import org.bukkit.craftbukkit.v1_21_R1.CraftChunk;
import org.bukkit.craftbukkit.v1_21_R1.CraftServer;
import org.bukkit.craftbukkit.v1_21_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_21_R1.block.data.CraftBlockData;
import org.bukkit.craftbukkit.v1_21_R1.entity.CraftDolphin;
import org.bukkit.craftbukkit.v1_21_R1.inventory.CraftItemStack;
import org.bukkit.craftbukkit.v1_21_R1.util.CraftNamespacedKey;
import org.bukkit.entity.Dolphin;
import org.bukkit.entity.Entity;
import org.bukkit.event.entity.CreatureSpawnEvent;
import org.bukkit.generator.ChunkGenerator;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.NotNull;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.volmit.iris.Iris;
import com.volmit.iris.core.nms.INMSBinding;
import com.volmit.iris.engine.data.cache.AtomicCache;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.util.collection.KList;
import com.volmit.iris.util.collection.KMap;
import com.volmit.iris.util.hunk.Hunk;
import com.volmit.iris.util.json.JSONObject;
import com.volmit.iris.util.mantle.Mantle;
import com.volmit.iris.util.math.Vector3d;
import com.volmit.iris.util.matter.MatterBiomeInject;
import com.volmit.iris.util.nbt.io.NBTUtil;
import com.volmit.iris.util.nbt.mca.NBTWorld;
import com.volmit.iris.util.nbt.mca.palette.*;
import com.volmit.iris.util.nbt.tag.CompoundTag;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.level.biome.BiomeSource;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import sun.misc.Unsafe;
public class NMSBinding implements INMSBinding {
private final KMap<Biome, Object> baseBiomeCache = new KMap<>();
private final BlockData AIR = Material.AIR.createBlockData();
private final AtomicCache<MCAIdMap<net.minecraft.world.level.biome.Biome>> biomeMapCache = new AtomicCache<>();
private final AtomicCache<MCAIdMapper<BlockState>> registryCache = new AtomicCache<>();
private final AtomicCache<MCAPalette<BlockState>> globalCache = new AtomicCache<>();
private final AtomicCache<RegistryAccess> registryAccess = new AtomicCache<>();
private final AtomicCache<Method> byIdRef = new AtomicCache<>();
private Field biomeStorageCache = null;
private static Object getFor(Class<?> type, Object source) {
Object o = fieldFor(type, source);
if (o != null) {
return o;
}
return invokeFor(type, source);
}
private static Object invokeFor(Class<?> returns, Object in) {
for (Method i : in.getClass().getMethods()) {
if (i.getReturnType().equals(returns)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returns.getSimpleName() + " in " + in.getClass().getSimpleName() + "." + i.getName() + "()");
return i.invoke(in);
} catch (Throwable e) {
e.printStackTrace();
}
}
}
return null;
}
private static Object fieldFor(Class<?> returns, Object in) {
return fieldForClass(returns, in.getClass(), in);
}
@SuppressWarnings("unchecked")
private static <T> T fieldForClass(Class<T> returnType, Class<?> sourceType, Object in) {
for (Field i : sourceType.getDeclaredFields()) {
if (i.getType().equals(returnType)) {
i.setAccessible(true);
try {
Iris.debug("[NMS] Found " + returnType.getSimpleName() + " in " + sourceType.getSimpleName() + "." + i.getName());
return (T) i.get(in);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return null;
}
private static Class<?> getClassType(Class<?> type, int ordinal) {
return type.getDeclaredClasses()[ordinal];
}
@Override
public boolean hasTile(Location l) {
return ((CraftWorld) l.getWorld()).getHandle().getBlockEntity(new BlockPos(l.getBlockX(), l.getBlockY(), l.getBlockZ()), false) != null;
}
@Override
public CompoundTag serializeTile(Location location) {
BlockEntity e = ((CraftWorld) location.getWorld()).getHandle().getBlockEntity(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), true);
if (e == null) {
return null;
}
net.minecraft.nbt.CompoundTag tag = e.saveWithFullMetadata(registry());
return convert(tag);
}
private CompoundTag convert(net.minecraft.nbt.CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(boas);
tag.write(dos);
dos.close();
return (CompoundTag) NBTUtil.read(new ByteArrayInputStream(boas.toByteArray()), false).getTag();
} catch (Throwable ex) {
ex.printStackTrace();
}
return null;
}
private net.minecraft.nbt.CompoundTag convert(CompoundTag tag) {
try {
ByteArrayOutputStream boas = new ByteArrayOutputStream();
NBTUtil.write(tag, boas, false);
DataInputStream din = new DataInputStream(new ByteArrayInputStream(boas.toByteArray()));
net.minecraft.nbt.CompoundTag c = NbtIo.read(din);
din.close();
return c;
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
@Override
public void deserializeTile(CompoundTag c, Location pos) {
((CraftWorld) pos.getWorld()).getHandle().getChunkAt(new BlockPos(pos.getBlockX(), 0, pos.getBlockZ())).setBlockEntityNbt(convert(c));
}
@Override
public CompoundTag serializeEntity(Entity location) {
return null;// TODO:
}
@Override
public Entity deserializeEntity(CompoundTag s, Location newPosition) {
return null;// TODO:
}
@Override
public boolean supportsCustomHeight() {
return true;
}
private RegistryAccess registry() {
return registryAccess.aquire(() -> (RegistryAccess) getFor(RegistryAccess.Frozen.class, ((CraftServer) Bukkit.getServer()).getHandle().getServer()));
}
private Registry<net.minecraft.world.level.biome.Biome> getCustomBiomeRegistry() {
return registry().registry(Registries.BIOME).orElse(null);
}
private Registry<Block> getBlockRegistry() {
return registry().registry(Registries.BLOCK).orElse(null);
}
@Override
public Object getBiomeBaseFromId(int id) {
return getCustomBiomeRegistry().getHolder(id);
}
@Override
public int getMinHeight(World world) {
return world.getMinHeight();
}
@Override
public boolean supportsCustomBiomes() {
return true;
}
@Override
public int getTrueBiomeBaseId(Object biomeBase) {
return getCustomBiomeRegistry().getId(((Holder<net.minecraft.world.level.biome.Biome>) biomeBase).value());
}
@Override
public Object getTrueBiomeBase(Location location) {
return ((CraftWorld) location.getWorld()).getHandle().getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
}
@Override
public String getTrueBiomeBaseKey(Location location) {
return getKeyForBiomeBase(getTrueBiomeBase(location));
}
@Override
public Object getCustomBiomeBaseFor(String mckey) {
return getCustomBiomeRegistry().get(ResourceLocation.parse(mckey));
}
@Override
public Object getCustomBiomeBaseHolderFor(String mckey) {
return getCustomBiomeRegistry().getHolder(getTrueBiomeBaseId(getCustomBiomeRegistry().get(ResourceLocation.parse(mckey)))).get();
}
public int getBiomeBaseIdForKey(String key) {
return getCustomBiomeRegistry().getId(getCustomBiomeRegistry().get(ResourceLocation.parse(key)));
}
@Override
public String getKeyForBiomeBase(Object biomeBase) {
return getCustomBiomeRegistry().getKey((net.minecraft.world.level.biome.Biome) biomeBase).getPath(); // something, not something:something
}
@Override
public Object getBiomeBase(World world, Biome biome) {
return biomeToBiomeBase(((CraftWorld) world).getHandle()
.registryAccess().registry(Registries.BIOME).orElse(null), biome);
}
@Override
public Object getBiomeBase(Object registry, Biome biome) {
Object v = baseBiomeCache.get(biome);
if (v != null) {
return v;
}
//noinspection unchecked
v = biomeToBiomeBase((Registry<net.minecraft.world.level.biome.Biome>) registry, biome);
if (v == null) {
// Ok so there is this new biome name called "CUSTOM" in Paper's new releases.
// But, this does NOT exist within CraftBukkit which makes it return an error.
// So, we will just return the ID that the plains biome returns instead.
//noinspection unchecked
return biomeToBiomeBase((Registry<net.minecraft.world.level.biome.Biome>) registry, Biome.PLAINS);
}
baseBiomeCache.put(biome, v);
return v;
}
@Override
public KList<Biome> getBiomes() {
return new KList<>(Biome.values()).qadd(Biome.CHERRY_GROVE).qdel(Biome.CUSTOM);
}
@Override
public boolean isBukkit() {
return true;
}
@Override
public int getBiomeId(Biome biome) {
for (World i : Bukkit.getWorlds()) {
if (i.getEnvironment().equals(World.Environment.NORMAL)) {
Registry<net.minecraft.world.level.biome.Biome> registry = ((CraftWorld) i).getHandle().registryAccess().registry(Registries.BIOME).orElse(null);
return registry.getId((net.minecraft.world.level.biome.Biome) getBiomeBase(registry, biome));
}
}
return biome.ordinal();
}
private MCAIdMap<net.minecraft.world.level.biome.Biome> getBiomeMapping() {
return biomeMapCache.aquire(() -> new MCAIdMap<>() {
@NotNull
@Override
public Iterator<net.minecraft.world.level.biome.Biome> iterator() {
return getCustomBiomeRegistry().iterator();
}
@Override
public int getId(net.minecraft.world.level.biome.Biome paramT) {
return getCustomBiomeRegistry().getId(paramT);
}
@Override
public net.minecraft.world.level.biome.Biome byId(int paramInt) {
return (net.minecraft.world.level.biome.Biome) getBiomeBaseFromId(paramInt);
}
});
}
@NotNull
private MCABiomeContainer getBiomeContainerInterface(MCAIdMap<net.minecraft.world.level.biome.Biome> biomeMapping, MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base) {
return new MCABiomeContainer() {
@Override
public int[] getData() {
return base.writeBiomes();
}
@Override
public void setBiome(int x, int y, int z, int id) {
base.setBiome(x, y, z, biomeMapping.byId(id));
}
@Override
public int getBiome(int x, int y, int z) {
return biomeMapping.getId(base.getBiome(x, y, z));
}
};
}
@Override
public MCABiomeContainer newBiomeContainer(int min, int max) {
MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base = new MCAChunkBiomeContainer<>(getBiomeMapping(), min, max);
return getBiomeContainerInterface(getBiomeMapping(), base);
}
@Override
public MCABiomeContainer newBiomeContainer(int min, int max, int[] data) {
MCAChunkBiomeContainer<net.minecraft.world.level.biome.Biome> base = new MCAChunkBiomeContainer<>(getBiomeMapping(), min, max, data);
return getBiomeContainerInterface(getBiomeMapping(), base);
}
@Override
public int countCustomBiomes() {
AtomicInteger a = new AtomicInteger(0);
getCustomBiomeRegistry().keySet().forEach((i) -> {
if (i.getNamespace().equals("minecraft")) {
return;
}
a.incrementAndGet();
Iris.debug("Custom Biome: " + i);
});
return a.get();
}
public boolean supportsDataPacks() {
return true;
}
public void setBiomes(int cx, int cz, World world, Hunk<Object> biomes) {
LevelChunk c = ((CraftWorld) world).getHandle().getChunk(cx, cz);
biomes.iterateSync((x, y, z, b) -> c.setBiome(x, y, z, (Holder<net.minecraft.world.level.biome.Biome>) b));
c.setUnsaved(true);
}
@Override
public void forceBiomeInto(int x, int y, int z, Object somethingVeryDirty, ChunkGenerator.BiomeGrid chunk) {
try {
ChunkAccess s = (ChunkAccess) getFieldForBiomeStorage(chunk).get(chunk);
Holder<net.minecraft.world.level.biome.Biome> biome = (Holder<net.minecraft.world.level.biome.Biome>) somethingVeryDirty;
s.setBiome(x, y, z, biome);
} catch (IllegalAccessException e) {
Iris.reportError(e);
e.printStackTrace();
}
}
private Field getFieldForBiomeStorage(Object storage) {
Field f = biomeStorageCache;
if (f != null) {
return f;
}
try {
f = storage.getClass().getDeclaredField("biome");
f.setAccessible(true);
return f;
} catch (Throwable e) {
Iris.reportError(e);
e.printStackTrace();
Iris.error(storage.getClass().getCanonicalName());
}
biomeStorageCache = f;
return null;
}
@Override
public MCAPaletteAccess createPalette() {
MCAIdMapper<BlockState> registry = registryCache.aquireNasty(() -> {
Field cf = net.minecraft.core.IdMapper.class.getDeclaredField("tToId");
Field df = net.minecraft.core.IdMapper.class.getDeclaredField("idToT");
Field bf = net.minecraft.core.IdMapper.class.getDeclaredField("nextId");
cf.setAccessible(true);
df.setAccessible(true);
bf.setAccessible(true);
net.minecraft.core.IdMapper<BlockState> blockData = Block.BLOCK_STATE_REGISTRY;
int b = bf.getInt(blockData);
Object2IntMap<BlockState> c = (Object2IntMap<BlockState>) cf.get(blockData);
List<BlockState> d = (List<BlockState>) df.get(blockData);
return new MCAIdMapper<BlockState>(c, d, b);
});
MCAPalette<BlockState> global = globalCache.aquireNasty(() -> new MCAGlobalPalette<>(registry, ((CraftBlockData) AIR).getState()));
MCAPalettedContainer<BlockState> container = new MCAPalettedContainer<>(global, registry,
i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState(),
i -> NBTWorld.getCompound(CraftBlockData.fromData(i)),
((CraftBlockData) AIR).getState());
return new MCAWrappedPalettedContainer<>(container,
i -> NBTWorld.getCompound(CraftBlockData.fromData(i)),
i -> ((CraftBlockData) NBTWorld.getBlockData(i)).getState());
}
@Override
public void injectBiomesFromMantle(Chunk e, Mantle mantle) {
ChunkAccess chunk = ((CraftChunk) e).getHandle(ChunkStatus.FULL);
AtomicInteger c = new AtomicInteger();
AtomicInteger r = new AtomicInteger();
mantle.iterateChunk(e.getX(), e.getZ(), MatterBiomeInject.class, (x, y, z, b) -> {
if (b != null) {
if (b.isCustom()) {
chunk.setBiome(x, y, z, getCustomBiomeRegistry().getHolder(b.getBiomeId()).get());
c.getAndIncrement();
} else {
chunk.setBiome(x, y, z, (Holder<net.minecraft.world.level.biome.Biome>) getBiomeBase(e.getWorld(), b.getBiome()));
r.getAndIncrement();
}
}
});
}
public ItemStack applyCustomNbt(ItemStack itemStack, KMap<String, Object> customNbt) throws IllegalArgumentException {
if (customNbt != null && !customNbt.isEmpty()) {
net.minecraft.world.item.ItemStack s = CraftItemStack.asNMSCopy(itemStack);
try {
net.minecraft.nbt.CompoundTag tag = TagParser.parseTag((new JSONObject(customNbt)).toString());
tag.merge(s.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).getUnsafe());
s.set(DataComponents.CUSTOM_DATA, CustomData.of(tag));
} catch (CommandSyntaxException var5) {
throw new IllegalArgumentException(var5);
}
return CraftItemStack.asBukkitCopy(s);
} else {
return itemStack;
}
}
public void setTreasurePos(Dolphin dolphin, com.volmit.iris.core.nms.container.BlockPos pos) {
CraftDolphin cd = (CraftDolphin)dolphin;
cd.getHandle().setTreasurePos(new BlockPos(pos.getX(), pos.getY(), pos.getZ()));
cd.getHandle().setGotFish(true);
}
public void inject(long seed, Engine engine, World world) throws NoSuchFieldException, IllegalAccessException {
var chunkMap = ((CraftWorld)world).getHandle().getChunkSource().chunkMap;
var worldGenContextField = getField(chunkMap.getClass(), WorldGenContext.class);
worldGenContextField.setAccessible(true);
var worldGenContext = (WorldGenContext) worldGenContextField.get(chunkMap);
Class<?> clazz = worldGenContext.generator().getClass();
Field biomeSource = getField(clazz, BiomeSource.class);
biomeSource.setAccessible(true);
Field unsafeField = Unsafe.class.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true);
Unsafe unsafe = (Unsafe)unsafeField.get(null);
CustomBiomeSource customBiomeSource = new CustomBiomeSource(seed, engine, world);
unsafe.putObject(biomeSource.get(worldGenContext.generator()), unsafe.objectFieldOffset(biomeSource), customBiomeSource);
biomeSource.set(worldGenContext.generator(), customBiomeSource);
}
public Vector3d getBoundingbox(org.bukkit.entity.EntityType entity) {
Field[] fields = EntityType.class.getDeclaredFields();
for (Field field : fields) {
if (Modifier.isStatic(field.getModifiers()) && field.getType().equals(EntityType.class)) {
try {
EntityType entityType = (EntityType) field.get(null);
if (entityType.getDescriptionId().equals("entity.minecraft." + entity.name().toLowerCase())) {
Vector<Float> v1 = new Vector<>();
v1.add(entityType.getHeight());
entityType.getDimensions();
Vector3d box = new Vector3d( entityType.getWidth(), entityType.getHeight(), entityType.getWidth());
//System.out.println("Entity Type: " + entityType.getDescriptionId() + ", " + "Height: " + height + ", Width: " + width);
return box;
}
} catch (IllegalAccessException e) {
Iris.error("Unable to get entity dimensions!");
e.printStackTrace();
}
}
}
return null;
}
@Override
public Entity spawnEntity(Location location, org.bukkit.entity.EntityType type, CreatureSpawnEvent.SpawnReason reason) {
return ((CraftWorld) location.getWorld()).spawn(location, type.getEntityClass(), null, reason);
}
@Override
public java.awt.Color getBiomeColor(Location location, BiomeColor type) {
LevelReader reader = ((CraftWorld) location.getWorld()).getHandle();
var holder = reader.getBiome(new BlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()));
var biome = holder.value();
if (biome == null) throw new IllegalArgumentException("Invalid biome: " + holder.unwrapKey().orElse(null));
int rgba = switch (type) {
case FOG -> biome.getFogColor();
case WATER -> biome.getWaterColor();
case WATER_FOG -> biome.getWaterFogColor();
case SKY -> biome.getSkyColor();
case FOLIAGE -> biome.getFoliageColor();
case GRASS -> biome.getGrassColor(location.getBlockX(), location.getBlockZ());
};
if (rgba == 0) {
if (BiomeColor.FOLIAGE == type && biome.getSpecialEffects().getFoliageColorOverride().isEmpty())
return null;
if (BiomeColor.GRASS == type && biome.getSpecialEffects().getGrassColorOverride().isEmpty())
return null;
}
return new Color(rgba, true);
}
private static Field getField(Class<?> clazz, Class<?> fieldType) throws NoSuchFieldException {
try {
for (Field f : clazz.getDeclaredFields()) {
if (f.getType().equals(fieldType))
return f;
}
throw new NoSuchFieldException(fieldType.getName());
} catch (NoSuchFieldException var4) {
Class<?> superClass = clazz.getSuperclass();
if (superClass == null) {
throw var4;
} else {
return getField(superClass, fieldType);
}
}
}
public static Holder<net.minecraft.world.level.biome.Biome> biomeToBiomeBase(Registry<net.minecraft.world.level.biome.Biome> registry, Biome biome) {
return registry.getHolderOrThrow(ResourceKey.create(Registries.BIOME, CraftNamespacedKey.toMinecraft(biome.getKey())));
}
@Override
public DataVersion getDataVersion() {
return DataVersion.V1205;
}
@Override
public int getSpawnChunkCount(World world) {
var radius = Optional.ofNullable(world.getGameRuleValue(GameRule.SPAWN_CHUNK_RADIUS))
.orElseGet(() -> world.getGameRuleDefault(GameRule.SPAWN_CHUNK_RADIUS));
if (radius == null) throw new IllegalStateException("GameRule.SPAWN_CHUNK_RADIUS is null!");
return (int) Math.pow(2 * radius + 1, 2);
}
}

View File

@@ -22,10 +22,16 @@ pluginManagement {
gradlePluginPortal()
}
}
plugins {
id "org.gradle.toolchains.foojay-resolver-convention" version "0.8.0"
}
rootProject.name = 'Iris'
include(':core')
include(
':nms:v1_21_R1',
':nms:v1_20_R4',
':nms:v1_20_R3',
':nms:v1_20_R2',
':nms:v1_20_R1',