Compare commits

...

397 Commits

Author SHA1 Message Date
James Seibel 17e375bc61 Return IBlockDetailWrappers 2022-03-19 20:04:11 -05:00
James Seibel a2c8c90a5e Merge branch '1.18.2' into preprocessor_test 2022-03-19 19:56:04 -05:00
James Seibel b376014df8 Update the manifold version 2022-03-19 18:20:28 -05:00
James Seibel b9ee54f6ad add multi-dim and brightness/saturation 2022-03-19 12:39:09 -05:00
James Seibel 6c7e1900a3 Merge in fog changes 2022-03-19 11:20:44 -05:00
tom lee 6f929f40f9 Update core 2022-03-19 22:34:11 +08:00
James Seibel b6a8930855 Add a config for the MultiDimension Similarity 2022-03-18 23:57:32 -05:00
coolGi2007 7a91b258de Updated mods, readme and fixed 1 thing in the config gui 2022-03-17 17:52:19 +10:30
TomTheFurry 35bef76aeb Fix 1.18.2 WorldRenderer renderSky() mixin falling 2022-03-16 19:57:27 +08:00
TomTheFurry 780d0ad9fb Complete the push 2022-03-16 18:53:16 +08:00
TomTheFurry c0d5dd6dee ADVANCED FOGGGGGGGGGGGGGGGG~~~~~~~~~~~~~~~~ 2022-03-16 18:52:56 +08:00
TomTheFurry 3e87e625ba Pushed the stuff leetom did on my macbook 2022-03-15 21:17:07 +10:30
TomTheFurry 56f9403859 Add proper multi FrameBuffer support(And fix MacOS?) 2022-03-15 16:38:39 +08:00
TomTheFurry 8259c79e9c Fixup MixinUtilBackgroudThread+more render log 2022-03-15 18:48:27 +10:30
TomTheFurry be1e2fe7e6 Merge remote-tracking branch 'origin/preprocessor_test' into preprocessor_test 2022-03-15 12:38:10 +08:00
TomTheFurry 609ee5c70d Improve GLMessage Parser 2022-03-15 12:37:51 +08:00
James Seibel 207cab9a0f Clean up the build script 2022-03-15 04:05:12 +00:00
James Seibel c80b025ac1 Clean up the build script 2022-03-15 03:52:25 +00:00
James Seibel 8610917b86 Update .gitlab-ci.yml file 2022-03-15 03:41:17 +00:00
James Seibel fae4bee871 Update .gitlab-ci.yml file 2022-03-15 03:34:52 +00:00
James Seibel b9608498a2 Check if Gradle setup is necessary + fix artifacts not being populated 2022-03-15 03:34:29 +00:00
James Seibel fe59c6b0c9 Check if Gradle setup is necessary 2022-03-15 03:25:09 +00:00
James Seibel b082b048d6 Update .gitlab-ci.yml file 2022-03-15 03:21:59 +00:00
James Seibel 91712cee2a Rough artifact test 2022-03-15 03:21:44 +00:00
James Seibel 5adfbb2dee Update .gitlab-ci.yml 2022-03-15 03:04:50 +00:00
James Seibel ec32d09468 Try separating the archiving into a separate step
This will make adding/removing MC versions to compile easier
2022-03-15 02:51:39 +00:00
James Seibel 919990820e Fix exporting duplicate jars 2022-03-15 02:43:12 +00:00
James Seibel 5cc31efa12 Attempt to add 1.18.1 and 1.18.2 auto building 2022-03-15 02:16:04 +00:00
TomTheFurry 5f48b41693 Add Advanced Fog config entries. Actual impl is a todo. 2022-03-15 00:00:36 +08:00
TomTheFurry 9530eea287 Update core and fix serverRenderDistanceMax not being checked 2022-03-14 16:23:04 +08:00
TomTheFurry ebbf304c94 Updated core 2022-03-14 15:10:20 +08:00
TomTheFurry 7c8ac0c2ff Fix mistakes + update core 2022-03-13 22:57:42 +08:00
TomTheFurry eefad5e052 Improved getMaximumRenderedChunk and fix GLMessage on forge 2022-03-13 22:57:07 +08:00
TomTheFurry 9a1e6e29d4 Update Readme.md on switching versions 2022-03-13 16:45:41 +08:00
TomTheFurry 62ab450d98 Update Core 2022-03-13 16:16:29 +08:00
TomTheFurry b4a5da4a74 Update Config defaults 2022-03-13 16:15:29 +08:00
TomTheFurry ed82480c89 Update .gitmodules properly this time 2022-03-13 07:41:53 +00:00
TomTheFurry 82449c5edc Update and fix core branch tracking(I think?) 2022-03-13 15:40:08 +08:00
TomTheFurry b165726bc9 Add new Config: BiomeBlending 2022-03-13 15:26:24 +08:00
TomTheFurry 11910d0f28 Fix IDE not reconising preprocessor 2022-03-10 17:29:27 +08:00
TomTheFurry f66e27b077 First version where 1.18.1 & 1.18.2 is merged 2022-03-10 17:05:14 +08:00
James Seibel 835beb607d Close #207 (re-add brightness/contrast configs) 2022-03-09 23:06:34 -06:00
TomTheFurry c4e2d3fb0f Remove unused stuff 2022-03-09 16:21:44 +08:00
TomTheFurry eb3d8d9da5 Add Manifold Preprocessor plugin to gradle 2022-03-09 16:14:16 +08:00
TomTheFurry 151d548099 Update core + Fix biome blending 2022-03-08 23:27:14 +08:00
TomTheFurry c5cdc2760f Update core 2022-03-08 16:05:30 +08:00
coolGi2007 a663bf9f19 Added the multiplayer folder thing from 1.18.X to 1.18.2 and fixed building 2022-03-08 17:43:10 +10:30
coolGi2007 7ddd48d132 Updated what james did from 1.18.X to 1.18.2 2022-03-07 16:56:35 +10:30
Ran ce10a43cc6 Fix accesswidener for 1.18.2 2022-03-03 14:34:47 +06:00
tom lee 5476af5bb3 Fixed chunkloader to work with 1.18.2 2022-03-02 19:28:16 +08:00
coolGi2007 25d2cfd7b8 Quick 1.18.2 branch (**DISABLE GENERATION TO WORK**) 2022-03-02 17:43:46 +10:30
James Seibel 1b754387e0 Refactor the dependency injectors 2022-03-01 21:20:00 -06:00
James Seibel bcad40069f Merge branch '1.18.X' of gitlab.com:jeseibel/minecraft-lod-mod into 1.18.X 2022-02-28 17:57:01 -06:00
James Seibel 5aa9061006 remove the discord notification experiment
Using this changed how the messages look in a way I don't like; removing the committer's icon and commit message.
2022-02-28 17:54:41 -06:00
James Seibel 873e8cec57 Update .gitlab-ci.yml file 2022-02-28 23:37:29 +00:00
James Seibel f6f96c3aea Test pipeline discord notifications 2022-02-28 17:18:02 -06:00
tom lee aeed672295 Update core 2022-02-27 17:02:06 +08:00
tom lee 832fbe6d15 Update core 2022-02-26 16:16:00 +08:00
tom lee 03deddf666 Optimized the McObjectConverter for Direction 2022-02-26 14:04:49 +08:00
tom lee d06413d1b4 Update core 2022-02-25 15:15:51 +08:00
tom lee 8afa50d585 Update core + improved GenEvent Terminate speed 2022-02-24 22:28:59 +08:00
Morippi 9f28f1f812 Added comments 2022-02-23 18:26:35 +01:00
Morippi 985388fd90 Removed border from details circles and regions 2022-02-23 16:38:19 +01:00
tom lee e27e10082a Update core 2022-02-22 23:12:59 +08:00
tom lee 4e510d96fc Update core + fix colors. See commit in core 2022-02-22 23:10:58 +08:00
coolGi2007 c0ec02f062 forgot this like 2022-02-22 07:22:33 +00:00
coolGi2007 bd27a96bde Updated the readme and updated the DHJarMerger (now marks the jar as an executable so linux users have an easier time when runnung the jar) 2022-02-22 17:49:23 +10:30
tom lee d6aeaf8e9d Update Core 2022-02-22 11:37:22 +08:00
Ran 2b9bba4aa7 Update core 2022-02-21 17:36:08 +06:00
Ran 58b0991891 Put logger in ApiShared.java 2022-02-21 17:34:52 +06:00
Ran 59cbbef327 Merge remote-tracking branch 'origin/1.18.X' into 1.18.X 2022-02-21 17:29:41 +06:00
Ran 7047c81a2b Put logger in ApiShared.java 2022-02-21 17:27:54 +06:00
tom lee 6e2ab47359 Rework Block color / shape 2022-02-21 19:23:30 +08:00
Ran f879332e1d Client 2 Server packets 2022-02-21 13:40:42 +06:00
coolGi2007 6fcafecc61 Updated fabric, modmenu and readme 2022-02-21 16:36:10 +10:30
coolGi2007 a5af93aef1 Renamed the thing to JarMain 2022-02-20 22:26:01 +00:00
coolGi2007 4b84fd2a67 Added a way to run jar (dosnt do anything but could be used to check opengl and move mod to mods folder) 2022-02-20 22:16:21 +10:30
cola98765 924efc0cbd update core 2022-02-20 12:34:09 +01:00
tom lee 288457b5bd Update core 2022-02-20 17:35:11 +08:00
James Seibel d29fa86de6 Merge branch 'jeffthejeffthejeff-1.18.X-patch-51031' into '1.18.X'
Added an image and improved start of Readme.md

See merge request jeseibel/minecraft-lod-mod!17
2022-02-20 05:13:39 +00:00
James Seibel 97be227e3d Add a missing "s" 2022-02-20 05:12:16 +00:00
James Seibel 909d6a54c3 Slightly reword the blurb 2022-02-20 05:10:35 +00:00
Ran 228b6a80dc Merge branch '1.18.X' of https://gitlab.com/jeseibel/minecraft-lod-mod into 1.18.X 2022-02-20 09:32:44 +06:00
Ran 6936a5f96f I forgor 💀 2022-02-20 09:31:55 +06:00
cola98765 740560a50a actually fix tint on custom water textures. 2022-02-19 22:32:53 +01:00
cola98765 47c28f0f37 actually fix tint on custom water textures. 2022-02-19 22:28:35 +01:00
Ran 1c859cd7da Oops was registering channels to wrong environments 2022-02-20 00:15:33 +06:00
tom lee e4a97dd76d Update core 2022-02-20 01:01:59 +08:00
Ran 4fd1e5ea06 Update core 2022-02-19 22:58:05 +06:00
Ran 6039aeabde Server client communication! maybe 2022-02-19 22:55:53 +06:00
tom lee 17a384f074 Update core 2022-02-19 22:15:04 +08:00
coolGi2007 25e8f5ec6a Forgot to push this file 2022-02-19 08:30:06 +00:00
coolGi2007 eac8cacd42 Removed new config 2022-02-19 18:53:34 +10:30
James Seibel 75193d76a3 Update the version number to 1.6.2a 2022-02-17 20:11:13 -06:00
James Seibel aa24fd341e Update the version number to 1.6.2a 2022-02-17 20:10:02 -06:00
Dog 81adade05b Capitalised Source Code Installation to be grammatically correct 2022-02-17 23:55:38 +00:00
Dog e3808dc986 Updated title of Readme to look nicer 2022-02-17 23:45:55 +00:00
tom lee d669b2a1fe Update and merge the render_test core 2022-02-17 22:26:48 +08:00
cola98765 2bd8dab240 #159 multiply color by color... not by alpha 2022-02-15 11:50:14 +01:00
cola98765 2b423c2edd squared colour averaging as in #159
please check if it works looks better.
2022-02-15 11:37:54 +01:00
cola98765 1a4faf4bdd close #188; fix lang parts in #189 2022-02-15 11:21:23 +01:00
cola98765 b70829aceb RotatedPillarBlock colors are taken form sides, resolving #191 2022-02-15 11:06:37 +01:00
cola98765 bba771d376 Potentially fix water texture packs. 2022-02-14 17:31:36 +01:00
James Seibel 75b18f8bd8 Update the forge version to fix a potential crash with Biomes-o-plenty 2022-02-13 16:28:21 -06:00
James Seibel 60da404900 Merge branch '1.18.X' of gitlab.com:jeseibel/minecraft-lod-mod into 1.18.X 2022-02-13 07:37:43 -06:00
coolGi2007 b75eebd0dc Getting more stuff ready for new config 2022-02-13 14:48:56 +10:30
James Seibel 72cbd1167a Prepare for 1.6.1a 2022-02-12 12:01:40 -06:00
tom lee e4e51ebf5b Update core 2022-02-12 23:54:23 +08:00
tom lee dd2096bf1b Frontported the forge mixin issue fix. (It may work without that but...) 2022-02-12 23:54:23 +08:00
coolGi2007 393a94a7a1 We don’t talk about this 1 line in the gradle 2022-02-12 14:04:18 +00:00
tom lee ef0023ef39 Switch to another way to do the world gen. Now more mod compat! 2022-02-12 22:00:09 +08:00
coolGi2007 f0994fff75 Added a way to add mods in code and not run on runtime and moved issues and source to gradle.properties 2022-02-12 19:34:54 +10:30
tom lee 31f41540c0 Fix chat format color. Add failsafe stopping of generator 2022-02-12 15:13:58 +08:00
tom lee 81fe13b9c0 Add backup to VanillaRenderedChunks & many generator stuff 2022-02-12 14:30:04 +08:00
tom lee 332df13b29 Fix loadChunk try/catch missing the mark & add WRAN on modded chunkGen 2022-02-12 13:12:25 +08:00
James Seibel b3af6df0c5 Update the version number to 1.6.1a-pre and re-enable dev code 2022-02-11 22:08:35 -06:00
James Seibel 9392e618c0 I accidently removed the "a" 2022-02-11 20:00:40 -06:00
James Seibel fd361a39a1 Update the version number and homepage link for a1.6.0 2022-02-11 19:59:23 -06:00
coolGi2007 f41de59f39 Removed some file stuff that didnt work 2022-02-11 13:05:23 +00:00
coolGi2007 c701cf987b Merge remote-tracking branch 'origin/1.18.X' into 1.18.X 2022-02-11 16:07:22 +10:30
coolGi2007 f05e878600 Added version to config file for the future 2022-02-11 16:07:10 +10:30
tom lee dc028db5ed update core + change a bit for sodium get chunk so it works better 2022-02-11 13:35:39 +08:00
James Seibel c59d7a7d27 Slightly improve the tooltips for the config GUI 2022-02-10 22:07:55 -06:00
tom lee a3dd346a02 Update core + Config + fixed blindness fog 2022-02-10 22:05:57 +08:00
tom lee dba8061f71 Update core 2022-02-10 17:08:00 +08:00
tom lee 3da2d961fc Update core 2022-02-10 16:23:33 +08:00
James Seibel aa83dc7465 Update Core 2022-02-09 19:22:29 -06:00
Morippi 392821c081 Tried to fix the render distance min detail bug 2022-02-09 22:01:17 +01:00
tom lee 7e5fc979cc Impl MEM LEAK fix from 1.16, though didn't think it was an issue before 2022-02-09 18:46:37 +08:00
tom lee 7ebb555b94 Update core 2022-02-08 13:45:04 +08:00
tom lee 3612a2f9e0 Updated core 2022-02-07 14:02:12 +08:00
coolGi2007 42b67825f8 Added custom toml to forge 2022-02-07 09:46:08 +10:30
coolGi2007 30a636c840 Added toml to be able to be used in core 2022-02-07 09:14:08 +10:30
tom lee e5722c19a9 Update core and impl the changing Region Size 2022-02-06 22:55:06 +08:00
tom lee 6b6a9ab0a9 Update core 2022-02-06 21:33:58 +08:00
tom lee 6da74c6f4e Forgot to update core... 2022-02-06 19:40:03 +08:00
tom lee 0bafa37f66 Fix and unify how key events work 2022-02-06 14:58:39 +08:00
coolGi2007 6ba6b11f6b Use cursedforge rather than modrinth for sodium download 2022-02-06 05:45:58 +00:00
James Seibel 739653f37a Add an expiration to the archives 2022-02-05 15:42:15 +00:00
coolGi2007 213d70f2d1 Removed clouds 2022-02-05 09:41:53 +00:00
tom lee dda3c7636b Update core + Moved ChunkLoader to be in line with other versions 2022-02-05 16:24:24 +08:00
tom lee 3956578043 Update core 2022-02-05 14:44:30 +08:00
tom lee d11f067392 Update core 2022-02-04 14:33:55 +08:00
tom lee 9f9fe6a231 Updated core 2022-02-04 00:32:55 +08:00
tom lee 486a30cb93 Update core 2022-02-04 00:16:25 +08:00
tom lee 01545dc295 Update the generator with 1.16 changes 2022-02-03 18:01:09 +08:00
coolGi2007 165a3799f3 Put some stuff that was duplicated in gradle to the main gradle 2022-02-02 22:40:41 +00:00
coolGi2007 308f809d5d Cleaned up some gradle stuff 2022-01-30 15:53:47 +10:30
tom lee 003dbdff02 Fixed C2ME log spam compat issue 2022-01-29 17:33:57 +08:00
tom lee 99f8dbb042 Mod compat: Fixed issue with Repurposed Structures 2022-01-29 16:50:02 +08:00
tom lee 4263ea9733 Add patch for BCLib to solve patchy features gen issue 2022-01-29 16:11:52 +08:00
tom lee c09b07a21b Greatly improve speed on loading existing chunks. 2022-01-27 14:08:06 +08:00
coolGi2007 4e0160648b Fixed issue 162 (renamed stuff) 2022-01-27 02:38:13 +00:00
coolGi2007 ad367f681d (made accidentally added string at the end of something) 2022-01-27 12:51:37 +10:30
coolGi2007 a5a70cd65b Made stuff about mod get from gradle.properties so it is easier to edit 2022-01-27 12:50:19 +10:30
coolGi2007 4ff37cfdad Fxed forge version 2022-01-27 11:14:07 +10:30
cola98765 9a1abdefa1 fixed mergeMultiData and lodBuilder with connected lods 2022-01-26 09:25:50 +01:00
tom lee 37cc7e7b37 Fixed a bug causing Fast Light mode stuck in gen loop 2022-01-26 13:14:57 +08:00
coolGi2007 04cbb1e92c Fixed forge crashing on world join 2022-01-26 04:53:45 +00:00
CodeF53 5033175808 Fix small typo. 2022-01-25 17:52:45 +00:00
tom lee 689928708c Update core and fix forge serverTickEvent firing 2 times per tick 2022-01-25 18:27:21 +08:00
tom lee 98327e6fdf Update core + Config Wrapper 2022-01-25 17:08:55 +08:00
coolGi2007 5aef0977c0 I always forget to update core 2022-01-25 04:58:09 +00:00
coolGi2007 e6738f1c80 Added comments to config file (temp solution) 2022-01-25 15:26:21 +10:30
James Seibel b55c1b8f56 Delete OptiFine_1.18.1_HD_U_H4.jar 2022-01-25 00:59:34 +00:00
tom lee 3764a4cc9e Updated core and follow core changes 2022-01-24 23:37:33 +08:00
tom lee d6bbb9d8dc Updated core and followed with some tweaks for FAR_FRIST gen 2022-01-24 23:02:53 +08:00
tom lee a38e7a00e4 Update core, Change some small stuff. 2022-01-24 21:08:17 +08:00
coolGi2007 2ec84ae3cf Fixed a typoish thing 2022-01-24 09:21:51 +00:00
coolGi2007 f03035e3f9 After all these years, the ints show up correctly after restarting (it was literally a 1 line fix) 2022-01-24 19:41:33 +10:30
coolGi2007 1d914b8f8a Refactored some stuff 2022-01-24 18:54:16 +10:30
Ran ee947b36a2 maybe it'll work 2022-01-24 10:58:26 +06:00
Ran ba393f61e5 I forgor 2022-01-24 10:32:00 +06:00
Ran 796c8e7bef Update DHJarMerger-1.0.jar 2022-01-24 10:29:03 +06:00
CodeF53 fe60de314d Dummy commit to force new job 2022-01-24 03:41:08 +00:00
CodeF53 d237db3302 remove invalid yaml code from prior commmit 2022-01-24 03:23:05 +00:00
CodeF53 f665b452b0 Don't cache old builds, uncomment jar versioning. 2022-01-24 03:19:31 +00:00
James Seibel 17750691d6 comment out the jar versioning 2022-01-23 20:52:28 -06:00
James Seibel 89ba5b9d15 Update the pipeline 2022-01-23 20:33:27 -06:00
James Seibel cea44a3f8a Update the pipeline 2022-01-23 20:17:50 -06:00
James Seibel a99c9aff76 Update the pipeline 2022-01-23 19:11:15 -06:00
James Seibel 1827ab646c Update the pipeline 2022-01-23 18:56:48 -06:00
James Seibel db00f7ebec Update the pipeline 2022-01-23 18:45:23 -06:00
James Seibel 0b93c7b5dc Update the pipeline 2022-01-23 18:25:17 -06:00
James Seibel 97204f3a3c Update the pipeline 2022-01-23 18:11:18 -06:00
James Seibel 02a6db0a62 Update the pipeline 2022-01-23 18:00:43 -06:00
James Seibel 577af4d854 Update the pipeline 2022-01-23 17:58:42 -06:00
James Seibel 68155142c3 Update the pipeline 2022-01-23 17:44:11 -06:00
James Seibel 43897e1298 Add the version name override to fabric 2022-01-23 16:48:33 -06:00
James Seibel bf2c520966 Fix a typo in the pipeline 2022-01-23 16:47:24 -06:00
James Seibel ee1528f694 Merge branch '1.18.X' of gitlab.com:jeseibel/minecraft-lod-mod into 1.18.X 2022-01-23 16:26:16 -06:00
James Seibel 8bd7556c89 Add the dateTime to compiled jars and the commit to artifacts 2022-01-23 16:25:37 -06:00
James Seibel facbb174f5 Remove logo and IDE files (they are stored in Core) 2022-01-23 16:22:29 -06:00
tom lee 9d3ce5307c Updated core + cleanup imports in WorldGen 2022-01-23 23:17:04 +08:00
tom lee 54f3e9e12d Update core 2022-01-23 21:19:53 +08:00
tom lee e294fc79eb Fixed using wrong func for makeBiome(). 2022-01-23 20:28:35 +08:00
tom lee a750aaf90a Update core + cleanup some junks 2022-01-23 19:12:18 +08:00
James Seibel be8e09eb9b Update jar merging pipeline 2022-01-22 22:47:35 -06:00
James Seibel 016d26a6f7 Update jar merging pipeline 2022-01-22 22:35:51 -06:00
James Seibel 539698c456 Update jar merging pipeline 2022-01-22 22:34:35 -06:00
James Seibel bcc11b8f0c Update jar merging pipeline 2022-01-22 22:24:52 -06:00
James Seibel c2a960162e Add a link to Ran's Jar merger repo 2022-01-22 22:24:42 -06:00
James Seibel c42a3a5fb3 Update jar merging pipeline 2022-01-22 22:13:59 -06:00
James Seibel 59d6289177 Update jar merging pipeline 2022-01-22 22:04:56 -06:00
James Seibel 4f028d118d Set the default Generation Priority to NEAR_FIRST closes #160 2022-01-22 22:04:36 -06:00
James Seibel b555e35016 Update jar merging pipeline 2022-01-22 21:58:57 -06:00
James Seibel 26b4c3a2d9 Update jar merging pipeline 2022-01-22 21:34:46 -06:00
James Seibel 2a5199f851 Update jar merging pipeline 2022-01-22 21:18:32 -06:00
James Seibel 408dbc2169 Update jar merging pipeline 2022-01-22 21:05:09 -06:00
James Seibel c9ffcfb1e8 Add jar merging to the pipeline 2022-01-22 20:50:16 -06:00
tom lee 3bd1eedcb8 Fixed Lithium WorldGen NullPtr issue cause by lazyness
Detail cause: I only override the getChunk(x,y,status,bool) and not its
sub set like getChunk(x,y), getChunk(x,y,status) because... Programmer
is always lazy. Aren't they?
2022-01-22 23:05:11 +08:00
tom lee 8500ec7a00 Fixed WorldGen to provide better support for StarLight 2022-01-22 22:38:33 +08:00
tom lee 223570a0b7 Update core. Fixed WorldGen using Util.background threads 2022-01-22 18:10:53 +08:00
tom lee de8c063731 Update core + cleanup debug logging 2022-01-22 16:10:32 +08:00
tom lee 0cffa30286 Updated core 2022-01-22 13:45:51 +08:00
coolGi2007 1d3a282c60 Added optifine tough dosnt run yet since forge dependances arnt set up yet 2022-01-21 17:49:47 +10:30
tom lee 9b6cd955b5 Updated core 2022-01-20 22:54:06 +08:00
tom lee 8e1559ac61 Update core and fix under lava (and powder snow) render fog issue 2022-01-20 21:55:17 +08:00
tom lee ce597576ba Update core and fixed slight bugs 2022-01-20 19:29:22 +08:00
tom lee d53a7a5fc4 Update core 2022-01-19 23:33:09 +08:00
tom lee 35bb5cdc92 Update core 2022-01-19 19:01:50 +08:00
tom lee 26e9cc21fd Add and fix mod compat issue with Optifine 2022-01-19 13:52:05 +08:00
tom lee 71fd448b7f Dummy commit to kick start CI, hopefully. 2022-01-18 23:15:36 +08:00
tom lee 93e18230f0 GENERATE LOD FROM FILE IS HERE!!!!!!!
Noted issue:

1. Non problematic WARN of `Tried to access a block entity before it
   was created`

2. The loading is.... a bit slow due to single thread action. Will be
   improved soon.

3. Possible Chunk Status not correct issue. It... sometimes happen, but
   it's mostly fine~

Special thanks to the YouTube commentors on the a1.6 Teaser Trailer
video. If not for them, I would not notice how many people want this,
and actually look into slapping in this feature in a1.6.
2022-01-18 22:50:57 +08:00
cola98765 d305741be2 resolved warnings. part 3 2022-01-18 11:29:01 +01:00
cola98765 5830c8d87a resolved warnings. part 2 2022-01-18 11:00:08 +01:00
cola98765 5161439536 resolved warnings. now more carefully. 2022-01-18 10:38:40 +01:00
coolGi2007 deb6ada6cc Fixed a typo 2022-01-18 09:18:36 +00:00
coolGi2007 e72a0546be Cleaned up comment on gradle and made stuff more consistent 2022-01-18 19:24:36 +10:30
jas35484 e27b43f03a Increment the version from '1.5.4a' to '1.6.0a-pre' 2022-01-17 20:33:35 -06:00
jas35484 daf4f06a30 Add .gitlab-ci.yml 2022-01-17 19:51:40 -06:00
Ran e5ef93a26d Universal jar for forge & fabric 2022-01-18 00:43:13 +06:00
cola98765 b158dff2c6 Revert "resolved couple warnings. If it causes problems just revert it."
This reverts commit b390e54801.
2022-01-17 16:27:27 +01:00
cola98765 23bbbce749 reverted config changes.... it was a bit too final 2022-01-17 16:14:52 +01:00
tom lee 898be82aab Update core 2022-01-17 22:51:28 +08:00
tom lee dc9ed37de2 Update core 2022-01-17 22:04:07 +08:00
cola98765 b390e54801 resolved couple warnings. If it causes problems just revert it. 2022-01-17 14:18:14 +01:00
tom lee 9736d2169e Update core+fabric disable StarLight 2022-01-16 17:34:35 +08:00
tom lee b507f459b3 Add basic StarLight compat. (Make it not crash) 2022-01-15 21:56:48 +08:00
tom lee 51a7053d7e Update core & make LightMode easy to switch. 2022-01-15 19:10:59 +08:00
coolGi2007 3ba40dd910 Added starlight 2022-01-15 10:14:44 +00:00
tom lee 248f8e5e70 ExpWorldGen: Add LightMode support. TODO: Config. 2022-01-15 16:58:16 +08:00
coolGi2007 49b0911aaf Escape saves config and added a immersive portals comment 2022-01-14 13:52:42 +10:30
tom lee e4b40c9383 Update core + Add disableVanillaFog for Forge 2022-01-13 23:35:18 +08:00
tom lee 328ac93178 Fixed Sodium Fog Issue. 2022-01-13 20:00:36 +08:00
tom lee d91f86aed5 Update core 2022-01-12 18:18:01 +08:00
tom lee 8119cc06ad Finally a reliable onClientChunkLoad event without light issues! 2022-01-12 16:16:20 +08:00
coolGi2007 94c9d0e276 Updated core 2022-01-11 08:45:33 +00:00
coolGi2007 e262dfa14a Fixed clouds for immersive portals 2022-01-11 08:39:09 +00:00
coolGi2007 5e0b63347e Fixes all (hopefully) problems with saving the config file 2022-01-11 17:35:45 +10:30
coolGi2007 b7df3bad22 Added a warning for clouds 2022-01-10 04:54:37 +00:00
coolGi2007 6a56c0c96f Update to add mod versions 2022-01-10 04:15:41 +00:00
tom lee fd8a94d77c Impl a semi-working getRenderedChunk for Sodium 2022-01-09 14:57:42 +08:00
tom lee 7d38fac16d Update core & try patch the light issue 2022-01-09 00:31:39 +08:00
tom lee 235ffb03a5 Make light works on pre generated chunks! Changed ChunkWrapper 2022-01-08 22:53:51 +08:00
tom lee fa2702209c Impl a getVanillaRenderedChunk 2022-01-08 15:05:12 +08:00
coolGi2007 f9f9f98750 Removed FogRenderer from forge(sorry for adding) 2022-01-08 06:25:06 +00:00
tom lee 0c46947f4d Update core 2022-01-07 19:09:07 +08:00
tom lee b5b57dfaba Update core and config 2022-01-07 18:59:02 +08:00
tom lee 39e7812f8b Updated core. Fixed wrong math in VanillaRenderedChunks 2022-01-07 15:53:30 +08:00
coolGi2007 025e8b3f9b Made clouds more optimised 2022-01-07 17:33:31 +10:30
coolGi2007 35e3a4262b Added disable vanilla fog to forge 2022-01-07 11:45:51 +10:30
coolGi2007 562c8154ff Fixed some config stuff 2022-01-06 10:49:25 +00:00
tom lee e23244181a Update core & comment out debug. Fixed/Cleaned up Fabric/Forge warpper 2022-01-06 16:28:25 +08:00
tom lee 6aa6c32299 Update core and tried fixing FAR_FIRST. Failed though.
Will continue tomorrow.
2022-01-06 00:09:45 +08:00
coolGi2007 fbdabf52e7 Made a way to save 1 config entry at a time 2022-01-05 23:07:40 +10:30
tom lee f4c1f1bcd7 Updated core and fixed generator bug 2022-01-05 19:19:14 +08:00
coolGi2007 965c19d426 Save config if you set something in the config wrapper singleton 2022-01-05 20:45:06 +10:30
tom lee 239a876fcf Update core 2022-01-05 16:58:31 +08:00
tom lee d53165881f Update core and ExperWorldGen for faster >Chunk details generation 2022-01-04 18:58:58 +08:00
tom lee 40733ea1fc Update core 2022-01-04 16:47:07 +08:00
coolGi2007 66a16ee508 Made clouds get from texture rather than use noise 2022-01-04 07:57:55 +00:00
tom lee b1a9a8ac8d Update core 2022-01-04 15:11:36 +08:00
tom lee 06a2f9f336 Updated core and comment out the @ConfigAnnotations.Category 2022-01-03 00:10:11 +08:00
coolGi2007 978bc58c11 Removed the need for any config category. The config now guesses the category 2022-01-02 16:34:47 +10:30
coolGi2007 a5577e80f1 Reordered forge mixin 2022-01-02 05:16:16 +00:00
Eric 9daf5a013c Changed cloud projection matrix to have custom clip values. 2022-01-01 21:28:56 -07:00
coolGi2007 72e2cb8a64 Updated core and fixed config crash 2022-01-02 03:51:19 +00:00
cola98765 db819698af fixed updateData 2022-01-01 13:31:23 +01:00
tom lee 09e427ab97 Updated core 2022-01-01 15:26:34 +08:00
tom lee a6b3a7ea5a Update core and fixed MixinFogs and added underwater fog 2022-01-01 13:51:35 +08:00
tom lee 4d08339f79 Updated core 2022-01-01 12:05:12 +08:00
tom lee 2ba32a8c94 Update core 2021-12-31 21:03:18 +08:00
coolGi2007 ebedd5e181 Moved some resources to core 2021-12-31 10:42:10 +00:00
tom lee 357c355e26 Updated core 2021-12-31 17:02:26 +08:00
tom lee faca159721 Updated core 2021-12-31 16:10:13 +08:00
coolGi2007 3556528932 I always forget to update core 2021-12-31 07:22:37 +00:00
coolGi2007 8513e46fdc Abstracting clouds 2021-12-31 17:51:32 +10:30
coolGi2007 323eced2a4 Fixed cloud problems 2021-12-31 17:24:45 +10:30
coolGi2007 6a87539ca3 Made a way to fully disable my clouds. Will be off by defult till clouds are done 2021-12-31 16:12:47 +10:30
coolGi2007 fe725b6795 Extended clouds 2021-12-31 04:55:01 +00:00
tom lee 02862a770f Fixed rebase issues and now it builds again 2021-12-30 22:06:30 +08:00
tom lee a7759ab8e9 Update core and config 2021-12-30 22:04:29 +08:00
cola98765 da1b2051dd made config for minimum back side culling distance. actual value is using prev player pos so on long flights it works better. 2021-12-30 13:19:47 +01:00
tom lee 4fdc596474 Update core 2021-12-29 20:38:13 +08:00
tom lee d0c710b7e1 Update core 2021-12-29 18:19:23 +08:00
tom lee 41ee9dcd99 ExperWorldGen: Hopefully fixed the ArrayIndexOutOfBound in StructStart 2021-12-29 15:10:22 +08:00
tom lee 506ce87f5f Updated core 2021-12-29 13:47:18 +08:00
coolGi2007 08e42ebfe5 Fixed ConfigGui 2021-12-29 16:16:21 +10:30
coolGi2007 699d27afd2 More universal config (works with java 8 & 16) 2021-12-28 10:50:32 +00:00
tom lee 4a64ce0bed Forge Bugfix: Fixed mixins metadata 2021-12-28 15:42:36 +08:00
tom lee b3b94d29b5 Forge Bugfix: Added accesswidener to fix access violations 2021-12-28 15:40:39 +08:00
tom lee 3a30516088 Update core & changed System.out to ClientApi.debug 2021-12-28 15:28:46 +08:00
Ran 6f469737f3 Fix forge's access transformers 2021-12-28 12:58:37 +06:00
coolGi2007 183720d1e5 Updated some config stuff for less crashing 2021-12-28 05:33:18 +00:00
tom lee b2dcc66bd0 update core 2021-12-28 00:10:18 +08:00
tom lee 5c67be30de Updated core 2021-12-27 23:43:46 +08:00
tom lee 4ad4e2c29c BufferUpload: Coresponding to core commit
Changed configs. Also added some more exception logging in
ExperWorldGen. And added a flag to JVM Minecraft to force JVM to always
capture Stack Traces.
2021-12-27 16:09:20 +08:00
cola98765 d1f805d178 optimised setupColorAndTint, specifically part where it calculates if block is gray for no reason if it's not going to be tinted anyway. 2021-12-26 16:08:02 +01:00
cola98765 73071119fa forgot I'm working on wrapper... still, I need color. 2021-12-26 15:41:58 +01:00
cola98765 97c52834f5 fixed SPRUCE and BIRCH leaves, as they require hardcoded biome color. TODO azalea also is like that 2021-12-26 15:36:18 +01:00
coolGi2007 3e472e454a Fixed bugs with ConfigGui 2021-12-26 16:47:28 +10:30
coolGi2007 7ddab31337 Updated comment for config 2021-12-26 03:50:07 +00:00
coolGi2007 fd5b9be523 WAHOO. CONFIG FINALLY SAVES!!! 2021-12-26 03:39:39 +00:00
cola98765 f9dd870067 changed fabric debug key to F8 2021-12-25 13:45:34 +01:00
cola98765 4908acd7ac fixed light requiring Y offset 2021-12-25 13:19:10 +01:00
coolGi2007 87486f6825 Fixed some config stuff. Only 1 more thing to go 2021-12-25 20:52:46 +10:30
tom lee c721c14e27 ExperWorldGen: Added perf logger
set ENABLE_PERF_LOGGING at WorldGenerationStep to true to enable it
2021-12-24 23:44:00 +08:00
tom lee 3521af9792 ExperWorldGen: Make it also works with non Feature 2021-12-24 22:23:02 +08:00
tom lee ff94dba348 ExperWorldGen: Fix major bugs and improved speed 2021-12-24 22:14:04 +08:00
cola98765 31d0a45555 potential fix to cherry leaves (call me if you see gray blocks that should not be gray) 2021-12-24 12:56:00 +01:00
tom lee 41c1473e04 ExperWorldGen: Use ThreadLocal to cache stuff 2021-12-24 17:18:58 +08:00
tom lee d5f12466b2 ExperWorldGen: Fixed World gen on non Overworld 2021-12-24 14:43:07 +08:00
coolGi2007 bdd9ef6b40 Fixed tooltip. Now only the saving is needed to be fixed 2021-12-24 16:14:35 +10:30
James Seibel 9b6895ec68 Refactor and comment ConfigGui 2021-12-23 20:01:53 -06:00
Ran a3854561fc Merge remote-tracking branch 'origin/1.18.X' into 1.18.X 2021-12-23 22:50:32 +06:00
Ran a66df74ec9 BlockEvents 2021-12-23 22:50:06 +06:00
tom lee eb4b31e876 Render: Changed rendered chunk getter to return circles 2021-12-23 18:40:22 +08:00
tom lee 6015b9a1dc ExperWorldGen: Increased timeout for slow CPUs 2021-12-23 18:40:22 +08:00
tom lee 146d42bbe9 Fabric: Added no vanilla fog support.
This isn't availible due to Forge default overrides something. Note that
this noFog also won't work on custom renderer.
2021-12-23 18:40:22 +08:00
Ran 16b14bc424 Add MinecraftForge License 2021-12-23 14:53:58 +06:00
Ran a37e4ca232 Merge remote-tracking branch 'origin/1.18.X' into 1.18.X 2021-12-23 14:47:59 +06:00
Ran 8103c16064 Fix warnings & add License 2021-12-23 14:47:38 +06:00
tom lee 6ae41b0caa ExperWorldGen: Polished stuff. No more error messages. use configs.
I would say this version is the first that is playable.
2021-12-23 16:36:14 +08:00
Ran ba81f31027 Update some stuffs 2021-12-22 22:16:08 +06:00
tom lee 71c72e26e7 ExprWorldGen: Fixed lots of stuff and Features now works!
Still Features exception, which I know how to fix I think.
2021-12-22 23:02:28 +08:00
Ran 97828f465d Server-sided Incoming 2021-12-22 20:32:03 +06:00
Ran ec37803572 Merge remote-tracking branch 'origin/1.18.X' into 1.18.X 2021-12-22 19:47:45 +06:00
Ran b7a54eff7a Explain why this exists 2021-12-22 19:47:22 +06:00
coolGi2007 9604ce297c Fixed not building 2021-12-22 09:53:56 +00:00
Ran 5ad961d80e Delete random log file; Sorry if this was important 2021-12-22 14:02:54 +06:00
Ran 843ec2fef8 Disable run for core & common 2021-12-22 14:01:27 +06:00
Ran 1b3e90b669 Make gradle compatible with Java 17 2021-12-22 13:53:34 +06:00
coolGi2007 55aadb73f1 Fixed the config button on forge menu 2021-12-22 07:07:21 +00:00
coolGi2007 e3d87c70c4 Updated config to be smaller 2021-12-22 05:37:59 +00:00
tom lee 8b1205f79e Fixed Fog color 2021-12-22 11:24:25 +08:00
tom lee 291f5d247c updated core 2021-12-21 21:13:44 +08:00
tom lee ad63825194 ExprWorldGen: Fixed some bugs. Still more to go. 2021-12-21 16:11:57 +08:00
tom lee b0e0cd107d Updated core 2021-12-21 15:49:44 +08:00
tom lee 5f60cd8d4d WorldGen: Added thread timeout failsafe 2021-12-20 14:31:32 +08:00
tom lee d0e17ccab7 Modified a bit of how it determine generation range 2021-12-19 22:35:21 +08:00
tom lee 38a4643cf3 WorldGen: Reversed priority for far vs near 2021-12-19 22:03:15 +08:00
tom lee 938adca022 Changed config for world gen 2021-12-19 21:42:05 +08:00
tom lee e2ec80134e Set the UseUnstable...Config to true by default for now 2021-12-19 21:39:51 +08:00
tom lee 903f166041 ExpWorldGen: Fix DeadLocks, improved cpu utilisations
Now world gen aways try to keep a certain amount of generation events
active.
2021-12-19 18:27:42 +08:00
TomTheFurry a9bdbfda4e Merge branch '1.18' into '1.18.X'
Merge the exprimental world gen

See merge request jeseibel/minecraft-lod-mod!13
2021-12-18 16:40:44 +00:00
tom lee 378349b870 Added experimental world generator. (Features mode only for now)
Turn on the AllowUnstableFeatureGeneration button to enable it. It is a
temp setting and will be renamed later. There will be many issues with
the generator, but at least it for now works... To be fixed tomorrow.
2021-12-19 00:32:42 +08:00
coolGi2007 190ce716ff Forgot to make the forge run client actually run forge 2021-12-17 11:59:05 +00:00
coolGi2007 d2c3a87fa8 Fixed some general stuff that broke when updating to .1.8.1 2021-12-17 11:47:39 +00:00
coolGi2007 2d5acbbf45 Updated to 1.18.1 but also works on 1.18 2021-12-17 08:52:46 +00:00
coolGi2007 4e973099f9 Updated my config 2021-12-17 08:29:14 +00:00
tom lee ee4f43cc59 WorldGen: Now only somewhat lock up server TPS
Use recent change to core so that we no longer request 8 chunk
generations per server tick, but instead just 1.
2021-12-17 16:00:44 +08:00
tom lee 3e64b7400e Updated core 2021-12-17 14:56:29 +08:00
James Seibel c44daa759c Remove the Forge server mod requirement and update the credits 2021-12-16 21:47:23 -06:00
tom lee 17c662b10f Fix -64 offset color bug: Impl' getMinHeight()
It calls works by calling getMinBuildHeight()
2021-12-16 18:39:58 +08:00
tom lee 3cfbb69dd9 Update core & fix Wrappers 2021-12-15 16:45:33 +08:00
tom lee 470668265b Updated core. Cann't test if works, in a hurry. 2021-12-15 00:08:38 +08:00
tom lee b6ced30d70 Updated core 2021-12-14 21:40:15 +08:00
coolGi2007 d3e0f1e14d leetom can you check it works before updating core 2021-12-14 08:36:33 +00:00
tom lee 910350ba3a Update core to use new Renderer system 2021-12-14 15:06:32 +08:00
coolGi2007 8dcf30e776 Updated core 2021-12-13 12:27:28 +00:00
coolGi2007 30d4bcd6a1 Updated config 2021-12-13 12:11:39 +00:00
tom lee 66300cbe70 WorldGen: Fix VersionConstants and more comments
More comments in WorldGenWrapper and fix version constants to always
return true in isWorldGeneratorSingleThreaded()
2021-12-12 23:28:18 +08:00
coolGi2007 50ae719f24 Updatec core 2021-12-12 04:01:04 +00:00
coolGi2007 dccad778fb Updaterd core 2021-12-12 01:44:05 +00:00
tom lee f163e31cd2 WorldGen: Half fixed world gen
Note that currently world gen is single threaded. Below is the current
mapped settings:

BIOME_ONLY -> ChunkStatus.BIOMES : <1 tick
BIOME_ONLY_SIMULATE_HEIGHT -> ChunkStatus.NOISE : <1 tick
SURFACE -> ChunkStatus.SURFACE : <1 tick
FEATURE -> ChunkStatus.FEATURE : 1-2 tick
FULL -> ChunkStatus.FULL : ~ 1-10 tick (?? Probably because of the threaded light engine update)
2021-12-12 02:05:12 +08:00
coolGi2007 5499079ada Updated readme to say to install git 2021-12-11 10:36:25 +00:00
coolGi2007 8d1277db1b Fixed build not building 2021-12-11 09:15:38 +00:00
coolGi2007 34fcac25c2 Updated behind the scenes config stuff 2021-12-11 06:06:10 +00:00
coolGi2007 cb0516cae8 Updated core 2021-12-11 04:05:48 +00:00
cola98765 4fdad05252 Merge branch '1.18' into '1.18'
FIx lightmap flicker on pause menu

See merge request jeseibel/minecraft-lod-mod!12
2021-12-10 10:39:40 +00:00
tom lee dc785b4fe1 Bugfix: Pause menu flicker issue 2021-12-10 17:29:16 +08:00
coolGi2007 8df7e1762a Updated core 2021-12-10 05:22:18 +00:00
coolGi2007 43d9b41648 Updated readme & removed stuff from conig 2021-12-10 01:21:04 +00:00
coolGi2007 880559f94a Updated core 2021-12-10 01:07:27 +00:00
Morippi 6f04ddce87 added the get names 2021-12-09 16:10:47 +01:00
Ran 6eb065f7c9 We do a little bit of coring here 2021-12-09 17:00:34 +06:00
Ran 17ebad9141 Merge remote-tracking branch 'origin/1.18' into 1.18 2021-12-09 16:59:51 +06:00
coolGi2007 9bcc799b0b Fixed forge not building 2021-12-09 10:44:38 +00:00
Ran f247410ae4 We do a little bit of coring here 2021-12-09 16:38:45 +06:00
coolGi2007 2f3bb2ec34 Update readme to be more accurate with architectury 2021-12-09 06:27:24 +00:00
coolGi2007 5c47170ef4 Now uses Architectury and added Forge support 2021-12-09 06:14:30 +00:00
coolGi2007 29d152b312 Updated core (i really need to add a subproject) 2021-12-08 23:54:04 +00:00
coolGi2007 aa48f0f5c6 Might fix windows not working 2021-12-07 05:24:13 +00:00
coolGi2007 05ea683fcf Fixed build problem 2021-12-06 12:39:42 +00:00
coolGi2007 65163a2477 Update Readme.md 2021-12-06 11:43:42 +00:00
coolGi2007 9dc4c46b99 Initual upload to branch 2021-12-06 11:39:57 +00:00
176 changed files with 12482 additions and 3311 deletions
+4
View File
@@ -47,3 +47,7 @@ classes/
*.launch *.launch
**/src/generated/ **/src/generated/
Merged/
# file from notepad++
*.bak
+100
View File
@@ -0,0 +1,100 @@
# use Eclipse's JDK
image: gradle:eclipse-temurin
# all stages need to be defined here
stages:
- build_18-1
- build_18-2
# - zip_artifacts
variables:
# If we have correctness issues when compiling this can be set to false
GRADLE_OPTS: "-Dorg.gradle.daemon=true"
# Pull core when building
GIT_SUBMODULE_STRATEGY: recursive
before_script:
- echo $CI_JOB_ID
# Writing GE_JOB_ID variable to environment file, will need the value in the next stage.
- echo GE_JOB_ID=$CI_JOB_ID >> generate_jars.env
# 1.18.1 build
build_18-1:
stage: build_18-1
script: ./gradlew build -PmcVer=1.18.1 --gradle-user-home cache/; ./gradlew merge --gradle-user-home cache/
# build using Java 17
image: eclipse-temurin:17
cache:
key: "$CI_COMMIT_REF_NAME_18-1"
policy: pull-push
paths:
- .gradle
- cache/
# 1.18.2 build
build_18-2:
stage: build_18-2
script: ./gradlew build -PmcVer=1.18.2 --gradle-user-home cache/; ./gradlew merge --gradle-user-home cache/
# build using Java 17
image: eclipse-temurin:17
cache:
key: "$CI_COMMIT_REF_NAME_18-2"
policy: pull-push
paths:
- .gradle
- cache/
# TEMPORARY, there should be a way of either generating artifacts per build or in a separate stage
artifacts:
# This should only be done after the last build, otherwise there will be duplicate jars
name: "Merged_NightlyBuild-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
paths:
# relative to the root directory
- Merged
expire_in: 1 day
# # put artifacts in a zip
# # This should only be done after all the builds have been completed
# zip_artifacts:
# stage: zip_artifacts
# # The complier complains if we don't do something with the script line
# script: echo 'Building complete. Creating artifact Zip.'
# # build using Java 17
# image: eclipse-temurin:17
# artifacts:
# # This should only be done after the last build, otherwise there will be duplicate jars
# name: "Merged_NightlyBuild-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
# paths:
# # relative to the root directory
# - Merged
# expire_in: 1 day
# unused deployment stage
#deploy:
# stage: deploy
# image: registry.gitlab.com/gitlab-org/release-cli:latest
# script:
# - echo 'running release_job'
# - echo 'Previous Job ID is printed below'
# - echo $GE_JOB_ID
# # Specifying that this job requires artifacts from the previous job to succeed
# needs:
# - job: build
# artifacts: true
# release:
# name: 'Unstable Jars for Latest Commit' #: $CI_COMMIT_SHORT_SHA'
# description: 'Created automatically using the release-cli.'
# # tag_name is a mendatory field and can not be an empty string
# tag_name: 'Unstable-$CI_COMMIT_SHORT_SHA'
# assets:
# links:
# - name: 'Fabric Jars'
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/fabric/build/libs'
# - name: 'Forge Jars'
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/forge/build/libs'
+1
View File
@@ -1,3 +1,4 @@
[submodule "core"] [submodule "core"]
path = core path = core
url = https://gitlab.com/jeseibel/distant-horizons-core.git url = https://gitlab.com/jeseibel/distant-horizons-core.git
branch = main
+37
View File
@@ -0,0 +1,37 @@
# 1.18.1 version based stuff
minecraft_version=1.18.1
java_version = 17
# Fabric loader
fabric_loader_version=0.13.3
fabric_api_version=0.46.6+1.18
# Fabric mod versions
modmenu_version=3.0.1
starlight_version_fabric=3554912
lithium_version=mc1.18.1-0.7.7
sodium_version=3605309
iris_version=1.18.x-v1.1.4
bclib_version=1.2.5
immersive_portals_version = v1.0.4-1.18
# Fabric mod run
# 0 = Don't enable and don't run
# 1 = Can be referenced in code but doesn't run
# 2 = Can be referenced in code and runs in client
enable_starlight=0
enable_sodium=1
enable_lithium=0
enable_iris=0
enable_bclib=0
# Forge loader
forge_version=39.1.2
# Forge mod versions
starlight_version_forge=3559934
# Forge mod run
# 0 = Dont enable and don't run
# 1 = Can be referenced in code but doesn't run
# 2 = Can be referenced in code and runs in client
enable_starlight_forge=0
+38
View File
@@ -0,0 +1,38 @@
# 1.18.2 version based stuff
# architectury_plugin_version = 3.4-SNAPSHOT
# dev_architectury_loom_version = 0.10.0-SNAPSHOT
minecraft_version=1.18.2
java_version = 17
# Fabric loader
fabric_loader_version=0.13.3
fabric_api_version=0.48.0+1.18.2
# Fabric mod versions
modmenu_version=3.1.0
starlight_version_fabric=3667443
lithium_version=mc1.18.2-0.7.9
sodium_version=3669187
iris_version=1.18.x-v1.2.2
immersive_portals_version = v1.0.4-1.18
bclib_version=0
# Fabric mod run
# 0 = Don't enable and don't run
# 1 = Can be referenced in code but doesn't run
# 2 = Can be referenced in code and runs in client
enable_starlight=0
enable_sodium=1
enable_lithium=0
enable_iris=0
enable_bclib=0
# Forge loader
forge_version=40.0.18
# Forge mod versions
starlight_version_forge=0
# Forge mod run
# 0 = Dont enable and don't run
# 1 = Can be referenced in code but doesn't run
# 2 = Can be referenced in code and runs in client
enable_starlight_forge=0
+68 -27
View File
@@ -1,4 +1,9 @@
# Distant Horizons # <img src="https://gitlab.com/jeseibel/distant-horizons-core/-/raw/main/_logo%20files/LOD%20logo%20flat%20-%20with%20boarder.png" width="32"> Distant Horizons
> A mod that adds a Level of Detail System to Minecraft
# What is Distant Horizons?
This mod adds a Level Of Detail (LOD) system to Minecraft.\ This mod adds a Level Of Detail (LOD) system to Minecraft.\
This implementation renders simplified chunks outside the normal render distance\ This implementation renders simplified chunks outside the normal render distance\
@@ -9,48 +14,78 @@ If you want to see a quick demo, check out a video covering the mod here:
<a href="https://www.youtube.com/watch?v=H2tnvEVbO1c" target="_blank">![Minecraft Level Of Detail (LOD) mod - Alpha 1.5](https://i.ytimg.com/vi_webp/H2tnvEVbO1c/mqdefault.webp)</a> <a href="https://www.youtube.com/watch?v=H2tnvEVbO1c" target="_blank">![Minecraft Level Of Detail (LOD) mod - Alpha 1.5](https://i.ytimg.com/vi_webp/H2tnvEVbO1c/mqdefault.webp)</a>
Forge version: 37.1.0\ ### Versions
Fabric version: 0.11.6\
Fabric API version: 0.37.1+1.17 Architectury version: 3.4-SNAPSHOT\
Java Compiler plugin: Manifold Preprocessor
#### 1.18.2 mods
Forge version: 40.0.18\
Fabric version: 0.13.3\
Fabric API version: 0.48.0+1.18.2\
Modmenu version: 3.1.0
#### 1.18.1 mods
Forge version: 39.1.2\
Fabric version: 0.13.3\
Fabric API version: 0.46.6+1.18\
Modmenu version: 3.0.1
Notes:\ Notes:\
This version has been confirmed to work in Eclipse and Retail Minecraft.\ This version has been confirmed to work in IDE and Retail Minecraft.\
(Retail running forge version 1.17.1-37.1.0 and fabric version 1.17.1-0.11.6) (Retail running forge version 1.18.1-39.0.5 and fabric version 1.18-0.12.12 and 1.18.1-0.13.2)
## source code installation ## Source Code Installation
See the Forge Documentation online for more detailed instructions:\ See the Fabric Documentation online for more detailed instructions:\
http://mcforge.readthedocs.io/en/latest/gettingstarted/ https://fabricmc.net/wiki/tutorial:setup
### Prerequisites ### Prerequisites
* A Java Development Kit (JDK) for Java 16 (recommended) or newer. Visit https://adoptium.net/releases.html for installers. * A Java Development Kit (JDK) for Java 17 (recommended) or newer. Visit https://www.oracle.com/java/technologies/downloads/ for installers.
* Any Java IDE, for example Intellij IDEA and Eclipse. You may also use any other code editors, such as Visual Studio Code. * Git or someway to clone git projects. Visit https://git-scm.com/ for installers.
* (Not required) Any Java IDE with plugins that support Manifold, for example Intellij IDEA.
**If using Ecplise:**
1. run the command: `./gradlew geneclipseruns`
2. run the command: `./gradlew eclipse`
3. Make sure eclipse has the JDK 16 installed. (This is needed so that eclipse can run minecraft)
4. Import the project into eclipse
**If using IntelliJ:** **If using IntelliJ:**
0. Install Manifold plugin
1. open IDEA and import the build.gradle 1. open IDEA and import the build.gradle
2. run the command: `./gradlew genIntellijRuns` 2. refresh the Gradle project in IDEA if required
3. refresh the Gradle project in IDEA if required
**If using Ecplise: (Note that Eclispe currently doesn't support Manifold's preprocessor!)**
1. run the command: `./gradlew geneclipseruns`
2. run the command: `./gradlew eclipse`
3. Make sure eclipse has the JDK 17 installed. (This is needed so that eclipse can run minecraft)
4. Import the project into eclipse
## Switching Versions
This branch support 2 built versions:
- 1.18.2
- 1.18.1 (which also runs on 1.18)
To switch between active versions, change `mcVer=1.18.?` in `gradle.properties` file.
If running on IDE, to ensure IDE pickup the changed versions, you will need to run a gradle command again to allow gradle to update all the libs. (In IntellJ you will also need to do a gradle sync again if it didn't start it automatically.)
>Note: There may be a `java.nio.file.FileSystemException` thrown on running the command after switching versions. To fix it, either restart your IDE (as your IDE is locking up a file) or use tools like LockHunter to unlock the linked file. (Often a lib file under `common\build\lib` or `forge\build\lib` or `fabric\build\lib`). If anyone knows how to solve this issue please comment to this issue: https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/233
## Compiling ## Compiling
**Using GUI** **Using GUI**
1. open a command line in the project folder 1. Download the zip of the project and extract it
2. run the command: `./gradlew build` 2. Download the core from https://gitlab.com/jeseibel/distant-horizons-core and extract into a folder called `core`
3. the compiled jar file will be in the folder `fabric/build/libs/` and `forge/build/libs/` 3. Open a command line in the project folder
4. Run the command: `./gradlew assemble`
5. Then run command: `./gradlew mergeJars`
6. The compiled jar file will be in the folder `Merged`
**If in terminal:** **If in terminal:**
1. `git clone -b 1.17.1 --recurse-submodules https://gitlab.com/jeseibel/minecraft-lod-mod.git` 1. `git clone -b preprocessor_test --recurse-submodules https://gitlab.com/jeseibel/minecraft-lod-mod.git`
2. `cd minecraft-lod-mod` 2. `cd minecraft-lod-mod`
3. `./gradlew build` (must be run as root on linux) 3. `./gradlew assemble`
4. The build should be in `fabric/build/libs/` and `forge/build/libs/` 4. `./gradlew mergeJars`
5. The compiled jar file will be in the folder `Merged`
>Note: You can add the arg: `-PmcVer=1.18.?` to tell gradle to build a selected MC version instead of having to manually modify the `gradle.properties` file.
## Other commands ## Other commands
@@ -66,11 +101,17 @@ The Minecraft source code is NOT added to your workspace in an editable way. Min
Source code uses Mojang mappings. Source code uses Mojang mappings.
The source code can be 'created' with the `./eclipse` command and can be found in the following path:\ ## Useful commands
`minecraft-lod-mod\build\fg_cache\mcp\ VERSION \joined\ RANDOM_STRING \patch\output.jar`
Build only Fabric: `./gradlew fabric:assemble` or `./gradlew fabric:build`\
Build only Forge: `./gradlew fabric:assemble` or `./gradlew forge:build`\
Run the Fabric client (for debugging): `./gradlew fabric:runClient`\
Run the Forge client (for debugging): `./gradlew forge:runClient`
## Open Source Acknowledgements ## Open Source Acknowledgements
XZ for Java (data compression)\ XZ for Java (data compression)\
https://tukaani.org/xz/java.html https://tukaani.org/xz/java.html
DHJarMerger (To merge multiple mod versions into one jar)\
https://github.com/Ran-helo/DHJarMerger
-390
View File
@@ -1,390 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="21">
<profile kind="CodeFormatterProfile" name="Eclipse (James' Edit)" version="21">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_with_spaces" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_before_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_switch_case_expressions" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_record_components" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_multiplicative_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_logical_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_annotation_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_abstract_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_constant_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.align_variable_declarations_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiplicative_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.keep_anonymous_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_switch_case_expressions" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_shift_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_loops" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_for_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_enum_constant" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.text_block_indentation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_names_descriptions" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_if_then_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_assignment_statements_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression_chain" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_annotations" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assertion_message_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_bitwise_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_not_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_package" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_record_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_bitwise_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_tag_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_constructor" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_string_concatenation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_shift_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_do_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_record_components" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_additive_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_getter_setter_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_record_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_end_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.align_tags_descriptions_grouped" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.keep_method_body_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_loop_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_type_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_additive_operator" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_constructor" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_relational_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_parameter" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_relational_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="99"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_string_concatenation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_record_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_after_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_type" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_local_variable" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_arrow_in_switch_default" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_between_different_tags" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_additive_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_field" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_shift_operator" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.keep_code_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_record_components" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_bitwise_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_record_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_lambda_body_block_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_annotations_on_method" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_record_constructor_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_record_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assertion_message" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_logical_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_record_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_relational_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_last_class_body_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.keep_simple_while_body_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_logical_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_statement_group_in_switch" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_enum_declaration_on_one_line" value="one_line_never"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="next_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_multiplicative_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_code_block" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="tab"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_string_concatenation" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="1200"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>
-11
View File
@@ -1,11 +0,0 @@
These Files are used when developing the mod.
Eclipse Auto Formatting
IntelliJ Auto Formatting
- These files are the auto-formatting settings that should be used when developing for the mod. We want to make sure the style of code is consistant regardless of who is writting the code.
renderDocMcDistantHorizonsSettings
- This file contains the configuration to run a remote debug instance so you can edit the mod in your IDE while also viewing the OpenGL code in RenderDoc.
minecraft launch options
- This file contains the Java command line arguments used to launch the mod from a development environment (specifically Eclipse, James didn't test it with IntelliJ), and is included to more easily edit the options for RenderDoc
@@ -1,50 +0,0 @@
<code_scheme name="Eclipse (James' Edit)" version="173">
<option name="RIGHT_MARGIN" value="1200" />
<JavaCodeStyleSettings>
<option name="JD_ALIGN_PARAM_COMMENTS" value="false" />
<option name="JD_ALIGN_EXCEPTION_COMMENTS" value="false" />
<option name="JD_ADD_BLANK_AFTER_DESCRIPTION" value="false" />
<option name="JD_P_AT_EMPTY_LINES" value="false" />
<option name="JD_KEEP_INVALID_TAGS" value="false" />
<option name="JD_DO_NOT_WRAP_ONE_LINE_COMMENTS" value="true" />
<option name="JD_KEEP_EMPTY_PARAMETER" value="false" />
<option name="JD_KEEP_EMPTY_EXCEPTION" value="false" />
<option name="JD_KEEP_EMPTY_RETURN" value="false" />
</JavaCodeStyleSettings>
<codeStyleSettings language="JAVA">
<option name="KEEP_CONTROL_STATEMENT_IN_ONE_LINE" value="false" />
<option name="KEEP_BLANK_LINES_IN_DECLARATIONS" value="10" />
<option name="KEEP_BLANK_LINES_IN_CODE" value="10" />
<option name="KEEP_BLANK_LINES_BEFORE_RBRACE" value="10" />
<option name="BLANK_LINES_BEFORE_PACKAGE" value="1" />
<option name="BRACE_STYLE" value="2" />
<option name="CLASS_BRACE_STYLE" value="2" />
<option name="METHOD_BRACE_STYLE" value="2" />
<option name="ELSE_ON_NEW_LINE" value="true" />
<option name="WHILE_ON_NEW_LINE" value="true" />
<option name="CATCH_ON_NEW_LINE" value="true" />
<option name="FINALLY_ON_NEW_LINE" value="true" />
<option name="INDENT_CASE_FROM_SWITCH" value="false" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_RESOURCES" value="false" />
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true" />
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
<option name="CALL_PARAMETERS_WRAP" value="1" />
<option name="METHOD_PARAMETERS_WRAP" value="1" />
<option name="RESOURCE_LIST_WRAP" value="5" />
<option name="EXTENDS_LIST_WRAP" value="1" />
<option name="THROWS_LIST_WRAP" value="1" />
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
<option name="THROWS_KEYWORD_WRAP" value="1" />
<option name="METHOD_CALL_CHAIN_WRAP" value="1" />
<option name="TERNARY_OPERATION_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_WRAP" value="1" />
<option name="METHOD_ANNOTATION_WRAP" value="0" />
<option name="CLASS_ANNOTATION_WRAP" value="0" />
<option name="FIELD_ANNOTATION_WRAP" value="0" />
<indentOptions>
<option name="USE_TAB_CHARACTER" value="true" />
<option name="KEEP_INDENTS_ON_EMPTY_LINES" value="true" />
</indentOptions>
</codeStyleSettings>
</code_scheme>
Binary file not shown.
File diff suppressed because one or more lines are too long
Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 191 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 B

+139 -5
View File
@@ -1,8 +1,44 @@
import io.github.ran.jarmerger.JarMergerPlugin
buildscript {
dependencies{
classpath files('plugins/DHJarMerger-1.0.jar')
}
}
plugins { plugins {
id "architectury-plugin" version "3.4-SNAPSHOT" id "architectury-plugin" version "3.4-SNAPSHOT"
id "dev.architectury.loom" version "0.10.0.195" apply false id "dev.architectury.loom" version "0.10.0-SNAPSHOT" apply false
} }
def writeBuildGradlePredefine() {
def excapedMCVersion = rootProject.minecraft_version.replace(".", "_")
new File(projectDir, "build.properties").text = "MC_VERSION_${excapedMCVersion}=\n"
}
def loadProperties() {
def defaultMcVersion = '1.18.2'
if (!project.hasProperty("mcVer")) {
println "No mcVer set! Defaulting to ${defaultMcVersion}."
println "Tip: Use -PmcVer='${defaultMcVersion}' in cmd arg to set mcVer."
}
def mcVersion = project.hasProperty("mcVer") ? mcVer : defaultMcVersion
println "Loading properties file at " + mcVersion + ".properties"
def props = new Properties()
props.load(new FileInputStream("$rootProject.rootDir/"+"$mcVersion"+".properties"))
props.each { prop ->
rootProject.ext.set(prop.key, prop.value)
// println "Added prop [key:" + prop.key + ", value:" + prop.value + "]"
}
writeBuildGradlePredefine()
}
loadProperties()
apply plugin: JarMergerPlugin
architectury { architectury {
minecraft = rootProject.minecraft_version minecraft = rootProject.minecraft_version
} }
@@ -25,21 +61,34 @@ subprojects { p ->
// The following line declares the mojmap mappings // The following line declares the mojmap mappings
mappings loom.officialMojangMappings() mappings loom.officialMojangMappings()
//Manifold
annotationProcessor "systems.manifold:manifold-preprocessor:${rootProject.manifold_version}"
// Toml
implementation("com.electronwill.night-config:toml:${rootProject.toml_version}")
if (p != project(":forge")) { if (p != project(":forge")) {
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
// Do NOT use other classes from fabric loader unless working with fabric // Do NOT use other classes from fabric loader unless working with fabric
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
} }
if (p != project(":core")) { if (p != project(":core")) {
common(project(":core")) { transitive false } common(project(":core")) { transitive false }
shadowMe(project(":core")) { transitive false } shadowMe(project(":core")) { transitive false }
} }
} }
jar {
manifest {
attributes 'Implementation-Title': rootProject.archives_base_name,
'Implementation-Version': rootProject.mod_version,
'Main-Class': 'com.seibel.lod.core.JarMain'
}
}
} }
allprojects { allprojects { p ->
apply plugin: "java" apply plugin: "java"
apply plugin: "architectury-plugin" apply plugin: "architectury-plugin"
apply plugin: "maven-publish" apply plugin: "maven-publish"
@@ -52,14 +101,99 @@ allprojects {
mavenCentral() mavenCentral()
// used to download and compile dependencies from git repos // used to download and compile dependencies from git repos
maven { url 'https://jitpack.io' } maven { url 'https://jitpack.io' }
// For Manifold Preprocessor
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
// Required for importing Modrinth mods
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
content {
includeGroup "maven.modrinth"
}
}
// Required for importing CursedForge mods
maven {
url "https://www.cursemaven.com"
content {
includeGroup "curse.maven"
}
}
// These 2 are for importing mods that arnt on CursedForge, Modrinth, GitHub, GitLab or anywhere opensource
flatDir {
dirs "${rootDir}/mods/fabric"
content {
includeGroup "fabric-mod"
}
}
flatDir {
dirs "${rootDir}/mods/forge"
content {
includeGroup "forge-mod"
}
}
} }
// Put stuff from gradle.properties into the mod info
processResources {
def resourceTargets = ["fabric.mod.json", "META-INF/mods.toml"] // Location of where to put
def intoTargets = ["$buildDir/resources/main/"] // Location of the built resources folder
def replaceProperties = [
version: mod_version,
mod_name: mod_name,
authors: mod_authors,
description: mod_description,
homepage: mod_homepage,
source: mod_source,
issues: mod_issues,
minecraft_version: minecraft_version,
java_version: java_version
] // The left side is what gets replaced in the mod info and the right side is where to get it from in the gradle.properties
//TODO: Make Forge loader version also be relaced with non hardcoded value instead of "[36,41)"
inputs.properties replaceProperties
replaceProperties.put 'project', project
filesMatching(resourceTargets) {
expand replaceProperties
}
intoTargets.each { target ->
if (file(target).exists()) {
copy {
from(sourceSets.main.resources) {
include resourceTargets
expand replaceProperties
}
into target
}
}
}
}
tasks.withType(JavaCompile) { tasks.withType(JavaCompile) {
options.encoding = "UTF-8" // Add Manifold Preprocessor
options.release = 16 // def excapedMCVersion = rootProject.minecraft_version.replace(".", "_")
// options.compilerArgs += ['-Xplugin:Manifold', "-AMC_VERSION_${excapedMCVersion}"]
//
options.compilerArgs += ['-Xplugin:Manifold']
// println options.compilerArgs
if (p != project(":core")) {
options.release = rootProject.java_version as Integer
}
} }
java { java {
withSourcesJar() withSourcesJar()
} }
if (p == project(":core") || p == project(":common")) {
runClient.enabled = false
runServer.enabled = false
}
} }
+1
View File
@@ -0,0 +1 @@
MC_VERSION_1_18_2=
@@ -19,20 +19,26 @@
package com.seibel.lod.common; package com.seibel.lod.common;
import com.seibel.lod.common.wrappers.config.ConfigGui; import com.seibel.lod.core.config.*;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.enums.config.*; import com.seibel.lod.core.enums.config.*;
import com.seibel.lod.core.enums.rendering.*; import com.seibel.lod.core.enums.rendering.*;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.*; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.*;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.*; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.*;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IFogQuality.IAdvancedFog;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IFogQuality.IAdvancedFog.IHeightFog;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IMultiplayer;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IWorldGenerator; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IWorldGenerator;
/** /**
* This handles any configuration the user has access to. * This handles any configuration the user has access to.
* @author coolGi2007 * @author coolGi2007
* @version 12-02-2021 * @version 12-12-2021
*/ */
public class Config extends ConfigGui
public class Config
//public class Config extends TinyConfig
{ {
// CONFIG STRUCTURE // CONFIG STRUCTURE
// -> Client // -> Client
@@ -51,185 +57,344 @@ public class Config extends ConfigGui
// Since the original config system uses forge stuff, that means we have to rewrite the whole config system // Since the original config system uses forge stuff, that means we have to rewrite the whole config system
@ScreenEntry(to = "client") @ConfigAnnotations.ScreenEntry
public static ScreenEntry client; public static Client client;
@ConfigAnnotations.FileComment
public static String _optionsButton = ILodConfigWrapperSingleton.IClient.OPTIONS_BUTTON_DESC;
// I know this option should be in Client
// This is a hacky method to not show the button in the options screen but show it in the mod menu
// Tough it is in client in the wrapper singleton
@ConfigAnnotations.Entry
public static boolean optionsButton = true;
public static class Client public static class Client
{ {
@Category("client") @ConfigAnnotations.ScreenEntry
@ScreenEntry(to = "graphics") public static Graphics graphics;
public static ScreenEntry graphics;
@Category("client") @ConfigAnnotations.ScreenEntry
@ScreenEntry(to = "worldGenerator") public static WorldGenerator worldGenerator;
public static ScreenEntry worldGenerator;
@Category("client") @ConfigAnnotations.ScreenEntry
@ScreenEntry(to = "advanced") public static Multiplayer multiplayer;
public static ScreenEntry advanced;
@ConfigAnnotations.ScreenEntry
public static Advanced advanced;
public static class Graphics public static class Graphics
{ {
@Category("client.graphics") @ConfigAnnotations.ScreenEntry
@ScreenEntry(to = "quality") public static Quality quality;
public static ScreenEntry quality;
@Category("client.graphics") @ConfigAnnotations.ScreenEntry
@ScreenEntry(to = "fogQuality") public static FogQuality fogQuality;
public static ScreenEntry fogQuality;
@Category("client.graphics") @ConfigAnnotations.ScreenEntry
@ScreenEntry(to = "advancedGraphics") public static AdvancedGraphics advancedGraphics;
public static ScreenEntry advancedGraphics;
public static class Quality public static class Quality
{ {
@Category("client.graphics.quality") @ConfigAnnotations.FileComment
@Entry public static String _drawResolution = IQuality.DRAW_RESOLUTION_DESC;
@ConfigAnnotations.Entry
public static HorizontalResolution drawResolution = IQuality.DRAW_RESOLUTION_DEFAULT; public static HorizontalResolution drawResolution = IQuality.DRAW_RESOLUTION_DEFAULT;
@Category("client.graphics.quality") @ConfigAnnotations.FileComment
@Entry(min = 16, max = 1024) public static String _lodChunkRenderDistance = IQuality.LOD_CHUNK_RENDER_DISTANCE_DESC;
@ConfigAnnotations.Entry(minValue = 16, maxValue = 2048)
public static int lodChunkRenderDistance = IQuality.LOD_CHUNK_RENDER_DISTANCE_MIN_DEFAULT_MAX.defaultValue; public static int lodChunkRenderDistance = IQuality.LOD_CHUNK_RENDER_DISTANCE_MIN_DEFAULT_MAX.defaultValue;
@Category("client.graphics.quality") @ConfigAnnotations.FileComment
@Entry public static String _verticalQuality = IQuality.VERTICAL_QUALITY_DESC;
@ConfigAnnotations.Entry
public static VerticalQuality verticalQuality = IQuality.VERTICAL_QUALITY_DEFAULT; public static VerticalQuality verticalQuality = IQuality.VERTICAL_QUALITY_DEFAULT;
@Category("client.graphics.quality") @ConfigAnnotations.FileComment
@Entry(min = 2, max = 32) public static String _horizontalScale = IQuality.HORIZONTAL_SCALE_DESC;
@ConfigAnnotations.Entry(minValue = 2, maxValue = 32)
public static int horizontalScale = IQuality.HORIZONTAL_SCALE_MIN_DEFAULT_MAX.defaultValue; public static int horizontalScale = IQuality.HORIZONTAL_SCALE_MIN_DEFAULT_MAX.defaultValue;
@Category("client.graphics.quality") @ConfigAnnotations.FileComment
@Entry public static String _horizontalQuality = IQuality.HORIZONTAL_SCALE_DESC;
@ConfigAnnotations.Entry
public static HorizontalQuality horizontalQuality = IQuality.HORIZONTAL_QUALITY_DEFAULT; public static HorizontalQuality horizontalQuality = IQuality.HORIZONTAL_QUALITY_DEFAULT;
@ConfigAnnotations.FileComment
public static String _dropoffQuality = IQuality.DROPOFF_QUALITY_DESC;
@ConfigAnnotations.Entry
public static DropoffQuality dropoffQuality = IQuality.DROPOFF_QUALITY_DEFAULT;
@ConfigAnnotations.FileComment
public static String _lodBiomeBlending = IQuality.LOD_BIOME_BLENDING_DESC;
@ConfigAnnotations.Entry(minValue = 0, maxValue = 7)
public static int lodBiomeBlending = IQuality.LOD_BIOME_BLENDING_MIN_DEFAULT_MAX.defaultValue;
} }
public static class FogQuality public static class FogQuality
{ {
@Category("client.graphics.fogQuality") @ConfigAnnotations.FileComment
@Entry public static String _fogDistance = IFogQuality.FOG_DISTANCE_DESC;
@ConfigAnnotations.Entry
public static FogDistance fogDistance = IFogQuality.FOG_DISTANCE_DEFAULT; public static FogDistance fogDistance = IFogQuality.FOG_DISTANCE_DEFAULT;
@Category("client.graphics.fogQuality") @ConfigAnnotations.FileComment
@Entry public static String _fogDrawMode = IFogQuality.FOG_DRAW_MODE_DESC;
@ConfigAnnotations.Entry
public static FogDrawMode fogDrawMode = IFogQuality.FOG_DRAW_MODE_DEFAULT; public static FogDrawMode fogDrawMode = IFogQuality.FOG_DRAW_MODE_DEFAULT;
@Category("client.graphics.fogQuality") @ConfigAnnotations.FileComment
@Entry public static String _fogColorMode = IFogQuality.FOG_COLOR_MODE_DESC;
@ConfigAnnotations.Entry
public static FogColorMode fogColorMode = IFogQuality.FOG_COLOR_MODE_DEFAULT; public static FogColorMode fogColorMode = IFogQuality.FOG_COLOR_MODE_DEFAULT;
@Category("client.graphics.fogQuality") @ConfigAnnotations.FileComment
@Entry public static String _disableVanillaFog = IFogQuality.DISABLE_VANILLA_FOG_DESC;
@ConfigAnnotations.Entry
public static boolean disableVanillaFog = IFogQuality.DISABLE_VANILLA_FOG_DEFAULT; public static boolean disableVanillaFog = IFogQuality.DISABLE_VANILLA_FOG_DEFAULT;
@ConfigAnnotations.ScreenEntry
public static AdvancedFog advancedFog;
public static class AdvancedFog {
static final double SQRT2 = 1.4142135623730951;
@ConfigAnnotations.FileComment
public static String _farFogStart = IAdvancedFog.FAR_FOG_START_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
public static double farFogStart = IAdvancedFog.FAR_FOG_START_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _farFogEnd = IAdvancedFog.FAR_FOG_END_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
public static double farFogEnd = IAdvancedFog.FAR_FOG_END_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _farFogMin = IAdvancedFog.FAR_FOG_MIN_DESC;
@ConfigAnnotations.Entry(minValue = -5.0, maxValue = SQRT2)
public static double farFogMin = IAdvancedFog.FAR_FOG_MIN_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _farFogMax = IAdvancedFog.FAR_FOG_MAX_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = 5.0)
public static double farFogMax = IAdvancedFog.FAR_FOG_MAX_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _farFogType = IAdvancedFog.FAR_FOG_TYPE_DESC;
@ConfigAnnotations.Entry
public static FogSetting.FogType farFogType = IAdvancedFog.FAR_FOG_TYPE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _farFogDensity = IAdvancedFog.FAR_FOG_DENSITY_DESC;
@ConfigAnnotations.Entry(minValue = 0.01, maxValue = 50.0)
public static double farFogDensity = IAdvancedFog.FAR_FOG_DENSITY_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.ScreenEntry
public static HeightFog heightFog;
public static class HeightFog {
@ConfigAnnotations.FileComment
public static String _heightFogMixMode = IHeightFog.HEIGHT_FOG_MIX_MODE_DESC;
@ConfigAnnotations.Entry
public static HeightFogMixMode heightFogMixMode = IHeightFog.HEIGHT_FOG_MIX_MODE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _heightFogMode = IHeightFog.HEIGHT_FOG_MODE_DESC;
@ConfigAnnotations.Entry
public static HeightFogMode heightFogMode = IHeightFog.HEIGHT_FOG_MODE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _heightFogHeight = IHeightFog.HEIGHT_FOG_HEIGHT_DESC;
@ConfigAnnotations.Entry(minValue = -4096.0, maxValue = 4096.0)
public static double heightFogHeight = IHeightFog.HEIGHT_FOG_HEIGHT_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _heightFogStart = IHeightFog.HEIGHT_FOG_START_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
public static double heightFogStart = IHeightFog.HEIGHT_FOG_START_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _heightFogEnd = IHeightFog.HEIGHT_FOG_END_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
public static double heightFogEnd = IHeightFog.HEIGHT_FOG_END_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _heightFogMin = IHeightFog.HEIGHT_FOG_MIN_DESC;
@ConfigAnnotations.Entry(minValue = -5.0, maxValue = SQRT2)
public static double heightFogMin = IHeightFog.HEIGHT_FOG_MIN_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _heightFogMax = IHeightFog.HEIGHT_FOG_MAX_DESC;
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = 5.0)
public static double heightFogMax = IHeightFog.HEIGHT_FOG_MAX_MIN_DEFAULT_MAX.defaultValue;
@ConfigAnnotations.FileComment
public static String _heightFogType = IHeightFog.HEIGHT_FOG_TYPE_DESC;
@ConfigAnnotations.Entry
public static FogSetting.FogType heightFogType = IHeightFog.HEIGHT_FOG_TYPE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _heightFogDensity = IHeightFog.HEIGHT_FOG_DENSITY_DESC;
@ConfigAnnotations.Entry(minValue = 0.01, maxValue = 50.0)
public static double heightFogDensity = IHeightFog.HEIGHT_FOG_DENSITY_MIN_DEFAULT_MAX.defaultValue;
}
}
} }
public static class AdvancedGraphics public static class AdvancedGraphics
{ {
@Category("client.graphics.advancedGraphics") @ConfigAnnotations.FileComment
@Entry public static String _disableDirectionalCulling = IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DESC;
public static LodTemplate lodTemplate = IAdvancedGraphics.LOD_TEMPLATE_DEFAULT; @ConfigAnnotations.Entry
@Category("client.graphics.advancedGraphics")
@Entry
public static boolean disableDirectionalCulling = IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DEFAULT; public static boolean disableDirectionalCulling = IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DEFAULT;
@Category("client.graphics.advancedGraphics") @ConfigAnnotations.FileComment
@Entry public static String _vanillaOverdraw = IAdvancedGraphics.VANILLA_OVERDRAW_DESC;
public static boolean alwaysDrawAtMaxQuality = IAdvancedGraphics.ALWAYS_DRAW_AT_MAD_QUALITY_DEFAULT; @ConfigAnnotations.Entry
@Category("client.graphics.advancedGraphics")
@Entry
public static VanillaOverdraw vanillaOverdraw = IAdvancedGraphics.VANILLA_OVERDRAW_DEFAULT; public static VanillaOverdraw vanillaOverdraw = IAdvancedGraphics.VANILLA_OVERDRAW_DEFAULT;
@Category("client.graphics.advancedGraphics") @ConfigAnnotations.FileComment
@Entry public static String _useExtendedNearClipPlane = IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DESC;
@ConfigAnnotations.Entry
public static boolean useExtendedNearClipPlane = IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DEFAULT; public static boolean useExtendedNearClipPlane = IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _brightnessMultiplier = IAdvancedGraphics.BRIGHTNESS_MULTIPLIER_DESC;
@ConfigAnnotations.Entry
public static double brightnessMultiplier = IAdvancedGraphics.BRIGHTNESS_MULTIPLIER_DEFAULT;
@ConfigAnnotations.FileComment
public static String _saturationMultiplier = IAdvancedGraphics.SATURATION_MULTIPLIER_DESC;
@ConfigAnnotations.Entry
public static double saturationMultiplier = IAdvancedGraphics.SATURATION_MULTIPLIER_DEFAULT;
/*
@ConfigAnnotations.FileComment
public static String _backsideCullingRange = IAdvancedGraphics.VANILLA_CULLING_RANGE_DESC;
@ConfigAnnotations.Entry(minValue = 0, maxValue = 512)
public static int backsideCullingRange = IAdvancedGraphics.VANILLA_CULLING_RANGE_MIN_DEFAULT_MAX.defaultValue;
*/
} }
} }
public static class WorldGenerator public static class WorldGenerator
{ {
@Category("client.worldGenerator") @ConfigAnnotations.FileComment
@Entry public static String _enableDistantGeneration = IWorldGenerator.ENABLE_DISTANT_GENERATION_DESC;
public static GenerationPriority generationPriority = IWorldGenerator.GENERATION_PRIORITY_DEFAULT; @ConfigAnnotations.Entry
public static boolean enableDistantGeneration = IWorldGenerator.ENABLE_DISTANT_GENERATION_DEFAULT;
@Category("client.worldGenerator") // @ConfigAnnotations.FileComment
@Entry // public static String _distanceGenerationMode = IWorldGenerator.getDistanceGenerationModeDesc();
@ConfigAnnotations.Entry
public static DistanceGenerationMode distanceGenerationMode = IWorldGenerator.DISTANCE_GENERATION_MODE_DEFAULT; public static DistanceGenerationMode distanceGenerationMode = IWorldGenerator.DISTANCE_GENERATION_MODE_DEFAULT;
@Category("client.worldGenerator") @ConfigAnnotations.FileComment
@Entry public static String _lightGenerationMode = IWorldGenerator.LIGHT_GENERATION_MODE_DESC;
public static boolean allowUnstableFeatureGeneration = IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT; @ConfigAnnotations.Entry
public static LightGenerationMode lightGenerationMode = IWorldGenerator.LIGHT_GENERATION_MODE_DEFAULT;
@Category("client.worldGenerator") @ConfigAnnotations.FileComment
@Entry public static String _generationPriority = IWorldGenerator.GENERATION_PRIORITY_DESC;
@ConfigAnnotations.Entry
public static GenerationPriority generationPriority = IWorldGenerator.GENERATION_PRIORITY_DEFAULT;
/*
@ConfigAnnotations.FileComment
public static String _allowUnstableFeatureGeneration = IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DESC;
// FIXME: Temperary override. In 1.18, the newer Unstable gnerator is more usable
@ConfigAnnotations.Entry
public static boolean allowUnstableFeatureGeneration = true;//IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT;
*/
@ConfigAnnotations.FileComment
public static String _blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DESC;
@ConfigAnnotations.Entry
public static BlocksToAvoid blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DEFAULT; public static BlocksToAvoid blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DEFAULT;
// public static boolean useExperimentalPreGenLoading = false;
} }
public static class Multiplayer
{
@ConfigAnnotations.FileComment
public static String _serverFolderNameMode = IMultiplayer.SERVER_FOLDER_NAME_MODE_DESC;
@ConfigAnnotations.Entry
public static ServerFolderNameMode serverFolderNameMode = IMultiplayer.SERVER_FOLDER_NAME_MODE_DEFAULT;
@ConfigAnnotations.FileComment
public static String _multiDimensionRequiredSimilarity = IMultiplayer.MULTI_DIMENSION_REQUIRED_SIMILARITY_DESC;
@ConfigAnnotations.Entry
public static double multiDimensionRequiredSimilarity = IMultiplayer.MULTI_DIMENSION_REQUIRED_SIMILARITY_DEFAULT;
}
public static class Advanced public static class Advanced
{ {
@Category("client.advanced") @ConfigAnnotations.ScreenEntry
@ScreenEntry(to = "threading") public static Threading threading;
public static ScreenEntry threading;
@Category("client.advanced") @ConfigAnnotations.ScreenEntry
@ScreenEntry(to = "debugging") public static Debugging debugging;
public static ScreenEntry debugging;
@Category("client.advanced") @ConfigAnnotations.ScreenEntry
@ScreenEntry(to = "buffers") public static Buffers buffers;
public static ScreenEntry buffers;
public static class Threading public static class Threading
{ {
@Category("client.advanced.threading") @ConfigAnnotations.FileComment
@Entry(min = 1, max = 50) public static String _numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DESC;
@ConfigAnnotations.Entry(minValue = 1, maxValue = 50)
public static int numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DEFAULT.defaultValue; public static int numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DEFAULT.defaultValue;
@Category("client.advanced.threading") @ConfigAnnotations.FileComment
@Entry(min = 1, max = 50) public static String _numberOfBufferBuilderThreads = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_DESC;
@ConfigAnnotations.Entry(minValue = 1, maxValue = 50)
public static int numberOfBufferBuilderThreads = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX.defaultValue; public static int numberOfBufferBuilderThreads = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX.defaultValue;
} }
public static class Debugging public static class Debugging
{ {
@Category("client.advanced.debugging") @ConfigAnnotations.FileComment
@Entry public static String _drawLods = IDebugging.DRAW_LODS_DESC;
@ConfigAnnotations.Entry
public static boolean drawLods = IDebugging.DRAW_LODS_DEFAULT; public static boolean drawLods = IDebugging.DRAW_LODS_DEFAULT;
@Category("client.advanced.debugging") @ConfigAnnotations.FileComment
@Entry public static String _debugMode = IDebugging.DEBUG_MODE_DESC;
@ConfigAnnotations.Entry
public static DebugMode debugMode = IDebugging.DEBUG_MODE_DEFAULT; public static DebugMode debugMode = IDebugging.DEBUG_MODE_DEFAULT;
@Category("client.advanced.debugging") @ConfigAnnotations.FileComment
@Entry public static String _enableDebugKeybindings = IDebugging.DEBUG_KEYBINDINGS_ENABLED_DESC;
@ConfigAnnotations.Entry
public static boolean enableDebugKeybindings = IDebugging.DEBUG_KEYBINDINGS_ENABLED_DEFAULT; public static boolean enableDebugKeybindings = IDebugging.DEBUG_KEYBINDINGS_ENABLED_DEFAULT;
} }
public static class Buffers public static class Buffers
{ {
@Category("client.advanced.buffers") @ConfigAnnotations.FileComment
@Entry public static String _gpuUploadMethod = IBuffers.GPU_UPLOAD_METHOD_DESC;
@ConfigAnnotations.Entry
public static GpuUploadMethod gpuUploadMethod = IBuffers.GPU_UPLOAD_METHOD_DEFAULT; public static GpuUploadMethod gpuUploadMethod = IBuffers.GPU_UPLOAD_METHOD_DEFAULT;
@Category("client.advanced.buffers") @ConfigAnnotations.FileComment
@Entry(min = 0, max = 5000) public static String _gpuUploadPerMegabyteInMilliseconds = IBuffers.GPU_UPLOAD_PER_MEGABYTE_IN_MILLISECONDS_DESC;
public static int gpuUploadTimeoutInMilleseconds = IBuffers.GPU_UPLOAD_TIMEOUT_IN_MILLISECONDS_DEFAULT.defaultValue; @ConfigAnnotations.Entry(minValue = 0, maxValue = 50)
public static int gpuUploadPerMegabyteInMilliseconds = IBuffers.GPU_UPLOAD_PER_MEGABYTE_IN_MILLISECONDS_DEFAULT.defaultValue;
@Category("client.advanced.buffers") @ConfigAnnotations.FileComment
@Entry public static String _rebuildTimes = IBuffers.REBUILD_TIMES_DESC;
@ConfigAnnotations.Entry
public static BufferRebuildTimes rebuildTimes = IBuffers.REBUILD_TIMES_DEFAULT; public static BufferRebuildTimes rebuildTimes = IBuffers.REBUILD_TIMES_DEFAULT;
} }
} }
@@ -1,9 +1,9 @@
package com.seibel.lod.common; package com.seibel.lod.common;
import com.seibel.lod.common.forge.LodForgeMethodCaller; import com.seibel.lod.common.forge.LodForgeMethodCaller;
import com.seibel.lod.common.networking.NetworkInterface;
import com.seibel.lod.common.wrappers.DependencySetup; import com.seibel.lod.common.wrappers.DependencySetup;
import com.seibel.lod.common.wrappers.config.ConfigGui; import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.core.ModInfo;
/** /**
* This is the common main class * This is the common main class
@@ -11,30 +11,29 @@ import com.seibel.lod.core.ModInfo;
*/ */
public class LodCommonMain { public class LodCommonMain {
public static boolean forge = false; public static boolean forge = false;
public static boolean serverSided;
public static LodForgeMethodCaller forgeMethodCaller; public static LodForgeMethodCaller forgeMethodCaller;
public static NetworkInterface networkInterface;
public static void startup(LodForgeMethodCaller caller) { public static void startup(LodForgeMethodCaller caller, boolean serverSided, NetworkInterface networkInterface) {
LodCommonMain.serverSided = serverSided;
if (caller != null) { if (caller != null) {
LodCommonMain.forge = true; LodCommonMain.forge = true;
forgeMethodCaller = caller; forgeMethodCaller = caller;
} }
DependencySetup.createInitialBindings(); DependencySetup.createInitialBindings();
LodCommonMain.networkInterface = networkInterface;
if (!serverSided) {
networkInterface.register_Client();
} else {
networkInterface.register_Server();
}
} }
// TODO[CONFIG]: Find a better way to initialise everything
public static void initConfig() { public static void initConfig() {
ConfigGui.init(ModInfo.ID, Config.class); ConfigGui.init(Config.class);
ConfigGui.init(ModInfo.ID, Config.Client.class);
ConfigGui.init(ModInfo.ID, Config.Client.Graphics.class);
ConfigGui.init(ModInfo.ID, Config.Client.Graphics.Quality.class);
ConfigGui.init(ModInfo.ID, Config.Client.Graphics.FogQuality.class);
ConfigGui.init(ModInfo.ID, Config.Client.Graphics.AdvancedGraphics.class);
ConfigGui.init(ModInfo.ID, Config.Client.WorldGenerator.class);
ConfigGui.init(ModInfo.ID, Config.Client.Advanced.class);
ConfigGui.init(ModInfo.ID, Config.Client.Advanced.Threading.class);
ConfigGui.init(ModInfo.ID, Config.Client.Advanced.Debugging.class);
ConfigGui.init(ModInfo.ID, Config.Client.Advanced.Buffers.class);
} }
} }
@@ -1,6 +1,6 @@
package com.seibel.lod.common.forge; package com.seibel.lod.common.forge;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper; import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
import net.minecraft.client.renderer.block.model.BakedQuad; import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
@@ -9,6 +9,11 @@ import net.minecraft.world.level.block.state.BlockState;
import java.util.List; import java.util.List;
import java.util.Random; import java.util.Random;
/**
* used for calling methods that forge modified
* (forge modifies vanilla methods for some reason)
* @author Ran
*/
public interface LodForgeMethodCaller { public interface LodForgeMethodCaller {
List<BakedQuad> getQuads(MinecraftWrapper mc, Block block, BlockState blockState, Direction direction, Random random); List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random);
} }
@@ -0,0 +1,30 @@
package com.seibel.lod.common.networking;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
/**
* This is packet handler for our mod
* It basically handles the packets sent from the server & client
*
* @author Ran
*/
public class NetworkHandler {
// If you need the response sender then tell me
// I'll add extra code to get the response sender
public static void receivePacketClient(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf) {
// TODO: Server sided stuff here
// You can make client execute something by using client.execute(Runnable)
// In the fabric docs it says that client.execute is ran on the render thread?
}
// If you need the response sender then tell me
// I'll add extra code to get the response sender
public static void receivePacketServer(MinecraftServer server, ServerPlayer client, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf) {
// TODO: Server sided stuff here
}
}
@@ -0,0 +1,9 @@
package com.seibel.lod.common.networking;
/**
* @author Ran
*/
public interface NetworkInterface {
void register_Client();
void register_Server();
}
@@ -0,0 +1,100 @@
package com.seibel.lod.common.networking;
import com.seibel.lod.core.ModInfo;
import io.netty.buffer.Unpooled;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import java.util.Objects;
/**
* This class holds most of the networking code for the mod.
* @author Ran
*/
public class Networking {
public static final ResourceLocation resourceLocation_meow = new ResourceLocation("lod", "meow");
public static FriendlyByteBuf createNew() {
// TODO: Probably replace the Unpooled.buffer()
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
buf.writeInt(ModInfo.PROTOCOL_VERSION);
return buf;
}
/*
* All code below is from the fabric api and might have been modified to work with Distant Horizons
* Which is licensed under the Apache License 2.0
*/
/**
* Sends a packet to a player.
*
* @param player the player to send the packet to
* @param buf the payload of the packet.
*/
public static void send(ServerPlayer player, FriendlyByteBuf buf) {
Objects.requireNonNull(player, "Server player entity cannot be null");
Objects.requireNonNull(resourceLocation_meow, "Channel name cannot be null");
Objects.requireNonNull(buf, "Packet byte buf cannot be null");
player.connection.send(createS2CPacket(resourceLocation_meow, buf));
}
/**
* Sends a packet to the connected server.
*
* @param buf the payload of the packet
* @throws IllegalStateException if the client is not connected to a server
*/
public static void send(FriendlyByteBuf buf) throws IllegalStateException {
// You cant send without a client player, so this is fine
if (Minecraft.getInstance().getConnection() != null) {
Minecraft.getInstance().getConnection().send(createC2SPacket(resourceLocation_meow, buf));
return;
}
throw new IllegalStateException("Cannot send packets when not in game!");
}
/**
* Creates a packet which may be sent to the connected client.
*
* @param channelName the channel name
* @param buf the packet byte buf which represents the payload of the packet
* @return a new packet
*/
public static Packet<?> createS2CPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
Objects.requireNonNull(channelName, "Channel cannot be null");
Objects.requireNonNull(buf, "Buf cannot be null");
return createPlayS2CPacket(channelName, buf);
}
public static Packet<?> createPlayS2CPacket(ResourceLocation channel, FriendlyByteBuf buf) {
return new ClientboundCustomPayloadPacket(channel, buf);
}
/**
* Creates a packet which may be sent to a the connected server.
*
* @param channelName the channel name
* @param buf the packet byte buf which represents the payload of the packet
* @return a new packet
*/
public static Packet<?> createC2SPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
Objects.requireNonNull(channelName, "Channel name cannot be null");
Objects.requireNonNull(buf, "Buf cannot be null");
return createPlayC2SPacket(channelName, buf);
}
public static Packet<?> createPlayC2SPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
return new ServerboundCustomPayloadPacket(channelName, buf);
}
}
@@ -1,15 +1,15 @@
package com.seibel.lod.common.wrappers; package com.seibel.lod.common.wrappers;
import com.seibel.lod.common.wrappers.block.BlockColorSingletonWrapper; import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftRenderWrapper; import com.seibel.lod.common.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.core.handlers.IReflectionHandler; import com.seibel.lod.core.handlers.IReflectionHandler;
import com.seibel.lod.core.handlers.ReflectionHandler; import com.seibel.lod.core.handlers.ReflectionHandler;
import com.seibel.lod.core.util.SingletonHandler; import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory; import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
/** /**
* Binds all necessary dependencies, so we * Binds all necessary dependencies, so we
@@ -22,12 +22,17 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
* @version 12-1-2021 * @version 12-1-2021
*/ */
public class DependencySetup { public class DependencySetup {
public static void createInitialBindings() { public static void createInitialBindings()
SingletonHandler.bind(IBlockColorSingletonWrapper.class, BlockColorSingletonWrapper.INSTANCE); {
SingletonHandler.bind(IMinecraftWrapper.class, MinecraftWrapper.INSTANCE); SingletonHandler.bind(IVersionConstants.class, VersionConstants.INSTANCE);
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE); if (!LodCommonMain.serverSided)
SingletonHandler.bind(IWrapperFactory.class, WrapperFactory.INSTANCE); {
SingletonHandler.bind(IMinecraftClientWrapper.class, MinecraftClientWrapper.INSTANCE);
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftClientWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftClientWrapper.INSTANCE.getOptions()));
}
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftWrapper.INSTANCE.getOptions())); SingletonHandler.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
DependencySetupDoneCheck.isDone = true;
} }
} }
@@ -0,0 +1,10 @@
package com.seibel.lod.common.wrappers;
import java.util.function.Supplier;
public class DependencySetupDoneCheck
{
public static boolean isDone = false;
public static Supplier<Boolean> getIsCurrentThreadDistantGeneratorThread = (() -> {return false;});
}
@@ -22,9 +22,12 @@ package com.seibel.lod.common.wrappers;
import java.nio.FloatBuffer; import java.nio.FloatBuffer;
import com.mojang.math.Matrix4f; import com.mojang.math.Matrix4f;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.objects.math.Mat4f; import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction; import net.minecraft.core.Direction;
/** /**
@@ -47,8 +50,30 @@ public class McObjectConverter
} }
static final Direction[] directions;
static final LodDirection[] lodDirections;
static {
LodDirection[] lodDirs = LodDirection.values();
directions = new Direction[lodDirs.length];
lodDirections = new LodDirection[lodDirs.length];
for (LodDirection lodDir : lodDirs) {
Direction dir = Direction.byName(lodDir.name());
directions[lodDir.ordinal()] = dir;
lodDirections[dir.ordinal()] = lodDir;
}
}
public static BlockPos Convert(AbstractBlockPosWrapper wrappedPos) {
return new BlockPos(wrappedPos.getX(),wrappedPos.getY(), wrappedPos.getZ());
}
public static Direction Convert(LodDirection lodDirection) public static Direction Convert(LodDirection lodDirection)
{ {
return Direction.byName(lodDirection.name()); return directions[lodDirection.ordinal()];
}
public static LodDirection Convert(Direction direction)
{
return lodDirections[direction.ordinal()];
} }
} }
@@ -0,0 +1,39 @@
package com.seibel.lod.common.wrappers;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
/**
* @author James Seibel
* @version 12-11-2021
*/
public class VersionConstants implements IVersionConstants
{
public static final VersionConstants INSTANCE = new VersionConstants();
private VersionConstants()
{
}
@Override
public int getMinimumWorldHeight()
{
return 0;
}
@Override
public int getWorldGenerationCountPerThread()
{
return 1;
}
@Override
public boolean isVanillaRenderedChunkSquare()
{
return false;
}
}
@@ -25,10 +25,10 @@ import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper; import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper; import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper; import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper; import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkPosWrapper; import com.seibel.lod.common.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.common.wrappers.worldGeneration.WorldGeneratorWrapper; import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
/** /**
* This handles creating abstract wrapper objects. * This handles creating abstract wrapper objects.
@@ -38,54 +38,57 @@ import com.seibel.lod.common.wrappers.worldGeneration.WorldGeneratorWrapper;
*/ */
public class WrapperFactory implements IWrapperFactory public class WrapperFactory implements IWrapperFactory
{ {
public static final WrapperFactory INSTANCE = new WrapperFactory(); public static final WrapperFactory INSTANCE = new WrapperFactory();
@Override @Override
public AbstractBlockPosWrapper createBlockPos() public AbstractBlockPosWrapper createBlockPos()
{ {
return new BlockPosWrapper(); return new BlockPosWrapper();
} }
@Override @Override
public AbstractBlockPosWrapper createBlockPos(int x, int y, int z) public AbstractBlockPosWrapper createBlockPos(int x, int y, int z)
{ {
return new BlockPosWrapper(x,y,z); return new BlockPosWrapper(x, y, z);
} }
@Override @Override
public AbstractChunkPosWrapper createChunkPos() public AbstractChunkPosWrapper createChunkPos()
{ {
return new ChunkPosWrapper(); return new ChunkPosWrapper();
} }
@Override @Override
public AbstractChunkPosWrapper createChunkPos(int x, int z) public AbstractChunkPosWrapper createChunkPos(long xAndZPositionCombined)
{ {
return new ChunkPosWrapper(x, z); return new ChunkPosWrapper(xAndZPositionCombined);
} }
@Override @Override
public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos) public AbstractChunkPosWrapper createChunkPos(int x, int z)
{ {
return new ChunkPosWrapper(newChunkPos); return new ChunkPosWrapper(x, z);
} }
@Override @Override
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos) public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos)
{ {
return new ChunkPosWrapper(blockPos); return new ChunkPosWrapper(newChunkPos);
} }
@Override
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos)
{
return new ChunkPosWrapper(blockPos);
}
public AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(LodBuilder newLodBuilder,
@Override LodDimension newLodDimension, IWorldWrapper worldWrapper)
public AbstractWorldGeneratorWrapper createWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper) {
{ return new BatchGenerationEnvironment(worldWrapper, newLodBuilder, newLodDimension);
return new WorldGeneratorWrapper(newLodBuilder, newLodDimension, worldWrapper); }
}
} }
@@ -1,46 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* 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, version 3.
*
* 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.seibel.lod.common.wrappers.block;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import net.minecraft.world.level.block.Blocks;
/**
* Contains methods that would have been static in BlockColorWrapper.
* Since interfaces can't create/implement static methods we have
* to split the object up in two.
*
* @author James Seibel
* @version 11-17-2021
*/
public class BlockColorSingletonWrapper implements IBlockColorSingletonWrapper
{
public static final BlockColorSingletonWrapper INSTANCE = new BlockColorSingletonWrapper();
@Override
public IBlockColorWrapper getWaterColor()
{
return BlockColorWrapper.getBlockColorWrapper(Blocks.WATER.defaultBlockState(), new BlockPosWrapper(0,0, 0));
}
}
@@ -1,302 +0,0 @@
package com.seibel.lod.common.wrappers.block;
import java.util.List;
import java.util.Objects;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.common.wrappers.minecraft.MinecraftWrapper;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.Direction;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.BushBlock;
import net.minecraft.world.level.block.FlowerBlock;
import net.minecraft.world.level.block.GrassBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.TallGrassBlock;
import net.minecraft.world.level.block.state.BlockState;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class BlockColorWrapper implements IBlockColorWrapper
{
//set of block which require tint
public static final ConcurrentMap<Block, IBlockColorWrapper> blockColorWrapperMap = new ConcurrentHashMap<>();
//public static final ModelDataMap dataMap = new ModelDataMap.Builder().build();
public static final AbstractBlockPosWrapper blockPos = new BlockPosWrapper(0,0,0);
public static Random random = new Random(0);
//public static BlockColourWrapper WATER_COLOR = getBlockColorWrapper(Blocks.WATER);
public static final Direction[] directions = new Direction[] { Direction.UP, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.DOWN };
private Block block;
private int color;
private boolean isColored;
private boolean toTint;
private boolean folliageTint;
private boolean grassTint;
private boolean waterTint;
/**Constructor only require for the block instance we are wrapping**/
public BlockColorWrapper(BlockState blockState, AbstractBlockPosWrapper blockPosWrapper)
{
this.block = blockState.getBlock();
this.color = 0;
this.isColored = true;
this.toTint = false;
this.folliageTint = false;
this.grassTint = false;
this.waterTint = false;
setupColorAndTint(blockState,blockPosWrapper);
System.out.println(block + " color " + Integer.toHexString(color) + " to tint " + toTint + " folliageTint " + folliageTint + " grassTint " + grassTint + " waterTint " + waterTint);
}
/**
* this return a wrapper of the block in input
* @param blockState of the block to wrap
*/
static public IBlockColorWrapper getBlockColorWrapper(BlockState blockState, AbstractBlockPosWrapper blockPosWrapper)
{
//first we check if the block has already been wrapped
if (blockColorWrapperMap.containsKey(blockState.getBlock()) && blockColorWrapperMap.get(blockState.getBlock()) != null)
return blockColorWrapperMap.get(blockState.getBlock());
//if it hasn't been created yet, we create it and save it in the map
IBlockColorWrapper blockWrapper = new BlockColorWrapper(blockState, blockPosWrapper);
blockColorWrapperMap.put(blockState.getBlock(), blockWrapper);
//we return the newly created wrapper
return blockWrapper;
}
/**
* Generate the color of the given block from its texture
* and store it for later use.
*/
private void setupColorAndTint(BlockState blockState, AbstractBlockPosWrapper blockPosWrapper)
{
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
TextureAtlasSprite texture;
List<BakedQuad> quads = null;
boolean isTinted = false;
int listSize = 0;
// first step is to check if this block has a tinted face
for (Direction direction : directions)
{
if (LodCommonMain.forge) {
quads = LodCommonMain.forgeMethodCaller.getQuads(mc, block, blockState, direction, random);
} else {
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random);
}
listSize = Math.max(listSize, quads.size());
for (BakedQuad bakedQuad : quads)
{
isTinted |= bakedQuad.isTinted();
}
}
//if it contains a tinted face then we store this block in the toTint set
if (isTinted)
this.toTint = true;
//now we get the first non-empty face
for (Direction direction : directions)
{
if (LodCommonMain.forge) {
quads = LodCommonMain.forgeMethodCaller.getQuads(mc, block, blockState, direction, random);
} else {
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random);
}
if (!quads.isEmpty())
break;
}
//the quads list is not empty we extract the first one
if (!quads.isEmpty())
{
isColored = true;
texture = quads.get(0).getSprite();
}
else
{
isColored = true;
texture = mc.getModelManager().getBlockModelShaper().getParticleIcon(block.defaultBlockState());
}
int count = 0;
int alpha = 0;
int red = 0;
int green = 0;
int blue = 0;
int numberOfGreyPixel = 0;
int tempColor;
int colorMultiplier;
// generate the block's color
//for (int frameIndex = 0; frameIndex < texture.getFrameCount(); frameIndex++)
int frameIndex = 0; // TODO
{
// textures normally use u and v instead of x and y
for (int u = 0; u < texture.getHeight(); u++)
{
for (int v = 0; v < texture.getWidth(); v++)
{
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, frameIndex, u, v);
if (ColorUtil.getAlpha(TextureAtlasSpriteWrapper.getPixelRGBA(texture, frameIndex, u, v)) == 0)
continue;
// determine if this pixel is gray
int colorMax = Math.max(Math.max(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
int colorMin = 4 + Math.min(Math.min(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
boolean isGray = colorMax < colorMin;
if (isGray)
numberOfGreyPixel++;
// for flowers, weight their non-green color higher
if (block instanceof FlowerBlock && (!(ColorUtil.getGreen(tempColor) > (ColorUtil.getBlue(tempColor) + 30)) || !(ColorUtil.getGreen(tempColor) > (ColorUtil.getRed(tempColor) + 30))))
colorMultiplier = 5;
else
colorMultiplier = 1;
// add to the running averages
count += colorMultiplier;
alpha += ColorUtil.getAlpha(tempColor) * colorMultiplier;
red += ColorUtil.getBlue(tempColor) * colorMultiplier;
green += ColorUtil.getGreen(tempColor) * colorMultiplier;
blue += ColorUtil.getRed(tempColor) * colorMultiplier;
}
}
}
if (count == 0)
// this block is entirely transparent
tempColor = 0;
else
{
// determine the average color
alpha /= count;
red /= count;
green /= count;
blue /= count;
tempColor = ColorUtil.rgbToInt(alpha, red, green, blue);
}
// determine if this block should use the biome color tint
if ((grassInstance() || leavesInstance() || waterIstance()) && (float) numberOfGreyPixel / count > 0.75f)
this.toTint = true;
// we check which kind of tint we need to apply
this.grassTint = grassInstance() && toTint;
this.folliageTint = leavesInstance() && toTint;
this.waterTint = waterIstance() && toTint;
color = tempColor;
}
/** determine if the given block should use the biome's grass color */
private boolean grassInstance()
{
return block instanceof GrassBlock
|| block instanceof BushBlock
|| block instanceof TallGrassBlock;
}
/** determine if the given block should use the biome's foliage color */
private boolean leavesInstance()
{
return block instanceof LeavesBlock
|| block == Blocks.VINE
|| block == Blocks.SUGAR_CANE;
}
/** determine if the given block should use the biome's foliage color */
private boolean waterIstance()
{
return block == Blocks.WATER;
}
//--------------//
//Colors getters//
//--------------//
@Override
public boolean hasColor()
{
return isColored;
}
@Override
public int getColor()
{
return color;
}
//------------//
//Tint getters//
//------------//
@Override
public boolean hasTint()
{
return toTint;
}
@Override
public boolean hasGrassTint()
{
return grassTint;
}
@Override
public boolean hasFolliageTint()
{
return folliageTint;
}
@Override
public boolean hasWaterTint()
{
return waterTint;
}
@Override public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof BlockColorWrapper))
return false;
BlockColorWrapper that = (BlockColorWrapper) o;
return Objects.equals(block, that.block);
}
@Override public int hashCode()
{
return Objects.hash(block);
}
}
@@ -0,0 +1,27 @@
package com.seibel.lod.common.wrappers.block;
import java.util.concurrent.ConcurrentHashMap;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.state.BlockState;
public class BlockDetailMap
{
private static ConcurrentHashMap<BlockState, BlockDetailWrapper> map = new ConcurrentHashMap<BlockState, BlockDetailWrapper>();
private BlockDetailMap() {}
public static BlockDetailWrapper getOrMakeBlockDetailCache(BlockState bs, BlockPos pos, LevelReader getter) {
BlockDetailWrapper cache = map.get(bs);
if (cache != null) return cache;
if (bs.getFluidState().isEmpty()) {
cache = BlockDetailWrapper.make(bs, pos, getter);
} else {
cache = BlockDetailWrapper.make(bs.getFluidState().createLegacyBlock(), pos, getter);
}
BlockDetailWrapper cacheCAS = map.putIfAbsent(bs, cache);
return cacheCAS==null ? cache : cacheCAS;
}
}
@@ -0,0 +1,315 @@
package com.seibel.lod.common.wrappers.block;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Stream;
import com.seibel.lod.common.Config;
import com.seibel.lod.common.wrappers.McObjectConverter;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockTintCache;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.client.renderer.block.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
import net.minecraft.core.Direction;
import net.minecraft.world.level.*;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.FlowerBlock;
import net.minecraft.world.level.block.LeavesBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.RotatedPillarBlock;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
public class BlockDetailWrapper extends IBlockDetailWrapper
{
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
public static final int FLOWER_COLOR_SCALE = 5;
public static final Random random = new Random(0);
enum ColorMode {
Default,
Flower,
Leaves;
static ColorMode getColorMode(Block b) {
if (b instanceof LeavesBlock) return Leaves;
if (b instanceof FlowerBlock) return Flower;
return Default;
}
}
//TODO: Perhaps make this not just use the first frame?
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode) {
int count = 0;
double alpha = 0;
double red = 0;
double green = 0;
double blue = 0;
int tempColor;
{
// textures normally use u and v instead of x and y
for (int u = 0; u < texture.getWidth(); u++)
{
for (int v = 0; v < texture.getHeight(); v++)
{
//note: Minecraft color format is: 0xAA BB GG RR
//________ DH mod color format is: 0xAA RR GG BB
//OpenGL RGBA format native order: 0xRR GG BB AA
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
double r = ((tempColor & 0x000000FF) )/255.;
double g = ((tempColor & 0x0000FF00) >>> 8)/255.;
double b = ((tempColor & 0x00FF0000) >>> 16)/255.;
double a = ((tempColor & 0xFF000000) >>> 24)/255.;
int scale = 1;
if (colorMode == ColorMode.Leaves) {
r *= a;
g *= a;
b *= a;
a = 1.;
} else if (a==0.) {
continue;
} else if (colorMode == ColorMode.Flower && (g+0.1<b || g+0.1<r)) {
scale = FLOWER_COLOR_SCALE;
}
count += scale;
alpha += a*a*scale;
red += r*r*scale;
green += g*g*scale;
blue += b*b*scale;
}
}
}
if (count == 0)
// this block is entirely transparent
tempColor = ColorUtil.rgbToInt(255,255,0,255);
else
{
// determine the average color
tempColor = ColorUtil.rgbToInt(
(int) (Math.sqrt(alpha/count)*255.),
(int) (Math.sqrt(red / count)*255.),
(int) (Math.sqrt(green / count)*255.),
(int) (Math.sqrt(blue / count)*255.));
}
// TODO: Remove this when transparency is added!
double colorAlpha = ColorUtil.getAlpha(tempColor)/255.;
tempColor = ColorUtil.rgbToInt(
ColorUtil.getAlpha(tempColor),
(int)(ColorUtil.getRed(tempColor) * colorAlpha),
(int)(ColorUtil.getGreen(tempColor) * colorAlpha),
(int)(ColorUtil.getBlue(tempColor) * colorAlpha)
);
return tempColor;
}
private static final Block[] BLOCK_TO_AVOID = {Blocks.AIR, Blocks.CAVE_AIR, Blocks.BARRIER};
private static final Direction[] DIRECTION_ORDER = {Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN};
private static boolean isBlockToBeAvoid(Block b) {
for (Block bta : BLOCK_TO_AVOID)
if (bta==b) return true;
return false;
}
final BlockState state;
final BlockPos samplePos;
final LevelReader sampleGetter;
boolean isShapeResolved = false;
boolean[] dontOccludeFaces = null;
boolean noCollision = false;
boolean noFullFace = false;
boolean isColorResolved = false;
int baseColor = 0; //TODO: Impl per-face color
boolean needShade = true;
boolean needPostTinting = false;
int tintIndex = 0;
public static BlockDetailWrapper NULL_BLOCK_DETAIL = new BlockDetailWrapper();
public BlockDetailWrapper(BlockState state, BlockPos pos, LevelReader getter) {
this.state = state;
this.samplePos = pos;
this.sampleGetter = getter;
}
private BlockDetailWrapper() {
this.state = null;
this.samplePos = null;
this.sampleGetter = null;
}
static BlockDetailWrapper make(BlockState bs, BlockPos pos, LevelReader getter) {
if(!bs.getFluidState().isEmpty()) { // Is a fluidBlock
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
if (bs.isAir()) return NULL_BLOCK_DETAIL;
return new BlockDetailWrapper(bs, pos, getter);
} else {
if (bs.getRenderShape() != RenderShape.MODEL) return NULL_BLOCK_DETAIL;
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
return new BlockDetailWrapper(bs, pos, getter);
}
}
private void resolveShapes() {
if (isShapeResolved) return;
if (state.getFluidState().isEmpty()) {
noCollision = state.getCollisionShape(sampleGetter, samplePos).isEmpty();
dontOccludeFaces = new boolean[6];
if (state.canOcclude()) {
/* FIXME: Figure out how or if needed to impl per-face culling?
for (Direction dir : Direction.values()) {
dontOccludeFaces[McObjectConverter.Convert(dir).ordinal()]
= state.getFaceOcclusionShape(sampleGetter, samplePos, dir).isEmpty();
}*/
} else {
Arrays.fill(dontOccludeFaces, true);
}
VoxelShape voxelShape = state.getShape(sampleGetter, samplePos);
if (voxelShape.isEmpty()) {
noFullFace = true;
} else {
AABB bbox = voxelShape.bounds();
double xWidth = (bbox.maxX - bbox.minX);
double yWidth = (bbox.maxY - bbox.minY);
double zWidth = (bbox.maxZ - bbox.minZ);
noFullFace = xWidth < 1 && zWidth < 1 && yWidth < 1;
}
} else { // Liquid Block
dontOccludeFaces = new boolean[6];
}
isShapeResolved = true;
}
private void resolveColors() {
if (isColorResolved) return;
if (state.getFluidState().isEmpty()) {
List<BakedQuad> quads = null;
for (Direction direction : DIRECTION_ORDER)
{
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
getBlockModel(state).getQuads(state, direction, random);
if (!quads.isEmpty() &&
!(state.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP))
break;
};
if (quads != null && !quads.isEmpty()) {
needPostTinting = quads.get(0).isTinted();
needShade = quads.get(0).isShade();
tintIndex = quads.get(0).getTintIndex();
baseColor = calculateColorFromTexture(quads.get(0).getSprite(),
ColorMode.getColorMode(state.getBlock()));
}
} else { // Liquid Block
needPostTinting = true;
needShade = false;
tintIndex = 0;
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
ColorMode.getColorMode(state.getBlock()));
}
isColorResolved = true;
}
private BlockAndTintGetter wrapColorResolver(LevelReader level) {
int blendDistance = CONFIG.client().graphics().quality().getLodBiomeBlending();
if (blendDistance == 0) {
return new TintGetterOverrideFast(level);
} else {
return new TintGetterOverrideSmooth(level, blendDistance);
}
}
@Override
public int getAndResolveFaceColor(LodDirection dir, IChunkWrapper chunk, AbstractBlockPosWrapper blockPos)
{
// FIXME: impl per-face colors
resolveColors();
if (!needPostTinting) return baseColor;
int tintColor = Minecraft.getInstance().getBlockColors()
.getColor(state, wrapColorResolver(((ChunkWrapper)chunk).getColorResolver()),
McObjectConverter.Convert(blockPos), tintIndex);
if (tintColor == -1) return baseColor;
return ColorUtil.multiplyARGBwithRGB(baseColor, tintColor);
}
@Override
public boolean hasFaceCullingFor(LodDirection dir)
{
resolveShapes();
return !dontOccludeFaces[dir.ordinal()];
}
@Override
public boolean hasNoCollision()
{
resolveShapes();
return noCollision;
}
@Override
public boolean noFaceIsFullFace()
{
resolveShapes();
return noFullFace;
}
@Override
public String serialize()
{
// FIXME: Impl this for the blockState Storage stuff
return null;
}
@Override
protected boolean isSame(IBlockDetailWrapper iBlockDetail)
{
return ((BlockDetailWrapper)iBlockDetail).state.getBlock().equals(state.getBlock());
}
}
@@ -14,7 +14,7 @@ import net.minecraft.core.BlockPos;
*/ */
public class BlockPosWrapper extends AbstractBlockPosWrapper public class BlockPosWrapper extends AbstractBlockPosWrapper
{ {
private BlockPos.MutableBlockPos blockPos; private final BlockPos.MutableBlockPos blockPos;
public BlockPosWrapper() public BlockPosWrapper()
@@ -1,159 +0,0 @@
package com.seibel.lod.common.wrappers.block;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.VoxelShape;
/**
* @author James Seibel
* @version 11-21-2021
*/
public class BlockShapeWrapper implements IBlockShapeWrapper
{
//set of block which require tint
public static final ConcurrentMap<Block, BlockShapeWrapper> blockShapeWrapperMap = new ConcurrentHashMap<>();
public static BlockShapeWrapper WATER_SHAPE = new BlockShapeWrapper();
private final Block block;
private final boolean toAvoid;
private boolean nonFull;
private boolean noCollision;
/**Constructor only require for the block instance we are wrapping**/
public BlockShapeWrapper(Block block, IChunkWrapper chunkWrapper, AbstractBlockPosWrapper blockPosWrapper)
{
this.block = block;
this.nonFull = false;
this.noCollision = false;
this.toAvoid = ofBlockToAvoid();
setupShapes(chunkWrapper, blockPosWrapper);
System.out.println(block + " non full " + nonFull + " no collision " + noCollision + " to avoid " + toAvoid);
}
private BlockShapeWrapper()
{
this.block = Blocks.WATER;
this.nonFull = false;
this.noCollision = false;
this.toAvoid = false;
}
/**
* this return a wrapper of the block in input
* @param block Block object to wrap
*/
static public BlockShapeWrapper getBlockShapeWrapper(Block block, ChunkWrapper chunkWrapper, AbstractBlockPosWrapper blockPosWrapper)
{
//first we check if the block has already been wrapped
if (blockShapeWrapperMap.containsKey(block) && blockShapeWrapperMap.get(block) != null)
return blockShapeWrapperMap.get(block);
//if it hasn't been created yet, we create it and save it in the map
BlockShapeWrapper blockWrapper = new BlockShapeWrapper(block, chunkWrapper, blockPosWrapper);
blockShapeWrapperMap.put(block, blockWrapper);
//we return the newly created wrapper
return blockWrapper;
}
private void setupShapes(IChunkWrapper chunkWrapper, AbstractBlockPosWrapper blockPosWrapper)
{
ChunkAccess chunk = ((ChunkWrapper) chunkWrapper).getChunk();
BlockPos blockPos = ((BlockPosWrapper) blockPosWrapper).getBlockPos();
boolean noCollisionSetted = false;
boolean nonFullSetted = false;
if (!block.defaultBlockState().getFluidState().isEmpty())// || block instanceof SixWayBlock)
{
noCollisionSetted = true;
nonFullSetted = true;
noCollision = false;
nonFull = false;
}
if (!nonFullSetted)
{
VoxelShape voxelShape = block.defaultBlockState().getShape(chunk, blockPos);
if (!voxelShape.isEmpty())
{
AABB bbox = voxelShape.bounds();
double xWidth = (bbox.maxX - bbox.minX);
double yWidth = (bbox.maxY - bbox.minY);
double zWidth = (bbox.maxZ - bbox.minZ);
nonFull = xWidth < 1 && zWidth < 1 && yWidth < 1;
}
else
{
nonFull = false;
}
}
if (!noCollisionSetted)
{
VoxelShape collisionShape = block.defaultBlockState().getCollisionShape(chunk, blockPos);
noCollision = collisionShape.isEmpty();
}
}
@Override
public boolean ofBlockToAvoid()
{
return block.equals(Blocks.AIR)
|| block.equals(Blocks.CAVE_AIR)
|| block.equals(Blocks.BARRIER);
}
//-----------------//
//Avoidance getters//
//-----------------//
@Override
public boolean isNonFull()
{
return nonFull;
}
@Override
public boolean hasNoCollision()
{
return noCollision;
}
@Override
public boolean isToAvoid()
{
return toAvoid;
}
@Override public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof BlockShapeWrapper))
return false;
BlockShapeWrapper that = (BlockShapeWrapper) o;
return Objects.equals(block, that.block);
}
@Override public int hashCode()
{
return Objects.hash(block);
}
}
@@ -0,0 +1,196 @@
package com.seibel.lod.common.wrappers.block;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.Util;
import net.minecraft.client.color.block.BlockTintCache;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
import net.minecraft.core.Direction;
import net.minecraft.world.level.*;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class TintGetterOverrideFast implements BlockAndTintGetter {
LevelReader parent;
private final Object2ObjectArrayMap<ColorResolver, ConcurrentHashMap<Biome, Integer>> tintCaches;
public TintGetterOverrideFast(LevelReader parent) {
this.parent = parent;
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
});
}
private Biome _getBiome(BlockPos pos) {
#if MC_VERSION_1_18_2
return parent.getBiome(pos).value();
#elif MC_VERSION_1_18_1
return parent.getBiome(pos);
#endif
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
Biome b = _getBiome(blockPos);
return tintCaches.get(colorResolver).computeIfAbsent(b, (key) -> colorResolver.getColor(b, blockPos.getX(), blockPos.getZ()));
}
@Override
public float getShade(Direction direction, boolean bl) {
return parent.getShade(direction, bl);
}
@Override
public LevelLightEngine getLightEngine() {
return parent.getLightEngine();
}
@Override
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
return parent.getBrightness(lightLayer, blockPos);
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
return parent.getRawBrightness(blockPos, i);
}
@Override
public boolean canSeeSky(BlockPos blockPos) {
return parent.canSeeSky(blockPos);
}
@Override
@Nullable
public BlockEntity getBlockEntity(BlockPos blockPos) {
return parent.getBlockEntity(blockPos);
}
@Override
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType) {
return parent.getBlockEntity(blockPos, blockEntityType);
}
@Override
public BlockState getBlockState(BlockPos blockPos) {
return parent.getBlockState(blockPos);
}
@Override
public FluidState getFluidState(BlockPos blockPos) {
return parent.getFluidState(blockPos);
}
@Override
public int getLightEmission(BlockPos blockPos) {
return parent.getLightEmission(blockPos);
}
@Override
public int getMaxLightLevel() {
return parent.getMaxLightLevel();
}
@Override
public Stream<BlockState> getBlockStates(AABB aABB) {
return parent.getBlockStates(aABB);
}
@Override
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext) {
return parent.isBlockInLine(clipBlockStateContext);
}
@Override
public BlockHitResult clip(ClipContext clipContext) {
return parent.clip(clipContext);
}
@Override
@Nullable
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState) {
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
}
@Override
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier) {
return parent.getBlockFloorHeight(voxelShape, supplier);
}
@Override
public double getBlockFloorHeight(BlockPos blockPos) {
return parent.getBlockFloorHeight(blockPos);
}
@Override
public int getHeight() {
return parent.getHeight();
}
@Override
public int getMinBuildHeight() {
return parent.getMinBuildHeight();
}
@Override
public int getMaxBuildHeight() {
return parent.getMaxBuildHeight();
}
@Override
public int getSectionsCount() {
return parent.getSectionsCount();
}
@Override
public int getMinSection() {
return parent.getMinSection();
}
@Override
public int getMaxSection() {
return parent.getMaxSection();
}
@Override
public boolean isOutsideBuildHeight(BlockPos blockPos) {
return parent.isOutsideBuildHeight(blockPos);
}
@Override
public boolean isOutsideBuildHeight(int i) {
return parent.isOutsideBuildHeight(i);
}
@Override
public int getSectionIndex(int i) {
return parent.getSectionIndex(i);
}
@Override
public int getSectionIndexFromSectionY(int i) {
return parent.getSectionIndexFromSectionY(i);
}
@Override
public int getSectionYFromSectionIndex(int i) {
return parent.getSectionYFromSectionIndex(i);
}
}
@@ -0,0 +1,219 @@
package com.seibel.lod.common.wrappers.block;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.Util;
import net.minecraft.client.color.block.BlockTintCache;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
import net.minecraft.core.Direction;
import net.minecraft.world.level.*;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import org.jetbrains.annotations.Nullable;
import java.util.Optional;
import java.util.function.Supplier;
import java.util.stream.Stream;
public class TintGetterOverrideSmooth implements BlockAndTintGetter {
LevelReader parent;
private final Object2ObjectArrayMap<ColorResolver, BlockTintCache> tintCaches;
public int smoothingRange;
public TintGetterOverrideSmooth(LevelReader parent, int smoothingRange) {
this.parent = parent;
this.smoothingRange = smoothingRange;
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.GRASS_COLOR_RESOLVER)));
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.FOLIAGE_COLOR_RESOLVER)));
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.WATER_COLOR_RESOLVER)));
});
}
private Biome _getBiome(BlockPos pos) {
#if MC_VERSION_1_18_2
return parent.getBiome(pos).value();
#elif MC_VERSION_1_18_1
return parent.getBiome(pos);
#endif
}
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
int i = smoothingRange;
if (i == 0)
return colorResolver.getColor(_getBiome(blockPos), blockPos.getX(), blockPos.getZ());
int j = (i * 2 + 1) * (i * 2 + 1);
int k = 0;
int l = 0;
int m = 0;
Cursor3D cursor3D = new Cursor3D(blockPos.getX() - i, blockPos.getY(), blockPos.getZ() - i, blockPos.getX() + i, blockPos.getY(), blockPos.getZ() + i);
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
while (cursor3D.advance())
{
mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
int n = colorResolver.getColor(_getBiome(mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
k += (n & 0xFF0000) >> 16;
l += (n & 0xFF00) >> 8;
m += n & 0xFF;
}
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
}
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
BlockTintCache blockTintCache = this.tintCaches.get(colorResolver);
return blockTintCache.getColor(blockPos);
}
@Override
public float getShade(Direction direction, boolean bl) {
return parent.getShade(direction, bl);
}
@Override
public LevelLightEngine getLightEngine() {
return parent.getLightEngine();
}
@Override
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
return parent.getBrightness(lightLayer, blockPos);
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
return parent.getRawBrightness(blockPos, i);
}
@Override
public boolean canSeeSky(BlockPos blockPos) {
return parent.canSeeSky(blockPos);
}
@Override
@Nullable
public BlockEntity getBlockEntity(BlockPos blockPos) {
return parent.getBlockEntity(blockPos);
}
@Override
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType) {
return parent.getBlockEntity(blockPos, blockEntityType);
}
@Override
public BlockState getBlockState(BlockPos blockPos) {
return parent.getBlockState(blockPos);
}
@Override
public FluidState getFluidState(BlockPos blockPos) {
return parent.getFluidState(blockPos);
}
@Override
public int getLightEmission(BlockPos blockPos) {
return parent.getLightEmission(blockPos);
}
@Override
public int getMaxLightLevel() {
return parent.getMaxLightLevel();
}
@Override
public Stream<BlockState> getBlockStates(AABB aABB) {
return parent.getBlockStates(aABB);
}
@Override
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext) {
return parent.isBlockInLine(clipBlockStateContext);
}
@Override
public BlockHitResult clip(ClipContext clipContext) {
return parent.clip(clipContext);
}
@Override
@Nullable
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState) {
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
}
@Override
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier) {
return parent.getBlockFloorHeight(voxelShape, supplier);
}
@Override
public double getBlockFloorHeight(BlockPos blockPos) {
return parent.getBlockFloorHeight(blockPos);
}
@Override
public int getHeight() {
return parent.getHeight();
}
@Override
public int getMinBuildHeight() {
return parent.getMinBuildHeight();
}
@Override
public int getMaxBuildHeight() {
return parent.getMaxBuildHeight();
}
@Override
public int getSectionsCount() {
return parent.getSectionsCount();
}
@Override
public int getMinSection() {
return parent.getMinSection();
}
@Override
public int getMaxSection() {
return parent.getMaxSection();
}
@Override
public boolean isOutsideBuildHeight(BlockPos blockPos) {
return parent.isOutsideBuildHeight(blockPos);
}
@Override
public boolean isOutsideBuildHeight(int i) {
return parent.isOutsideBuildHeight(i);
}
@Override
public int getSectionIndex(int i) {
return parent.getSectionIndex(i);
}
@Override
public int getSectionIndexFromSectionY(int i) {
return parent.getSectionIndexFromSectionY(i);
}
@Override
public int getSectionYFromSectionIndex(int i) {
return parent.getSectionYFromSectionIndex(i);
}
}
@@ -2,6 +2,8 @@ package com.seibel.lod.common.wrappers.chunk;
import java.util.Objects; import java.util.Objects;
import com.seibel.lod.core.util.LevelPosUtil;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper; import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper; import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
@@ -16,7 +18,7 @@ import net.minecraft.world.level.ChunkPos;
*/ */
public class ChunkPosWrapper extends AbstractChunkPosWrapper public class ChunkPosWrapper extends AbstractChunkPosWrapper
{ {
private net.minecraft.world.level.ChunkPos chunkPos; private final net.minecraft.world.level.ChunkPos chunkPos;
public ChunkPosWrapper() public ChunkPosWrapper()
{ {
@@ -43,6 +45,10 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
this.chunkPos = new ChunkPos(chunkX, chunkZ); this.chunkPos = new ChunkPos(chunkX, chunkZ);
} }
public ChunkPosWrapper(long l) {
this.chunkPos = new ChunkPos(l);
}
public ChunkPosWrapper(ChunkPos pos) public ChunkPosWrapper(ChunkPos pos)
{ {
@@ -79,13 +85,18 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
@Override @Override
public int getRegionX() public int getRegionX()
{ {
return chunkPos.getRegionX(); return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, LodUtil.REGION_DETAIL_LEVEL);
} }
@Override @Override
public int getRegionZ() public int getRegionZ()
{ {
return chunkPos.getRegionZ(); return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.z, LodUtil.REGION_DETAIL_LEVEL);
}
@Override
public long getLong() {
return chunkPos.toLong();
} }
public ChunkPos getChunkPos() public ChunkPos getChunkPos()
@@ -96,7 +107,16 @@ public class ChunkPosWrapper extends AbstractChunkPosWrapper
@Override @Override
public boolean equals(Object o) public boolean equals(Object o)
{ {
return chunkPos.equals(o); // If the object is compared with itself then return true
if (o == this) {
return true;
}
// Check if o is an instance of RegionPos or not
if (!(o instanceof ChunkPosWrapper)) {
return false;
}
ChunkPosWrapper c = (ChunkPosWrapper) o;
return c.chunkPos.equals(chunkPos);
} }
@Override @Override
@@ -1,130 +1,208 @@
package com.seibel.lod.common.wrappers.chunk; package com.seibel.lod.common.wrappers.chunk;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; import com.seibel.lod.common.wrappers.block.BlockDetailWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper; import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper; import com.seibel.lod.core.util.LevelPosUtil;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper; import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.lod.common.wrappers.WrapperUtil;
import com.seibel.lod.common.wrappers.block.BlockColorWrapper;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
import com.seibel.lod.common.wrappers.block.BlockShapeWrapper;
import com.seibel.lod.common.wrappers.world.BiomeWrapper;
import net.minecraft.world.level.block.LiquidBlock; import com.seibel.lod.common.wrappers.WrapperUtil;
import com.seibel.lod.common.wrappers.block.BlockDetailMap;
import com.seibel.lod.common.wrappers.world.BiomeWrapper;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
import net.minecraft.core.BlockPos;
import net.minecraft.core.QuartPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.block.LiquidBlockContainer;
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.chunk.ChunkAccess; import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.levelgen.Heightmap;
/** /**
* *
* @author James Seibel * @author James Seibel
* @version 11-21-2021 * @version 3-5-2022
*/ */
public class ChunkWrapper implements IChunkWrapper public class ChunkWrapper implements IChunkWrapper
{ {
private final ChunkAccess chunk;
private final LevelReader lightSource;
private ChunkAccess chunk;
private AbstractChunkPosWrapper chunkPos; public ChunkWrapper(ChunkAccess chunk, LevelReader lightSource)
{
this.chunk = chunk;
this.lightSource = lightSource;
}
@Override
public int getHeight(){
return chunk.getHeight();
}
@Override
public int getMinBuildHeight()
{
return chunk.getMinBuildHeight();
}
@Override
public int getMaxBuildHeight()
{
return chunk.getMaxBuildHeight();
}
@Override
public int getHeightMapValue(int xRel, int zRel)
{
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
}
@Override
public IBiomeWrapper getBiome(int x, int y, int z)
{
#if MC_VERSION_1_18_2
return BiomeWrapper.getBiomeWrapper(chunk.getNoiseBiome(
QuartPos.fromBlock(x), QuartPos.fromBlock(y), QuartPos.fromBlock(z)).value());
#elif MC_VERSION_1_18_1
return BiomeWrapper.getBiomeWrapper(chunk.getNoiseBiome(
QuartPos.fromBlock(x), QuartPos.fromBlock(y), QuartPos.fromBlock(z)));
#endif
}
@Override
public IBlockDetailWrapper getBlockDetail(int x, int y, int z) {
BlockPos pos = new BlockPos(x,y,z);
BlockState blockState = chunk.getBlockState(pos);
IBlockDetailWrapper blockDetail = BlockDetailMap.getOrMakeBlockDetailCache(blockState, pos, lightSource);
return blockDetail == BlockDetailWrapper.NULL_BLOCK_DETAIL ? null : blockDetail;
}
@Override @Override
public int getHeight(){ public IBlockDetailWrapper getBlockDetailAtFace(int x, int y, int z, LodDirection dir) {
return chunk.getMaxBuildHeight(); int fy = y+dir.getNormal().y;
if (fy < getMinBuildHeight() || fy > getMaxBuildHeight()) return null;
BlockPos pos = new BlockPos(x+dir.getNormal().x,fy,z+dir.getNormal().z);
BlockState blockState;
if (blockPosInsideChunk(x,y,z))
blockState = chunk.getBlockState(pos);
else {
blockState = lightSource.getBlockState(pos);
}
if (blockState == null || blockState.isAir()) return null;
IBlockDetailWrapper blockDetail = BlockDetailMap.getOrMakeBlockDetailCache(blockState, pos, lightSource);
return blockDetail == BlockDetailWrapper.NULL_BLOCK_DETAIL ? null : blockDetail;
} }
@Override public ChunkAccess getChunk() {
public boolean isPositionInWater(AbstractBlockPosWrapper blockPos) return chunk;
{ }
BlockState blockState = chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos());
//This type of block is always in water @Override
if((blockState.getBlock() instanceof LiquidBlock))// && !(blockState.getBlock() instanceof IWaterLoggable)) public int getChunkPosX(){
return true; return chunk.getPos().x;
}
//This type of block could be in water @Override
if(blockState.getOptionalValue(BlockStateProperties.WATERLOGGED).isPresent() && blockState.getOptionalValue(BlockStateProperties.WATERLOGGED).get()) public int getChunkPosZ(){
return true; return chunk.getPos().z;
}
return false; @Override
} public int getRegionPosX(){
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, LodUtil.REGION_DETAIL_LEVEL);
}
@Override @Override
public int getHeightMapValue(int xRel, int zRel) public int getRegionPosZ(){
{ return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().z, LodUtil.REGION_DETAIL_LEVEL);
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel); }
}
@Override @Override
public IBiomeWrapper getBiome(int xRel, int yAbs, int zRel) public int getMaxY(int x, int z) {
{ return chunk.getHeight(Heightmap.Types.MOTION_BLOCKING, Math.floorMod(x, 16), Math.floorMod(z, 16));
return BiomeWrapper.getBiomeWrapper(chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2)); }
}
@Override @Override
public IBlockColorWrapper getBlockColorWrapper(AbstractBlockPosWrapper blockPos) public int getMaxX(){
{ return chunk.getPos().getMaxBlockX();
return BlockColorWrapper.getBlockColorWrapper(chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos()), blockPos); }
} @Override
public int getMaxZ(){
return chunk.getPos().getMaxBlockZ();
}
@Override
public int getMinX(){
return chunk.getPos().getMinBlockX();
}
@Override
public int getMinZ() {
return chunk.getPos().getMinBlockZ();
}
@Override @Override
public IBlockShapeWrapper getBlockShapeWrapper(AbstractBlockPosWrapper blockPos) public long getLongChunkPos() {
{ return chunk.getPos().toLong();
return BlockShapeWrapper.getBlockShapeWrapper(chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos()).getBlock(), this, blockPos); }
}
public ChunkWrapper(ChunkAccess chunk) @Override
{ public boolean isLightCorrect(){
this.chunk = chunk; //return true;
this.chunkPos = new ChunkPosWrapper(chunk.getPos()); if (chunk instanceof LevelChunk) {
} return ((LevelChunk) chunk).isClientLightReady();
}
return chunk.isLightCorrect();
}
public ChunkAccess getChunk(){ public boolean isWaterLogged(int x, int y, int z)
return chunk; {
} BlockState blockState = chunk.getBlockState(new BlockPos(x,y,z));
@Override
public AbstractChunkPosWrapper getPos()
{
return chunkPos;
}
@Override //This type of block is always in water
public boolean isLightCorrect(){ return (!(blockState.getBlock() instanceof LiquidBlockContainer) && (blockState.getBlock() instanceof SimpleWaterloggedBlock))
return chunk.isLightCorrect(); && (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED));
} }
public boolean @Override
isWaterLogged(BlockPosWrapper blockPos) public int getEmittedBrightness(int x, int y, int z)
{ {
BlockState blockState = chunk.getBlockState(blockPos.getBlockPos()); return chunk.getLightEmission(new BlockPos(x,y,z));
}
// //This type of block is always in water @Override
// if((blockState.getBlock() instanceof ILiquidContainer) && !(blockState.getBlock() instanceof IWaterLoggable)) public int getBlockLight(int x, int y, int z) {
// return true; if (lightSource == null) return -1;
return lightSource.getBrightness(LightLayer.BLOCK, new BlockPos(x,y,z));
}
//This type of block could be in water @Override
if(blockState.getOptionalValue(BlockStateProperties.WATERLOGGED).isPresent() && blockState.getOptionalValue(BlockStateProperties.WATERLOGGED).get()) public int getSkyLight(int x, int y, int z) {
return true; if (lightSource == null) return -1;
return lightSource.getBrightness(LightLayer.SKY, new BlockPos(x,y,z));
}
return false; @Override
} public boolean doesNearbyChunksExist() {
if (lightSource instanceof LightedWorldGenRegion) return true;
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
if (dx==0 && dz==0) continue;
if (lightSource.getChunk(dx+getChunkPosX(), dz+getChunkPosZ(), ChunkStatus.BIOMES, false) == null) return false;
}
}
return true;
}
public int getEmittedBrightness(BlockPosWrapper blockPos) public LevelReader getColorResolver()
{ {
return chunk.getLightEmission(blockPos.getBlockPos()); return lightSource;
} }
@Override
public boolean isWaterLogged(AbstractBlockPosWrapper blockPos)
{
// TODO Auto-generated method stub
return false;
}
@Override
public int getEmittedBrightness(AbstractBlockPosWrapper blockPos)
{
// TODO Auto-generated method stub
return 0;
}
} }
File diff suppressed because it is too large Load Diff
@@ -28,6 +28,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
{ {
public final IGraphics graphics; public final IGraphics graphics;
public final IWorldGenerator worldGenerator; public final IWorldGenerator worldGenerator;
public final IMultiplayer multiplayer;
public final IAdvanced advanced; public final IAdvanced advanced;
@@ -43,6 +44,11 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
return worldGenerator; return worldGenerator;
} }
@Override
public IMultiplayer multiplayer() {
return multiplayer;
}
@Override @Override
public IAdvanced advanced() public IAdvanced advanced()
{ {
@@ -50,6 +56,18 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
} }
@Override
public boolean getOptionsButton()
{
return Config.optionsButton;
}
@Override
public void setOptionsButton(boolean newOptionsButton)
{
ConfigGui.editSingleOption.getEntry("optionsButton").value = newOptionsButton;
ConfigGui.editSingleOption.saveOption("optionsButton");
}
//================// //================//
// Client Configs // // Client Configs //
@@ -58,6 +76,7 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
{ {
graphics = new Graphics(); graphics = new Graphics();
worldGenerator = new WorldGenerator(); worldGenerator = new WorldGenerator();
multiplayer = new Multiplayer();
advanced = new Advanced(); advanced = new Advanced();
} }
@@ -95,8 +114,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
Graphics() Graphics()
{ {
quality = new Quality(); quality = new Quality();
advancedGraphics = new AdvancedGraphics();
fogQuality = new FogQuality(); fogQuality = new FogQuality();
advancedGraphics = new AdvancedGraphics();
} }
@@ -110,7 +129,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setDrawResolution(HorizontalResolution newHorizontalResolution) public void setDrawResolution(HorizontalResolution newHorizontalResolution)
{ {
Config.Client.Graphics.Quality.drawResolution = newHorizontalResolution; ConfigGui.editSingleOption.getEntry("client.graphics.quality.drawResolution").value = newHorizontalResolution;
ConfigGui.editSingleOption.saveOption("client.graphics.quality.drawResolution");
} }
@@ -122,7 +142,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setLodChunkRenderDistance(int newLodChunkRenderDistance) public void setLodChunkRenderDistance(int newLodChunkRenderDistance)
{ {
Config.Client.Graphics.Quality.lodChunkRenderDistance = newLodChunkRenderDistance; ConfigGui.editSingleOption.getEntry("client.graphics.quality.lodChunkRenderDistance").value = newLodChunkRenderDistance;
ConfigGui.editSingleOption.saveOption("client.graphics.quality.lodChunkRenderDistance");
} }
@@ -134,7 +155,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setVerticalQuality(VerticalQuality newVerticalQuality) public void setVerticalQuality(VerticalQuality newVerticalQuality)
{ {
Config.Client.Graphics.Quality.verticalQuality = newVerticalQuality; ConfigGui.editSingleOption.getEntry("client.graphics.quality.verticalQuality").value = newVerticalQuality;
ConfigGui.editSingleOption.saveOption("client.graphics.quality.verticalQuality");
} }
@@ -146,7 +168,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setHorizontalScale(int newHorizontalScale) public void setHorizontalScale(int newHorizontalScale)
{ {
Config.Client.Graphics.Quality.horizontalScale = newHorizontalScale; ConfigGui.editSingleOption.getEntry("client.graphics.quality.horizontalScale").value = newHorizontalScale;
ConfigGui.editSingleOption.saveOption("client.graphics.quality.horizontalScale");
} }
@@ -158,13 +181,42 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setHorizontalQuality(HorizontalQuality newHorizontalQuality) public void setHorizontalQuality(HorizontalQuality newHorizontalQuality)
{ {
Config.Client.Graphics.Quality.horizontalQuality = newHorizontalQuality; ConfigGui.editSingleOption.getEntry("client.graphics.quality.horizontalQuality").value = newHorizontalQuality;
ConfigGui.editSingleOption.saveOption("client.graphics.quality.horizontalQuality");
}
@Override
public DropoffQuality getDropoffQuality() {
return Config.Client.Graphics.Quality.dropoffQuality;
}
@Override
public void setDropoffQuality(DropoffQuality newDropoffQuality) {
ConfigGui.editSingleOption.getEntry("client.graphics.quality.dropoffQuality").value = newDropoffQuality;
ConfigGui.editSingleOption.saveOption("client.graphics.quality.dropoffQuality");
}
@Override
public int getLodBiomeBlending() {
return Config.Client.Graphics.Quality.lodBiomeBlending;
}
@Override
public void setLodBiomeBlending(int newLodBiomeBlending) {
ConfigGui.editSingleOption.getEntry("client.graphics.quality.lodBiomeBlending").value = newLodBiomeBlending;
ConfigGui.editSingleOption.saveOption("client.graphics.quality.lodBiomeBlending");
} }
} }
public static class FogQuality implements IFogQuality public static class FogQuality implements IFogQuality
{ {
public final IAdvancedFog advancedFog;
FogQuality()
{
advancedFog = new AdvancedFog();
}
@Override @Override
public FogDistance getFogDistance() public FogDistance getFogDistance()
{ {
@@ -173,7 +225,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setFogDistance(FogDistance newFogDistance) public void setFogDistance(FogDistance newFogDistance)
{ {
Config.Client.Graphics.FogQuality.fogDistance = newFogDistance; ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.fogDistance").value = newFogDistance;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.fogDistance");
} }
@@ -186,7 +239,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setFogDrawMode(FogDrawMode setFogDrawMode) public void setFogDrawMode(FogDrawMode setFogDrawMode)
{ {
Config.Client.Graphics.FogQuality.fogDrawMode = setFogDrawMode; ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.fogDrawMode").value = setFogDrawMode;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.fogDrawMode");
} }
@@ -199,7 +253,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setFogColorMode(FogColorMode newFogColorMode) public void setFogColorMode(FogColorMode newFogColorMode)
{ {
Config.Client.Graphics.FogQuality.fogColorMode = newFogColorMode; ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.fogColorMode").value = newFogColorMode;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.fogColorMode");
} }
@@ -211,25 +266,175 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setDisableVanillaFog(boolean newDisableVanillaFog) public void setDisableVanillaFog(boolean newDisableVanillaFog)
{ {
Config.Client.Graphics.FogQuality.disableVanillaFog = newDisableVanillaFog; ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.disableVanillaFog").value = newDisableVanillaFog;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.disableVanillaFog");
} }
@Override
public IAdvancedFog advancedFog() {
return advancedFog;
}
public static class AdvancedFog implements IAdvancedFog {
public final IHeightFog heightFog;
public AdvancedFog() {
heightFog = new HeightFog();
}
@Override
public double getFarFogStart() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogStart;
}
@Override
public double getFarFogEnd() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogEnd;
}
@Override
public double getFarFogMin() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogMin;
}
@Override
public double getFarFogMax() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogMax;
}
@Override
public FogSetting.FogType getFarFogType() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogType;
}
@Override
public double getFarFogDensity() {
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogDensity;
}
@Override
public void setFarFogStart(double newFarFogStart) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogStart").value = newFarFogStart;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogStart");
}
@Override
public void setFarFogEnd(double newFarFogEnd) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogEnd").value = newFarFogEnd;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogEnd");
}
@Override
public void setFarFogMin(double newFarFogMin) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogMin").value = newFarFogMin;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogMin");
}
@Override
public void setFarFogMax(double newFarFogMax) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogMax").value = newFarFogMax;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogMax");
}
@Override
public void setFarFogType(FogSetting.FogType newFarFogType) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogType").value = newFarFogType;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogType");
}
@Override
public void setFarFogDensity(double newFarFogDensity) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogDensity").value = newFarFogDensity;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogDensity");
}
@Override
public IHeightFog heightFog() {
return heightFog;
}
public static class HeightFog implements IHeightFog {
@Override
public HeightFogMixMode getHeightFogMixMode() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMixMode;
}
@Override
public HeightFogMode getHeightFogMode() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMode;
}
@Override
public double getHeightFogHeight() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogHeight;
}
@Override
public double getHeightFogStart() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogStart;
}
@Override
public double getHeightFogEnd() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogEnd;
}
@Override
public double getHeightFogMin() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMin;
}
@Override
public double getHeightFogMax() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMax;
}
@Override
public FogSetting.FogType getHeightFogType() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogType;
}
@Override
public double getHeightFogDensity() {
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogDensity;
}
@Override
public void setHeightFogMixMode(HeightFogMixMode newHeightFogMixMode) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMixMode").value = newHeightFogMixMode;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMixMode");
}
@Override
public void setHeightFogMode(HeightFogMode newHeightFogMode) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMode").value = newHeightFogMode;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMode");
}
@Override
public void setHeightFogHeight(double newHeightFogHeight) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogHeight").value = newHeightFogHeight;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogHeight");
}
@Override
public void setHeightFogStart(double newHeightFogStart) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogStart").value = newHeightFogStart;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogStart");
}
@Override
public void setHeightFogEnd(double newHeightFogEnd) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogEnd").value = newHeightFogEnd;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogEnd");
}
@Override
public void setHeightFogMin(double newHeightFogMin) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMin").value = newHeightFogMin;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMin");
}
@Override
public void setHeightFogMax(double newHeightFogMax) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMax").value = newHeightFogMax;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMax");
}
@Override
public void setHeightFogType(FogSetting.FogType newHeightFogType) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogType").value = newHeightFogType;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogType");
}
@Override
public void setHeightFogDensity(double newHeightFogDensity) {
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogDensity").value = newHeightFogDensity;
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogDensity");
}
}
}
} }
public static class AdvancedGraphics implements IAdvancedGraphics public static class AdvancedGraphics implements IAdvancedGraphics
{ {
@Override
public LodTemplate getLodTemplate()
{
return Config.Client.Graphics.AdvancedGraphics.lodTemplate;
}
@Override
public void setLodTemplate(LodTemplate newLodTemplate)
{
Config.Client.Graphics.AdvancedGraphics.lodTemplate = newLodTemplate;
}
@Override @Override
public boolean getDisableDirectionalCulling() public boolean getDisableDirectionalCulling()
{ {
@@ -238,19 +443,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setDisableDirectionalCulling(boolean newDisableDirectionalCulling) public void setDisableDirectionalCulling(boolean newDisableDirectionalCulling)
{ {
Config.Client.Graphics.AdvancedGraphics.disableDirectionalCulling = newDisableDirectionalCulling; ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.disableDirectionalCulling").value = newDisableDirectionalCulling;
} ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.disableDirectionalCulling");
@Override
public boolean getAlwaysDrawAtMaxQuality()
{
return Config.Client.Graphics.AdvancedGraphics.alwaysDrawAtMaxQuality;
}
@Override
public void setAlwaysDrawAtMaxQuality(boolean newAlwaysDrawAtMaxQuality)
{
Config.Client.Graphics.AdvancedGraphics.alwaysDrawAtMaxQuality = newAlwaysDrawAtMaxQuality;
} }
@@ -262,9 +456,21 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setVanillaOverdraw(VanillaOverdraw newVanillaOverdraw) public void setVanillaOverdraw(VanillaOverdraw newVanillaOverdraw)
{ {
Config.Client.Graphics.AdvancedGraphics.vanillaOverdraw = newVanillaOverdraw; ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.vanillaOverdraw").value = newVanillaOverdraw;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.vanillaOverdraw");
} }
/*
@Override
public int getBacksideCullingRange()
{
return Config.Client.Graphics.AdvancedGraphics.backsideCullingRange;
}
@Override
public void setBacksideCullingRange(int newBacksideCullingRange)
{
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.backsideCullingRange").value = newBacksideCullingRange;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.backsideCullingRange");
}*/
@Override @Override
public boolean getUseExtendedNearClipPlane() public boolean getUseExtendedNearClipPlane()
@@ -274,7 +480,32 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setUseExtendedNearClipPlane(boolean newUseExtendedNearClipPlane) public void setUseExtendedNearClipPlane(boolean newUseExtendedNearClipPlane)
{ {
Config.Client.Graphics.AdvancedGraphics.useExtendedNearClipPlane = newUseExtendedNearClipPlane; ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.useExtendedNearClipPlane").value = newUseExtendedNearClipPlane;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.useExtendedNearClipPlane");
}
@Override
public double getBrightnessMultiplier()
{
return Config.Client.Graphics.AdvancedGraphics.brightnessMultiplier;
}
@Override
public void setBrightnessMultiplier(double newBrightnessMultiplier)
{
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.brightnessMultiplier").value = newBrightnessMultiplier;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.brightnessMultiplier");
}
@Override
public double getSaturationMultiplier()
{
return Config.Client.Graphics.AdvancedGraphics.saturationMultiplier;
}
@Override
public void setSaturationMultiplier(double newSaturationMultiplier)
{
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.saturationMultiplier").value = newSaturationMultiplier;
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.saturationMultiplier");
} }
} }
} }
@@ -295,7 +526,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setGenerationPriority(GenerationPriority newGenerationPriority) public void setGenerationPriority(GenerationPriority newGenerationPriority)
{ {
Config.Client.WorldGenerator.generationPriority = newGenerationPriority; ConfigGui.editSingleOption.getEntry("client.worldGenerator.generationPriority").value = newGenerationPriority;
ConfigGui.editSingleOption.saveOption("client.worldGenerator.generationPriority");
} }
@@ -307,10 +539,11 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setDistanceGenerationMode(DistanceGenerationMode newDistanceGenerationMode) public void setDistanceGenerationMode(DistanceGenerationMode newDistanceGenerationMode)
{ {
Config.Client.WorldGenerator.distanceGenerationMode = newDistanceGenerationMode; ConfigGui.editSingleOption.getEntry("client.worldGenerator.distanceGenerationMode").value = newDistanceGenerationMode;
ConfigGui.editSingleOption.saveOption("client.worldGenerator.distanceGenerationMode");
} }
/*
@Override @Override
public boolean getAllowUnstableFeatureGeneration() public boolean getAllowUnstableFeatureGeneration()
{ {
@@ -319,8 +552,9 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setAllowUnstableFeatureGeneration(boolean newAllowUnstableFeatureGeneration) public void setAllowUnstableFeatureGeneration(boolean newAllowUnstableFeatureGeneration)
{ {
Config.Client.WorldGenerator.allowUnstableFeatureGeneration = newAllowUnstableFeatureGeneration; ConfigGui.editSingleOption.getEntry("client.worldGenerator.allowUnstableFeatureGeneration").value = newAllowUnstableFeatureGeneration;
} ConfigGui.editSingleOption.saveOption("client.worldGenerator.allowUnstableFeatureGeneration");
}*/
@Override @Override
@@ -331,12 +565,67 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setBlockToAvoid(BlocksToAvoid newBlockToAvoid) public void setBlockToAvoid(BlocksToAvoid newBlockToAvoid)
{ {
Config.Client.WorldGenerator.blocksToAvoid = newBlockToAvoid; ConfigGui.editSingleOption.getEntry("client.worldGenerator.blocksToAvoid").value = newBlockToAvoid;
ConfigGui.editSingleOption.saveOption("client.worldGenerator.blocksToAvoid");
}
@Override
public boolean getEnableDistantGeneration()
{
return (boolean) ConfigGui.editSingleOption.getEntry("client.worldGenerator.enableDistantGeneration").value;
}
@Override
public void setEnableDistantGeneration(boolean newEnableDistantGeneration)
{
ConfigGui.editSingleOption.getEntry("client.worldGenerator.enableDistantGeneration").value = newEnableDistantGeneration;
ConfigGui.editSingleOption.saveOption("client.worldGenerator.enableDistantGeneration");
}
@Override
public LightGenerationMode getLightGenerationMode()
{
return Config.Client.WorldGenerator.lightGenerationMode;
}
@Override
public void setLightGenerationMode(LightGenerationMode newLightGenerationMode)
{
ConfigGui.editSingleOption.getEntry("client.worldGenerator.lightGenerationMode").value = newLightGenerationMode;
ConfigGui.editSingleOption.saveOption("client.worldGenerator.lightGenerationMode");
} }
} }
//=====================//
// Multiplayer Configs //
//=====================//
public static class Multiplayer implements IMultiplayer
{
@Override
public ServerFolderNameMode getServerFolderNameMode()
{
return Config.Client.Multiplayer.serverFolderNameMode;
}
@Override
public void setServerFolderNameMode(ServerFolderNameMode newServerFolderNameMode)
{
ConfigGui.editSingleOption.getEntry("client.multiplayer.serverFolderNameMode").value = newServerFolderNameMode;
ConfigGui.editSingleOption.saveOption("client.multiplayer.serverFolderNameMode");
}
@Override
public double getMultiDimensionRequiredSimilarity()
{
return Config.Client.Multiplayer.multiDimensionRequiredSimilarity;
}
@Override
public void setMultiDimensionRequiredSimilarity(double newMultiDimensionMinimumSimilarityPercent)
{
ConfigGui.editSingleOption.getEntry("client.multiplayer.multiDimensionMinimumSimilarityPercent").value = newMultiDimensionMinimumSimilarityPercent;
ConfigGui.editSingleOption.saveOption("client.multiplayer.multiDimensionMinimumSimilarityPercent");
}
}
//============================// //============================//
// AdvancedModOptions Configs // // AdvancedModOptions Configs //
@@ -386,7 +675,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setNumberOfWorldGenerationThreads(int newNumberOfWorldGenerationThreads) public void setNumberOfWorldGenerationThreads(int newNumberOfWorldGenerationThreads)
{ {
Config.Client.Advanced.Threading.numberOfWorldGenerationThreads = newNumberOfWorldGenerationThreads; ConfigGui.editSingleOption.getEntry("client.advanced.threading.numberOfWorldGenerationThreads").value = newNumberOfWorldGenerationThreads;
ConfigGui.editSingleOption.saveOption("client.advanced.threading.numberOfWorldGenerationThreads");
} }
@@ -398,7 +688,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setNumberOfBufferBuilderThreads(int newNumberOfWorldBuilderThreads) public void setNumberOfBufferBuilderThreads(int newNumberOfWorldBuilderThreads)
{ {
Config.Client.Advanced.Threading.numberOfBufferBuilderThreads = newNumberOfWorldBuilderThreads; ConfigGui.editSingleOption.getEntry("client.advanced.threading.numberOfBufferBuilderThreads").value = newNumberOfWorldBuilderThreads;
ConfigGui.editSingleOption.saveOption("client.advanced.threading.numberOfBufferBuilderThreads");
} }
} }
@@ -413,36 +704,39 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public boolean getDrawLods() public boolean getDrawLods()
{ {
return Config.Client.Advanced.Debugging.drawLods; return (boolean) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.drawLods").value;
} }
@Override @Override
public void setDrawLods(boolean newDrawLods) public void setDrawLods(boolean newDrawLods)
{ {
Config.Client.Advanced.Debugging.drawLods = newDrawLods; ConfigGui.editSingleOption.getEntry("client.advanced.debugging.drawLods").value = newDrawLods;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.drawLods");
} }
@Override @Override
public DebugMode getDebugMode() public DebugMode getDebugMode()
{ {
return Config.Client.Advanced.Debugging.debugMode; return (DebugMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugMode").value;
} }
@Override @Override
public void setDebugMode(DebugMode newDebugMode) public void setDebugMode(DebugMode newDebugMode)
{ {
Config.Client.Advanced.Debugging.debugMode = newDebugMode; ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugMode").value = newDebugMode;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugMode");
} }
@Override @Override
public boolean getDebugKeybindingsEnabled() public boolean getDebugKeybindingsEnabled()
{ {
return Config.Client.Advanced.Debugging.enableDebugKeybindings; return (boolean) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.enableDebugKeybindings").value;
} }
@Override @Override
public void setDebugKeybindingsEnabled(boolean newEnableDebugKeybindings) public void setDebugKeybindingsEnabled(boolean newEnableDebugKeybindings)
{ {
Config.Client.Advanced.Debugging.enableDebugKeybindings = newEnableDebugKeybindings; ConfigGui.editSingleOption.getEntry("client.advanced.debugging.enableDebugKeybindings").value = newEnableDebugKeybindings;
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.enableDebugKeybindings");
} }
} }
@@ -458,18 +752,20 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setGpuUploadMethod(GpuUploadMethod newDisableVanillaFog) public void setGpuUploadMethod(GpuUploadMethod newDisableVanillaFog)
{ {
Config.Client.Advanced.Buffers.gpuUploadMethod = newDisableVanillaFog; ConfigGui.editSingleOption.getEntry("client.advanced.buffers.gpuUploadMethod").value = newDisableVanillaFog;
ConfigGui.editSingleOption.saveOption("client.advanced.buffers.gpuUploadMethod");
} }
@Override @Override
public int getGpuUploadTimeoutInMilliseconds() public int getGpuUploadPerMegabyteInMilliseconds()
{ {
return Config.Client.Advanced.Buffers.gpuUploadTimeoutInMilleseconds; return Config.Client.Advanced.Buffers.gpuUploadPerMegabyteInMilliseconds;
} }
@Override @Override
public void setGpuUploadTimeoutInMilliseconds(int newTimeoutInMilliseconds) { public void setGpuUploadPerMegabyteInMilliseconds(int newMilliseconds) {
Config.Client.Advanced.Buffers.gpuUploadTimeoutInMilleseconds = newTimeoutInMilliseconds; ConfigGui.editSingleOption.getEntry("client.advanced.buffers.gpuUploadPerMegabyteInMilliseconds").value = newMilliseconds;
ConfigGui.editSingleOption.saveOption("client.advanced.buffers.gpuUploadPerMegabyteInMilliseconds");
} }
@@ -481,7 +777,8 @@ public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
@Override @Override
public void setRebuildTimes(BufferRebuildTimes newBufferRebuildTimes) public void setRebuildTimes(BufferRebuildTimes newBufferRebuildTimes)
{ {
Config.Client.Advanced.Buffers.rebuildTimes = newBufferRebuildTimes; ConfigGui.editSingleOption.getEntry("client.advanced.buffers.newBufferRebuildTimes").value = newBufferRebuildTimes;
ConfigGui.editSingleOption.saveOption("client.advanced.buffers.newBufferRebuildTimes");
} }
} }
} }
@@ -31,7 +31,7 @@ public class TexturedButtonWidget extends ImageButton {
RenderSystem.setShader(GameRenderer::getPositionTexShader); RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderTexture(0, WIDGETS_LOCATION); RenderSystem.setShaderTexture(0, WIDGETS_LOCATION);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha);
int i = this.getYImage(this.isHovered()); int i = this.getYImage(this.isHovered);
RenderSystem.enableBlend(); RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc(); RenderSystem.defaultBlendFunc();
RenderSystem.enableDepthTest(); RenderSystem.enableDepthTest();
@@ -26,10 +26,10 @@ import java.util.ArrayList;
import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.platform.Window;
import com.seibel.lod.core.ModInfo; import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.api.ClientApi; import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.enums.LodDirection; import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.util.LodUtil; import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper; import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper; import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper; import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
@@ -67,13 +67,13 @@ import org.jetbrains.annotations.Nullable;
* to allow for easier movement between Minecraft versions. * to allow for easier movement between Minecraft versions.
* *
* @author James Seibel * @author James Seibel
* @version 9-16-2021 * @version 3-5-2022
*/ */
public class MinecraftWrapper implements IMinecraftWrapper public class MinecraftClientWrapper implements IMinecraftClientWrapper
{ {
public static final MinecraftWrapper INSTANCE = new MinecraftWrapper(); public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
private final Minecraft mc = Minecraft.getInstance(); public final Minecraft mc = Minecraft.getInstance();
/** /**
* The lightmap for the current: * The lightmap for the current:
@@ -84,7 +84,7 @@ public class MinecraftWrapper implements IMinecraftWrapper
private ProfilerWrapper profilerWrapper; private ProfilerWrapper profilerWrapper;
private MinecraftWrapper() private MinecraftClientWrapper()
{ {
} }
@@ -153,7 +153,9 @@ public class MinecraftWrapper implements IMinecraftWrapper
@Override @Override
public IDimensionTypeWrapper getCurrentDimension() public IDimensionTypeWrapper getCurrentDimension()
{ {
return DimensionTypeWrapper.getDimensionTypeWrapper(mc.player.level.dimensionType()); if (mc.player != null)
return DimensionTypeWrapper.getDimensionTypeWrapper(mc.player.level.dimensionType());
else return null;
} }
@Override @Override
@@ -178,31 +180,36 @@ public class MinecraftWrapper implements IMinecraftWrapper
/** /**
* Returns the color int at the given pixel coordinates * Returns the color int at the given pixel coordinates
* from the current lightmap. * from the current lightmap.
* @param u x location in texture space * @param blockLight x location in texture space
* @param v z location in texture space * @param skyLight z location in texture space
*/ */
@Override @Override
public int getColorIntFromLightMap(int u, int v) public int getColorIntFromLightMap(int blockLight, int skyLight)
{ {
if (lightMap == null) if (lightMap == null)
{ {
sendChatMessage("new");
// make sure the lightMap is up-to-date // make sure the lightMap is up-to-date
getCurrentLightMap(); getCurrentLightMap();
} }
return lightMap.getPixelRGBA(u, v); return lightMap.getPixelRGBA(blockLight, skyLight);
} }
/** /**
* Returns the Color at the given pixel coordinates * Returns the Color at the given pixel coordinates
* from the current lightmap. * from the current lightmap.
* @param u x location in texture space * @param blockLight x location in texture space
* @param v z location in texture space * @param skyLight z location in texture space
*/ */
@Override @Override
public Color getColorFromLightMap(int u, int v) public Color getColorFromLightMap(int blockLight, int skyLight) {
{ if (lightMap == null) {
return LodUtil.intToColor(lightMap.getPixelRGBA(u, v)); // make sure the lightMap is up-to-date
getCurrentLightMap();
}
return LodUtil.intToColor(lightMap.getPixelRGBA(blockLight, skyLight));
} }
@@ -411,7 +418,7 @@ public class MinecraftWrapper implements IMinecraftWrapper
@Override @Override
public void crashMinecraft(String errorMessage, Throwable exception) public void crashMinecraft(String errorMessage, Throwable exception)
{ {
ClientApi.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft..."); ApiShared.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
CrashReport report = new CrashReport(errorMessage, exception); CrashReport report = new CrashReport(errorMessage, exception);
Minecraft.crash(report); Minecraft.crash(report);
} }
@@ -2,28 +2,46 @@ package com.seibel.lod.common.wrappers.minecraft;
import java.awt.*; import java.awt.*;
import java.util.HashSet; import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.stream.Collectors;
import org.lwjgl.opengl.GL20; import com.mojang.blaze3d.pipeline.RenderTarget;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.lod.common.wrappers.misc.LightMapWrapper;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.LodUtil;
import net.minecraft.client.renderer.LightTexture;
import com.mojang.math.Vector3f; import com.mojang.math.Vector3f;
import com.seibel.lod.core.objects.math.Mat4f; import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3d; import com.seibel.lod.core.objects.math.Vec3d;
import com.seibel.lod.core.objects.math.Vec3f; import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper; import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import com.seibel.lod.common.wrappers.McObjectConverter; import com.seibel.lod.common.wrappers.McObjectConverter;
import com.seibel.lod.common.wrappers.WrapperFactory;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper; import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkPosWrapper;
import net.minecraft.client.Camera; import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.LevelRenderer.RenderChunkInfo;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.world.effect.MobEffects; import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.material.FogType;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.Vec3;
@@ -32,130 +50,279 @@ import net.minecraft.world.phys.Vec3;
* related to rendering in Minecraft. * related to rendering in Minecraft.
* *
* @author James Seibel * @author James Seibel
* @version 11-26-2021 * @version 12-12-2021
*/ */
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
{ {
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper(); public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
private final GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer; private static final Minecraft MC = Minecraft.getInstance();
private final static Minecraft mc = Minecraft.getInstance(); private static final GameRenderer GAME_RENDERER = MC.gameRenderer;
private static final IWrapperFactory FACTORY = WrapperFactory.INSTANCE;
@Override
public Vec3f getLookAtVector()
{
Camera camera = GAME_RENDERER.getMainCamera();
Vector3f cameraDir = camera.getLookVector();
return new Vec3f(cameraDir.x(), cameraDir.y(), cameraDir.z());
}
@Override
public AbstractBlockPosWrapper getCameraBlockPosition()
{
Camera camera = GAME_RENDERER.getMainCamera();
BlockPos blockPos = camera.getBlockPosition();
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
}
@Override @Override
public Vec3f getLookAtVector() public boolean playerHasBlindnessEffect()
{ {
Camera camera = gameRenderer.getMainCamera(); return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null;
Vector3f cameraDir = camera.getLookVector(); }
return new Vec3f(cameraDir.x(), cameraDir.y(), cameraDir.z());
@Override
public Vec3d getCameraExactPosition()
{
Camera camera = GAME_RENDERER.getMainCamera();
Vec3 projectedView = camera.getPosition();
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
}
@Override
public Mat4f getDefaultProjectionMatrix(float partialTicks)
{
return McObjectConverter.Convert(GAME_RENDERER.getProjectionMatrix(GAME_RENDERER.getFov(GAME_RENDERER.getMainCamera(), partialTicks, true)));
}
@Override
public double getGamma()
{
return MC.options.gamma;
}
@Override
public Color getFogColor(float partialTicks) {
FogRenderer.setupColor(GAME_RENDERER.getMainCamera(), partialTicks, MC.level, 1, GAME_RENDERER.getDarkenWorldAmount(partialTicks));
float[] colorValues = RenderSystem.getShaderFogColor();
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
}
// getSpecialFogColor() is the same as getFogColor()
@Override
public Color getSkyColor() {
if (MC.level.dimensionType().hasSkyLight()) {
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), MC.getFrameTime());
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
} else
return new Color(0, 0, 0);
}
@Override
public double getFov(float partialTicks)
{
return GAME_RENDERER.getFov(GAME_RENDERER.getMainCamera(), partialTicks, true);
}
/** Measured in chunks */
@Override
public int getRenderDistance()
{
return MC.options.getEffectiveRenderDistance();
}
@Override
public int getScreenWidth()
{
return MC.getWindow().getWidth();
}
@Override
public int getScreenHeight()
{
return MC.getWindow().getHeight();
}
private RenderTarget getRenderTarget() {
RenderTarget r = null; //MC.levelRenderer.getCloudsTarget();
return r!=null ? r : MC.getMainRenderTarget();
} }
@Override @Override
public AbstractBlockPosWrapper getCameraBlockPosition() public int getTargetFrameBuffer() {
{ return getRenderTarget().frameBufferId;
Camera camera = gameRenderer.getMainCamera();
BlockPos blockPos = camera.getBlockPosition();
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
} }
@Override @Override
public boolean playerHasBlindnessEffect() public int getTargetFrameBufferViewportWidth() {
{ return getRenderTarget().viewWidth;
return mc.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null;
} }
@Override @Override
public Vec3d getCameraExactPosition() public int getTargetFrameBufferViewportHeight() {
{ return getRenderTarget().viewHeight;
Camera camera = gameRenderer.getMainCamera();
Vec3 projectedView = camera.getPosition();
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
} }
@Override /**
public Mat4f getDefaultProjectionMatrix(float partialTicks) * This method returns the ChunkPos of all chunks that Minecraft
{ * is going to render this frame. <br><br>
return McObjectConverter.Convert(gameRenderer.getProjectionMatrix(gameRenderer.getFov(gameRenderer.getMainCamera(), partialTicks, true))); * <p>
} */
@Override public boolean usingBackupGetVanillaRenderedChunks = true;
public double getGamma() @Override
{ public HashSet<AbstractChunkPosWrapper> getVanillaRenderedChunks()
return mc.options.gamma; {
} ISodiumAccessor sodium = ModAccessorHandler.get(ISodiumAccessor.class);
if (sodium != null)
{
return sodium.getNormalRenderedChunks();
}
IOptifineAccessor optifine = ModAccessorHandler.get(IOptifineAccessor.class);
if (optifine != null)
{
HashSet<AbstractChunkPosWrapper> pos = optifine.getNormalRenderedChunks();
if (pos == null)
pos = getMaximumRenderedChunks();
return pos;
}
if (!usingBackupGetVanillaRenderedChunks) {
try {
LevelRenderer levelRenderer = MC.levelRenderer;
LinkedHashSet<LevelRenderer.RenderChunkInfo> chunks = levelRenderer.renderChunkStorage.get().renderChunks;
return (chunks.stream().map((chunk) -> {
#if MC_VERSION_1_18_2
AABB chunkBoundingBox = chunk.chunk.getBoundingBox();
#elif MC_VERSION_1_18_1
AABB chunkBoundingBox = chunk.chunk.bb;
#endif
return FACTORY.createChunkPos(Math.floorDiv((int) chunkBoundingBox.minX, 16),
Math.floorDiv((int) chunkBoundingBox.minZ, 16));
}).collect(Collectors.toCollection(HashSet::new)));
} catch (LinkageError e) {
try {
MinecraftClientWrapper.INSTANCE.sendChatMessage(
"\u00A7e\u00A7l\u00A7uWARNING: Distant Horizons: getVanillaRenderedChunks method failed."
+ " Using Backup Method.");
MinecraftClientWrapper.INSTANCE.sendChatMessage(
"\u00A7eOverdraw prevention will be worse than normal.");
} catch (Exception e2) {}
ApiShared.LOGGER.error("getVanillaRenderedChunks Error: ", e);
usingBackupGetVanillaRenderedChunks = true;
}
}
return getMaximumRenderedChunks();
}
@Override @Override
public Color getFogColor() { public int[] getLightmapPixels()
float[] colorValues = new float[4]; {
GL20.glGetFloatv(GL20.GL_FOG_COLOR, colorValues); LightTexture tex = GAME_RENDERER.lightTexture();
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]); tex.tick(); // This call makes no sense, but it fixes pause menu flicker bug
} NativeImage lightMapPixels = tex.lightPixels;
LightMapWrapper lightMap = new LightMapWrapper(lightMapPixels);
@Override
public Color getSkyColor() {
if (mc.level.dimensionType().hasSkyLight()) {
Vec3 colorValues = mc.level.getSkyColor(mc.gameRenderer.getMainCamera().getPosition(), mc.getFrameTime());
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
} else
return new Color(0, 0, 0);
}
@Override int lightMapHeight = getLightmapTextureHeight();
public double getFov(float partialTicks) int lightMapWidth = getLightmapTextureWidth();
{
return gameRenderer.getFov(gameRenderer.getMainCamera(), partialTicks, true);
}
/** Measured in chunks */ int[] pixels = new int[lightMapWidth * lightMapHeight];
@Override for (int u = 0; u < lightMapWidth; u++)
public int getRenderDistance() {
{ for (int v = 0; v < lightMapWidth; v++)
return mc.options.renderDistance; {
} // this could probably be kept as a int, but
// it is easier to test and see the colors when debugging this way.
// When creating a new release this should be changed to the int version.
Color c = LodUtil.intToColor(lightMap.getLightValue(u, v));
@Override // these should both create a totally white image
public int getScreenWidth() // int col =
{ // Integer.MAX_VALUE;
return mc.getWindow().getWidth(); // int col =
} // 0b11111111 + // red
@Override // (0b11111111 << 8) + // green
public int getScreenHeight() // (0b11111111 << 16) + // blue
{ // (0b11111111 << 24); // blue
return mc.getWindow().getHeight();
}
/** int col =
* This method returns the ChunkPos of all chunks that Minecraft ((c.getRed() & 0xFF) << 16) | // blue
* is going to render this frame. <br><br> ((c.getGreen() & 0xFF) << 8) | // green
* <p> ((c.getBlue() & 0xFF)) | // red
* Note: This isn't perfect. It will return some chunks that are outside ((c.getAlpha() & 0xFF) << 24); // alpha
* the clipping plane. (For example, if you are high above the ground some chunks
* will be incorrectly added, even though they are outside render range).
*/
@Override
public HashSet<AbstractChunkPosWrapper> getRenderedChunks()
{
HashSet<AbstractChunkPosWrapper> loadedPos = new HashSet<>();
// Wow, those are some long names! // 2D array stored in a 1D array.
// Thank you Tim from College ;)
pixels[u * lightMapWidth + v] = col;
}
}
// go through every RenderInfo to get the compiled chunks return pixels;
LevelRenderer renderer = mc.levelRenderer; }
for (RenderChunkInfo worldRenderer$LocalRenderInformationContainer : renderer.renderChunks)
{
CompiledChunk compiledChunk = worldRenderer$LocalRenderInformationContainer.chunk.getCompiledChunk();
if (!compiledChunk.hasNoRenderableLayers())
{
// add the ChunkPos for every rendered chunk
BlockPos bpos = worldRenderer$LocalRenderInformationContainer.chunk.getOrigin();
loadedPos.add(new ChunkPosWrapper(bpos));
}
}
return loadedPos; @Override
} public int getLightmapTextureHeight()
{
int height = -1;
LightTexture lightTexture = GAME_RENDERER.lightTexture();
if (lightTexture != null)
{
NativeImage tex = lightTexture.lightPixels;
if (tex != null)
{
height = tex.getHeight();
}
}
return height;
}
@Override
public int getLightmapTextureWidth()
{
int width = -1;
LightTexture lightTexture = GAME_RENDERER.lightTexture();
if (lightTexture != null)
{
NativeImage tex = lightTexture.lightPixels;
if (tex != null)
{
width = tex.getWidth();
}
}
return width;
}
@Override
public int getLightmapGLFormat() {
int glFormat = -1;
LightTexture lightTexture = GAME_RENDERER.lightTexture();
if (lightTexture != null) {
NativeImage tex = lightTexture.lightPixels;
if (tex != null) {
glFormat = tex.format().glFormat();
}
}
return glFormat;
}
@Override
public boolean isFogStateSpecial() {
Entity entity = GAME_RENDERER.getMainCamera().getEntity();
boolean isBlind = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
return GAME_RENDERER.getMainCamera().getFluidInCamera() != FogType.NONE || isBlind;
}
@Override
public boolean tryDisableVanillaFog() {
return true; // Handled via MixinFogRenderer in both forge and fabric
}
} }
@@ -1,59 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* 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, version 3.
*
* 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.seibel.lod.common.wrappers.world;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeColorWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
import net.minecraft.client.renderer.BiomeColors;
/**
* @author Cola?
* @version 11-15-2021
*/
public class BiomeColorWrapperSingleton implements IBiomeColorWrapperSingleton
{
private static final BiomeColorWrapperSingleton instance = new BiomeColorWrapperSingleton();
@Override
public IBiomeColorWrapperSingleton getInstance()
{
return instance;
}
@Override
public int getGrassColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
{
return BiomeColors.getAverageGrassColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
}
@Override
public int getWaterColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
{
return BiomeColors.getAverageWaterColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
}
@Override
public int getFoliageColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
{
return BiomeColors.getAverageFoliageColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
}
}
@@ -36,7 +36,7 @@ public class BiomeWrapper implements IBiomeWrapper
{ {
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>(); public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
private Biome biome; private final Biome biome;
public BiomeWrapper(Biome biome) public BiomeWrapper(Biome biome)
{ {
@@ -65,7 +65,7 @@ public class BiomeWrapper implements IBiomeWrapper
{ {
int colorInt; int colorInt;
switch (biome.getBiomeCategory()) switch (biome.biomeCategory)
{ {
case NETHER: case NETHER:
@@ -120,6 +120,11 @@ public class BiomeWrapper implements IBiomeWrapper
return colorInt; return colorInt;
} }
@Override public String getName()
{
return biome.toString();
}
@Override @Override
public int getGrassTint(int x, int z) public int getGrassTint(int x, int z)
{ {
@@ -34,7 +34,7 @@ import net.minecraft.world.level.dimension.DimensionType;
public class DimensionTypeWrapper implements IDimensionTypeWrapper public class DimensionTypeWrapper implements IDimensionTypeWrapper
{ {
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>(); private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
private DimensionType dimensionType; private final DimensionType dimensionType;
public DimensionTypeWrapper(DimensionType dimensionType) public DimensionTypeWrapper(DimensionType dimensionType)
{ {
@@ -24,16 +24,21 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.enums.WorldType; import com.seibel.lod.core.enums.WorldType;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper; import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper; import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.common.wrappers.block.BlockPosWrapper; import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LightLayer; import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.chunk.ChunkStatus;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/** /**
@@ -96,21 +101,15 @@ public class WorldWrapper implements IWorldWrapper
} }
@Override @Override
public int getBlockLight(AbstractBlockPosWrapper blockPos) public int getBlockLight(int x, int y, int z)
{ {
return world.getBrightness(LightLayer.BLOCK, ((BlockPosWrapper) blockPos).getBlockPos()); return world.getBrightness(LightLayer.BLOCK, new BlockPos(x,y,z));
} }
@Override @Override
public int getSkyLight(AbstractBlockPosWrapper blockPos) public int getSkyLight(int x, int y, int z)
{ {
return world.getBrightness(LightLayer.SKY, ((BlockPosWrapper) blockPos).getBlockPos()); return world.getBrightness(LightLayer.SKY, new BlockPos(x,y,z));
}
@Override
public IBiomeWrapper getBiome(AbstractBlockPosWrapper blockPos)
{
return BiomeWrapper.getBiomeWrapper(world.getBiome(((BlockPosWrapper) blockPos).getBlockPos()));
} }
public LevelAccessor getWorld() public LevelAccessor getWorld()
@@ -130,18 +129,18 @@ public class WorldWrapper implements IWorldWrapper
return world.dimensionType().hasSkyLight(); return world.dimensionType().hasSkyLight();
} }
@Override
public boolean isEmpty()
{
return world == null;
}
@Override @Override
public int getHeight() public int getHeight()
{ {
return world.getHeight(); return world.getHeight();
} }
@Override
public short getMinHeight()
{
return (short) world.getMinBuildHeight();
}
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */ /** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
@Override @Override
public File getSaveFolder() throws UnsupportedOperationException public File getSaveFolder() throws UnsupportedOperationException
@@ -170,5 +169,19 @@ public class WorldWrapper implements IWorldWrapper
return world.getSeaLevel(); return world.getSeaLevel();
} }
@Override
public IChunkWrapper tryGetChunk(AbstractChunkPosWrapper pos) {
ChunkAccess chunk = world.getChunk(pos.getX(), pos.getZ(), ChunkStatus.EMPTY, false);
if (chunk == null) return null;
return new ChunkWrapper(chunk, world);
}
@Override
public boolean hasChunkLoaded(int chunkX, int chunkZ) {
// world.hasChunk(chunkX, chunkZ); THIS DOES NOT WORK FOR CLIENT LEVEL CAUSE MOJANG ALWAYS RETURN TRUE FOR THAT!
ChunkSource source = world.getChunkSource();
return source.hasChunk(chunkX, chunkZ);
}
} }
@@ -0,0 +1,607 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2021 Tom Lee (TomTheFurry)
*
* 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, version 3.
*
* 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.seibel.lod.common.wrappers.worldGeneration;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.enums.config.LightGenerationMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.util.gridList.ArrayGridList;
import com.seibel.lod.core.util.LodThreadFactory;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
import java.time.Duration;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.seibel.lod.common.wrappers.DependencySetupDoneCheck;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.common.wrappers.world.WorldWrapper;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.ChunkLoader;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightGetterAdaptor;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenLevelLightEngine;
import com.seibel.lod.common.wrappers.worldGeneration.step.StepBiomes;
import com.seibel.lod.common.wrappers.worldGeneration.step.StepFeatures;
import com.seibel.lod.common.wrappers.worldGeneration.step.StepLight;
import com.seibel.lod.common.wrappers.worldGeneration.step.StepNoise;
import com.seibel.lod.common.wrappers.worldGeneration.step.StepStructureReference;
import com.seibel.lod.common.wrappers.worldGeneration.step.StepStructureStart;
import com.seibel.lod.common.wrappers.worldGeneration.step.StepSurface;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.levelgen.DebugLevelSource;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.core.Registry;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.lighting.LevelLightEngine;
/*
Total: 3.135214124s
=====================================
Empty Chunks: 0.000558328s
StructureStart Step: 0.025177207s
StructureReference Step: 0.00189559s
Biome Step: 0.13789155s
Noise Step: 1.570347555s
Surface Step: 0.741238194s
Carver Step: 0.000009923s
Feature Step: 0.389072425s
Lod Generation: 0.269023348s
*/
public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnvionmentWrapper
{
public static final boolean ENABLE_PERF_LOGGING = false;
public static final boolean ENABLE_EVENT_LOGGING = false;
public static final boolean ENABLE_LOAD_EVENT_LOGGING = false;
//TODO: Make actual proper support for StarLight
public static class PrefEvent
{
long beginNano = 0;
long emptyNano = 0;
long structStartNano = 0;
long structRefNano = 0;
long biomeNano = 0;
long noiseNano = 0;
long surfaceNano = 0;
long carverNano = 0;
long featureNano = 0;
long lightNano = 0;
long endNano = 0;
@Override
public String toString()
{
return "beginNano: " + beginNano + ",\n" +
"emptyNano: " + emptyNano + ",\n" +
"structStartNano: " + structStartNano + ",\n" +
"structRefNano: " + structRefNano + ",\n" +
"biomeNano: " + biomeNano + ",\n" +
"noiseNano: " + noiseNano + ",\n" +
"surfaceNano: " + surfaceNano + ",\n" +
"carverNano: " + carverNano + ",\n" +
"featureNano: " + featureNano + ",\n" +
"lightNano: " + lightNano + ",\n" +
"endNano: " + endNano + "\n";
}
}
public static class PerfCalculator
{
public static final int SIZE = 50;
Rolling totalTime = new Rolling(SIZE);
Rolling emptyTime = new Rolling(SIZE);
Rolling structStartTime = new Rolling(SIZE);
Rolling structRefTime = new Rolling(SIZE);
Rolling biomeTime = new Rolling(SIZE);
Rolling noiseTime = new Rolling(SIZE);
Rolling surfaceTime = new Rolling(SIZE);
Rolling carverTime = new Rolling(SIZE);
Rolling featureTime = new Rolling(SIZE);
Rolling lightTime = new Rolling(SIZE);
Rolling lodTime = new Rolling(SIZE);
public void recordEvent(PrefEvent e)
{
long preTime = e.beginNano;
totalTime.add(e.endNano - preTime);
if (e.emptyNano != 0)
{
emptyTime.add(e.emptyNano - preTime);
preTime = e.emptyNano;
}
if (e.structStartNano != 0)
{
structStartTime.add(e.structStartNano - preTime);
preTime = e.structStartNano;
}
if (e.structRefNano != 0)
{
structRefTime.add(e.structRefNano - preTime);
preTime = e.structRefNano;
}
if (e.biomeNano != 0)
{
biomeTime.add(e.biomeNano - preTime);
preTime = e.biomeNano;
}
if (e.noiseNano != 0)
{
noiseTime.add(e.noiseNano - preTime);
preTime = e.noiseNano;
}
if (e.surfaceNano != 0)
{
surfaceTime.add(e.surfaceNano - preTime);
preTime = e.surfaceNano;
}
if (e.carverNano != 0)
{
carverTime.add(e.carverNano - preTime);
preTime = e.carverNano;
}
if (e.featureNano != 0)
{
featureTime.add(e.featureNano - preTime);
preTime = e.featureNano;
}
if (e.lightNano != 0)
{
lightTime.add(e.lightNano - preTime);
preTime = e.lightNano;
}
if (e.endNano != 0)
{
lodTime.add(e.endNano - preTime);
}
}
public String toString()
{
return "Total: " + Duration.ofNanos((long) totalTime.getAverage()) + ", Empty/LoadChunk: "
+ Duration.ofNanos((long) emptyTime.getAverage()) + ", StructStart: "
+ Duration.ofNanos((long) structStartTime.getAverage()) + ", StructRef: "
+ Duration.ofNanos((long) structRefTime.getAverage()) + ", Biome: "
+ Duration.ofNanos((long) biomeTime.getAverage()) + ", Noise: "
+ Duration.ofNanos((long) noiseTime.getAverage()) + ", Surface: "
+ Duration.ofNanos((long) surfaceTime.getAverage()) + ", Carver: "
+ Duration.ofNanos((long) carverTime.getAverage()) + ", Feature: "
+ Duration.ofNanos((long) featureTime.getAverage()) + ", Light: "
+ Duration.ofNanos((long) lightTime.getAverage()) + ", Lod: "
+ Duration.ofNanos((long) lodTime.getAverage());
}
}
public static final int TIMEOUT_SECONDS = 60;
//=================Generation Step===================
public final LinkedList<GenerationEvent> events = new LinkedList<>();
public final GlobalParameters params;
public final StepStructureStart stepStructureStart = new StepStructureStart(this);
public final StepStructureReference stepStructureReference = new StepStructureReference(this);
public final StepBiomes stepBiomes = new StepBiomes(this);
public final StepNoise stepNoise = new StepNoise(this);
public final StepSurface stepSurface = new StepSurface(this);
public final StepFeatures stepFeatures = new StepFeatures(this);
public final StepLight stepLight = new StepLight(this);
public boolean unsafeThreadingRecorded = false;
//public boolean safeMode = false;
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
public static final long EXCEPTION_TIMER_RESET_TIME = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
public static final int EXCEPTION_COUNTER_TRIGGER = 20;
public static final int RANGE_TO_RANGE_EMPTY_EXTENSION = 1;
public int unknownExceptionCount = 0;
public long lastExceptionTriggerTime = 0;
public static final LodThreadFactory threadFactory = new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY);
public static ThreadLocal<Boolean> isDistantGeneratorThread = new ThreadLocal<>();
public static boolean isCurrentThreadDistantGeneratorThread() {
return (isDistantGeneratorThread.get() != null);
}
static {
DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
}
public ExecutorService executors = Executors.newFixedThreadPool(
CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads(), threadFactory);
public <T> T joinSync(CompletableFuture<T> f) {
if (!unsafeThreadingRecorded && !f.isDone()) {
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons: Unsafe Threading in Chunk Generator Detected!");
MC.sendChatMessage("\u00A7eTo increase stability, it is recommended to set world generation threads count to 1.");
ApiShared.LOGGER.error("Unsafe Threading in Chunk Generator: ", new RuntimeException("Concurrent future"));
unsafeThreadingRecorded = true;
}
return f.join();
}
public void resizeThreadPool(int newThreadCount)
{
executors = Executors.newFixedThreadPool(newThreadCount,
new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY));
}
public boolean tryAddPoint(int px, int pz, int range, Steps target, boolean genAllDetails)
{
int boxSize = range * 2 + 1;
int x = Math.floorDiv(px, boxSize) * boxSize + range;
int z = Math.floorDiv(pz, boxSize) * boxSize + range;
for (GenerationEvent event : events)
{
if (event.tooClose(x, z, range))
return false;
}
// System.out.println(x + ", "+z);
events.add(new GenerationEvent(new ChunkPos(x, z), range, this, target, genAllDetails));
return true;
}
public void updateAllFutures()
{
if (unknownExceptionCount > 0) {
if (System.nanoTime() - lastExceptionTriggerTime >= EXCEPTION_TIMER_RESET_TIME) {
unknownExceptionCount = 0;
}
}
// Update all current out standing jobs
Iterator<GenerationEvent> iter = events.iterator();
while (iter.hasNext())
{
GenerationEvent event = iter.next();
if (event.isCompleted())
{
try
{
event.join();
}
catch (Throwable e)
{
ApiShared.LOGGER.error("Batching World Generator: Event {} gotten an exception", event);
ApiShared.LOGGER.error("Exception: ", e);
unknownExceptionCount++;
lastExceptionTriggerTime = System.nanoTime();
}
finally
{
iter.remove();
}
}
else if (event.hasTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS))
{
ApiShared.LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
ApiShared.LOGGER.info("Dump PrefEvent: " + event.pEvent);
try
{
if (!event.terminate())
ApiShared.LOGGER.error("Failed to terminate the stuck generation event!");
}
finally
{
iter.remove();
}
}
}
if (unknownExceptionCount > EXCEPTION_COUNTER_TRIGGER) {
try {
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons: Too many exceptions in Batching World Generator! Disabling the generator.");
} catch (Exception e) {}
ApiShared.LOGGER.error("Too many exceptions in Batching World Generator! Now disabling.");
unknownExceptionCount = 0;
CONFIG.client().worldGenerator().setEnableDistantGeneration(false);
}
}
public BatchGenerationEnvironment(IWorldWrapper serverlevel, LodBuilder lodBuilder, LodDimension lodDim)
{
super(serverlevel, lodBuilder, lodDim);
ApiShared.LOGGER.info("================WORLD_GEN_STEP_INITING=============");
ChunkGenerator generator = ((WorldWrapper) serverlevel).getServerWorld().getChunkSource().getGenerator();
if (!(generator instanceof NoiseBasedChunkGenerator ||
generator instanceof DebugLevelSource ||
generator instanceof FlatLevelSource)) {
MC.sendChatMessage("\u00A74\u00A7l\u00A7uWARNING: Distant Horizons: Unknown Chunk Generator Detected! Distant Generation May Fail!");
MC.sendChatMessage("\u00A7eIf it does crash, set Distant Generation to OFF or Generation Mode to None.");
ApiShared.LOGGER.warn("Unknown Chunk Generator detected: {}", generator.getClass());
}
params = new GlobalParameters((ServerLevel) ((WorldWrapper) serverlevel).getWorld(), lodBuilder, lodDim);
}
@SuppressWarnings("resource")
public static ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, ServerLevel level, LevelLightEngine lightEngine)
{
CompoundTag chunkData = null;
try
{
chunkData = level.getChunkSource().chunkMap.readChunk(chunkPos);
}
catch (Exception e)
{
ApiShared.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
}
if (chunkData == null)
{
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null);
}
else
{
try {
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
} catch (Exception e) {
ApiShared.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null);
}
}
}
public void generateLodFromList(GenerationEvent e)
{
if (ENABLE_EVENT_LOGGING)
ApiShared.LOGGER.info("Lod Generate Event: " + e.pos);
e.pEvent.beginNano = System.nanoTime();
ArrayGridList<ChunkAccess> referencedChunks;
ArrayGridList<ChunkAccess> genChunks;
DistanceGenerationMode generationMode;
LightedWorldGenRegion region;
WorldGenLevelLightEngine lightEngine;
LightGetterAdaptor adaptor;
int refRange = e.range + RANGE_TO_RANGE_EMPTY_EXTENSION;
int refOffsetX = e.pos.x - refRange;
int refOffsetZ = e.pos.z - refRange;
try
{
adaptor = new LightGetterAdaptor(params.level);
lightEngine = new WorldGenLevelLightEngine(adaptor);
@SuppressWarnings("resource")
EmptyChunkGenerator generator = (int x, int z) ->
{
ChunkPos chunkPos = new ChunkPos(x, z);
ChunkAccess target = null;
try
{
target = loadOrMakeChunk(chunkPos, params.level, lightEngine);
}
catch (RuntimeException e2)
{
// Continue...
}
if (target == null)
target = new ProtoChunk(chunkPos, UpgradeData.EMPTY, params.level,
params.biomes, null);
return target;
};
referencedChunks = new ArrayGridList<>(refRange*2+1,
(x,z) -> generator.generate(x + refOffsetX,z + refOffsetZ)
);
e.pEvent.emptyNano = System.nanoTime();
e.refreshTimeout();
region = new LightedWorldGenRegion(params.level, lightEngine, referencedChunks,
ChunkStatus.STRUCTURE_STARTS, refRange, e.lightMode, generator);
adaptor.setRegion(region);
e.tParam.makeStructFeat(region);
genChunks = new ArrayGridList<>(referencedChunks, RANGE_TO_RANGE_EMPTY_EXTENSION,
referencedChunks.gridSize - RANGE_TO_RANGE_EMPTY_EXTENSION);
generateDirect(e, genChunks, e.target, region);
}
catch (StepStructureStart.StructStartCorruptedException f)
{
e.tParam.markAsInvalid();
return;
}
switch (e.target)
{
case Empty:
case StructureStart:
case StructureReference:
generationMode = DistanceGenerationMode.NONE;
break;
case Biomes:
generationMode = DistanceGenerationMode.BIOME_ONLY;
case Noise:
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
break;
case Surface:
case Carvers:
generationMode = DistanceGenerationMode.SURFACE;
break;
case Features:
generationMode = DistanceGenerationMode.FEATURES;
break;
case Light:
case LiquidCarvers:
default:
return;
}
for (int oy = 0; oy < genChunks.gridSize; oy++)
{
for (int ox = 0; ox < genChunks.gridSize; ox++)
{
ChunkAccess target = genChunks.get(ox, oy);
ChunkWrapper wrappedChunk = new ChunkWrapper(target, region);
if (!wrappedChunk.isLightCorrect()) {
throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false");
}
boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk;
boolean isPartial = target.isOldNoiseGeneration();
if (isFull)
{
if (ENABLE_LOAD_EVENT_LOGGING)
ApiShared.LOGGER.info("Detected full existing chunk at {}", target.getPos());
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
new LodBuilderConfig(DistanceGenerationMode.FULL), true, e.genAllDetails);
}
else if (isPartial)
{
if (ENABLE_LOAD_EVENT_LOGGING)
ApiShared.LOGGER.info("Detected old existing chunk at {}", target.getPos());
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
new LodBuilderConfig(generationMode), true, e.genAllDetails);
}
else if (target.getStatus() == ChunkStatus.EMPTY && generationMode == DistanceGenerationMode.NONE)
{
params.lodBuilder.generateLodNodeFromChunk(params.lodDim,wrappedChunk,
LodBuilderConfig.getFillVoidConfig(), true, e.genAllDetails);
}
else
{
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
new LodBuilderConfig(generationMode), true, e.genAllDetails);
}
if (e.lightMode == LightGenerationMode.FANCY || isFull)
{
lightEngine.retainData(target.getPos(), false);
}
}
}
e.pEvent.endNano = System.nanoTime();
e.refreshTimeout();
if (ENABLE_PERF_LOGGING)
{
e.tParam.perf.recordEvent(e.pEvent);
ApiShared.LOGGER.info(e.tParam.perf);
}
}
public void generateDirect(GenerationEvent e, ArrayGridList<ChunkAccess> subRange, Steps step,
LightedWorldGenRegion region)
{
try
{
subRange.forEach((chunk) ->
{
if (chunk instanceof ProtoChunk)
{
((ProtoChunk) chunk).setLightEngine(region.getLightEngine());
region.getLightEngine().retainData(chunk.getPos(), true);
}
});
if (step == Steps.Empty)
return;
stepStructureStart.generateGroup(e.tParam, region, subRange);
e.pEvent.structStartNano = System.nanoTime();
e.refreshTimeout();
if (step == Steps.StructureStart)
return;
stepStructureReference.generateGroup(e.tParam, region, subRange);
e.pEvent.structRefNano = System.nanoTime();
e.refreshTimeout();
if (step == Steps.StructureReference)
return;
stepBiomes.generateGroup(e.tParam, region, subRange);
e.pEvent.biomeNano = System.nanoTime();
e.refreshTimeout();
if (step == Steps.Biomes)
return;
stepNoise.generateGroup(e.tParam, region, subRange);
e.pEvent.noiseNano = System.nanoTime();
e.refreshTimeout();
if (step == Steps.Noise)
return;
stepSurface.generateGroup(e.tParam, region, subRange);
e.pEvent.surfaceNano = System.nanoTime();
e.refreshTimeout();
if (step == Steps.Surface)
return;
if (step == Steps.Carvers)
return;
stepFeatures.generateGroup(e.tParam, region, subRange);
e.pEvent.featureNano = System.nanoTime();
e.refreshTimeout();
}
finally
{
switch (region.lightMode)
{
case FANCY:
stepLight.generateGroup(region.getLightEngine(), subRange);
break;
case FAST:
subRange.forEach((p) ->
{
if (p instanceof ProtoChunk)
((ProtoChunk) p).setLightCorrect(true);
if (p instanceof LevelChunk) {
((LevelChunk) p).setLightCorrect(true);
((LevelChunk) p).setClientLightReady(true);
}
});
break;
}
e.pEvent.lightNano = System.nanoTime();
e.refreshTimeout();
}
}
public interface EmptyChunkGenerator
{
ChunkAccess generate(int x, int z);
}
@Override
public int getEventCount() {
return events.size();
}
@Override
public void stop(boolean blocking) {
ApiShared.LOGGER.info("Batch Chunk Generator shutting down...");
executors.shutdownNow();
if (blocking) try {
if (!executors.awaitTermination(10, TimeUnit.SECONDS)) {
ApiShared.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...");
}
} catch (InterruptedException e) {
ApiShared.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...", e);
}
}
}
@@ -0,0 +1,111 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PrefEvent;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.enums.config.LightGenerationMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper.Steps;
import net.minecraft.world.level.ChunkPos;
//======================= Main Event class======================
public final class GenerationEvent
{
static private final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static int generationFutureDebugIDs = 0;
final ThreadedParameters tParam;
final ChunkPos pos;
final int range;
final Future<?> future;
long nanotime;
final int id;
final Steps target;
final LightGenerationMode lightMode;
final PrefEvent pEvent = new PrefEvent();
final boolean genAllDetails;
public GenerationEvent(ChunkPos pos, int range, BatchGenerationEnvironment generationGroup, Steps target, boolean genAllDetails)
{
nanotime = System.nanoTime();
this.pos = pos;
this.range = range;
id = generationFutureDebugIDs++;
this.target = target;
this.tParam = ThreadedParameters.getOrMake(generationGroup.params);
LightGenerationMode mode = CONFIG.client().worldGenerator().getLightGenerationMode();
this.lightMode = mode;
this.genAllDetails = genAllDetails;
future = generationGroup.executors.submit(() ->
{
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
try {
generationGroup.generateLodFromList(this);
} finally {
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
}
});
}
public boolean isCompleted()
{
return future.isDone();
}
public boolean hasTimeout(int duration, TimeUnit unit)
{
long currentTime = System.nanoTime();
long delta = currentTime - nanotime;
return (delta > TimeUnit.NANOSECONDS.convert(duration, unit));
}
public boolean terminate()
{
ApiShared.LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
BatchGenerationEnvironment.threadFactory.dumpAllThreadStacks();
future.cancel(true);
return future.isCancelled();
}
public void join()
{
try
{
future.get();
}
catch (InterruptedException | ExecutionException e)
{
throw new RuntimeException(e.getCause()==null? e : e.getCause());
}
}
public boolean tooClose(int cx, int cz, int cr)
{
int distX = Math.abs(cx - pos.x);
int distZ = Math.abs(cz - pos.z);
int minRange = cr + range + 1; // Need one to account for the center
minRange += 1 + 1; // Account for required empty chunks
return distX < minRange && distZ < minRange;
}
public void refreshTimeout()
{
nanotime = System.nanoTime();
LodUtil.checkInterruptsUnchecked();
}
@Override
public String toString()
{
return id + ":" + range + "@" + pos + "(" + target + ")";
}
}
@@ -0,0 +1,59 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import com.mojang.datafixers.DataFixer;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.objects.lod.LodDimension;
import net.minecraft.core.Registry;
import net.minecraft.core.RegistryAccess;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.storage.ChunkScanAccess;
import net.minecraft.world.level.levelgen.DebugLevelSource;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
import net.minecraft.world.level.storage.WorldData;
public final class GlobalParameters
{
public final ChunkGenerator generator;
public final StructureManager structures;
public final BiomeManager biomeManager;
public final WorldGenSettings worldGenSettings;
public final ThreadedLevelLightEngine lightEngine;
public final LodBuilder lodBuilder;
public final LodDimension lodDim;
public final Registry<Biome> biomes;
public final RegistryAccess registry;
public final long worldSeed;
public final ChunkScanAccess chunkScanner;
public final ServerLevel level; // TODO: Figure out a way to remove this. Maybe ClientLevel also works?
public final DataFixer fixerUpper;
public GlobalParameters(ServerLevel level, LodBuilder lodBuilder, LodDimension lodDim)
{
this.lodBuilder = lodBuilder;
this.lodDim = lodDim;
this.level = level;
lightEngine = (ThreadedLevelLightEngine) level.getLightEngine();
MinecraftServer server = level.getServer();
WorldData worldData = server.getWorldData();
worldGenSettings = worldData.worldGenSettings();
registry = server.registryAccess();
biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
worldSeed = worldGenSettings.seed();
biomeManager = new BiomeManager(level, BiomeManager.obfuscateSeed(worldSeed));
structures = server.getStructureManager();
generator = level.getChunkSource().getGenerator();
chunkScanner = level.getChunkSource().chunkScanner();
fixerUpper = server.getFixerUpper();
}
}
@@ -1,357 +0,0 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* 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, version 3.
*
* 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.seibel.lod.common.wrappers.worldGeneration;
import java.util.HashMap;
import java.util.List;
import java.util.Random;
import java.util.function.Predicate;
import java.util.stream.Stream;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.common.wrappers.WrapperUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.RegistryAccess;
import net.minecraft.core.SectionPos;
import net.minecraft.core.particles.ParticleOptions;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.DifficultyInstance;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.EmptyTickList;
import net.minecraft.world.level.TickList;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.BiomeManager;
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.border.WorldBorder;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.dimension.DimensionType;
import net.minecraft.world.level.entity.EntityTypeTest;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.storage.LevelData;
import net.minecraft.world.phys.AABB;
import org.jetbrains.annotations.Nullable;
/**
* This is a fake ServerWorld used when generating features.
* It allows us to keep each LodChunk generation independent
* of the actual ServerWorld, allowing
* multithread generation.
*
* @author James Seibel
* @version 7-26-2021
*/
public class LodServerWorld implements WorldGenLevel
{
public HashMap<Heightmap.Types, Heightmap> heightmaps = new HashMap<>();
public final ChunkAccess chunk;
public final ServerLevel serverWorld;
public LodServerWorld(ServerLevel newServerWorld, ChunkAccess newChunk)
{
chunk = newChunk;
serverWorld = newServerWorld;
}
@Override
public int getHeight(Heightmap.Types heightmapType, int x, int z)
{
// make sure the block position is set relative to the chunk
x = x % LodUtil.CHUNK_WIDTH;
x = (x < 0) ? x + 16 : x;
z = z % LodUtil.CHUNK_WIDTH;
z = (z < 0) ? z + 16 : z;
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(x, z);
}
@Override
public Biome getBiome(BlockPos pos)
{
return chunk.getBiomes().getNoiseBiome(pos.getX() >> 2, pos.getY() >> 2, pos.getZ() >> 2);
}
@Override
public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft)
{
return chunk.setBlockState(pos, state, false) == state;
}
@Override
public BlockState getBlockState(BlockPos pos)
{
return chunk.getBlockState(pos);
}
@Override
public FluidState getFluidState(BlockPos pos)
{
return chunk.getFluidState(pos);
}
@Override
public boolean isStateAtPosition(BlockPos pos, Predicate<BlockState> state)
{
return state.test(chunk.getBlockState(pos));
}
@Override
public boolean isFluidAtPosition(BlockPos blockPos, Predicate<FluidState> predicate) {
return predicate.test(chunk.getFluidState(blockPos));
}
@Override
public TickList<Block> getBlockTicks()
{
return EmptyTickList.empty();
}
@Override
public ChunkAccess getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull)
{
return chunk;
}
@Override
public Stream<? extends StructureStart<?>> startsForFeature(SectionPos p_241827_1_, StructureFeature<?> p_241827_2_)
{
return serverWorld.startsForFeature(p_241827_1_, p_241827_2_);
}
@Override
public TickList<Fluid> getLiquidTicks()
{
return EmptyTickList.empty();
}
@Override
public LevelLightEngine getLightEngine()
{
return new LevelLightEngine(null, false, false);
}
@Override
public long getSeed()
{
return serverWorld.getSeed();
}
@Override
public RegistryAccess registryAccess()
{
return serverWorld.registryAccess();
}
/**
* All methods below shouldn't be needed
* and thus have been left unimplemented.
*/
@Override
public Random getRandom()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public void playSound(Player player, BlockPos pos, SoundEvent soundIn, SoundSource category, float volume,
float pitch)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public void addParticle(ParticleOptions particleData, double x, double y, double z, double xSpeed, double ySpeed,
double zSpeed)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public BiomeManager getBiomeManager()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public int getSeaLevel()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public float getShade(Direction p_230487_1_, boolean p_230487_2_)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public WorldBorder getWorldBorder()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public boolean removeBlock(BlockPos pos, boolean isMoving)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public boolean destroyBlock(BlockPos pos, boolean dropBlock, Entity entity, int recursionLeft)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public ServerLevel getLevel()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public ChunkSource getChunkSource()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public DifficultyInstance getCurrentDifficultyAt(BlockPos arg0)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Nullable
@Override
public MinecraftServer getServer() {
return serverWorld.getServer();
}
@Override
public LevelData getLevelData()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public void levelEvent(Player arg0, int arg1, BlockPos arg2, int arg3)
{
throw new UnsupportedOperationException("Not Implemented");
}
// TODO: Check if this causes any issues
@Override
public void gameEvent(@Nullable Entity entity, GameEvent gameEvent, BlockPos blockPos) {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public List<Entity> getEntities(Entity arg0, AABB arg1, Predicate<? super Entity> arg2)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public <T extends Entity> List<T> getEntities(EntityTypeTest<Entity, T> entityTypeTest, AABB aABB, Predicate<? super T> predicate) {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public <T extends Entity> List<T> getEntitiesOfClass(Class<T> arg0, AABB arg1,
Predicate<? super T> arg2)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public List<? extends Player> players()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public int getSkyDarken()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public Biome getUncachedNoiseBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public boolean isClientSide()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public DimensionType dimensionType()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public BlockEntity getBlockEntity(BlockPos p_175625_1_)
{
throw new UnsupportedOperationException("Not Implemented");
}
}
@@ -0,0 +1,34 @@
package com.seibel.lod.common.wrappers.worldGeneration;
//FIXME: Move this outside the WorldGenerationStep thingy
public class Rolling
{
private final int size;
private double total = 0d;
private int index = 0;
private final double[] samples;
public Rolling(int size)
{
this.size = size;
samples = new double[size];
for (int i = 0; i < size; i++)
samples[i] = 0d;
}
public void add(double x)
{
total -= samples[index];
samples[index] = x;
total += x;
if (++index == size)
index = 0; // cheaper than modulus
}
public double getAverage()
{
return total / size;
}
}
@@ -0,0 +1,48 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PerfCalculator;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenStructFeatManager;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.levelgen.structure.StructureCheck;
public final class ThreadedParameters
{
private static final ThreadLocal<ThreadedParameters> localParam = new ThreadLocal<ThreadedParameters>();
final ServerLevel level;
public final WorldGenStructFeatManager structFeat;
public final StructureCheck structCheck;
boolean isValid = true;
public final PerfCalculator perf = new PerfCalculator();
public static ThreadedParameters getOrMake(GlobalParameters param)
{
ThreadedParameters tParam = localParam.get();
if (tParam != null && tParam.isValid && tParam.level == param.level)
return tParam;
tParam = new ThreadedParameters(param);
localParam.set(tParam);
return tParam;
}
public void markAsInvalid()
{
isValid = false;
}
private ThreadedParameters(GlobalParameters param)
{
level = param.level;
structCheck = new StructureCheck(param.chunkScanner, param.registry, param.structures,
param.level.dimension(), param.generator, level, param.generator.getBiomeSource(), param.worldSeed,
param.fixerUpper);
structFeat = new WorldGenStructFeatManager(level, param.worldGenSettings, null, structCheck);
}
public void makeStructFeat(WorldGenLevel genLevel)
{
structFeat.setGenLevel(genLevel);
}
}
@@ -1,393 +0,0 @@
package com.seibel.lod.common.wrappers.worldGeneration;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Supplier;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
import com.seibel.lod.common.wrappers.WrapperUtil;
import com.seibel.lod.common.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.common.wrappers.world.WorldWrapper;
import net.minecraft.core.Registry;
import net.minecraft.server.level.ServerChunkCache;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.*;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.feature.ConfiguredFeature;
import net.minecraft.world.level.levelgen.feature.FeaturePlaceContext;
import net.minecraft.world.level.levelgen.feature.SnowAndFreezeFeature;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
/**
* @author James Seibel
* @version 11-13-2021
*/
public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper
{
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
/**
* If a configured feature fails for whatever reason,
* add it to this list. This will hopefully remove any
* features that could cause issues down the line.
*/
private static final ConcurrentHashMap<Integer, ConfiguredFeature<?, ?>> FEATURES_TO_AVOID = new ConcurrentHashMap<>();
private static ExecutorService Executor = Executors.newSingleThreadExecutor();
public final ServerLevel serverWorld;
public final LodDimension lodDim;
public final LodBuilder lodBuilder;
public WorldGeneratorWrapper(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
{
super(newLodBuilder, newLodDimension, worldWrapper);
lodBuilder = newLodBuilder;
lodDim = newLodDimension;
serverWorld = ((WorldWrapper) worldWrapper).getServerWorld();
}
/** takes about 2-5 ms */
@Override
public void generateBiomesOnly(AbstractChunkPosWrapper pos, DistanceGenerationMode generationMode)
{
List<ChunkAccess> chunkList = new LinkedList<>();
ProtoChunk chunk = new ProtoChunk(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY, serverWorld);
chunkList.add(chunk);
ServerChunkCache chunkSource = serverWorld.getChunkSource();
ChunkGenerator chunkGen = chunkSource.getGenerator();
// generate the terrain (this is thread safe)
ChunkStatus.EMPTY.generate(Executor, serverWorld, chunkGen, serverWorld.getStructureManager(), (ThreadedLevelLightEngine) serverWorld.getLightEngine(), null, chunkList);
// override the chunk status, so we can run the next generator stage
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
// generate fake height data for this LOD
int seaLevel = serverWorld.getSeaLevel();
boolean simulateHeight = generationMode == DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
boolean inTheEnd = false;
// add fake heightmap data so our LODs aren't at height 0
Heightmap heightmap = new Heightmap(chunk, WrapperUtil.DEFAULT_HEIGHTMAP);
for (int x = 0; x < LodUtil.CHUNK_WIDTH && !inTheEnd; x++)
{
for (int z = 0; z < LodUtil.CHUNK_WIDTH && !inTheEnd; z++)
{
if (simulateHeight)
{
// these heights are of course aren't super accurate,
// they are just to simulate height data where there isn't any
switch (chunk.getBiomes().getNoiseBiome(x >> 2, seaLevel >> 2, z >> 2).getBiomeCategory())
{
case NETHER:
heightmap.setHeight(x, z, serverWorld.getHeight() / 2);
break;
case EXTREME_HILLS:
heightmap.setHeight(x, z, seaLevel + 30);
break;
case MESA:
case JUNGLE:
heightmap.setHeight(x, z, seaLevel + 20);
break;
case BEACH:
heightmap.setHeight(x, z, seaLevel + 5);
break;
case NONE:
heightmap.setHeight(x, z, 0);
break;
case OCEAN:
case RIVER:
heightmap.setHeight(x, z, seaLevel);
break;
case THEEND:
inTheEnd = true;
break;
// DESERT
// FOREST
// ICY
// MUSHROOM
// SAVANNA
// SWAMP
// TAIGA
// PLAINS
default:
heightmap.setHeight(x, z, seaLevel + 10);
break;
}// heightmap switch
}
else
{
// we aren't simulating height
// always use sea level
heightmap.setHeight(x, z, seaLevel);
}
}// z
}// x
chunk.setHeightmap(WrapperUtil.DEFAULT_HEIGHTMAP, heightmap.getRawData());
if (!inTheEnd)
{
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(true, true, false));
}
else
{
// if we are in the end, don't generate any chunks.
// Since we don't know where the islands are, everything
// generates the same, and it looks awful.
//TODO it appears that 'if' can be collapsed, but comment says that it should not be a case
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(true, true, false));
}
// long startTime = System.currentTimeMillis();
// long endTime = System.currentTimeMillis();
// System.out.println(endTime - startTime);
}
/** takes about 10 - 20 ms */
@Override
public void generateSurface(AbstractChunkPosWrapper pos)
{
List<ChunkAccess> chunkList = new LinkedList<>();
ProtoChunk chunk = new ProtoChunk(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY, serverWorld);
chunkList.add(chunk);
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
ServerChunkCache chunkSource = serverWorld.getChunkSource();
ThreadedLevelLightEngine lightEngine = (ThreadedLevelLightEngine) serverWorld.getLightEngine();
StructureManager templateManager = serverWorld.getStructureManager();
ChunkGenerator chunkGen = chunkSource.getGenerator();
// generate the terrain (this is thread safe)
ChunkStatus.EMPTY.generate(Executor, serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// override the chunk status, so we can run the next generator stage
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
ChunkStatus.NOISE.generate(Executor, serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// TODO: Find why this dosnt work (seems like the "Executor" is doing this)
ChunkStatus.SURFACE.generate(Executor, serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// this feature has been proven to be thread safe,
// so we will add it
FeaturePlaceContext<NoneFeatureConfiguration> featurePlaceContext = new FeaturePlaceContext<>(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition(), null);
SnowAndFreezeFeature snowFeature = new SnowAndFreezeFeature(NoneFeatureConfiguration.CODEC);
snowFeature.place(featurePlaceContext);
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(DistanceGenerationMode.SURFACE));
/*TODO if we want to use Biome utils and terrain utils for overworld
* lodBuilder.generateLodNodeFromChunk(lodDim, pos ,detailLevel, serverWorld.getSeed());*/
}
/**
* takes about 15 - 20 ms
* <p>
* Causes concurrentModification Exceptions,
* which could cause instability or world generation bugs
*/
@Override
public void generateFeatures(AbstractChunkPosWrapper pos)
{
List<ChunkAccess> chunkList = new LinkedList<>();
ProtoChunk chunk = new ProtoChunk(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY, serverWorld);
chunkList.add(chunk);
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
ServerChunkCache chunkSource = serverWorld.getChunkSource();
ThreadedLevelLightEngine lightEngine = (ThreadedLevelLightEngine) serverWorld.getLightEngine();
StructureManager templateManager = serverWorld.getStructureManager();
ChunkGenerator chunkGen = chunkSource.getGenerator();
// generate the terrain (this is thread safe)
ChunkStatus.EMPTY.generate(Executor, serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// override the chunk status, so we can run the next generator stage
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
ChunkStatus.NOISE.generate(Executor, serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// TODO[FABRIC]: Find whay this dosnt work
ChunkStatus.SURFACE.generate(Executor, serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// get all the biomes in the chunk
HashSet<Biome> biomes = new HashSet<>();
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
{
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
{
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, serverWorld.getSeaLevel() >> 2, z >> 2);
// Issue #35
// For some reason Jungle biomes cause incredible lag
// the features here must be interacting with each other
// in unpredictable ways (specifically tree feature generation).
// When generating Features my CPU usage generally hovers around 30 - 40%
// when generating Jungles it spikes to 100%.
if (biome.getBiomeCategory() != Biome.BiomeCategory.JUNGLE)
{
// should probably use the heightmap here instead of seaLevel,
// but this seems to get the job done well enough
biomes.add(biome);
}
}
}
boolean allowUnstableFeatures = CONFIG.client().worldGenerator().getAllowUnstableFeatureGeneration();
// generate all the features related to this chunk.
// this may or may not be thread safe
for (Biome biome : biomes)
{
List<List<Supplier<ConfiguredFeature<?, ?>>>> featuresForState = biome.generationSettings.features();
for (List<Supplier<ConfiguredFeature<?, ?>>> suppliers : featuresForState)
{
for (Supplier<ConfiguredFeature<?, ?>> featureSupplier : suppliers)
{
ConfiguredFeature<?, ?> configuredFeature = featureSupplier.get();
if (!allowUnstableFeatures &&
FEATURES_TO_AVOID.containsKey(configuredFeature.hashCode()))
continue;
try
{
configuredFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition());
}
catch (ConcurrentModificationException | UnsupportedOperationException e)
{
// This will happen. I'm not sure what to do about it
// except pray that it doesn't affect the normal world generation
// in any harmful way.
// Update: this can cause crashes and high CPU usage.
// Issue #35
// I tried cloning the config for each feature, but that
// path was blocked since I can't clone lambda methods.
// I tried using a deep cloning library and discovered
// the problem there.
// ( https://github.com/kostaskougios/cloning
// and
// https://github.com/EsotericSoftware/kryo )
if (!allowUnstableFeatures)
FEATURES_TO_AVOID.put(configuredFeature.hashCode(), configuredFeature);
// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
}
// This will happen when the LodServerWorld
// isn't able to return something that a feature
// generator needs
catch (Exception e)
{
// I'm not sure what happened, print to the log
e.printStackTrace();
if (!allowUnstableFeatures)
FEATURES_TO_AVOID.put(configuredFeature.hashCode(), configuredFeature);
// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
}
}
}
}
// generate a Lod like normal
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(DistanceGenerationMode.FEATURES));
}
/**
* Generates using MC's ServerWorld.
* <p>
* on pre generated chunks 0 - 1 ms <br>
* on un generated chunks 0 - 50 ms <br>
* with the median seeming to hover around 15 - 30 ms <br>
* and outliers in the 100 - 200 ms range <br>
* <p>
* Note this should not be multithreaded and does cause server/simulation lag
* (Higher lag for generating than loading)
*/
@Override
public void generateFull(AbstractChunkPosWrapper pos)
{
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(serverWorld.getChunk(pos.getX(), pos.getZ(), ChunkStatus.FEATURES)), new LodBuilderConfig(DistanceGenerationMode.FULL));
}
/*
* performance/generation tests related to
* serverWorld.getChunk(x, z, ChunkStatus. *** )
true/false is whether they generated blocks or not
the time is how long it took to generate
ChunkStatus.EMPTY 0 - 1 ms false (empty, what did you expect? :P)
ChunkStatus.STRUCTURE_REFERENCES 1 - 2 ms false (no height, only generates some chunks)
ChunkStatus.BIOMES 1 - 10 ms false (no height)
ChunkStatus.NOISE 4 - 15 ms true (all blocks are stone)
ChunkStatus.LIQUID_CARVERS 6 - 12 ms true (no snow/trees, just grass)
ChunkStatus.SURFACE 5 - 15 ms true (no snow/trees, just grass)
ChunkStatus.CARVERS 5 - 30 ms true (no snow/trees, just grass)
ChunkStatus.FEATURES 7 - 25 ms true
ChunkStatus.HEIGHTMAPS 20 - 40 ms true
ChunkStatus.LIGHT 20 - 40 ms true
ChunkStatus.FULL 30 - 50 ms true
ChunkStatus.SPAWN 50 - 80 ms true
At this point I would suggest using FEATURES, as it generates snow and trees
(and any other object that are needed to make biomes distinct)
Otherwise, if snow/trees aren't necessary SURFACE is the next fastest (although not by much)
*/
}
@@ -0,0 +1,323 @@
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import com.google.common.collect.Maps;
import com.mojang.serialization.Codec;
import com.mojang.serialization.Dynamic;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
#if MC_VERSION_1_18_2
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
#endif
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.biome.Biomes;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.DataLayer;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.level.chunk.UpgradeData;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.blending.BlendingData;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.ticks.LevelChunkTicks;
import org.apache.logging.log4j.Logger;
public class ChunkLoader
{
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codec(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
private static final Logger LOGGER = ApiShared.LOGGER;
private static final String TAG_UPGRADE_DATA = "UpgradeData";
private static final String BLOCK_TICKS_TAG = "block_ticks";
private static final String FLUID_TICKS_TAG = "fluid_ticks";
private static BlendingData readBlendingData(CompoundTag chunkData)
{
BlendingData blendingData = null;
if (chunkData.contains("blending_data", 10))
{
@SuppressWarnings({ "unchecked", "rawtypes" })
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null);
}
return blendingData;
}
private static LevelChunkSection[] readSections(LevelAccessor level, LevelLightEngine lightEngine, ChunkPos chunkPos, CompoundTag chunkData)
{
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
#if MC_VERSION_1_18_1
Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(
biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
#elif MC_VERSION_1_18_2
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
#endif
int i = level.getSectionsCount();
LevelChunkSection[] chunkSections = new LevelChunkSection[i];
boolean isLightOn = chunkData.getBoolean("isLightOn");
boolean hasSkyLight = level.dimensionType().hasSkyLight();
ListTag tagSections = chunkData.getList("sections", 10);
for (int j = 0; j < tagSections.size(); ++j)
{
CompoundTag tagSection = tagSections.getCompound(j);
byte sectionYPos = tagSection.getByte("Y");
int sectionId = level.getSectionIndexFromSectionY(sectionYPos);
if (sectionId >= 0 && sectionId < chunkSections.length)
{
PalettedContainer<BlockState> blockStateContainer;
#if MC_VERSION_1_18_1
PalettedContainer<Biome> biomeContainer;
#elif MC_VERSION_1_18_2
PalettedContainer<Holder<Biome>> biomeContainer;
#endif
blockStateContainer = tagSection.contains("block_states", 10)
? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error)
: new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
#if MC_VERSION_1_18_1
biomeContainer = tagSection.contains("biomes", 10)
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error)
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
#elif MC_VERSION_1_18_2
biomeContainer = tagSection.contains("biomes", 10)
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, i, (String) string)).getOrThrow(false, LOGGER::error)
: new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(), biomes.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
#endif
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
}
if (!isLightOn)
continue;
if (tagSection.contains("BlockLight", 7))
lightEngine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, sectionYPos), new DataLayer(tagSection.getByteArray("BlockLight")), true);
if (hasSkyLight && tagSection.contains("SkyLight", 7))
lightEngine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, sectionYPos), new DataLayer(tagSection.getByteArray("SkyLight")), true);
}
return chunkSections;
}
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
{
CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps");
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
{
String heightmap = type.getSerializationKey();
if (tagHeightmaps.contains(heightmap, 12))
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
}
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
}
#if MC_VERSION_1_18_1
private static Map<StructureFeature<?>, StructureStart<?>> unpackStructureStart(StructurePieceSerializationContext structurePieceSerializationContext, CompoundTag compoundTag, long l)
{
HashMap<StructureFeature<?>, StructureStart<?>> map = Maps.newHashMap();
CompoundTag compoundTag2 = compoundTag.getCompound("starts");
for (String string : compoundTag2.getAllKeys())
{
String string2 = string.toLowerCase(Locale.ROOT);
StructureFeature<?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
if (structureFeature == null)
{
LOGGER.error("Unknown structure start: {}", (Object) string2);
continue;
}
StructureStart<?> structureStart = StructureFeature.loadStaticStart(structurePieceSerializationContext, compoundTag2.getCompound(string), l);
if (structureStart == null)
continue;
map.put(structureFeature, structureStart);
}
return map;
}
private static Map<StructureFeature<?>, LongSet> unpackStructureReferences(ChunkPos chunkPos, CompoundTag compoundTag)
{
HashMap<StructureFeature<?>, LongSet> map = Maps.newHashMap();
CompoundTag compoundTag2 = compoundTag.getCompound("References");
for (String string : compoundTag2.getAllKeys())
{
String string2 = string.toLowerCase(Locale.ROOT);
StructureFeature<?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
if (structureFeature == null)
{
LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", (Object) string2, (Object) chunkPos);
continue;
}
map.put(structureFeature, new LongOpenHashSet(Arrays.stream(compoundTag2.getLongArray(string)).filter(l ->
{
ChunkPos chunkPos2 = new ChunkPos(l);
if (chunkPos2.getChessboardDistance(chunkPos) > 8)
{
LOGGER.warn("Found invalid structure reference [ {} @ {} ] for chunk {}.", (Object) string2, (Object) chunkPos2, (Object) chunkPos);
return false;
}
return true;
}).toArray()));
}
return map;
}
#elif MC_VERSION_1_18_2
private static Map<ConfiguredStructureFeature<?, ?>, StructureStart> unpackStructureStart(StructurePieceSerializationContext structurePieceSerializationContext, CompoundTag compoundTag, long l) {
Map<ConfiguredStructureFeature<?, ?>, StructureStart> map = Maps.newHashMap();
Registry<ConfiguredStructureFeature<?, ?>> structStartRegistry = structurePieceSerializationContext.registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
CompoundTag compoundTag2 = compoundTag.getCompound("starts");
for (String string : compoundTag2.getAllKeys()) {
ResourceLocation resourceLocation = ResourceLocation.tryParse(string);
ConfiguredStructureFeature<?, ?> structureFeature = structStartRegistry.get(resourceLocation);
// String string2 = string.toLowerCase(Locale.ROOT);
// ConfiguredStructureFeature<?, ?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
if (structureFeature == null) {
LOGGER.error("Unknown structure start: {}", resourceLocation);
continue;
}
StructureStart structureStart = StructureFeature.loadStaticStart(structurePieceSerializationContext, compoundTag2.getCompound(string), l);
if (structureStart == null)
continue;
map.put(structureFeature, structureStart);
}
return map;
}
private static Map<ConfiguredStructureFeature<?, ?>, LongSet> unpackStructureReferences(RegistryAccess registryAccess, ChunkPos chunkPos, CompoundTag compoundTag)
{
Map<ConfiguredStructureFeature<?, ?>, LongSet> map = Maps.newHashMap();
Registry<ConfiguredStructureFeature<?, ?>> structRegistry = registryAccess.registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
CompoundTag compoundTag2 = compoundTag.getCompound("References");
for (String string : compoundTag2.getAllKeys())
{
ResourceLocation resourceLocation = ResourceLocation.tryParse(string);
ConfiguredStructureFeature<?, ?> structureFeature = structRegistry.get(resourceLocation);
// String string2 = string.toLowerCase(Locale.ROOT);
// ConfiguredStructureFeature<?, ?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
if (structureFeature == null)
{
LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", resourceLocation, chunkPos);
continue;
}
map.put(structureFeature, new LongOpenHashSet(Arrays.stream(compoundTag2.getLongArray(string)).filter(l ->
{
ChunkPos chunkPos2 = new ChunkPos(l);
if (chunkPos2.getChessboardDistance(chunkPos) > 8)
{
LOGGER.warn("Found invalid structure reference [ {} @ {} ] for chunk {}.", resourceLocation, chunkPos2, chunkPos);
return false;
}
return true;
}).toArray()));
}
return map;
}
#endif
private static void readStructures(WorldGenLevel level, LevelChunk chunk, CompoundTag chunkData)
{
CompoundTag tagStructures = chunkData.getCompound("structures");
chunk.setAllStarts(
unpackStructureStart(StructurePieceSerializationContext.fromLevel(level.getLevel()), tagStructures, level.getSeed()));
chunk.setAllReferences(unpackStructureReferences(#if MC_VERSION_1_18_2 level.registryAccess() ,#endif chunk.getPos(), tagStructures));
}
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
{
ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9);
for (int n = 0; n < tagPostProcessings.size(); ++n)
{
ListTag listTag3 = tagPostProcessings.getList(n);
for (int o = 0; o < listTag3.size(); ++o)
{
chunk.addPackedPostProcess(listTag3.getShort(o), n);
}
}
}
public static ChunkStatus.ChunkType readChunkType(CompoundTag compoundTag)
{
return ChunkStatus.byName(compoundTag.getString("Status")).getChunkType();
}
public static LevelChunk read(WorldGenLevel level, LevelLightEngine lightEngine, ChunkPos chunkPos, CompoundTag chunkData)
{
ChunkPos actualPos = new ChunkPos(chunkData.getInt("xPos"), chunkData.getInt("zPos"));
if (!Objects.equals(chunkPos, actualPos))
{
LOGGER.error("Distant Horizons: Chunk file at {} is in the wrong location; Ignoring. (Expected {}, got {})", (Object) chunkPos, (Object) chunkPos, (Object) actualPos);
return null;
}
ChunkStatus.ChunkType chunkType = readChunkType(chunkData);
BlendingData blendingData = readBlendingData(chunkData);
if (chunkType == ChunkStatus.ChunkType.PROTOCHUNK && (blendingData == null || !blendingData.oldNoise()))
return null;
// Prepare the light engine
boolean isLightOn = chunkData.getBoolean("isLightOn");
if (isLightOn)
level.getLightEngine().retainData(chunkPos, true);
// Read params for making the LevelChunk
UpgradeData upgradeData = chunkData.contains(TAG_UPGRADE_DATA, 10)
? new UpgradeData(chunkData.getCompound(TAG_UPGRADE_DATA), level)
: UpgradeData.EMPTY;
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(chunkData.getList(BLOCK_TICKS_TAG, 10),
string -> Registry.BLOCK.getOptional(ResourceLocation.tryParse(string)), chunkPos);
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(chunkData.getList(FLUID_TICKS_TAG, 10),
string -> Registry.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
long inhabitedTime = chunkData.getLong("InhabitedTime");
LevelChunkSection[] chunkSections = readSections(level, lightEngine, actualPos, chunkData);
// Make chunk
LevelChunk chunk = new LevelChunk((Level) level, chunkPos, upgradeData, blockTicks, fluidTicks, inhabitedTime, chunkSections, null, blendingData);
// Set some states after object creation
chunk.setLightCorrect(isLightOn);
readHeightmaps(chunk, chunkData);
readStructures(level, chunk, chunkData);
readPostPocessings(chunk, chunkData);
return chunk;
}
private static void logErrors(ChunkPos chunkPos, int i, String string)
{
LOGGER.error("Distant Horizons: Recoverable errors when loading section [" + chunkPos.x + ", " + i + ", " + chunkPos.z + "]: " + string);
}
}
@@ -0,0 +1,40 @@
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LightChunkGetter;
public class LightGetterAdaptor implements LightChunkGetter {
private final BlockGetter heightGetter;
public LightedWorldGenRegion genRegion = null;
final boolean shouldReturnNull;
public LightGetterAdaptor(BlockGetter heightAccessor) {
this.heightGetter = heightAccessor;
shouldReturnNull = ModAccessorHandler.get(IStarlightAccessor.class) != null;
}
public void setRegion(LightedWorldGenRegion region) {
genRegion = region;
}
@Override
public BlockGetter getChunkForLighting(int chunkX, int chunkZ) {
if (genRegion == null)
throw new IllegalStateException("World Gen region has not been set!");
// May be null
return genRegion.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY, false);
}
@Override
public BlockGetter getLevel() {
return shouldReturnNull ? null : (genRegion != null ? genRegion : heightGetter);
}
public LevelHeightAccessor getLevelHeightAccessor() {
return heightGetter;
}
}
@@ -0,0 +1,281 @@
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import java.util.List;
import com.seibel.lod.core.api.ApiShared;
import org.jetbrains.annotations.Nullable;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.EmptyChunkGenerator;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.config.LightGenerationMode;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.block.BlockTintCache;
import net.minecraft.client.renderer.BiomeColors;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
import net.minecraft.core.SectionPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.ColorResolver;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ImposterProtoChunk;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.lighting.LevelLightEngine;
public class LightedWorldGenRegion extends WorldGenRegion {
public final WorldGenLevelLightEngine light;
public final LightGenerationMode lightMode;
public final EmptyChunkGenerator generator;
public final int writeRadius;
public final int size;
private final ChunkPos firstPos;
private final List<ChunkAccess> cache;
Long2ObjectOpenHashMap<ChunkAccess> chunkMap = new Long2ObjectOpenHashMap<ChunkAccess>();
public LightedWorldGenRegion(ServerLevel serverLevel, WorldGenLevelLightEngine lightEngine,
List<ChunkAccess> list, ChunkStatus chunkStatus, int i,
LightGenerationMode lightMode, EmptyChunkGenerator generator) {
super(serverLevel, list, chunkStatus, i);
this.lightMode = lightMode;
this.firstPos = list.get(0).getPos();
this.generator = generator;
light = lightEngine;
writeRadius = i;
cache = list;
size = Mth.floor(Math.sqrt(list.size()));
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new BlockTintCache((pos) -> {return calculateBlockTint(pos, BiomeColors.GRASS_COLOR_RESOLVER);}));
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache((pos) -> {return calculateBlockTint(pos, BiomeColors.FOLIAGE_COLOR_RESOLVER);}));
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache((pos) -> {return calculateBlockTint(pos, BiomeColors.WATER_COLOR_RESOLVER);}));
});
}
// Bypass BCLib mixin overrides.
@Override
public boolean ensureCanWrite(BlockPos blockPos) {
int i = SectionPos.blockToSectionCoord(blockPos.getX());
int j = SectionPos.blockToSectionCoord(blockPos.getZ());
ChunkPos chunkPos = this.getCenter();
ChunkAccess center = this.getChunk(chunkPos.x, chunkPos.z);
int k = Math.abs(chunkPos.x - i);
int l = Math.abs(chunkPos.z - j);
if (k > this.writeRadius || l > this.writeRadius) {
return false;
}
if (center.isUpgrading()) {
LevelHeightAccessor levelHeightAccessor = center.getHeightAccessorForGeneration();
if (blockPos.getY() < levelHeightAccessor.getMinBuildHeight() || blockPos.getY() >= levelHeightAccessor.getMaxBuildHeight()) {
return false;
}
}
return true;
}
// TODO Check this
// @Override
// public List<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
// StructureFeature<?> structureFeature) {
// return structFeat.startsForFeature(sectionPos, structureFeature);
// }
// Skip updating the related tile entities
@Override
public boolean setBlock(BlockPos blockPos, BlockState blockState, int i, int j) {
ChunkAccess chunkAccess = this.getChunk(blockPos);
if (chunkAccess instanceof LevelChunk)
return true;
chunkAccess.setBlockState(blockPos, blockState, false);
// This is for post ticking for water on gen and stuff like that. Not enabled
// for now.
// if (blockState.hasPostProcess(this, blockPos))
// this.getChunk(blockPos).markPosForPostprocessing(blockPos);
return true;
}
// Skip Dropping the item on destroy
@Override
public boolean destroyBlock(BlockPos blockPos, boolean bl, @Nullable Entity entity, int i) {
BlockState blockState = this.getBlockState(blockPos);
if (blockState.isAir()) {
return false;
}
return this.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3, i);
}
// Skip BlockEntity stuff. It aren't really needed
@Override
public BlockEntity getBlockEntity(BlockPos blockPos) {
return null;
}
// Skip BlockEntity stuff. It aren't really needed
@Override
public boolean addFreshEntity(Entity entity) {
return true;
}
// Allays have empty chunks even if it's outside the worldGenRegion
// @Override
// public boolean hasChunk(int i, int j) {
// return true;
// }
// Override to ensure no other mod mixins cause skipping the overrided
// getChunk(...)
@Override
public ChunkAccess getChunk(int i, int j) {
return this.getChunk(i, j, ChunkStatus.EMPTY);
}
// Override to ensure no other mod mixins cause skipping the overrided
// getChunk(...)
@Override
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus) {
return this.getChunk(i, j, chunkStatus, true);
}
// Use this instead of super.getChunk() to bypass C2ME concurrency checks
private ChunkAccess superGetChunk(int x, int z, ChunkStatus cs) {
int k = x - firstPos.x;
int l = z - firstPos.z;
return cache.get(k + l * size);
}
// Use this instead of super.hasChunk() to bypass C2ME concurrency checks
private boolean superHasChunk(int x, int z) {
int k = x - firstPos.x;
int l = z - firstPos.z;
return l >= 0 && l < size && k >= 0 && k < size;
}
// Allow creating empty chunks even if it's outside the worldGenRegion
@Override
@Nullable
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus, boolean bl) {
ChunkAccess chunk = getChunkAccess(i, j, chunkStatus, bl);
if (chunk instanceof LevelChunk) {
chunk = new ImposterProtoChunk((LevelChunk) chunk, true);
}
return chunk;
}
private static ChunkStatus debugTriggeredForStatus = null;
private ChunkAccess getChunkAccess(int i, int j, ChunkStatus chunkStatus, boolean bl) {
ChunkAccess chunk = superHasChunk(i, j) ? superGetChunk(i, j, ChunkStatus.EMPTY) : null;
if (chunk != null && chunk.getStatus().isOrAfter(chunkStatus)) {
return chunk;
}
if (!bl)
return null;
if (chunk == null) {
chunk = chunkMap.get(ChunkPos.asLong(i, j));
if (chunk == null) {
chunk = generator.generate(i, j);
if (chunk == null)
throw new NullPointerException("The provided generator should not return null!");
chunkMap.put(ChunkPos.asLong(i, j), chunk);
}
}
if (chunkStatus != ChunkStatus.EMPTY && chunkStatus != debugTriggeredForStatus) {
ApiShared.LOGGER.info("WorldGen requiring " + chunkStatus
+ " outside expected range detected. Force passing EMPTY chunk and seeing if it works.");
debugTriggeredForStatus = chunkStatus;
}
return chunk;
}
// Override force use of my own light engine
@Override
public LevelLightEngine getLightEngine() {
return light;
}
// Override force use of my own light engine
@Override
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
if (lightMode != LightGenerationMode.FAST) {
return light.getLayerListener(lightLayer).getLightValue(blockPos);
}
if (lightLayer == LightLayer.BLOCK)
return 0;
BlockPos p = super.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockPos);
return (p.getY() <= blockPos.getY()) ? getMaxLightLevel() : 0;
}
// Override force use of my own light engine
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
if (lightMode != LightGenerationMode.FAST) {
return light.getRawBrightness(blockPos, i);
}
BlockPos p = super.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockPos);
return (p.getY() <= blockPos.getY()) ? getMaxLightLevel() : 0;
}
// Override force use of my own light engine
@Override
public boolean canSeeSky(BlockPos blockPos) {
return (getBrightness(LightLayer.SKY, blockPos) >= getMaxLightLevel());
}
private final Object2ObjectArrayMap<ColorResolver, BlockTintCache> tintCaches;
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
BlockTintCache blockTintCache = (BlockTintCache) this.tintCaches.get(colorResolver);
return blockTintCache.getColor(blockPos);
}
private Biome _getBiome(BlockPos pos) {
#if MC_VERSION_1_18_2
return getBiome(pos).value();
#elif MC_VERSION_1_18_1
return getBiome(pos);
#endif
}
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
int i = (Minecraft.getInstance()).options.biomeBlendRadius;
if (i == 0)
return colorResolver.getColor((Biome) _getBiome(blockPos), blockPos.getX(), blockPos.getZ());
int j = (i * 2 + 1) * (i * 2 + 1);
int k = 0;
int l = 0;
int m = 0;
Cursor3D cursor3D = new Cursor3D(blockPos.getX() - i, blockPos.getY(), blockPos.getZ() - i, blockPos.getX() + i, blockPos.getY(), blockPos.getZ() + i);
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
while (cursor3D.advance())
{
mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
int n = colorResolver.getColor((Biome) _getBiome((BlockPos) mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
k += (n & 0xFF0000) >> 16;
l += (n & 0xFF00) >> 8;
m += n & 0xFF;
}
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
}
}
@@ -0,0 +1,176 @@
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import org.jetbrains.annotations.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.DataLayer;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.lighting.BlockLightEngine;
import net.minecraft.world.level.lighting.LayerLightEventListener;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.world.level.lighting.SkyLightEngine;
public class WorldGenLevelLightEngine extends LevelLightEngine {
public static final int MAX_SOURCE_LEVEL = 15;
public static final int LIGHT_SECTION_PADDING = 1;
protected final LevelHeightAccessor levelHeightAccessor;
@Nullable
public final BlockLightEngine blockEngine;
@Nullable
public final SkyLightEngine skyEngine;
public WorldGenLevelLightEngine(LightGetterAdaptor genRegion) {
super(genRegion, false, false);
this.levelHeightAccessor = genRegion.getLevelHeightAccessor();
this.blockEngine = new BlockLightEngine(genRegion);
this.skyEngine = new SkyLightEngine(genRegion);
}
@Override
public void checkBlock(BlockPos blockPos) {
if (this.blockEngine != null) {
this.blockEngine.checkBlock(blockPos);
}
if (this.skyEngine != null) {
this.skyEngine.checkBlock(blockPos);
}
}
@Override
public void onBlockEmissionIncrease(BlockPos blockPos, int i) {
if (this.blockEngine != null) {
this.blockEngine.onBlockEmissionIncrease(blockPos, i);
}
}
@Override
public boolean hasLightWork() {
if (this.skyEngine != null && this.skyEngine.hasLightWork()) {
return true;
}
return this.blockEngine != null && this.blockEngine.hasLightWork();
}
@Override
public int runUpdates(int i, boolean bl, boolean bl2) {
if (this.blockEngine != null && this.skyEngine != null) {
int j = i / 2;
int k = this.blockEngine.runUpdates(j, bl, bl2);
int l = i - j + k;
int m = this.skyEngine.runUpdates(l, bl, bl2);
if (k == 0 && m > 0) {
return this.blockEngine.runUpdates(m, bl, bl2);
}
return m;
}
if (this.blockEngine != null) {
return this.blockEngine.runUpdates(i, bl, bl2);
}
if (this.skyEngine != null) {
return this.skyEngine.runUpdates(i, bl, bl2);
}
return i;
}
@Override
public void updateSectionStatus(SectionPos sectionPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.updateSectionStatus(sectionPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.updateSectionStatus(sectionPos, bl);
}
}
@Override
public void enableLightSources(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.enableLightSources(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.enableLightSources(chunkPos, bl);
}
}
@Override
public LayerLightEventListener getLayerListener(LightLayer lightLayer) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.blockEngine;
}
if (this.skyEngine == null) {
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
}
return this.skyEngine;
}
@Override
public int getRawBrightness(BlockPos blockPos, int i) {
int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
return Math.max(k, j);
}
public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate) {
ChunkPos chunkPos = chunkAccess.getPos();
chunkAccess.setLightCorrect(false);
LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
for (int i = 0; i < chunkAccess.getSectionsCount(); ++i) {
LevelChunkSection levelChunkSection = levelChunkSections[i];
if (levelChunkSection.hasOnlyAir()) continue;
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
updateSectionStatus(SectionPos.of(chunkPos, j), false);
}
enableLightSources(chunkPos, true);
if (needLightBlockUpdate) {
chunkAccess.getLights().forEach(blockPos ->
onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
}
chunkAccess.setLightCorrect(true);
}
@Override
public String getDebugData(LightLayer lightLayer, SectionPos sectionPos) {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer, boolean bl) {
if (lightLayer == LightLayer.BLOCK) {
if (this.blockEngine != null) {
this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
}
} else if (this.skyEngine != null) {
this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
}
}
@Override
public void retainData(ChunkPos chunkPos, boolean bl) {
if (this.blockEngine != null) {
this.blockEngine.retainData(chunkPos, bl);
}
if (this.skyEngine != null) {
this.skyEngine.retainData(chunkPos, bl);
}
}
@Override
public int getLightSectionCount() {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public int getMinLightSection() {
throw new UnsupportedOperationException("This should never be used!");
}
@Override
public int getMaxLightSection() {
throw new UnsupportedOperationException("This should never be used!");
}
}
@@ -0,0 +1,82 @@
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
import java.util.List;
import java.util.stream.Stream;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.longs.LongIterator;
import it.unimi.dsi.fastutil.longs.LongSet;
import net.minecraft.core.BlockPos;
import net.minecraft.core.SectionPos;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.WorldGenLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.levelgen.WorldGenSettings;
import net.minecraft.world.level.levelgen.feature.StructureFeature;
import net.minecraft.world.level.levelgen.structure.StructureCheck;
import net.minecraft.world.level.levelgen.structure.StructureStart;
public class WorldGenStructFeatManager extends StructureFeatureManager {
WorldGenLevel genLevel;
WorldGenSettings worldGenSettings;
StructureCheck structureCheck;
public WorldGenStructFeatManager(LevelAccessor levelAccessor, WorldGenSettings worldGenSettings,
WorldGenLevel genLevel, StructureCheck structureCheck) {
super(levelAccessor, worldGenSettings, structureCheck);
this.genLevel = genLevel;
this.worldGenSettings = worldGenSettings;
}
public void setGenLevel(WorldGenLevel genLevel) {
this.genLevel = genLevel;
}
@Override
public WorldGenStructFeatManager forWorldGenRegion(WorldGenRegion worldGenRegion) {
if (worldGenRegion == genLevel)
return this;
return new WorldGenStructFeatManager(worldGenRegion, worldGenSettings, worldGenRegion, structureCheck);
}
@Override
public boolean hasAnyStructureAt(BlockPos blockPos) {
SectionPos sectionPos = SectionPos.of(blockPos);
ChunkAccess chunk = genLevel.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES,
false);
if (chunk == null) return false;
return chunk.hasAnyStructureReferences();
}
// TODO Check this
/*
@Override
@SuppressWarnings({ "rawtypes", "unchecked" })
public List<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
StructureFeature<?> structureFeature) {
if (genLevel == null)
return List.of();
ChunkAccess chunk = genLevel.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES,
false);
if (chunk == null)
return List.of();
LongSet longSet = chunk.getReferencesForFeature(structureFeature);
ImmutableList.Builder builder = ImmutableList.builder();
LongIterator longIterator = longSet.iterator();
while (longIterator.hasNext()) {
long l = (Long)longIterator.next();
SectionPos sectPos = SectionPos.of(new ChunkPos(l), genLevel.getMinSection());
ChunkAccess startChunk = genLevel.getChunk(sectPos.x(), sectPos.z(), ChunkStatus.STRUCTURE_STARTS, false);
if (startChunk == null) continue;
StructureStart<?> structureStart = this.getStartForFeature(sectPos, structureFeature, startChunk);
if (structureStart == null || !structureStart.isValid()) continue;
builder.add(structureStart);
}
return builder.build();
}
*/
}
@@ -0,0 +1,55 @@
package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.core.Registry;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.biome.Biome;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkGenerator;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.DebugLevelSource;
import net.minecraft.world.level.levelgen.FlatLevelSource;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.blending.Blender;
public final class StepBiomes {
/**
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
public StepBiomes(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.BIOMES;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepBiomes: "+chunk.getPos());
chunk = environment.joinSync(environment.params.generator.createBiomes(environment.params.biomes, Runnable::run, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
}
}
}
@@ -0,0 +1,60 @@
package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import com.seibel.lod.core.util.gridList.ArrayGridList;
import net.minecraft.ReportedException;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.blending.Blender;
public final class StepFeatures {
/**
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
public StepFeatures(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.FEATURES;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
ArrayGridList<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
try {
environment.params.generator.applyBiomeDecoration(worldGenRegion, chunk,
tParams.structFeat.forWorldGenRegion(worldGenRegion));
Blender.generateBorderTicks(worldGenRegion, chunk);
} catch (ReportedException e) {
e.printStackTrace();
// FIXME: Features concurrent modification issue. Something about cocobeans just
// aren't happy
// For now just retry.
}
}/*
for (ChunkAccess chunk : chunks) {
Heightmap.primeHeightmaps(chunk,
EnumSet.of(Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES,
Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE));
}*/
}
}
@@ -0,0 +1,60 @@
package com.seibel.lod.common.wrappers.worldGeneration.step;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenLevelLightEngine;
import com.seibel.lod.core.util.gridList.ArrayGridList;
import net.minecraft.server.level.ThreadedLevelLightEngine;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.lighting.LightEventListener;
public final class StepLight {
/**
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
public StepLight(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.LIGHT;
public void generateGroup(LightEventListener lightEngine,
ArrayGridList<ChunkAccess> chunks) {
//ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
}
for (ChunkAccess chunk : chunks) {
boolean hasCorrectBlockLight = (chunk instanceof LevelChunk && chunk.isLightCorrect());
try {
if (lightEngine == null) {
// Do nothing
} else if (lightEngine instanceof WorldGenLevelLightEngine) {
((WorldGenLevelLightEngine)lightEngine).lightChunk(chunk, !hasCorrectBlockLight);
} else if (lightEngine instanceof ThreadedLevelLightEngine) {
((ThreadedLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight).join();
} else {
assert(false);
}
} catch (Exception e) {
e.printStackTrace();
}
if (chunk instanceof LevelChunk) ((LevelChunk)chunk).setClientLightReady(true);
chunk.setLightCorrect(true);
}
lightEngine.runUpdates(Integer.MAX_VALUE, true, true);
}
}
@@ -0,0 +1,57 @@
package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import com.google.common.collect.Sets;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.util.Mth;
import net.minecraft.world.level.LevelHeightAccessor;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
import net.minecraft.world.level.levelgen.NoiseSettings;
import net.minecraft.world.level.levelgen.blending.Blender;
public final class StepNoise {
/**
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
public StepNoise(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.NOISE;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepNoise: "+chunk.getPos());
chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
}
}
}
@@ -0,0 +1,54 @@
package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.CrashReport;
import net.minecraft.CrashReportCategory;
import net.minecraft.ReportedException;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.StructureFeatureManager;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.structure.StructureStart;
public final class StepStructureReference {
/**
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
public StepStructureReference(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepStructureReference: "+chunk.getPos());
environment.params.generator.createReferences(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
}
}
}
@@ -0,0 +1,67 @@
package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ProtoChunk;
public final class StepStructureStart {
/**
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
public StepStructureStart(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
public static class StructStartCorruptedException extends RuntimeException {
private static final long serialVersionUID = -8987434342051563358L;
public StructStartCorruptedException(ArrayIndexOutOfBoundsException e) {
super("StructStartCorruptedException");
super.initCause(e);
fillInStackTrace();
}
}
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
if (environment.params.worldGenSettings.generateFeatures()) {
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepStructureStart: "+chunk.getPos());
environment.params.generator.createStructures(environment.params.registry, tParams.structFeat, chunk, environment.params.structures,
environment.params.worldSeed);
try {
tParams.structCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts());
} catch (ArrayIndexOutOfBoundsException e) {
// There's a rare issue with StructStart where it throws ArrayIndexOutOfBounds
// This means the structFeat is corrupted (For some reason) and I need to reset it.
// TODO: Figure out in the future why this happens even though I am using new structFeat
throw new StepStructureStart.StructStartCorruptedException(e);
}
}
}
}
}
@@ -0,0 +1,46 @@
package com.seibel.lod.common.wrappers.worldGeneration.step;
import java.util.ArrayList;
import java.util.List;
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.ProtoChunk;
public final class StepSurface {
/**
*
*/
private final BatchGenerationEnvironment environment;
/**
* @param batchGenerationEnvironment
*/
public StepSurface(BatchGenerationEnvironment batchGenerationEnvironment)
{
environment = batchGenerationEnvironment;
}
public final ChunkStatus STATUS = ChunkStatus.SURFACE;
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
List<ChunkAccess> chunks) {
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
for (ChunkAccess chunk : chunks) {
if (chunk.getStatus().isOrAfter(STATUS)) continue;
((ProtoChunk) chunk).setStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo) {
// System.out.println("StepSurface: "+chunk.getPos());
environment.params.generator.buildSurface(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion),
chunk);
}
}
}
@@ -1,124 +0,0 @@
{
"lod.title": "Distant Horizons",
"lod.config.title": "Distant Horizons config",
"lod.config.client": "Client",
"lod.config.client.graphics": "Graphics",
"lod.config.client.graphics.quality": "Quality options",
"lod.config.client.graphics.quality.drawResolution": "Draw resolution",
"lod.config.client.graphics.quality.drawResolution.@tooltip": "What is the maximum detail fake chunks should be drawn at?",
"lod.config.client.graphics.quality.lodChunkRenderDistance": "Chunk render distance",
"lod.config.client.graphics.quality.lodChunkRenderDistance.@tooltip": "The mod's render distance, measured in chunks",
"lod.config.client.graphics.quality.verticalQuality": "Vertical quality",
"lod.config.client.graphics.quality.verticalQuality.@tooltip": "This indicates how detailed fake chunks will represent overhangs, caves, floating islands, ect. \nHigher options will use more memory and increase GPU usage",
"lod.config.client.graphics.quality.horizontalScale": "Horizontal scale",
"lod.config.client.graphics.quality.horizontalScale.@tooltip": "This indicates how quickly fake chunks drop off in quality",
"lod.config.client.graphics.quality.horizontalQuality": "Horizontal quality",
"lod.config.client.graphics.quality.horizontalQuality.@tooltip": "This indicates the exponential base of the quadratic drop-off",
"lod.config.client.graphics.fogQuality": "Fog options",
"lod.config.client.graphics.fogQuality.fogDistance": "Fog distance",
"lod.config.client.graphics.fogQuality.fogDistance.@tooltip": "At what distance should Fog be drawn on the fake chunks?",
"lod.config.client.graphics.fogQuality.fogDrawMode": "Fog draw mode",
"lod.config.client.graphics.fogQuality.fogDrawMode.@tooltip": "When should fog be drawn?",
"lod.config.client.graphics.fogQuality.fogColorMode": "Fog color mode",
"lod.config.client.graphics.fogQuality.fogColorMode.@tooltip": "What color should fog use?",
"lod.config.client.graphics.fogQuality.disableVanillaFog": "Disable vanilla fog",
"lod.config.client.graphics.fogQuality.disableVanillaFog.@tooltip": "If true disable Minecraft's fog. \nMay cause issues with other mods that edit fog. \nMay cause errors with other fog editing mods",
"lod.config.client.graphics.advancedGraphics": "Advanced quality option",
"lod.config.client.graphics.advancedGraphics.lodTemplate": "LOD template",
"lod.config.client.graphics.advancedGraphics.lodTemplate.@tooltip": "How should the LODs be drawn? \nNOTE: Currently only CUBIC is implemented!",
"lod.config.client.graphics.advancedGraphics.disableDirectionalCulling": "Disable directional culling",
"lod.config.client.graphics.advancedGraphics.disableDirectionalCulling.@tooltip": "If false fake chunks behind the player's camera aren't drawn, increasing performance. \nIf true all LODs are drawn, even those behind the player's camera, decreasing performance",
"lod.config.client.graphics.advancedGraphics.alwaysDrawAtMaxQuality": "Always draw at max quality",
"lod.config.client.graphics.advancedGraphics.alwaysDrawAtMaxQuality.@tooltip": "Disable quality falloff, all fake chunks will be drawn at the highest available detail level",
"lod.config.client.graphics.advancedGraphics.vanillaOverdraw": "Vanilla overdraw",
"lod.config.client.graphics.advancedGraphics.vanillaOverdraw.@tooltip": "How often should LODs be drawn on top of regular chunks? \nHALF and ALWAYS will prevent holes in the world, but may look odd for transparent blocks or in caves.",
"lod.config.client.graphics.advancedGraphics.useExtendedNearClipPlane": "Use extended near clip plane",
"lod.config.client.graphics.advancedGraphics.useExtendedNearClipPlane.@tooltip": "Will prevent some overdraw issues, but may cause nearby fake chunks to render incorrectly especially when in/near an ocean",
"lod.config.client.worldGenerator": "World generator",
"lod.config.client.worldGenerator.generationPriority": "Generation priority",
"lod.config.client.worldGenerator.generationPriority.@tooltip": "What is the priority of the chunks being generated around the player",
"lod.config.client.worldGenerator.distanceGenerationMode": "Distance generation mode",
"lod.config.client.worldGenerator.distanceGenerationMode.@tooltip": "How much of the generation should be used when generating fake chunks",
"lod.config.client.worldGenerator.allowUnstableFeatureGeneration": "Allow unstable feature generation",
"lod.config.client.worldGenerator.allowUnstableFeatureGeneration.@tooltip": "Some features may not be thread safe. \nCould cause instability and crashes",
"lod.config.client.worldGenerator.blocksToAvoid": "Block to avoid",
"lod.config.client.worldGenerator.blocksToAvoid.@tooltip": "What block to avoid when generating fake chunks",
"lod.config.client.advanced": "Advance options",
"lod.config.client.advanced.threading": "Threading",
"lod.config.client.advanced.threading.numberOfWorldGenerationThreads": "NO. of world generation threads",
"lod.config.client.advanced.threading.numberOfWorldGenerationThreads.@tooltip": "This is how many threads are used when generating LODs outside the normal render distance. \nIf you experience stuttering when generating distant LODs, decrease this number. If you want to increase LOD generation speed, increase this number \nCan only be between 1 and your current number of threads",
"lod.config.client.advanced.threading.numberOfBufferBuilderThreads": "NO. of buffer builder threads",
"lod.config.client.advanced.threading.numberOfBufferBuilderThreads.@tooltip": "This is how many threads are used when building vertex buffers (The things sent to your GPU to draw the fake chunks) \nCan only be between 1 and your current number of threads",
"lod.config.client.advanced.buffers": "Buffers",
"lod.config.client.advanced.buffers.gpuUploadMethod": "GPU upload method",
"lod.config.client.advanced.buffers.gpuUploadMethod.@tooltip": "What method should be used to upload geometry to the GPU?",
"lod.config.client.advanced.buffers.gpuUploadTimeoutInMilleseconds": "GPU upload timeout (milliseconds)",
"lod.config.client.advanced.buffers.gpuUploadTimeoutInMilleseconds.@tooltip": "How long should we wait before uploading a buffer to the GPU? \nHelpful resource for frame times: https://fpstoms.com",
"lod.config.client.advanced.buffers.rebuildTimes": "Rebuild times",
"lod.config.client.advanced.buffers.rebuildTimes.@tooltip": "Rebuild times",
"lod.config.client.advanced.debugging": "Debug",
"lod.config.client.advanced.debugging.drawLods": "Draw LOD's",
"lod.config.client.advanced.debugging.drawLods.@tooltip": "If true, the mod is enabled and fake chunks will be drawn.",
"lod.config.client.advanced.debugging.debugMode": "Debug mode",
"lod.config.client.advanced.debugging.debugMode.@tooltip": "What type of debug mode do you want",
"lod.config.client.advanced.debugging.enableDebugKeybindings": "Enable debug keybindings",
"lod.config.client.advanced.debugging.enableDebugKeybindings.@tooltip": "Enable debug keybindings to change the Debug mode on the fly in game",
"lod.config.enum.HorizontalResolution.BLOCK": "Block",
"lod.config.enum.HorizontalResolution.TWO_BLOCKS": "2 blocks",
"lod.config.enum.HorizontalResolution.FOUR_BLOCKS": "4 blocks",
"lod.config.enum.HorizontalResolution.HALF_CHUNK": "Half a chunk",
"lod.config.enum.HorizontalResolution.CHUNK": "Chunk",
"lod.config.enum.VerticalQuality.LOW": "Low",
"lod.config.enum.VerticalQuality.MEDIUM": "Medium",
"lod.config.enum.VerticalQuality.HIGH": "High",
"lod.config.enum.HorizontalScale.LOW": "Low",
"lod.config.enum.HorizontalScale.MEDIUM": "Medium",
"lod.config.enum.HorizontalScale.HIGH": "High",
"lod.config.enum.HorizontalQuality.LOWEST": "Lowest",
"lod.config.enum.HorizontalQuality.LOW": "Low",
"lod.config.enum.HorizontalQuality.MEDIUM": "Medium",
"lod.config.enum.HorizontalQuality.HIGH": "High",
"lod.config.enum.FogDistance.NEAR": "Near",
"lod.config.enum.FogDistance.FAR": "Far",
"lod.config.enum.FogDistance.NEAR_AND_FAR": "Near and far",
"lod.config.enum.FogDrawMode.USE_OPTIFINE_SETTING": "Use modded settings",
"lod.config.enum.FogDrawMode.FOG_ENABLED": "Fog enabled",
"lod.config.enum.FogDrawMode.FOG_DISABLED": "Fog disabled",
"lod.config.enum.FogColorMode.USE_WORLD_FOG_COLOR": "Use world fog",
"lod.config.enum.FogColorMode.USE_SKY_COLOR": "Use sky color",
"lod.config.enum.LodTemplate.CUBIC": "Cubic",
"lod.config.enum.LodTemplate.TRIANGULAR": "Triangular",
"lod.config.enum.LodTemplate.DYNAMIC": "Dynamic",
"lod.config.enum.VanillaOverdraw.NEVER": "Never",
"lod.config.enum.VanillaOverdraw.DYNAMIC": "Dynamic",
"lod.config.enum.VanillaOverdraw.ALWAYS": "Always",
"lod.config.enum.VanillaOverdraw.BORDER": "Border",
"lod.config.enum.GenerationPriority.AUTO": "Auto",
"lod.config.enum.GenerationPriority.NEAR_FIRST": "Near first",
"lod.config.enum.GenerationPriority.FAR_FIRST": "Far first",
"lod.config.enum.DistanceGenerationMode.NONE": "None",
"lod.config.enum.DistanceGenerationMode.BIOME_ONLY": "Biome only",
"lod.config.enum.DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT": "Biome only simulate height",
"lod.config.enum.DistanceGenerationMode.SURFACE": "Surface",
"lod.config.enum.DistanceGenerationMode.FEATURES": "Features",
"lod.config.enum.DistanceGenerationMode.FULL": "Full",
"lod.config.enum.BlocksToAvoid.NONE": "None",
"lod.config.enum.BlocksToAvoid.NON_FULL": "Non full",
"lod.config.enum.BlocksToAvoid.NO_COLLISION": "No collision",
"lod.config.enum.BlocksToAvoid.BOTH": "Both",
"lod.config.enum.DebugMode.OFF": "Off",
"lod.config.enum.DebugMode.SHOW_DETAIL": "Show detail",
"lod.config.enum.DebugMode.SHOW_DETAIL_WIREFRAME": "Show detail with wireframe",
"lod.config.enum.GpuUploadMethod.AUTO": "Auto",
"lod.config.enum.GpuUploadMethod.BUFFER_STORAGE": "Buffer storage",
"lod.config.enum.GpuUploadMethod.SUB_DATA": "Sub data",
"lod.config.enum.GpuUploadMethod.BUFFER_MAPPING": "Buffer mapping",
"lod.config.enum.GpuUploadMethod.DATA": "Data",
"lod.config.enum.BufferRebuildTimes.FREQUENT": "Frequent",
"lod.config.enum.BufferRebuildTimes.NORMAL": "Normal",
"lod.config.enum.BufferRebuildTimes.RARE": "Rare",
"toast.lod.title": "Distant Horizons",
"key.lod.category": "Distant Horizons",
"key.lod.DebugToggle": "Debug toggle",
"key.lod.DrawToggle": "Draw toggle"
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

+19 -3
View File
@@ -1,6 +1,6 @@
accessWidener v1 named accessWidener v1 named
# used when determining where to save files too # used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File; accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used when rendering # used when rendering
@@ -8,8 +8,9 @@ accessible field com/mojang/blaze3d/vertex/VertexBuffer indexCount I
accessible field com/mojang/blaze3d/vertex/VertexBuffer vertextBufferId I accessible field com/mojang/blaze3d/vertex/VertexBuffer vertextBufferId I
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
# pre-render setup # used for grabbing vanilla rendered chunks
accessible field net/minecraft/client/renderer/LevelRenderer renderChunks Lit/unimi/dsi/fastutil/objects/ObjectArrayList; accessible field net/minecraft/client/renderer/LevelRenderer renderChunkStorage Ljava/util/concurrent/atomic/AtomicReference;
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkStorage
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk; accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
@@ -21,12 +22,27 @@ accessible field net/minecraft/world/level/lighting/LevelLightEngine skyEngine L
# world generation # world generation
accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V
accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings; accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings;
accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecraft/world/level/biome/Biome$BiomeCategory;
# accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Lnet/minecraft/core/Holder;
accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doFill (Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;II)Lnet/minecraft/world/level/chunk/ChunkAccess;
#accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doCreateBiomes (Lnet/minecraft/core/Registry;Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;)V
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
# lod generation from save file
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
accessible method net/minecraft/server/level/ChunkMap readChunk (Lnet/minecraft/world/level/ChunkPos;)Lnet/minecraft/nbt/CompoundTag;
# grabbing textures # grabbing textures
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite animatedTexture Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture; accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite animatedTexture Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture;
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite width I accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite width I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite height I accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite height I
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite mainImage [Lcom/mojang/blaze3d/platform/NativeImage; accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite mainImage [Lcom/mojang/blaze3d/platform/NativeImage;
accessible class net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameX (I)I accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameX (I)I
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameY (I)I accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameY (I)I
extendable class com/mojang/math/Matrix4f extendable class com/mojang/math/Matrix4f
# hacky stuff
accessible field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
mutable field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
Binary file not shown.

Before

Width:  |  Height:  |  Size: 172 KiB

+1 -1
Submodule core updated: f3b6b15bcb...6cd0281d0e
+52 -7
View File
@@ -1,7 +1,9 @@
plugins { plugins {
id "com.github.johnrengelman.shadow" version "7.0.0" id "com.github.johnrengelman.shadow" version "7.1.0"
} }
version = rootProject.mod_version+"-"+rootProject.minecraft_version+"-"+new Date().format("yyyy_MM_dd_HH_mm")
loom { loom {
accessWidenerPath.set(project(":common").file("src/main/resources/lod.accesswidener")) accessWidenerPath.set(project(":common").file("src/main/resources/lod.accesswidener"))
} }
@@ -22,11 +24,17 @@ repositories {
maven { url "https://maven.terraformersmc.com/" } maven { url "https://maven.terraformersmc.com/" }
} }
def addMod(path, enabled) {
if (enabled == "2")
dependencies { modImplementation(path) }
else if (enabled == "1")
dependencies { modCompileOnly(path) }
}
dependencies { dependencies {
// Fabric loader
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}" modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
// TODO: This is only for LodMain, try to find a way to remove it
// Fabric API // Fabric API
modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}" modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
@@ -35,9 +43,47 @@ dependencies {
exclude(group: "net.fabricmc.fabric-api") exclude(group: "net.fabricmc.fabric-api")
} }
// Starlight
addMod("curse.maven:starlight-521783:${rootProject.starlight_version_fabric}", rootProject.enable_starlight)
// Sodium
addMod("curse.maven:sodium-394468:${rootProject.sodium_version}", rootProject.enable_sodium)
implementation "org.joml:joml:1.10.2"
// Lithium
addMod("maven.modrinth:lithium:${rootProject.lithium_version}", rootProject.enable_lithium)
// Iris
addMod("maven.modrinth:iris:${rootProject.iris_version}", rootProject.enable_iris)
// BCLib
addMod("com.github.paulevsGitch:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib)
// Immersive Portals
/*
modImplementation("com.github.qouteall.ImmersivePortalsMod:build:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
modImplementation("com.github.qouteall.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
modImplementation("com.github.qouteall.ImmersivePortalsMod:q_misc_util:${rootProject.immersive_portals_version}") {
exclude(group: "net.fabricmc.fabric-api")
transitive(false)
}
*/
// Toml
shadowMe("com.electronwill.night-config:toml:${rootProject.toml_version}") {}
common(project(path: ":common", configuration: "namedElements")) { transitive false } common(project(path: ":common", configuration: "namedElements")) { transitive false }
shadowMe(project(path: ":common", configuration: "transformProductionFabric")) { transitive false } shadowMe(project(path: ":common", configuration: "transformProductionFabric")) { transitive false }
// Compression
common 'org.tukaani:xz:1.9' common 'org.tukaani:xz:1.9'
common 'org.apache.commons:commons-compress:1.21' common 'org.apache.commons:commons-compress:1.21'
shadowMe 'org.tukaani:xz:1.9' shadowMe 'org.tukaani:xz:1.9'
@@ -67,22 +113,21 @@ task copyCommonResources(type: Copy) {
runClient { runClient {
dependsOn(copyCoreResources) dependsOn(copyCoreResources)
dependsOn(copyCommonResources) dependsOn(copyCommonResources)
jvmArgs "-XX:-OmitStackTraceInFastThrow"
finalizedBy(deleteResources) finalizedBy(deleteResources)
} }
processResources { processResources {
dependsOn(copyAccessWidener) dependsOn(copyAccessWidener)
inputs.property "version", project.version
filesMatching("fabric.mod.json") {
expand "version": project.version
}
} }
shadowJar { shadowJar {
configurations = [project.configurations.shadowMe] configurations = [project.configurations.shadowMe]
relocate 'org.tukaani', 'shaded.tukaani' relocate 'org.tukaani', 'shaded.tukaani'
relocate 'org.apache.commons.compress', 'shaded.apache.commons.compress' relocate 'org.apache.commons.compress', 'shaded.apache.commons.compress'
relocate 'com.electronwill.nightconfig', 'shaded.electronwill.nightconfig'
relocate 'com.seibel.lod.common', 'fabric.com.seibel.lod.common'
classifier "dev-shadow" classifier "dev-shadow"
} }
@@ -19,23 +19,34 @@
package com.seibel.lod.fabric; package com.seibel.lod.fabric;
import com.seibel.lod.common.Config; import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.api.EventApi; import com.seibel.lod.core.api.EventApi;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.mojang.blaze3d.platform.InputConstants;
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper; import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.common.wrappers.world.DimensionTypeWrapper; import com.seibel.lod.common.wrappers.world.DimensionTypeWrapper;
import com.seibel.lod.common.wrappers.world.WorldWrapper; import com.seibel.lod.common.wrappers.world.WorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientChunkEvents; import com.seibel.lod.fabric.mixins.MixinUtilBackgroudThread;
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerChunkEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents; import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
import net.minecraft.client.KeyMapping; import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.chunk.LevelChunk; import net.minecraft.world.level.chunk.LevelChunk;
import java.util.HashSet;
import java.util.List;
import java.util.function.Supplier;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
/** /**
@@ -49,26 +60,29 @@ import org.lwjgl.glfw.GLFW;
public class ClientProxy public class ClientProxy
{ {
private final EventApi eventApi = EventApi.INSTANCE; private final EventApi eventApi = EventApi.INSTANCE;
private final ClientApi clientApi = ClientApi.INSTANCE;
public static Supplier<Boolean> isGenerationThreadChecker = null;
/** /**
* Registers Fabric Events * Registers Fabric Events
* @author Ran * @author Ran
*/ */
public void registerEvents() { public void registerEvents() {
// TODO: Fix this if it's wrong /* Registor the mod accessor*/
/* World Events */ /* World Events */
ServerTickEvents.START_SERVER_TICK.register(this::serverTickEvent); //ServerTickEvents.START_SERVER_TICK.register(this::serverTickEvent);
ServerTickEvents.END_SERVER_TICK.register(this::serverTickEvent); ServerTickEvents.END_SERVER_TICK.register(this::serverTickEvent);
/* World Events */ /* World Events */
ServerChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent); //ServerChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
ClientChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent); //ClientChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
/* World Events */ /* World Events */
ServerWorldEvents.LOAD.register((server, level) -> this.worldLoadEvent(level)); ServerWorldEvents.LOAD.register((server, level) -> this.worldLoadEvent(level));
ServerWorldEvents.UNLOAD.register((server, level) -> this.worldUnloadEvent()); ServerWorldEvents.UNLOAD.register((server, level) -> this.worldUnloadEvent(level));
/* The Client World Events are in the mixins /* The Client World Events are in the mixins
Client world load event is in MixinClientLevel Client world load event is in MixinClientLevel
Client world unload event is in MixinMinecraft */ Client world unload event is in MixinMinecraft */
@@ -78,6 +92,8 @@ public class ClientProxy
ClientTickEvents.END_CLIENT_TICK.register(client -> { ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (client.player != null) onKeyInput(); if (client.player != null) onKeyInput();
}); });
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
} }
@@ -88,7 +104,8 @@ public class ClientProxy
public void chunkLoadEvent(LevelAccessor level, LevelChunk chunk) public void chunkLoadEvent(LevelAccessor level, LevelChunk chunk)
{ {
eventApi.chunkLoadEvent(new ChunkWrapper(chunk), DimensionTypeWrapper.getDimensionTypeWrapper(level.dimensionType())); clientApi.clientChunkLoadEvent(new ChunkWrapper(chunk, level),
WorldWrapper.getWorldWrapper(level));
} }
public void worldSaveEvent() public void worldSaveEvent()
@@ -104,54 +121,74 @@ public class ClientProxy
} }
} }
public void worldUnloadEvent() public void worldUnloadEvent(Level level)
{ {
eventApi.worldUnloadEvent(); if (level != null) {
} eventApi.worldUnloadEvent(WorldWrapper.getWorldWrapper(level));
/*
public void blockChangeEvent(BlockEventData event)
{
// we only care about certain block events
if (event.getClass() == BlockEventData.BreakEvent.class ||
event.getClass() == BlockEventData.EntityPlaceEvent.class ||
event.getClass() == BlockEventData.EntityMultiPlaceEvent.class ||
event.getClass() == BlockEventData.FluidPlaceBlockEvent.class ||
event.getClass() == BlockEventData.PortalSpawnEvent.class)
{
IChunkWrapper chunk = new ChunkWrapper(event.getWorld().getChunk(event.getPos()));
DimensionTypeWrapper dimType = DimensionTypeWrapper.getDimensionTypeWrapper(event.getWorld().dimensionType());
// recreate the LOD where the blocks were changed
eventApi.blockChangeEvent(chunk, dimType);
} }
} }
*/
/**
* Can someone tell me how to make this better
* @author Ran
*
* public void blockChangeEvent(BlockEventData event) {
* // we only care about certain block events
* if (event.getClass() == BlockEventData.BreakEvent.class ||
* event.getClass() == BlockEventData.EntityPlaceEvent.class ||
* event.getClass() == BlockEventData.EntityMultiPlaceEvent.class ||
* event.getClass() == BlockEventData.FluidPlaceBlockEvent.class ||
* event.getClass() == BlockEventData.PortalSpawnEvent.class)
* {
* IChunkWrapper chunk = new ChunkWrapper(event.getWorld().getChunk(event.getPos()));
* DimensionTypeWrapper dimType = DimensionTypeWrapper.getDimensionTypeWrapper(event.getWorld().dimensionType());
*
* // recreate the LOD where the blocks were changed
* eventApi.blockChangeEvent(chunk, dimType);
* }
* }
*/
public void blockChangeEvent(LevelAccessor world, BlockPos pos) {
IChunkWrapper chunk = new ChunkWrapper(world.getChunk(pos), world);
DimensionTypeWrapper dimType = DimensionTypeWrapper.getDimensionTypeWrapper(world.dimensionType());
// recreate the LOD where the blocks were changed
eventApi.blockChangeEvent(chunk, dimType);
}
// The debug mode keybinding, which will be registered private static final List<Integer> KEY_TO_CHECK_FOR = List.of(GLFW.GLFW_KEY_F6, GLFW.GLFW_KEY_F8);
public static final KeyMapping DebugToggle = KeyBindingHelper.registerKeyBinding(
new KeyMapping("key.lod.DebugToggle", GLFW.GLFW_KEY_F4, "key.lod.category"));
// The draw toggle keybinding, which will be registered HashSet<Integer> previousKeyDown = new HashSet<Integer>();
public static final KeyMapping DrawToggle = KeyBindingHelper.registerKeyBinding(
new KeyMapping("key.lod.DrawToggle", GLFW.GLFW_KEY_F6, "key.lod.category"));
boolean PreDebugToggle = false;
boolean PreDrawToggle = false;
public void onKeyInput() { public void onKeyInput() {
if (Config.Client.Advanced.Debugging.enableDebugKeybindings) ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
if (CONFIG.client().advanced().debugging().getDebugKeybindingsEnabled())
{ {
// Only activates when you press the key HashSet<Integer> currectKeyDown = new HashSet<Integer>();
if (DebugToggle.isDown() && DebugToggle.isDown() != PreDebugToggle)
Config.Client.Advanced.Debugging.debugMode = Config.Client.Advanced.Debugging.debugMode.getNext();
if (DrawToggle.isDown() && DrawToggle.isDown() != PreDebugToggle) // Note: Minecraft's InputConstants is same as GLFW Key values
Config.Client.Advanced.Debugging.drawLods = !Config.Client.Advanced.Debugging.drawLods; //TODO: Use mixin to hook directly into the GLFW Keyboard event in minecraft KeyboardHandler
// Check all keys we need
for (int i = InputConstants.KEY_A; i <= InputConstants.KEY_Z; i++) {
if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), i)) {
currectKeyDown.add(i);
}
}
for (int i : KEY_TO_CHECK_FOR) {
if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), i)) {
currectKeyDown.add(i);
}
}
// Diff and trigger events
for (int c : currectKeyDown) {
if (!previousKeyDown.contains(c)) {
ClientApi.INSTANCE.keyPressedEvent(c);
}
}
// Update the set
previousKeyDown = currectKeyDown;
} }
PreDebugToggle = DebugToggle.isDown();
PreDrawToggle = DrawToggle.isDown();
} }
} }
@@ -19,12 +19,22 @@
package com.seibel.lod.fabric; package com.seibel.lod.fabric;
import com.seibel.lod.common.Config;
import com.seibel.lod.common.LodCommonMain; import com.seibel.lod.common.LodCommonMain;
import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.core.ModInfo; import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi; import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.fabric.wrappers.DependencySetup; import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
import com.seibel.lod.fabric.networking.NetworkHandler;
import com.seibel.lod.fabric.wrappers.modAccessor.ModChecker;
import com.seibel.lod.fabric.wrappers.modAccessor.OptifineAccessor;
import com.seibel.lod.fabric.wrappers.modAccessor.SodiumAccessor;
import com.seibel.lod.fabric.wrappers.modAccessor.StarlightAccessor;
import com.seibel.lod.fabric.wrappers.FabricDependencySetup;
import net.fabricmc.api.ClientModInitializer; import net.fabricmc.api.ClientModInitializer;
@@ -42,8 +52,6 @@ public class Main implements ClientModInitializer
// This is a client mod so it should implement ClientModInitializer and in fabric.mod.json it should have "environment": "client" // This is a client mod so it should implement ClientModInitializer and in fabric.mod.json it should have "environment": "client"
// Once it works on servers change the implement to ModInitializer and in fabric.mod.json it should be "environment": "*" // Once it works on servers change the implement to ModInitializer and in fabric.mod.json it should be "environment": "*"
public static Main instance;
public static ClientProxy client_proxy; public static ClientProxy client_proxy;
@@ -57,12 +65,32 @@ public class Main implements ClientModInitializer
// This loads the mod after minecraft loads which doesn't causes a lot of issues // This loads the mod after minecraft loads which doesn't causes a lot of issues
public static void init() { public static void init() {
LodCommonMain.initConfig(); LodCommonMain.initConfig();
LodCommonMain.startup(null); LodCommonMain.startup(null, false, new NetworkHandler());
DependencySetup.createInitialBindings(); FabricDependencySetup.createInitialBindings();
ClientApi.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION); FabricDependencySetup.finishBinding();
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
// Check if this works // Check if this works
client_proxy = new ClientProxy(); client_proxy = new ClientProxy();
client_proxy.registerEvents(); client_proxy.registerEvents();
if (SingletonHandler.get(IModChecker.class).isModLoaded("sodium")) {
ModAccessorHandler.bind(ISodiumAccessor.class, new SodiumAccessor());
}
if (SingletonHandler.get(IModChecker.class).isModLoaded("starlight")) {
ModAccessorHandler.bind(IStarlightAccessor.class, new StarlightAccessor());
}
if (SingletonHandler.get(IModChecker.class).isModLoaded("optifine")) {
ModAccessorHandler.bind(IOptifineAccessor.class, new OptifineAccessor());
}
ModAccessorHandler.finishBinding();
}
public static void initServer() {
LodCommonMain.initConfig();
LodCommonMain.startup(null, true, new NetworkHandler());
FabricDependencySetup.createInitialBindings();
FabricDependencySetup.finishBinding();
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
} }
} }
@@ -0,0 +1,16 @@
package com.seibel.lod.fabric.mixins;
import com.seibel.lod.fabric.Main;
import net.minecraft.server.dedicated.DedicatedServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(DedicatedServer.class)
public class MixinDedicatedServer {
@Inject(method = "initServer", at = @At("TAIL"))
public void initServer(CallbackInfoReturnable<Boolean> cir) {
Main.initServer();
}
}
@@ -0,0 +1,40 @@
package com.seibel.lod.fabric.mixins;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.renderer.FogRenderer.FogMode;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.material.FogType;
@Mixin(FogRenderer.class)
public class MixinFogRenderer {
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
@Inject(at = @At("RETURN"), method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZ)V")
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback) {
FogType fogTypes = camera.getFluidInCamera();
Entity entity = camera.getEntity();
boolean isUnderWater = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
if (!isUnderWater) {
if (fogMode == FogMode.FOG_TERRAIN && fogTypes == FogType.NONE && CONFIG.client().graphics().fogQuality().getDisableVanillaFog()) {
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
}
}
}
}
@@ -1,8 +1,10 @@
package com.seibel.lod.common.mixins; package com.seibel.lod.fabric.mixins;
import com.seibel.lod.common.wrappers.config.ConfigGui; import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.common.wrappers.config.TexturedButtonWidget; import com.seibel.lod.common.wrappers.config.TexturedButtonWidget;
import com.seibel.lod.core.ModInfo; import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import net.minecraft.client.gui.screens.OptionsScreen; import net.minecraft.client.gui.screens.OptionsScreen;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
@@ -31,7 +33,8 @@ public class MixinOptionsScreen extends Screen {
@Inject(at = @At("HEAD"),method = "init") @Inject(at = @At("HEAD"),method = "init")
private void lodconfig$init(CallbackInfo ci) { private void lodconfig$init(CallbackInfo ci) {
this.addRenderableWidget(new TexturedButtonWidget( if (SingletonHandler.get(ILodConfigWrapperSingleton.class).client().getOptionsButton())
this.addRenderableWidget(new TexturedButtonWidget(
// Where the button is on the screen // Where the button is on the screen
this.width / 2 - 180, this.height / 6 - 12, this.width / 2 - 180, this.height / 6 - 12,
// Width and height of the button // Width and height of the button
@@ -42,7 +45,7 @@ public class MixinOptionsScreen extends Screen {
20, ICON_TEXTURE, 20, 40, 20, ICON_TEXTURE, 20, 40,
// Create the button and tell it where to go // Create the button and tell it where to go
// For now it goes to the client option by default // For now it goes to the client option by default
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(ConfigGui.getScreen(this, ModInfo.ID, "client")), (buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(ConfigGui.getScreen(this, "client")),
// Add a title to the screen // Add a title to the screen
new TranslatableComponent("text.autoconfig." + ModInfo.ID + ".title"))); new TranslatableComponent("text.autoconfig." + ModInfo.ID + ".title")));
} }
@@ -0,0 +1,50 @@
package com.seibel.lod.fabric.mixins;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
import com.seibel.lod.fabric.ClientProxy;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.seibel.lod.core.util.DummyRunExecutorService;
import net.minecraft.Util;
@Mixin(Util.class)
public class MixinUtilBackgroudThread
{
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/lang/Runnable;)Ljava/lang/Runnable;",
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
{
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
{
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
ci.setReturnValue(r);
}
}
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/util/function/Supplier;)Ljava/util/function/Supplier;",
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
{
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
{
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
ci.setReturnValue(r);
}
}
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
{
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
{
//ApiShared.LOGGER.info("util backgroundExecutor triggered");
ci.setReturnValue(new DummyRunExecutorService());
}
}
}
@@ -0,0 +1,96 @@
/*
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
* licensed under the GNU GPL v3 License.
*
* Copyright (C) 2020 James Seibel
*
* 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, version 3.
*
* 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.seibel.lod.fabric.mixins;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Matrix4f;
import com.seibel.lod.common.wrappers.McObjectConverter;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.client.Camera;
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.RenderType;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* This class is used to mix in my rendering code
* before Minecraft starts rendering blocks.
* If this wasn't done, and we used Forge's
* render last event, the LODs would render on top
* of the normal terrain.
*
* This is also the mixin for rendering the clouds
*
* @author coolGi2007
* @author James Seibel
* @version 12-31-2021
*/
@Mixin(LevelRenderer.class)
public class MixinWorldRenderer
{
private static float previousPartialTicks = 0;
public MixinWorldRenderer() {
throw new NullPointerException("Null cannot be cast to non-null type.");
}
@Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true)
public void renderClouds(PoseStack poseStack, Matrix4f projectionMatrix, float tickDelta, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) {
// get the partial ticks since renderChunkLayer doesn't
// have access to them
previousPartialTicks = tickDelta;
}
// HEAD or RETURN
@Inject(at = @At("RETURN"),
method = "renderSky",
cancellable = true)
private void renderLod(PoseStack modelViewMatrixStack, Matrix4f projectionMatrix, float f,
#if MC_VERSION_1_18_2 Camera camera, boolean bl,#endif Runnable r, CallbackInfo callback) {
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
}
/*
// HEAD or RETURN
@Inject(at = @At("HEAD"),
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V",
cancellable = true)
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
{
// only render before solid blocks
if (renderType.equals(RenderType.solid()))
{
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
}
//callback.cancel();
}*/
}
@@ -0,0 +1,27 @@
package com.seibel.lod.fabric.mixins.events;
import com.seibel.lod.fabric.Main;
import net.minecraft.client.Minecraft;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* If someone has a better way to do this then please let me know.
*
* @author Ran
*/
@Mixin(ClientboundBlockUpdatePacket.class)
public abstract class MixinBlockUpdate {
@Shadow public abstract BlockPos getPos();
@Inject(method = "handle(Lnet/minecraft/network/protocol/game/ClientGamePacketListener;)V", at = @At("TAIL"))
private void onBlockUpdate(ClientGamePacketListener clientGamePacketListener, CallbackInfo ci) {
Main.client_proxy.blockChangeEvent(Minecraft.getInstance().player.clientLevel, this.getPos());
}
}
@@ -4,9 +4,11 @@ import com.seibel.lod.fabric.Main;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.LevelRenderer;
#if MC_VERSION_1_18_2
import net.minecraft.core.Holder;
#endif
import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceKey;
import net.minecraft.util.profiling.ProfilerFiller; import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.dimension.DimensionType; import net.minecraft.world.level.dimension.DimensionType;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -19,10 +21,26 @@ import java.util.function.Supplier;
* This class is used for world loading events * This class is used for world loading events
* @author Ran * @author Ran
*/ */
@Mixin(ClientLevel.class) @Mixin(ClientLevel.class)
public class MixinClientLevel { public class MixinClientLevel {
#if MC_VERSION_1_18_2
@Inject(method = "<init>", at = @At("TAIL")) @Inject(method = "<init>", at = @At("TAIL"))
private void loadWorldEvent(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey<Level> resourceKey, DimensionType dimensionType, int i, Supplier<ProfilerFiller> supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) { private void loadWorldEvent(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey resourceKey, Holder holder, int i, int j, Supplier supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) {
Main.client_proxy.worldLoadEvent((ClientLevel) (Object) this); Main.client_proxy.worldLoadEvent((ClientLevel) (Object) this);
} }
#elif MC_VERSION_1_18_1
@Inject(method = "<init>", at = @At("TAIL"))
private void loadWorldEvent(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey resourceKey, DimensionType dimensionType, int i, int j, Supplier supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) {
Main.client_proxy.worldLoadEvent((ClientLevel) (Object) this);
}
#endif
@Inject(method = "setLightReady", at = @At("HEAD"))
private void onChunkLightReady(int x, int z, CallbackInfo ci) {
ClientLevel l = (ClientLevel) (Object) this;
LevelChunk chunk = l.getChunkSource().getChunk(x, z, false);
if (chunk!=null && !chunk.isClientLightReady())
Main.client_proxy.chunkLoadEvent(l, chunk);
}
} }
@@ -4,6 +4,7 @@ import com.seibel.lod.fabric.Main;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientLevel;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@@ -21,11 +22,11 @@ public class MixinMinecraft {
@Inject(method = "setLevel", at = @At("HEAD")) @Inject(method = "setLevel", at = @At("HEAD"))
private void unloadWorldEvent_sL(ClientLevel clientLevel, CallbackInfo ci) { private void unloadWorldEvent_sL(ClientLevel clientLevel, CallbackInfo ci) {
if (level != null) Main.client_proxy.worldUnloadEvent(); if (level != null) Main.client_proxy.worldUnloadEvent(level);
} }
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/Minecraft;updateScreenAndTick(Lnet/minecraft/client/gui/screens/Screen;)V", shift = At.Shift.AFTER)) @Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At("HEAD"))
private void unloadWorldEvent_cL(Screen screen, CallbackInfo ci) { private void unloadWorldEvent_cL(Screen screen, CallbackInfo ci) {
if (this.level != null) Main.client_proxy.worldUnloadEvent(); if (this.level != null) Main.client_proxy.worldUnloadEvent(this.level);
} }
} }
@@ -0,0 +1,26 @@
package com.seibel.lod.fabric.mixins.unsafe;
import net.minecraft.util.ThreadingDetector;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.concurrent.Semaphore;
/**
* Why does this exist? But okay! (Will be probably removed when the experimental generator is done)
*/
@Mixin(ThreadingDetector.class)
public class MixinThreadingDectector {
@Mutable
@Shadow
private Semaphore lock;
@Inject(method = "<init>", at = @At("RETURN"))
private void setSemaphore(CallbackInfo ci) {
this.lock = new Semaphore(2);
}
}
@@ -0,0 +1,25 @@
package com.seibel.lod.fabric.networking;
import com.seibel.lod.common.networking.NetworkInterface;
import com.seibel.lod.common.networking.Networking;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
/**
* @author Ran
*/
public class NetworkHandler implements NetworkInterface {
@Override
public void register_Client() {
ClientPlayNetworking.registerGlobalReceiver(Networking.resourceLocation_meow, (client, handler, buf, responseSender) -> {
com.seibel.lod.common.networking.NetworkHandler.receivePacketClient(client, handler, buf);
});
}
@Override
public void register_Server() {
ServerPlayNetworking.registerGlobalReceiver(Networking.resourceLocation_meow, (server, player, handler, buf, responseSender) -> {
com.seibel.lod.common.networking.NetworkHandler.receivePacketServer(server, player, handler, buf);
});
}
}
@@ -1,8 +1,10 @@
package com.seibel.lod.fabric.wrappers; package com.seibel.lod.fabric.wrappers;
import com.seibel.lod.core.util.SingletonHandler; import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton; import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.common.wrappers.config.LodConfigWrapperSingleton; import com.seibel.lod.common.wrappers.config.LodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.lod.fabric.wrappers.modAccessor.ModChecker;
/** /**
* Binds all necessary dependencies, so we * Binds all necessary dependencies, so we
@@ -12,12 +14,18 @@ import com.seibel.lod.common.wrappers.config.LodConfigWrapperSingleton;
* *
* @author James Seibel * @author James Seibel
* @author Ran * @author Ran
* @version 12-1-2021 * @version 3-5-2022
*/ */
public class DependencySetup public class FabricDependencySetup
{ {
public static void createInitialBindings() public static void createInitialBindings()
{ {
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);; SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);
}
public static void finishBinding() {
SingletonHandler.finishBinding();
} }
} }
@@ -1,16 +1,11 @@
package com.seibel.lod.fabric.wrappers.config; package com.seibel.lod.fabric.wrappers.config;
import com.seibel.lod.common.wrappers.config.ConfigGui; import com.seibel.lod.common.wrappers.config.ConfigGui;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.common.Config;
import com.terraformersmc.modmenu.api.ConfigScreenFactory; import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi; import com.terraformersmc.modmenu.api.ModMenuApi;
import net.fabricmc.api.EnvType; import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment; import net.fabricmc.api.Environment;
import java.util.HashMap;
import java.util.Map;
/** /**
* For making the config show up in modmenu * For making the config show up in modmenu
*/ */
@@ -19,14 +14,6 @@ public class ModMenuIntegration implements ModMenuApi {
// For the custom config code // For the custom config code
@Override @Override
public ConfigScreenFactory<?> getModConfigScreenFactory() { public ConfigScreenFactory<?> getModConfigScreenFactory() {
return parent -> Config.getScreen(parent, ModInfo.ID, ""); return parent -> ConfigGui.getScreen(parent, "");
}
@Override
public Map<String, ConfigScreenFactory<?>> getProvidedConfigScreenFactories() {
HashMap<String, ConfigScreenFactory<?>> map = new HashMap<>();
// For now it goes to the client option by default
Config.configClass.forEach((modid, cClass) -> map.put(modid, parent -> ConfigGui.getScreen(parent, modid, "client")));
return map;
} }
} }
@@ -0,0 +1,13 @@
package com.seibel.lod.fabric.wrappers.modAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
import net.fabricmc.loader.api.FabricLoader;
public class ModChecker implements IModChecker {
public static final ModChecker INSTANCE = new ModChecker();
@Override
public boolean isModLoaded(String modid) {
return FabricLoader.getInstance().isModLoaded(modid);
}
}
@@ -0,0 +1,24 @@
package com.seibel.lod.fabric.wrappers.modAccessor;
import java.util.HashSet;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
public class OptifineAccessor implements IOptifineAccessor
{
@Override
public String getModName()
{
return "Optifine-Fabric-1.18.X";
}
@Override
public HashSet<AbstractChunkPosWrapper> getNormalRenderedChunks()
{
// TODO: Impl proper methods here
return null;
}
}
@@ -0,0 +1,42 @@
package com.seibel.lod.fabric.wrappers.modAccessor;
import java.util.HashSet;
import java.util.stream.Collectors;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer;
import net.minecraft.client.Minecraft;
import net.minecraft.world.level.LevelHeightAccessor;
public class SodiumAccessor implements ISodiumAccessor {
IWrapperFactory factory = SingletonHandler.get(IWrapperFactory.class);
@Override
public String getModName() {
return "Sodium-Fabric-1.18.X";
}
@Override
public HashSet<AbstractChunkPosWrapper> getNormalRenderedChunks() {
SodiumWorldRenderer renderer = SodiumWorldRenderer.instance();
LevelHeightAccessor height = Minecraft.getInstance().level;
// 0b11 = Lighted chunk & loaded chunk
return renderer.getChunkTracker().getChunks(0b00).filter(
(long l) -> {
return true;
//for (int i = height.getMinSection(); i<height.getMaxSection(); i++) {
// SectionPos p = SectionPos.of(new ChunkPos(l), i);
// if (renderer.isBoxVisible(p.minBlockX()+1, p.minBlockY()+1, p.minBlockZ()+1,
// p.maxBlockX()-1, p.maxBlockY()-1, p.maxBlockZ()-1)) return true;
//}
//return false;
}).mapToObj((long l) -> {
return (AbstractChunkPosWrapper)factory.createChunkPos(l);
}).collect(Collectors.toCollection(HashSet::new));
}
}
@@ -0,0 +1,16 @@
package com.seibel.lod.fabric.wrappers.modAccessor;
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
public class StarlightAccessor implements IStarlightAccessor {
@Override
public String getModName() {
return "Starlight-Fabric-1.18.X";
}
public StarlightAccessor() {
}
}
@@ -0,0 +1,458 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
@@ -0,0 +1,26 @@
{
"required": true,
"minVersion": "0.8",
"package": "com.seibel.lod.fabric.mixins",
"compatibilityLevel": "JAVA_17",
"mixins": [
"unsafe.MixinThreadingDectector",
"MixinUtilBackgroudThread",
"events.MixinServerLevel"
],
"client": [
"MixinMinecraft",
"MixinOptionsScreen",
"MixinWorldRenderer",
"MixinFogRenderer",
"events.MixinClientLevel",
"events.MixinMinecraft",
"events.MixinBlockUpdate"
],
"server": [
"MixinDedicatedServer"
],
"injectors": {
"defaultRequire": 1
}
}
+10 -15
View File
@@ -3,18 +3,14 @@
"id": "lod", "id": "lod",
"version": "${version}", "version": "${version}",
"name": "Distant Horizons Fabric", "name": "${mod_name}",
"description": "This mod generates and renders simplified terrain beyond the normal view distance, at a low performance cost", "description": "${description}",
"authors": [ "authors": ["${authors}"],
"coolGi2007",
"Ran",
"Original LOD Creators"
],
"contact": { "contact": {
"homepage": "https://www.curseforge.com/minecraft/mc-mods/lod-level-of-detail", "homepage": "${homepage}",
"sources": "https://gitlab.com/jeseibel/minecraft-lod-mod/-/tree/1.17.1_fabric", "sources": "${source}",
"issues": "https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues" "issues": "${issues}"
}, },
"license": "CC0-1.0", "license": "CC0-1.0",
@@ -31,16 +27,15 @@
}, },
"mixins": [ "mixins": [
"lod.mixins.json", "fabric.lod.mixins.json"
"lod.common.mixins.json"
], ],
"accessWidener" : "lod.accesswidener", "accessWidener" : "lod.accesswidener",
"depends": { "depends": {
"fabricloader": ">=0.11.3", "fabricloader": "*",
"fabric": "*", "fabric": "*",
"minecraft": "1.17.x", "minecraft": "${minecraft_version}",
"java": ">=16" "java": ">=${java_version}"
}, },
"suggests": { "suggests": {
"another-mod": "*" "another-mod": "*"

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