Compare commits

..

967 Commits

Author SHA1 Message Date
James Seibel d5740c5d7f Update core 2021-11-28 18:14:37 -06:00
James Seibel 816249acdb Update core 2021-11-28 16:54:23 -06:00
James Seibel 23d9cf10d3 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-11-28 16:28:49 -06:00
James Seibel eeea070fd1 Update core 2021-11-28 16:28:47 -06:00
James Seibel e47cdaa2e4 update the version number to a1.5.3 2021-11-28 16:09:25 -06:00
cola98765 db074a6a5b Fix Starlight (mod) once more 2021-11-28 11:28:40 +01:00
James Seibel f2f0e291d8 Add a missing comment 2021-11-27 23:28:28 -06:00
James Seibel db123072bd Add Legacy OpenGL vanilla fog removal 2021-11-27 23:24:58 -06:00
James Seibel 6bbb99ff39 Update the version number to a1.5.3 2021-11-27 21:14:50 -06:00
James Seibel 88c5fc8fde Fix gradle issues (compiling works again) 2021-11-27 21:12:42 -06:00
James Seibel a40417bbd6 Remove logo and IDE files (they are in core now) 2021-11-27 18:05:04 -06:00
James Seibel cf7373a303 Improve the config descriptions 2021-11-27 16:17:14 -06:00
James Seibel 49c0581b1d rename DistantHorizons_Server_Data -> Distant_Horizons_server_data 2021-11-27 14:48:41 -06:00
Ran 72d3b50077 Add core resources to the jar (Isn't tested yet) 2021-11-28 01:10:12 +06:00
Ran aaedc8e384 Fix NPE when loading up the world 2021-11-28 00:21:01 +06:00
James Seibel b63f24c92e rename the server data folder 2021-11-27 12:03:38 -06:00
Ran 76154aada0 Fix shadow 2021-11-27 23:41:40 +06:00
James Seibel 6b029da899 Add setUniform(color) 2021-11-27 10:32:18 -06:00
James Seibel 818c4243e0 Add FogColorMode 2021-11-27 10:10:21 -06:00
James Seibel a41a4fe77f remove a debug command 2021-11-26 21:20:41 -06:00
James Seibel 9a03a45cd7 Clean up Fog, remove Fast fog, close issue #77 (near-far incorrect center) 2021-11-26 21:14:06 -06:00
James Seibel e2eaca7869 Add fog as a fragment shader 2021-11-26 19:25:05 -06:00
James Seibel 0bfef6b3d3 change the submodule path to https instead of ssh 2021-11-26 09:43:21 -06:00
James Seibel 03345924f3 Update core 2021-11-25 11:51:45 -06:00
James Seibel 37f72980ee Downgrade Gradle to 7.1 (from 7.2) This should be the latest available to MC 1.16.5 2021-11-25 08:15:43 -06:00
James Seibel 7fd43deaca Update gradle to 7.2 (from 4.10.3) and fix the build.gradle file 2021-11-22 19:23:49 -06:00
James Seibel 05a3d4002f Add support for disabling rendering 2021-11-21 22:15:10 -06:00
James Seibel 8a574074c5 Merge branch '1.16.5_Core' into '1.16.5'
1.16.5 core

See merge request jeseibel/minecraft-lod-mod!10
2021-11-22 00:28:09 +00:00
James Seibel f801567301 Update core 2021-11-21 18:26:48 -06:00
James Seibel 632947c8ce minor spelling fix 2021-11-21 18:26:12 -06:00
James Seibel 5cb32d6181 Delete 1.5 release notes.txt 2021-11-21 16:16:26 -06:00
James Seibel 505f48cebc Add DH-Core's source folders to Gradle 2021-11-21 15:53:35 -06:00
James Seibel e2bdfcc2da Initial implementation of Core 2021-11-21 15:28:59 -06:00
cola98765 cd72edf9a6 Merge branch 'CodeF53-1.16.5-patch-42921' into '1.16.5'
Add icon for catalogue mod & Update logo displayed in configured

Closes #97

See merge request jeseibel/minecraft-lod-mod!9
2021-11-07 11:07:43 +00:00
cola98765 5172fec97f changed back how sky/block light is accessed for Starlight (mod) compatibility 2021-11-06 23:04:14 +01:00
cola98765 b1a39ce74b disabled try catch in LodGenWorker. It made logs useless 2021-11-06 22:55:26 +01:00
cola98765 563fea608e WorldWrapper -> LevelWrapper 2021-11-05 12:19:36 +01:00
cola98765 be6e52ded0 changed world to level in minecraft wrapper for consistency with other versions 2021-11-05 12:09:07 +01:00
cola98765 6d54edd74c removed client world dependency in buffer builder; minor changes 2021-11-05 11:10:56 +01:00
CodeF53 492c634cc4 Add icon for catalogue mod
Update logo displayed in configured to match new name
2021-11-05 00:01:51 +00:00
cola98765 d92cb6016f cleaned out some code 2021-11-04 11:56:43 +01:00
cola98765 0250eba715 cleaned out some code 2021-11-04 11:45:02 +01:00
cola98765 cbf1bf698d cleaned out imports 2021-11-04 11:43:13 +01:00
cola98765 2aed897b9b pulled some changes around wrappers from 1.17.1_fabric 2021-11-04 11:30:33 +01:00
cola98765 7402ad6be0 added getHashFromFile for future use with servers 2021-11-03 19:03:42 +01:00
Leonardo d4556e7f84 Biome colors is calculated using the block color wrapper 2021-11-01 22:34:39 +01:00
Leonardo 7b910ba4fd Changed waterlogged check, the biome getter and other small stuff 2021-11-01 22:34:17 +01:00
cola98765 5762c41f1a protect full regions against being overwritten by a partial one 2021-11-01 10:18:49 +01:00
cola98765 dee9fa793d cleanup 2021-10-30 17:45:32 +02:00
cola98765 1962053a2f improved adj lighting 2021-10-30 16:38:22 +02:00
cola98765 bb16cfa4fe when there are too many gaps, remove the bottom one of the smallest size first. 2021-10-30 15:52:16 +02:00
cola98765 73ddbd66b5 fixed EXCEPTION_ACCESS_VIOLATION when stitching lods on and off using F6 2021-10-30 15:43:55 +02:00
cola98765 8e727011de now recreate buffers when you reenable rendering. Doing it using debug keys can sometimes lead to crash tho 2021-10-30 13:36:00 +02:00
cola98765 717e189107 made "Enable Rendering" only affect buffer building to enable generation with no rendering 2021-10-30 12:49:58 +02:00
cola98765 cff8326810 Fixed "generate at max quality" TODO make generation work with disabled rendering at world join 2021-10-30 11:37:52 +02:00
James Seibel fd0604c7e7 Fix a few potential null pointers when on a server world 2021-10-29 19:56:03 -05:00
James Seibel f822aed285 make the fog disabler config experimental and disabled by default 2021-10-29 19:50:50 -05:00
cola98765 26535ef81c remove debug message 2021-10-29 16:03:06 +02:00
cola98765 2b0c0f89a2 cleaned up some code 2021-10-29 15:13:37 +02:00
cola98765 51e7e318ac removed weird math.ceil that was used on int 2021-10-29 14:21:23 +02:00
cola98765 e5ef7e7026 fixed index out of bounds and void air appearing purple bugs 2021-10-29 13:22:28 +02:00
cola98765 62794766c6 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-10-29 12:27:14 +02:00
cola98765 e32addfd06 actually fixed non-square non-animated textures 2021-10-29 12:26:54 +02:00
cola98765 42678a27a4 clean out previous 2021-10-29 12:21:16 +02:00
cola98765 1488747075 fixed non-square non-animated textures 2021-10-29 12:07:41 +02:00
cola98765 a03ddf7339 applied autoformat to that vivecraft commit 2021-10-29 09:18:22 +02:00
cola98765 c537e0cf49 Merge branch '1.16.5' into '1.16.5'
Add vivecraft support

See merge request jeseibel/minecraft-lod-mod!7
2021-10-29 07:02:51 +00:00
Eric 853c706b77 Add vivecraft support 2021-10-28 22:16:19 -06:00
James Seibel 65c091bb63 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-27 21:25:09 -05:00
James Seibel 9b389332be update the version number to a1.5.2 2021-10-26 19:26:23 -05:00
Leonardo 1093001841 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-10-26 23:11:16 +02:00
cola98765 a3db8e50f5 removed NativeImage dependency outside of wrappers. Now LodRenderer only triggers regen without storing lightmap 2021-10-26 23:09:31 +02:00
Leonardo db15e8684c Another small fix to light 2021-10-26 22:44:21 +02:00
Leonardo 00ac368bba fixed light being wrong 2021-10-26 22:38:14 +02:00
Leonardo f2face9782 small change to light value getters in lod builde. Added WorldLightWrapper for future implementation 2021-10-26 21:59:35 +02:00
Leonardo 923d57b377 Fixed the colors in the lodBuilder 2021-10-26 21:46:06 +02:00
Leonardo 447325e5a1 Fixed the colors for now 2021-10-26 21:43:11 +02:00
Leonardo bf712e893e removed default color use from the BlockColorWrapper 2021-10-26 21:28:18 +02:00
Leonardo 27f9a527bc Fixed part of the colors problems 2021-10-26 21:19:09 +02:00
Leonardo bde14012d9 Divided the Block Wrapper in two different class 2021-10-26 12:31:06 +02:00
Leonardo 12a32b9fb4 Implemented the wrappers in the lodBuilder 2021-10-26 11:58:33 +02:00
James Seibel 4ad081e0c6 Add a advanced graphics option to use a extended near clip plain
This prevents some overdraw issues but causes LODs in the ocean to render incorrectly.
2021-10-25 22:20:00 -05:00
James Seibel 936a3a7ece Fix #84 (misaligned LODs in third person) 2021-10-25 21:56:22 -05:00
Leonardo 98f36936d0 smallFix 2021-10-25 22:57:37 +02:00
Leonardo f6f012c42c Added some other classes/methods to the wrappers 2021-10-25 22:51:01 +02:00
Leonardo a3e6c09268 Added more methods to the wrapper 2021-10-25 22:31:43 +02:00
Leonardo 10cb46c9f9 Added biomeWrapper 2021-10-25 21:30:44 +02:00
Leonardo 95aa9cb9ab Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-10-25 20:20:47 +02:00
Leonardo 638a0ddae1 BlockPosWrapper and BlockWrapper almost completed 2021-10-25 20:20:40 +02:00
James Seibel d321833335 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-25 07:21:26 -05:00
James Seibel b8cba0dc4c increase the near clip plane to 1/5 MC's vanilla render distance 2021-10-25 07:21:17 -05:00
cola98765 bd8ccb4a05 reverted las change, fixed vanillaRenderedChunksChanged at hight altitudes 2021-10-25 13:20:13 +02:00
cola98765 895895da04 update buffers only when lightmap changes. 2021-10-25 12:43:59 +02:00
Leonardo 09d5df2856 Added the main wrapper classes (empty) 2021-10-25 11:14:17 +02:00
James Seibel 668f225528 Fix the blindness potion effect 2021-10-24 23:02:30 -05:00
James Seibel 1cd71a6b50 Re-arange Vanilla Overdraw config options 2021-10-24 22:18:09 -05:00
James Seibel f041f79ae3 Close #78 (Add a config to disable vanilla MC's fog)
And change the config to use FAR fog and disable MC's fog by default.
2021-10-24 22:17:57 -05:00
James Seibel ef3ac96b2c Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-24 21:30:35 -05:00
James Seibel 59f527e6de Update 1.5 release notes.txt 2021-10-24 15:19:59 -05:00
James Seibel 16a082b17f rename "Disable Drawing" to "Enable Rendering" in the config
The config name was incorrect.
2021-10-24 15:19:54 -05:00
jas35484 a24d28b0e2 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-24 14:57:56 -05:00
jas35484 910f11f688 Fix #63 (OpenGL errors)
NVFogDistance doesn't work on low end GPUs which causes the OpenGL error I was seeing with Optifine
2021-10-24 14:57:53 -05:00
cola98765 e00de99e31 Found place where addData was used for adding whole vertical array. We have addVerticalData for that. 2021-10-24 12:11:43 +02:00
cola98765 f80af39e0e halving every array related to worldHeight, as you can't get worldHeight lods, as half of that needs to be a gaps 2021-10-24 11:57:08 +02:00
cola98765 5bba3cb3eb minor cleanup 2021-10-24 11:35:45 +02:00
cola98765 d4261d4ccf a little improvement to 'pow' changes 2021-10-24 11:01:02 +02:00
cola98765 8b854e3abd removed debug message 2021-10-24 10:33:02 +02:00
cola98765 4064155567 changed Math.pow usages with simpler (and possibly faster) x*x and 1 << x. reduced repetitions 2021-10-24 10:28:35 +02:00
cola98765 6243201f2d removed couple Math.floorDiv and Mod as for positive inputs they are slower and give the same result as standard operands 2021-10-24 10:08:12 +02:00
James Seibel c5a2944d68 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-23 12:04:26 -05:00
James Seibel 1405b7a433 Add support for OpenGL 1.5 and 3.0 2021-10-23 12:04:16 -05:00
cola98765 be00670b7e Merge branch 'CodeF53-1.16.5-patch-77785' into '1.16.5'
Update youtube video

See merge request jeseibel/minecraft-lod-mod!5
2021-10-23 13:29:09 +00:00
CodeF53 6f2c02d283 Make link open in new tab 2021-10-23 05:11:10 +00:00
CodeF53 309526e7b9 Update youtube video 2021-10-23 05:01:37 +00:00
James Seibel d5466e0fda Fix a potential null pointer exception when leaving the world
The thread dealing with these should probably be killed and recreated when leaving the world instead of just catching the problem here.
2021-10-22 20:46:26 -05:00
James Seibel 7a0b95a105 minor refactor in LodGenWorker 2021-10-22 20:45:37 -05:00
James Seibel 7c59e33aee remove some commented out code 2021-10-22 20:42:02 -05:00
James Seibel 9907d2ddd5 Temporary null pointer fix 2021-10-22 18:48:32 -05:00
cola98765 1a838d4bd8 pushed FAR fog out by *1.6. I don't know why this number, but it works ok. 2021-10-22 20:07:02 +02:00
cola98765 dce3227bf1 Fixed compression on retail. Don't change your gradle tasks 2021-10-22 08:28:30 +02:00
cola98765 ea6f3e9881 now it's game crashes on launch when build using file made by "shadowJar" option 2021-10-21 16:42:30 +02:00
Leonardo 2f57b67bdc fixed underwater problem with always overdraw 2021-10-21 13:19:23 +02:00
Leonardo be024f524d Fixed regions wall not showing (which would cause holes in the rendering) and added border as possible overdraw config 2021-10-21 12:57:40 +02:00
cola98765 e0a176c0c4 tried to make XZ actually part of the jar 2021-10-21 12:16:39 +02:00
James Seibel b00795a0ab Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-20 22:34:26 -05:00
James Seibel 8bfa8e70a1 Create 1.5 release notes.txt 2021-10-20 22:34:14 -05:00
James Seibel 2a0653419f Update Readme.md
Ah so there is a way to preview this online, that's nice.
2021-10-21 02:21:28 +00:00
James Seibel cc1b9ea28e change the version to a1.5.0 and fix a line in the readme 2021-10-20 21:19:40 -05:00
James Seibel b32bdb3807 Add a acknowledgement for the use of the XZ data compression project 2021-10-20 21:14:15 -05:00
James Seibel 42bac2bd57 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-20 21:07:21 -05:00
James Seibel 9bd89accd3 re-add dynamic overdraw 2021-10-20 21:07:18 -05:00
Leonardo 5493ef9033 removed a print 2021-10-21 02:36:57 +02:00
Leonardo 7d1df26cc5 Shading is only disabled for lod that should be transparent 2021-10-21 02:28:37 +02:00
Leonardo 63f6d4cc56 Fixed chorus plant 2021-10-21 02:17:57 +02:00
James Seibel 6066a572d9 finish two incomplete comments 2021-10-20 18:09:08 -05:00
Leonardo ea679992e8 Small change 2021-10-21 00:40:21 +02:00
Leonardo fedce10917 Overdraw should now be fixed 2021-10-21 00:39:37 +02:00
Leonardo 80448ce990 Small change to the buffer builder 2021-10-20 23:03:13 +02:00
Leonardo 89fac88b7e Added method to check water logged block 2021-10-20 23:02:35 +02:00
Leonardo 032b63208c Added IWaterLoggable blocks to block to use in the generation 2021-10-20 21:23:53 +02:00
Leonardo 9faed3a2c8 Commented the buffer builder and added a method 2021-10-20 20:18:42 +02:00
Leonardo 05800089cb Changed fog enum name 2021-10-20 19:30:42 +02:00
James Seibel 8585511007 Update two of the config overrides 2021-10-19 22:11:11 -05:00
James Seibel 890de58c72 Fix regions culled incorrectly if far from the buffer's center
This would happen if the buffer builder died or was slow
2021-10-19 22:10:28 -05:00
James Seibel 8def361f63 rename LodNodeGenWorker to LodGenWorker 2021-10-19 21:16:58 -05:00
James Seibel 58d5a8beda Update the License header to match the new mod name
LOD -> Distance Horizons
2021-10-19 21:14:57 -05:00
James Seibel 443bb64df0 Improve the wording of the config file 2021-10-19 20:43:43 -05:00
James Seibel 400e00f572 auto-indent 2021-10-19 20:11:31 -05:00
Leonardo 5c36a3df16 Small fix to push and pop of configs 2021-10-19 23:11:39 +02:00
Leonardo 8578a833b4 Fixed crash caused by config 2021-10-19 22:36:01 +02:00
Leonardo 974a9b4452 Small change to configs name + comments 2021-10-19 22:30:23 +02:00
Leonardo d35fbb0bb3 New configs 2021-10-19 22:24:21 +02:00
Leonardo 0551fbb2d4 Small fix to config 2021-10-19 19:15:07 +02:00
Leonardo fe8a847637 Reversed resolution enum order 2021-10-19 19:09:32 +02:00
Leonardo b04eec91bc Fully disabled pre-gen code 2021-10-19 18:50:11 +02:00
Leonardo 6eddef2fb0 simplified block to avoid config 2021-10-19 18:10:59 +02:00
Leonardo 10382342d8 Added some more pre-gen testing code (disabled) 2021-10-19 13:35:22 +02:00
Leonardo 9d80b81378 Now the game doesn't use Biome class to calculate colors 2021-10-19 01:21:25 +02:00
Leonardo 12abc4f018 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-10-19 01:20:35 +02:00
Leonardo 21e774489c Added the ability to use pregenerated chunks, (bugged still to fix) 2021-10-19 01:20:29 +02:00
cola98765 f6f7f1043e cleaned out code after save compression refactor 2021-10-18 14:32:32 +02:00
cola98765 30e9dd1aac Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-10-18 11:51:14 +02:00
cola98765 219f3eba17 actually read old files as compressed 2021-10-18 11:50:50 +02:00
Leonardo d737500d95 Added a new section to the LodRegion which may be useful to identify pre-generated chunk in the future 2021-10-18 11:50:38 +02:00
Leonardo 2a402ef1d6 fully disabled the pregen code 2021-10-18 11:47:56 +02:00
Leonardo 84c0fd994d Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-10-18 11:46:33 +02:00
Leonardo cf782c5b6f changed default thread number 2021-10-18 11:46:23 +02:00
cola98765 96c19620cb now compressing using proper algorithm 2021-10-18 11:00:58 +02:00
cola98765 d0f93a2c89 Fixed light on predicted chunks in caveworld. 2021-10-17 22:15:06 +02:00
Leonardo 85157d0da0 Disabled pre-gen loading for now + small fix 2021-10-17 20:33:28 +02:00
Leonardo 33d150b090 Disabled pre-gen loading for now + small fix 2021-10-17 19:56:29 +02:00
Leonardo e6949dcd14 Fixed shadow with no tree bug 2021-10-17 19:37:06 +02:00
Leonardo b411f083e2 Added config for pre-generated chunk loading 2021-10-17 19:21:56 +02:00
Leonardo d3cd714f48 Added pre-generated chunk loading 2021-10-17 19:17:44 +02:00
Leonardo df0d1483c7 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-10-17 18:52:40 +02:00
Leonardo 0e82afd6e1 Disabled config override 2021-10-17 18:52:34 +02:00
cola98765 d80253546f fixed chunks resetting after loading save 2021-10-17 16:37:48 +02:00
Leonardo 441e4ff1f2 SmallFix to generation 2021-10-17 14:41:28 +02:00
Leonardo cbdfabeaeb Real chunks are always converted in max quality (could make it a config) 2021-10-17 14:34:39 +02:00
cola98765 bdf7fb3466 fixed blocklight one more time 2021-10-17 13:34:15 +02:00
cola98765 7595248406 cleaned a bit of code 2021-10-17 12:13:17 +02:00
cola98765 b5bcab36cd cleaned a bit of code 2021-10-17 11:53:47 +02:00
cola98765 5ed1e6135b now blocklight also uses server world when applicable 2021-10-17 11:33:07 +02:00
James Seibel 636d4129bd Rename HorizontalQuality LINEAR to LOWEST 2021-10-16 21:38:28 -05:00
James Seibel a90dfb695d Make the config file more easily readable 2021-10-16 21:07:07 -05:00
James Seibel 15c1a64cfd Update the version number to b1.5.0 2021-10-16 20:58:10 -05:00
James Seibel c5f823c54e Add generation Resolution checking to Dynamic vanilla overdraw 2021-10-16 20:56:00 -05:00
James Seibel a7c2e8a6ed Update the config file to use mod name (Distant Horizons) vs the mod id (lod) 2021-10-16 18:48:25 -05:00
James Seibel cb496208f5 If avoiding non full/solid blocks use the above block's color
This fixes snow and flowers not being used.
2021-10-16 18:08:17 -05:00
James Seibel 4ff1815436 Clean up a few compiler warnings 2021-10-16 16:28:57 -05:00
cola98765 31ada4e5d2 No longer removing 1 block gaps as with new lighting it shouldn't look worse 2021-10-16 22:43:25 +02:00
cola98765 accf082309 No longer removing 1 block gaps as with new lighting it shouldn't look worse 2021-10-16 22:42:58 +02:00
cola98765 e1b1f26f37 made project actually build after removing experimental light option 2021-10-16 22:18:24 +02:00
James Seibel a0c14c86ca Improve the lighting on local worlds
ClientWorld apparently doesn't actually know what the lighting is anywhere, so we will have to find another way to determine shadows on servers.
2021-10-16 13:45:31 -05:00
Leonardo a122015f6d Experimental light system is a config now 2021-10-16 15:52:39 +02:00
Leonardo 164d407153 Experimental light system is a config now 2021-10-16 15:51:35 +02:00
cola98765 893bfa096f made new light optional with internal boolean 2021-10-16 11:25:13 +02:00
cola98765 37995af19e fixed flag setting, and changed code back as if isLightCorrect and getBrightness actually worked 2021-10-16 10:39:06 +02:00
James Seibel c637d23121 Merge branch 'CodeF53/minecraft-lod-mod-1.16.5' into 1.16.5 2021-10-15 21:00:54 -05:00
James Seibel d762508188 Only return Minecraft Chunks from the chunkLoadEvent 2021-10-15 20:26:56 -05:00
James Seibel f5437f00a2 slight refactoring 2021-10-15 20:25:33 -05:00
CodeF53 dec20962b2 Switch readme to markdown format, adding headers and misc formatting. 2021-10-15 21:24:32 +00:00
cola98765 30e796f5bf fixed side lighting 2021-10-15 23:20:54 +02:00
cola98765 4ab4dc59e7 now renders default Skylight as 0 when player is in Skylight 0 situation 2021-10-15 18:41:58 +02:00
cola98765 839a76c594 minor adjustment that was annoying me 2021-10-15 17:24:04 +02:00
Leonardo 3fb4d16e41 New sky light handling system (not complete) 2021-10-15 16:23:20 +02:00
Leonardo 002d86af9f Added comment + small refactor + removed TODO 2021-10-15 16:22:41 +02:00
cola98765 e1877f9149 Now using flag bit in data as "is light default" 2021-10-15 15:37:51 +02:00
cola98765 4da1fcc118 since new method of getting skyLight is objectively better, I've commented out old method and 'if' used to switch between those methods 2021-10-14 23:36:27 +02:00
cola98765 af123a8c80 added fast track when we want to add whole column of data, so it doesn't call 5 different methods for each lod block. 2021-10-14 23:33:14 +02:00
cola98765 94bc7fd011 now ignoring isLightCorrect completely, old method is still available 2021-10-14 19:29:50 +02:00
cola98765 905d8bddf3 made new sky lighting calculation optional with internal boolean 2021-10-14 18:56:51 +02:00
cola98765 5ee762cc78 now actually remove garbage vertical lods 2021-10-14 18:51:39 +02:00
cola98765 7c07a88b45 small fix to that light fix 2021-10-14 18:02:58 +02:00
cola98765 d8981af7aa possible fix to skylight... revert if worse than before 2021-10-14 15:11:36 +02:00
Leonardo 9906eb75f4 Changed the Far fog on fancy. Now fog start after the real game render distance 2021-10-14 14:06:11 +02:00
Leonardo d94fedc61e Changed the Far fog on fancy. Now fog start after the real game render distance 2021-10-14 14:02:47 +02:00
cola98765 3e3b979530 indents in LodConfig 2021-10-14 07:49:02 +02:00
James Seibel 6ad94d3362 Update the version number to 1.5.0 and replace the LOD name with Distant Horizons 2021-10-13 23:28:43 -05:00
James Seibel 31f8cecc92 Add the minimum OpenGL version to the readme
BufferStorage technically only requires OpenGL 4.4, but I already had 4.5 written everywhere. If it becomes a problem that going to 4.4 fixes I could probably roll back to that.
2021-10-13 22:04:41 -05:00
James Seibel b4106a8c3c Improve the buffer rebuild logic related to light change 2021-10-13 21:59:46 -05:00
James Seibel b6390c57ef auto-indent 2021-10-13 21:03:03 -05:00
James Seibel 5172c66b9b Merge branch 'CodeF53-1.16.5-patch-87033' into '1.16.5'
Update demo video to latest

See merge request jeseibel/minecraft-lod-mod!3
2021-10-14 01:59:33 +00:00
James Seibel 067fa92419 Improve the logic for vanilla overdraw to work better on different horizontal resolutions 2021-10-13 20:44:38 -05:00
Leonardo 15e80ed063 ceiled dimension now have 64 max render distance + various small changes 2021-10-14 02:29:42 +02:00
Leonardo 2c6549e815 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5
# Conflicts:
#	src/main/java/com/seibel/lod/builders/lodBuilding/LodBuilder.java
#	src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java
2021-10-14 02:28:24 +02:00
CodeF53 32423c07eb Update demo video to latest 2021-10-13 15:03:27 +00:00
cola98765 4a0640a219 cleaned out some code. 2021-10-13 14:27:27 +02:00
cola98765 5f9f20a064 cleaned out some code. 2021-10-13 13:45:23 +02:00
cola98765 ef4ba7208e cleaned out some code. 2021-10-13 13:31:47 +02:00
cola98765 80edf19b33 cleaned out some code. 2021-10-13 13:24:07 +02:00
cola98765 4baa649972 cleaned out some code. Applied autoformat everywhere 2021-10-13 12:45:21 +02:00
cola98765 c7dbc28a9a cleaned out some code 2021-10-13 12:08:47 +02:00
cola98765 707c55653a removed single level container 2021-10-13 12:01:56 +02:00
Leonardo 40cb7f4efc Merge remote-tracking branch 'origin/1.16.5' into 1.16.5
# Conflicts:
#	src/main/java/com/seibel/lod/objects/SingleLevelContainer.java
2021-10-13 11:35:24 +02:00
Leonardo df22a082a1 Added option to avoid block with no collision + removed SingleLevelContainer class use 2021-10-13 11:34:59 +02:00
cola98765 3a7f411aa4 cleaned java ocs in DataPointUtil 2021-10-13 10:36:29 +02:00
cola98765 11c419e503 updated some TODO's 2021-10-13 10:15:48 +02:00
James Seibel 30b82e8009 update dynamic vanilla overdraw in LodUtil 2021-10-12 22:31:51 -05:00
James Seibel 7df4a161dd Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-12 22:20:53 -05:00
James Seibel 56160db7ec comment out the buffer builder expanding console logging 2021-10-12 22:20:44 -05:00
James Seibel ac84c3707a Remove a illegal import 2021-10-12 22:20:27 -05:00
Leonardo d16f571467 Small changed to border shading + changed overdraw ratio 2021-10-12 17:12:31 +02:00
cola98765 d7bd0498a0 When there are no files for current gen mode, try to load more detailed ones instead. 2021-10-12 11:58:21 +02:00
James Seibel 57a2b956dd Improve the VanillaOverdraw config to work better in roofed dimensions 2021-10-11 23:05:49 -05:00
James Seibel 51aadc8d39 Maybe fix a OpenGL error? 2021-10-11 23:00:28 -05:00
James Seibel 70e2f7f3e6 prevent a potential out of bounds exception 2021-10-11 23:00:11 -05:00
James Seibel 0ef8615a98 Extract the main work of the buffer builder into a method for easier hot swapping 2021-10-11 22:12:35 -05:00
James Seibel 4c6412d09f comment out a debug override 2021-10-11 20:55:02 -05:00
Leonardo 27b8cfea09 Fixed the purple color bug 2021-10-11 23:17:20 +02:00
cola98765 b5ab06bfb6 resolved warning 2021-10-11 22:14:56 +02:00
James Seibel 732476b454 Add the overdraw
Overdraw renders LODs on top of vanilla chunks based with  three different settings.
2021-10-10 21:31:45 -05:00
James Seibel 9d1a9eb9f3 Remove the memory estimation code.
Buffers will now be purposely created smaller than expected and then expanded to fit the need.
2021-10-10 14:01:13 -05:00
James Seibel 6018449cbe Quick formatting change and remove a completed TODO 2021-10-10 08:10:05 -05:00
cola98765 8f43695a47 did someone say warnings and typos? 2021-10-10 13:07:23 +02:00
cola98765 30913a0c29 more typos 2021-10-10 11:36:10 +02:00
cola98765 d8cee2b10c Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-10-10 11:19:09 +02:00
cola98765 33a706f660 autoformat 2021-10-10 11:19:02 +02:00
cola98765 6c2b707c02 autoformat 2021-10-10 11:16:54 +02:00
cola98765 ecb01c731e Resolved "ALOT" of typos. 2021-10-10 11:09:15 +02:00
cola98765 72737a56c1 Resolved more warnings. 2021-10-10 10:38:00 +02:00
cola98765 1d1b5f6115 Resolved more warnings. Applied auto format in affected files. 2021-10-10 10:34:34 +02:00
cola98765 b67ab59a89 Resolved more warnings. Applied auto format in affected files. 2021-10-10 09:50:44 +02:00
cola98765 ca4597e3d9 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-10-10 08:38:00 +02:00
cola98765 efd9a5a51b merge all 1 block gaps for better look o trees 2021-10-10 08:37:47 +02:00
cola98765 4c3d19a6c6 merge all 1 block gaps for better look o trees 2021-10-10 08:36:45 +02:00
cola98765 6c4faa9103 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-10-10 08:24:05 +02:00
James Seibel 6066957584 Update LodConfig.java 2021-10-09 20:14:51 -05:00
James Seibel c3f8b0b677 Remove the experimental useFovSetting setting 2021-10-09 19:47:26 -05:00
James Seibel e2cdf1549a auto-indent 2021-10-09 19:42:02 -05:00
James Seibel fe9bc5e77e Delete Reference.java 2021-10-09 19:41:22 -05:00
cola98765 ea0ef9e394 boosted skylight prediction to 13 so most trees look better 2021-10-09 23:22:39 +02:00
James Seibel 27d74958bf Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-09 14:48:53 -05:00
James Seibel dc8db97f33 Fix the region at 0,0 (-X,-Z) rendering incorrectly 2021-10-09 14:48:47 -05:00
cola98765 3ec30d49be put guts of mergeSingleData into mergeMultiData and make dataPoint smaller to make it faster 2021-10-09 17:47:58 +02:00
cola98765 627327140e reversed logic in mergeMultiData to improve performance of initial compression to maxVerticalData 2021-10-09 17:07:38 +02:00
James Seibel 2ebbb6f591 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-09 09:46:33 -05:00
James Seibel 126b581e97 Add BufferStorage recreation, improving memory usage
I still want the buffers to be created the right size at the start, but this will work for now.
2021-10-09 09:46:24 -05:00
cola98765 f625e714d4 made mergeMultiData a bit faster 2021-10-09 11:00:59 +02:00
cola98765 5db7e349b9 in mergeMultiData skip empty data 2021-10-09 08:16:58 +02:00
James Seibel 272546af4d Improve the buffer expansion console logging 2021-10-08 22:16:12 -05:00
James Seibel c0a9e3061c reformatting / commenting 2021-10-08 22:13:20 -05:00
James Seibel 5872dc3be5 Fix a memory leak when changing worlds 2021-10-07 22:47:16 -05:00
James Seibel 8fe6eff36c improve the buffer expanding logging 2021-10-07 22:45:48 -05:00
James Seibel d89f2dc9b8 Refactoring / reformatting 2021-10-07 21:34:34 -05:00
James Seibel e0ac03db6c Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-07 21:25:05 -05:00
James Seibel ee58f3d9dc Use OpenGL BufferStorage to improve upload performance
I need to change how the memory is determined, right now they fill to the maximum amount; which is very bad and only for testing.
2021-10-07 20:59:45 -05:00
cola98765 b02d58227c reworked mergeMultiData 2021-10-07 20:17:37 +02:00
Leonardo 61cb27020c small change to a print 2021-10-07 18:03:09 +02:00
Leonardo 443da5eede other config change, set roofed dimension max distance to 64 2021-10-07 17:37:02 +02:00
Leonardo 78ab4b8598 Changed configs 2021-10-07 17:20:39 +02:00
cola98765 028aed53f8 resolved some more warnings and applied autoformat in affected files 2021-10-07 11:17:02 +02:00
cola98765 1ed36ba6c4 resolved some more warnings and applied autoformat in affected files 2021-10-07 11:07:10 +02:00
cola98765 6deca8e235 resolved many warnings and applied autoformat in affected files 2021-10-07 10:36:30 +02:00
Leonardo a6f3c2478e Some refactor + fixed cpu problem with near_first 2021-10-07 00:19:32 +02:00
cola98765 a66554f2dd resolved todo 2021-10-06 11:45:36 +02:00
cola98765 28cf2eb450 removed debug message when saving 2021-10-06 10:37:36 +02:00
cola98765 e154f552c7 fixed bug where only some regions were saved when player was not moving 2021-10-06 10:36:37 +02:00
Leonardo 0c275e1495 Added back the toString in the PosToGenerateContainer 2021-10-05 19:06:51 +02:00
Leonardo 2b15c089f4 Added back the toString in the PosToGenerateContainer 2021-10-05 18:59:40 +02:00
Leonardo fca926bc8f Added some comment, fixed the thread conflict problem 2021-10-05 11:25:06 +02:00
James Seibel f6ea990ab0 Reduce buffer uploading stuttering
I also included commented out versions of several other buffer uploading options and comments on how well they perform.
2021-10-04 22:52:11 -05:00
James Seibel ee6c8d597c Hopefully prevent the buffer builder from dying if an exception is thrown 2021-10-03 14:45:38 -05:00
James Seibel 1e819bd555 temporarily disable transparency in the AbstractLodTemplate 2021-10-03 14:08:55 -05:00
James Seibel a0358dd298 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-03 13:57:34 -05:00
James Seibel 90987fc389 Add a constant to LodUtil and remove a few unused ones 2021-10-03 13:57:24 -05:00
cola98765 f72c846fe5 removed old commented code 2021-10-03 09:42:50 +02:00
James Seibel 2ca8576ad7 auto-indent 2021-10-02 21:33:09 -05:00
James Seibel 0194cffaba auto indent 2021-10-02 21:28:52 -05:00
James Seibel cc52815315 update a override option in the clientProxy 2021-10-02 21:24:19 -05:00
James Seibel 900b67920c re-add transparency rendering 2021-10-02 21:24:04 -05:00
James Seibel 9c1e5c33a5 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-10-02 21:08:22 -05:00
James Seibel d7a1d330d9 Re-add Linux and (hopefully) Mac support
I have tested Windows and Ubuntu (Linux). I didn't test Mac but I am reasonably confident that it should work.
2021-10-02 21:08:15 -05:00
cola98765 3ac05c6a2b fixed multiplyRGBcolors to not make off by 1 error 2021-10-02 15:34:02 +02:00
James Seibel eeff5437b5 Hopefully add Mac and Linux support 2021-10-01 23:25:51 -05:00
James Seibel ee89d6f512 Update the Readme to include IntelliJ install instructions 2021-10-01 07:19:55 -05:00
James Seibel a577851f6b Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-09-30 21:42:00 -05:00
James Seibel 536bff2fe7 Hopefully fix the OpenGL context switching error 2021-09-30 21:41:49 -05:00
James Seibel b1995445e2 auto-format 2021-09-30 19:24:30 -05:00
Leonardo 5d4d483b16 re-added the avoidNonFullBlock and avoidSmallBlock options 2021-10-01 01:26:11 +02:00
Leonardo c13abc3b7d Added thread data for the buffer builder 2021-09-30 19:50:05 +02:00
Leonardo 1cbb15045f Added a reset when unloading and loading world 2021-09-30 19:47:04 +02:00
Leonardo 48ea096ff1 Added comment and changed some small variables 2021-09-30 17:52:51 +02:00
cola98765 2e08b61672 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-09-30 17:46:59 +02:00
cola98765 b0bb01fde4 reworked ThreadMapUtil to actually save arrays between uses. 2021-09-30 17:46:03 +02:00
Leonardo cc666e917e Now the border chunk only work for render distance higher than 4 2021-09-30 15:26:28 +02:00
Leonardo 9e0abd06fb Better fake chunk/ real chunk blending, less holes 2021-09-30 14:48:52 +02:00
cola98765 0f56a98499 attempt to fix grass colors by setting biome opacity to 255 2021-09-30 13:04:43 +02:00
cola98765 529c52b93f getBuilderArray wasn't initialised correctly causing a lot of new long[] 2021-09-30 12:28:04 +02:00
cola98765 8020b298fb fixed saving transparency and calculating it around biome colors 2021-09-30 11:11:23 +02:00
Leonardo 37db05d18f added a borderChunk finder function 2021-09-30 01:38:39 +02:00
Leonardo 555e5a78b5 simplified the culling (still disabled) 2021-09-30 01:37:48 +02:00
Leonardo 32d492f5f6 Changed some package and added a dimension to the buffer builders 2021-09-29 14:57:43 +02:00
James Seibel d9ee9135d7 revert the config override message 2021-09-29 07:55:46 -05:00
James Seibel d59f9dc4c6 Create pre-release a1.5.1
I made this version so hopefully someone could test if Vivecraft is just ignoring Minecraft's FOV when creating their projection matrices or if they are doing something more complicated.
2021-09-28 22:56:17 -05:00
James Seibel 8f329ac785 auto-format 2021-09-28 22:18:38 -05:00
James Seibel 9865b23e5b Move MAX_ALLOCATEABLE_DIRECT_MEMORY to LodUtil 2021-09-28 21:29:25 -05:00
James Seibel a987149aa3 Create Eclipse Auto Formatting V1.xml 2021-09-28 21:06:15 -05:00
Leonardo 22b7e46d39 small fixes 2021-09-29 02:38:19 +02:00
Leonardo e5c1e67369 Changed various names, changed the memory calculator 2021-09-29 02:16:23 +02:00
James Seibel 328792cf4e Start commenting and refactoring SingleLevelContainer 2021-09-28 07:50:07 -05:00
James Seibel 344901aad5 Comment RegionPos 2021-09-28 07:41:13 -05:00
James Seibel 5f89bd8e7d comment and refactor PosToGenerateContainer 2021-09-27 22:12:55 -05:00
James Seibel 7c5713fac2 Refactor and comment LodWorld 2021-09-27 21:59:51 -05:00
James Seibel d222854717 auto-indent 2021-09-27 21:49:11 -05:00
James Seibel 6b9be10635 Add a few missing comments and refactors to LodRegion 2021-09-27 21:48:19 -05:00
James Seibel 69a72312e4 Refactor and comment LodRegion 2021-09-27 21:43:16 -05:00
James Seibel 948b58d8e9 auto-indent and move a reminder comment 2021-09-27 20:20:26 -05:00
James Seibel 86406fd12b Rename MULTI_LOD to VOXEL 2021-09-27 20:17:33 -05:00
James Seibel cc3e1d1b12 Fix a null pointer and finish commenting/refactoring LodDimension 2021-09-27 20:13:16 -05:00
James Seibel 85a0110af6 comments and regactor LodDimension 2021-09-27 07:59:55 -05:00
James Seibel a76436b73d Bring back the drawLODs config 2021-09-26 08:20:37 -05:00
James Seibel 391c99fd21 comment and refactor LodDimensionFildHandler and ReflectionHandler 2021-09-25 23:51:14 -05:00
James Seibel fb5aceb44d auto-indent 2021-09-25 23:20:05 -05:00
James Seibel 4c76a48e84 Update comments for many enums 2021-09-25 23:17:17 -05:00
James Seibel d7a42d3a51 auto-indent 2021-09-25 20:35:12 -05:00
James Seibel e0a946673e refactor LodBuilderConfig 2021-09-25 20:30:44 -05:00
James Seibel ad793fe17e Refactor and comment LodBufferBuilder and LodBuilder 2021-09-25 18:52:53 -05:00
James Seibel 209e2579c3 refactor and comment LodWorldGenerator 2021-09-25 16:09:29 -05:00
James Seibel 8627b87aa4 auto-indent 2021-09-25 16:09:12 -05:00
James Seibel 5f855dd573 CubicLodTemplate refactoring and commenting 2021-09-25 15:34:39 -05:00
James Seibel d6c918427b have the LodRenderer recreated only when leaving a server 2021-09-25 15:34:25 -05:00
James Seibel a9bdbc4300 Potentially fix a false buffer IndexOutOfBoundsException 2021-09-25 15:32:34 -05:00
James Seibel 58a150f8de fix the ThreadMapUtil not creating arrays correctly 2021-09-25 13:22:31 -05:00
James Seibel 1a3e1dfa8c add get fresh methods to TheadMapUtil
the getFresh versions create/clear the data for the given map.
2021-09-25 11:48:05 -05:00
James Seibel 430a908829 refactor clientProxy 2021-09-25 11:42:49 -05:00
James Seibel 0ca0cd9213 auto-indent 2021-09-25 09:07:07 -05:00
James Seibel 2f392375fe Refactor and Comment Box 2021-09-25 09:04:26 -05:00
James Seibel ff43118976 Update the version number to a1.5.0-pre 2021-09-24 18:06:57 -05:00
James Seibel 3b4e28d74a Add a warning chat message for the 1.5.0 pre-release 2021-09-24 18:05:05 -05:00
James Seibel 13abed4eb8 comment out the shadingMode config since it isn't currently used 2021-09-24 07:59:26 -05:00
James Seibel ccb2c601a6 add a temporary fix to color debug mode not having shading 2021-09-24 07:59:07 -05:00
James Seibel f6816d9974 auto-indent 2021-09-24 07:45:00 -05:00
James Seibel 5156ae8e63 auto-format 2021-09-24 07:43:22 -05:00
James Seibel 55c0c95339 Improve config wording 2021-09-24 07:37:14 -05:00
James Seibel 0b8503f1fa move applyConfigOverrides 2021-09-24 07:27:07 -05:00
James Seibel 79d9ac5d56 auto-indent 2021-09-24 07:26:50 -05:00
James Seibel 6cf4e663fb Fix a potential null pointer exception and improve clientProxy error logging 2021-09-23 22:07:46 -05:00
cola98765 bf9c3ce567 fixed saving multidata in void dimentions 2021-09-23 23:52:34 +02:00
Leonardo 5bbdd22b58 light works again, changed the region_fast option, fixed a indexout of buond, added a TODO for the future for better memery use 2021-09-23 16:02:32 +02:00
Leonardo 6c1c04bb5f Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-09-23 15:18:39 +02:00
Leonardo 66728cc1eb fixed the memory crash problem.
Added config to draw always in generation quality (if true the game will crash with  render distance>256)
2021-09-23 15:18:33 +02:00
James Seibel d4739b9bed Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-09-23 07:55:44 -05:00
James Seibel a93bb63c44 Fix an index out of bounds exception for vanillaRenderedChunks 2021-09-23 07:55:33 -05:00
Leonardo a2e18de9f3 small fix to generation 2021-09-23 14:38:35 +02:00
Leonardo 6183152d99 small fix to culling 2021-09-23 14:37:57 +02:00
James Seibel 5d9f36bb5f Hopefully fix the openGL errors 2021-09-22 22:26:23 -05:00
James Seibel d330083d7b auto-format 2021-09-22 22:20:03 -05:00
James Seibel 6d489b498e add additional error checking to BufferBuilder vboUpload 2021-09-22 22:16:10 -05:00
James Seibel d36d836bb3 prevent a null point in LodRegion addData 2021-09-22 22:15:42 -05:00
James Seibel 29d2d1cff1 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into
1.16.5

# Conflicts:
#	src/main/java/com/seibel/lod/objects/LodDimension.java
2021-09-22 21:52:03 -05:00
James Seibel 0a9ea1dfce improve the error reporting in GlProxy 2021-09-22 21:50:05 -05:00
James Seibel b9424cbe9f Fix a index out of bounds error in ThreadMapUtil 2021-09-22 21:04:11 -05:00
Leonardo 593a014dfc fixed far and near generation, fixed holes in the rendering in near gen 2021-09-23 02:03:02 +02:00
James Seibel 83ac04dca4 auto-format 2021-09-22 18:33:20 -05:00
Leonardo c9aed389ae various changes to the generation + some small fixes 2021-09-23 01:05:54 +02:00
Leonardo 00da0e0520 Fixed tall grass and flower colors 2021-09-22 21:32:08 +02:00
Leonardo 5124739348 removed reset of bufferBuilder and added better color creation for grass, leaves, water and flowers 2021-09-22 20:47:31 +02:00
Leonardo d65bfd408e Fixed the artifacts (was caused by wrong array initialisation) and added the reset to while changing dimension 2021-09-22 19:38:04 +02:00
Leonardo da413f594e Added different detail drop off option 2021-09-22 17:17:17 +02:00
cola98765 1fcef4be96 some warnings taken care of 2021-09-22 15:10:20 +02:00
cola98765 d7cddd9b39 fixed null check 2021-09-22 15:02:08 +02:00
Leonardo fb480c2695 fix to memory use 2021-09-22 13:17:56 +02:00
James Seibel 265abb64b3 Improve the wording for a few config options 2021-09-21 21:15:02 -05:00
James Seibel 1cf4852788 auto-format 2021-09-21 20:27:55 -05:00
Leonardo 90d0fbe45b various fix to the generation 2021-09-22 01:26:55 +02:00
cola98765 ea9eac89ec podzol netherrack and other blocks now use proper top color without biome color (nether plants might still be broken didn't test it) 2021-09-22 00:26:11 +02:00
cola98765 017cc201b1 enabled save loading for vertical lods 2021-09-21 23:09:48 +02:00
Leonardo bda963036d Introduced correctly spiral generation 2021-09-21 18:35:48 +02:00
Leonardo 46bdf5763f Added spiral generation, changed how some arrays are created 2021-09-21 18:12:15 +02:00
Leonardo 8228a3b7a6 fixed a thread problem 2021-09-21 16:30:53 +02:00
cola98765 e3df6c99da added void and !exist compression to VerticalLevelContainer 2021-09-21 16:18:58 +02:00
Leonardo a4e9e22d2c fixed end bug 2021-09-21 16:09:24 +02:00
Leonardo 435c5ee73a fixed nether roof bug 2021-09-21 15:09:28 +02:00
cola98765 c6b063a380 in SingleLevelContainer made void chunks save as 1 byte instead of 8 2021-09-21 11:34:07 +02:00
cola98765 1f5c3f5bd8 in SingleLevelContainer made void chunks save as 1 byte instead of 8 2021-09-21 11:33:01 +02:00
Leonardo 688cb3f89a New memory getter system 2021-09-20 18:58:02 +02:00
Leonardo af80ff5267 Refactoring 2021-09-20 16:33:24 +02:00
Leonardo 2bc5c43b19 small fix 2021-09-20 15:51:34 +02:00
Leonardo e7c4827d08 Now the single merge use min and max depth and height and no more the mean to make it more consistent with the multi-lod 2021-09-20 15:49:22 +02:00
Leonardo 482dfb918e Refactoring + added the ability to disable lods with f6 2021-09-20 15:44:18 +02:00
Leonardo 5aaf6e0185 removed redundant toString() 2021-09-20 15:23:56 +02:00
Leonardo ab014af15d more refactoring 2021-09-20 15:15:10 +02:00
Leonardo 772de1b869 Refactoring, removed unused class/enum, fixed a small array bug 2021-09-20 14:59:42 +02:00
Leonardo cb42683774 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-09-20 14:01:28 +02:00
Leonardo a00698ccab added the dataPoint to the threadMaputil 2021-09-20 14:01:18 +02:00
cola98765 29ed26f023 More warnings addressed 2021-09-20 13:31:16 +02:00
cola98765 af3c4ab801 More warnings addressed 2021-09-20 13:23:22 +02:00
cola98765 1156b7dd28 now using ThreadMapUtil for temp array during saving 2021-09-20 12:50:49 +02:00
cola98765 25fd29b97e replaced short[][] with short[] in mergeMultiData hotfix 2021-09-20 12:16:47 +02:00
cola98765 a11ff5b493 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-09-20 12:13:32 +02:00
cola98765 7655ae03b0 replaced short[][] with short[] in mergeMultiData 2021-09-20 12:13:24 +02:00
Leonardo 075e29c617 small fixes for better gc use 2021-09-20 12:09:45 +02:00
cola98765 e482bf02a5 fixed negative numbers in mergeMultiData 2021-09-20 11:57:32 +02:00
cola98765 0dab4a2274 addressed couple warnings 2021-09-20 11:54:01 +02:00
cola98765 001335ab47 I'm stupid 2021-09-20 11:46:47 +02:00
Leonardo faedb85f41 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-09-20 11:35:31 +02:00
Leonardo 01b9a3f3b0 Fixed culling 2021-09-20 11:35:20 +02:00
cola98765 cfd9bd903d + 1 will not hurt anyone 2021-09-20 11:34:25 +02:00
cola98765 3e634c082a addressed couple warnings 2021-09-20 11:30:56 +02:00
cola98765 6e86a808a5 addressed couple warnings 2021-09-20 11:12:54 +02:00
cola98765 e615674246 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-09-20 11:03:48 +02:00
cola98765 86b5fc48a2 addressed couple warnings 2021-09-20 11:03:24 +02:00
Leonardo 2fab33fa78 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-09-20 10:57:28 +02:00
Leonardo b56b581bb6 Refactoring 2021-09-20 10:57:20 +02:00
cola98765 2ee5289881 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-09-20 10:56:36 +02:00
cola98765 3da4e4818c replaced arraycopy in mergeMultiData in favor of simpler method for debugging 2021-09-20 10:56:28 +02:00
Leonardo 686062f39c Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-09-20 10:46:25 +02:00
Leonardo ae857dfeae fixed a small bug in the datapoint
Simplified the code in the LodBufferBuilder
2021-09-20 10:46:14 +02:00
cola98765 686592effb fixed bug in loading vertical data 2021-09-20 10:43:12 +02:00
James Seibel 34b92d1053 Fix #67 (LODs not rotating with camera) and #68 (LODs culled based on player direction, not camera) 2021-09-19 19:25:01 -05:00
James Seibel 01a850eb9d Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-09-19 18:14:09 -05:00
James Seibel 7d6f7f35ff Fix the buffer builder failing on LodQualityMode.HEIGHTMAP 2021-09-19 18:13:48 -05:00
James Seibel 28764bc16c auto-format 2021-09-19 17:58:22 -05:00
Leonardo ee1657a798 fixed a small bug 2021-09-19 23:58:24 +02:00
cola98765 c7bf60b4e0 fixed byte cast 2021-09-19 23:34:55 +02:00
cola98765 031af5f25c Merge branch '1.16.5' of https://gitlab.com/jeseibel/minecraft-lod-mod into vertical_merging
 Conflicts:
	src/main/java/com/seibel/lod/objects/VerticalLevelContainer.java
	src/main/java/com/seibel/lod/util/DataPointUtil.java
2021-09-19 23:31:16 +02:00
Leonardo d8200422b2 disabled the clear + small change 2021-09-19 23:18:31 +02:00
cola98765 c89cd54429 implemented multi level saving and loading. they use new long[] system instead of long[][][] 2021-09-19 23:16:03 +02:00
cola98765 ca940d5a36 reworked mergeMultiData to take in long[] instead of long[][] 2021-09-19 22:59:15 +02:00
Leonardo 2241492bc5 there is a thunderstorm i don't want to loose progress 2021-09-19 22:08:30 +02:00
Leonardo 7b807bcea2 small changes 2021-09-19 21:32:13 +02:00
Leonardo ebe2c22a28 Changed how the VerticalLevelContainer contains the data 2021-09-19 20:48:07 +02:00
cola98765 cffb17aeb1 reversed grass brightness boost as it's better that way at 4+ view distance 2021-09-19 16:35:47 +02:00
cola98765 c67a5a5e29 removed commented and now unused code 2021-09-19 16:25:53 +02:00
cola98765 1d687fd1d4 new mergeMultiData. Now actually working 2021-09-19 14:44:55 +02:00
cola98765 783d4086c6 some fixes to new mergeMultiData 2021-09-19 14:40:06 +02:00
cola98765 d5243b7d16 some fixes to new mergeMultiData 2021-09-19 14:18:42 +02:00
cola98765 43f3854068 some fixes to new mergeMultiData 2021-09-19 11:41:29 +02:00
cola98765 0025f43a2e Merge branch '1.16.5' of https://gitlab.com/jeseibel/minecraft-lod-mod into vertical_merging
 Conflicts:
	src/main/java/com/seibel/lod/util/ThreadMapUtil.java
2021-09-19 10:36:33 +02:00
James Seibel 07d792979c downgrade to frogeGradle 3.+ from 5.1.+
mixins weren't compiling correctly on the newer version
2021-09-18 23:34:15 -05:00
James Seibel a939d29357 hopefully prevent a index out of bounds exception 2021-09-18 17:44:52 -05:00
James Seibel ba1d096a48 Add error catching / logging 2021-09-18 17:44:37 -05:00
James Seibel 1c9c72cfe3 Clean up a lot of warnings related to: type casting, unused variables, and unused imports 2021-09-18 17:06:41 -05:00
James Seibel aa95361866 Refactor LodDimension and change some error reporting in PosToRenderContainer 2021-09-18 16:58:23 -05:00
James Seibel ff5139d403 Remove debug code and fix a potential OpenGL error 2021-09-18 14:52:14 -05:00
James Seibel 16fc4914fb Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-09-18 14:13:05 -05:00
James Seibel c110524c11 fix vanillaRenderedChunks having index out of bounds exceptions 2021-09-18 14:12:54 -05:00
James Seibel 400b263059 Try to fix GlProxy.setGlContext failing in the BufferBuilder 2021-09-18 14:12:33 -05:00
Leonardo dadda4bdc9 Disabled the culling until it's fixed 2021-09-18 17:32:34 +02:00
Leonardo 1888ac7adc Fixed the culling coordinate 2021-09-18 17:09:13 +02:00
James Seibel 5c59ba7a80 Prevent a error related to loading textures on a null clientWorld 2021-09-18 09:39:53 -05:00
James Seibel f3dd99e792 Improve error message in GlProxy 2021-09-18 09:38:51 -05:00
Leonardo 103ec128ac small fix 2021-09-18 14:46:18 +02:00
Leonardo b4226ec9ec small fix 2021-09-18 14:46:06 +02:00
Leonardo 7c28dd70d3 Fixed the culling 2021-09-18 13:58:19 +02:00
Leonardo d8c9a41314 fixed face culling 2021-09-18 10:09:35 +02:00
Leonardo 5a7f77479f Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-09-18 10:09:14 +02:00
James Seibel d200a5ac24 Add the ability to disable direction based culling
This is a band aid fix for #68, hopefully a better solution can be found in the future.
2021-09-17 23:33:21 -05:00
James Seibel 5099f85da6 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into
1.16.5

# Conflicts:
#	src/main/java/com/seibel/lod/render/LodRenderer.java
2021-09-17 23:11:28 -05:00
James Seibel 6e150fe378 Update to ForgeGradlew from 3.+ to 5.1.+ 2021-09-17 22:58:09 -05:00
James Seibel fd67d1ac66 Change setupProjectionMatrix to be mc version agnostic
Now the LOD projection matrix's zoom, transformation, distortion, etc. are all gotten dynamically from Minecraft's projection matrix.
Hopefully this should prevent camera mods from breaking the mod.
2021-09-17 22:57:20 -05:00
cola98765 7161bd52de reworked mergeVerticalData... not actually working 2021-09-18 00:09:22 +02:00
Leonardo 82cf25c341 fixed colors 2021-09-17 23:37:16 +02:00
Leonardo 68d279807f small fix to the vertex order 2021-09-17 22:50:48 +02:00
Leonardo 3530158def Added new culling system 2021-09-17 22:37:33 +02:00
Leonardo 62223480e2 Fixed nether roof 2021-09-17 16:58:59 +02:00
Leonardo 50ab424497 added regen for the lightmap 2021-09-17 15:57:01 +02:00
Leonardo 900467cef2 System uses lightmap now 2021-09-17 13:02:05 +02:00
cola98765 fa1d950ff9 grass is actually using texture now 2021-09-17 12:55:14 +02:00
Leonardo 83571951be Added the ability to get the top texture 2021-09-17 12:29:57 +02:00
Leonardo c31b1f4039 added the ability to avoid not full block or small block 2021-09-17 11:14:23 +02:00
James Seibel 8fcd428194 improve error handling and error messages related to contexts 2021-09-16 20:32:32 -05:00
James Seibel 87c275f768 Add improved error reporting and commenting 2021-09-16 20:32:03 -05:00
James Seibel 8df6e972cb Fix a out of memory error when changing worlds 2021-09-16 20:28:07 -05:00
James Seibel d7d88d61ee Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into
1.16.5

# Conflicts:
#	src/main/java/com/seibel/lod/wrappers/MinecraftWrapper.java
2021-09-16 19:05:05 -05:00
James Seibel 9b1c0a1125 Add the ability to access the lightmap from the MinecraftWrapper 2021-09-16 19:03:43 -05:00
cola98765 b008b70255 colors are better than it were... again 2021-09-17 00:05:29 +02:00
cola98765 b6c350f667 colors are better than it were 2021-09-16 22:21:04 +02:00
Leonardo e23bbfcd91 small changes 2021-09-16 18:53:26 +02:00
cola98765 6bc14fbb2d brightness fix with real block colors TODO foliage 2021-09-16 18:12:22 +02:00
Leonardo d911017112 new color for grass, leaf and water 2021-09-16 17:11:08 +02:00
Leonardo fc4546538f Reintroduced manual color for nether blocks 2021-09-16 16:17:38 +02:00
Leonardo a90b3e9d37 Merge remote-tracking branch 'origin/1.16.5_new_file_handling' into 1.16.5 2021-09-16 16:15:29 +02:00
Leonardo b2aca27615 Added texture mean in lod builder 2021-09-16 15:44:28 +02:00
cola98765 6bf9e187e0 this breaks old file version system by simply ignoring the old files. 2021-09-16 11:41:53 +02:00
James Seibel b5f32705e8 remove commented out code 2021-09-15 23:12:10 -05:00
James Seibel 8bc72af63f Improve rendering performance and improve buffer building stability
Specifically improve the rendering speed so we can get over 100 fps again.
2021-09-15 22:01:52 -05:00
Leonardo 0e4cf8e882 added a TODO in data util 2021-09-15 17:02:44 +02:00
Leonardo 5ede5fa202 Added fake lighting system. Improved some point 2021-09-15 16:17:26 +02:00
Leonardo cdeba2616c Re-Introduced HEIGHMAP mode correctly.
Added single get and add to the LevelContainer to avoid using temp arrays
2021-09-15 13:23:41 +02:00
Leonardo 6dc94b0cc2 Introduced lodQualityMode in config to change from 3d to 2d 2021-09-15 10:42:09 +02:00
James Seibel 7f9c7d8722 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into
1.16.5

# Conflicts:
#	src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
2021-09-14 23:46:01 -05:00
James Seibel aebbeb6ade Simplify the multi-context uploading, improve stability, and refactor 2021-09-14 22:49:08 -05:00
James Seibel a945eb4579 Fully add multi-context uploading 2021-09-14 21:27:36 -05:00
Leonardo f9cf27a2c7 Changed the dataPoint, started the introduction of the lightmap use 2021-09-14 23:21:48 +02:00
Leonardo e03e09a243 Fixed various bugs and introduced more maps in the ThreadMapUtil 2021-09-14 19:02:37 +02:00
Leonardo fe02813d17 Disabled a section in the getNearbyLodChunkPosToSkip 2021-09-14 13:45:08 +02:00
Leonardo 145479267d Fixed Nether color 2021-09-14 13:15:36 +02:00
Leonardo 77ccd9eec3 changed how the valid block is determined, and added a mask and a shift for future use 2021-09-14 12:58:09 +02:00
Leonardo 9b216fedad Vertical lod now works (optimization required) 2021-09-14 01:05:41 +02:00
Leonardo e9798ace13 kinda working version 2021-09-13 23:23:55 +02:00
Leonardo 75e78d9000 First vertical data working 2021-09-13 17:34:37 +02:00
Leonardo 34776074fd added the vertical merge 2021-09-13 13:16:52 +02:00
James Seibel 8822e2d8a1 partially add different context rendering 2021-09-12 23:14:43 -05:00
Leonardo 32de70b4f0 Removed the normals 2021-09-13 01:48:11 +02:00
Leonardo 76a7baeb32 Saving works again 2021-09-13 01:47:04 +02:00
Leonardo 95d9c17e49 Added new colors for the torches 2021-09-13 01:19:39 +02:00
Leonardo a6544d3bb6 Introduced light and added normal in the template for future shading improvement 2021-09-13 00:37:23 +02:00
Leonardo c3115caa8f Re-organized the LodBuilder code 2021-09-12 16:29:41 +02:00
Leonardo 4e1e5b24ee Changed the lodBuilder to use a single function 2021-09-11 20:05:11 +02:00
Leonardo 7b73445f4d Changed the lodBuilder to use a single function 2021-09-11 19:59:30 +02:00
Leonardo 5f1f5f0948 Fixed some smalls bugs 2021-09-11 16:29:20 +02:00
Leonardo bdcc4c7755 Introduced map util and now the Loading does not create new String object. 2021-09-11 15:56:46 +02:00
Leonardo 1395e32a50 introduced the mergeSingleData function 2021-09-11 13:49:51 +02:00
Leonardo 99f7d70613 disabled the class until it's ready 2021-09-10 18:22:13 +02:00
Leonardo 59bfd739f4 Added max detail at FULL 2021-09-10 18:21:46 +02:00
Leonardo 3f1cf6c305 Added some new temporal data storing 2021-09-10 18:21:09 +02:00
Leonardo 5c05df0361 changed the thread names 2021-09-10 18:20:33 +02:00
Leonardo feebc3564a Created the single level container 2021-09-10 16:42:21 +02:00
Leonardo a9aa630aff Started convertion for vertical data 2021-09-10 15:47:43 +02:00
James Seibel 6ec146ba60 re-add depreciation warning suppressions 2021-09-09 19:06:09 -05:00
Leonardo 21140593e2 Started convertion for vertical data 2021-09-10 01:05:12 +02:00
Leonardo 878714dae3 Fixed the lod not showing at screen corner bug 2021-09-09 15:51:14 +02:00
Leonardo e876d7bec6 Fixed the lod not showing at screen corner bug 2021-09-09 14:43:04 +02:00
Leonardo 4f06395557 Fixed glass color 2021-09-09 14:36:05 +02:00
Leonardo aa3dbe8f32 Fixed the allocation of long[] 2021-09-09 14:10:45 +02:00
James Seibel b1bcdb24f0 comment out the config override for release a1.4.1 2021-09-08 18:30:37 -05:00
James Seibel cbd7f4300e Improve logging wording 2021-09-08 18:17:36 -05:00
James Seibel 4d8e30121e fix a spelling mistake 2021-09-08 18:17:17 -05:00
James Seibel fbe39542fc update the version number to a1.4.1 2021-09-08 18:13:25 -05:00
James Seibel 6a1f448b41 comment out testing code 2021-09-08 18:13:06 -05:00
James Seibel e13b23832c Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-09-08 18:09:15 -05:00
James Seibel 4c9e0edf32 Add barrier blocks to the list of blocks to ignore 2021-09-08 18:08:59 -05:00
Leonardo 8664a06d3b fixed a small bug that was causing visual artifacts 2021-09-08 19:38:17 +02:00
James Seibel 18b8359f0d rename the wrapper package to wrappers 2021-09-07 21:12:58 -05:00
James Seibel 7de4c7c72a Make the reflection handler a singleton 2021-09-07 21:12:16 -05:00
James Seibel b4bbabae42 enable debugging settings in ClientProxy 2021-09-07 19:52:27 -05:00
James Seibel 40321d6e21 Remove unused variables, imports, etc. 2021-09-07 19:52:06 -05:00
James Seibel cf1702bd0c Fix file reading/writing not working, Closes #61 2021-09-07 19:38:41 -05:00
James Seibel a9b50cdb32 remove invalid imports / organize imports 2021-09-07 19:10:30 -05:00
James Seibel 7eed472029 Fix stuttering caused by a merge 2021-09-07 19:09:50 -05:00
James Seibel 0262e452c7 Improve FileHandler info message 2021-09-07 19:04:48 -05:00
James Seibel 30287d5a7d Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-09-07 18:54:41 -05:00
James Seibel 83346fed1f Improve the error messages in the LodDimensionFileHandler 2021-09-07 18:54:24 -05:00
Leonardo e897c3edba fixed generation 2021-09-08 00:51:39 +02:00
Leonardo bd9e2acaf6 Changed the default heigth and depth and small fix to the culling 2021-09-08 00:23:44 +02:00
Leonardo 1e15d372c4 Added box caching 2021-09-07 21:22:12 +02:00
Leonardo 849d563425 Added box to replace AxisAlignedBB 2021-09-07 20:07:39 +02:00
Leonardo aa5a8aa3b8 small change 2021-09-07 19:05:58 +02:00
Leonardo b096cc53aa Working version 2021-09-07 19:02:51 +02:00
Leonardo 94d994e761 re-added the commit 2021-09-07 18:52:58 +02:00
Leonardo f76fa17e25 Removed level pos and data arrays 2021-09-07 17:23:22 +02:00
James Seibel 53a66268cb Close issue #37 (z-fighting far from the origin)
I'm not certain why in LodRenderer swapBuffers has to be called after the frame has been rendered, but otherwise it causes stuttering / rubber banding.
2021-09-06 22:51:46 -05:00
James Seibel 139867d4b8 auto-indent 2021-09-06 12:17:49 -05:00
James Seibel 81cf05ba19 fix a issue where nothing renders in the compiled version 2021-09-06 11:55:44 -05:00
James Seibel 13a1e7ed56 Add the MinecraftWrapper 2021-09-06 11:20:32 -05:00
James Seibel 42bd0fbde9 Delete 1.4 release notes.txt 2021-09-05 17:25:46 -05:00
James Seibel ebe2bd97bc Remove the compiled jars (they are now handled by CurseForge) 2021-09-05 16:51:26 -05:00
James Seibel a3ac3386d0 Update 1.4 release notes.txt 2021-09-05 16:50:42 -05:00
Leonardo 69ba83d34f small change to far Fog 2021-09-05 16:15:14 +02:00
James Seibel e048d277f8 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-09-04 11:01:26 -05:00
James Seibel 0bca47a92b Update pack.mcmeta
I don't even know if we need this file
2021-09-04 11:01:05 -05:00
James Seibel ce84b30ddb Change a println to use the logger 2021-09-04 11:00:54 -05:00
Leonardo 1843f96526 various fix to the new classes 2021-09-04 12:48:22 +02:00
Leonardo e46864431b Fixing the new classes 2021-09-03 23:33:54 +02:00
Leonardo 152a3fa108 Optimized the generation memory use 2021-09-03 22:35:08 +02:00
Leonardo 3420133bd3 Added LevelPosUtil, PosToGenerateContainer and PosToRenderContainer to be used in the future 2021-09-03 19:34:04 +02:00
Leonardo c79bf7c3f7 Fixed chunk data generation during first world loading 2021-09-03 13:10:16 +02:00
James Seibel 2219da4050 revert the fog changes 2021-09-01 21:47:31 -05:00
James Seibel a1aa90cccb Split up the configs to make it easier to understand 2021-09-01 21:39:02 -05:00
Leonardo d19abaef7b small fix to a bug that was causing crash if the player went over y 256 2021-09-01 18:20:51 +02:00
Leonardo 77625c65c7 small fix 2021-09-01 18:11:25 +02:00
Leonardo 91ba48ad4a Max draw detail now works correctly and node bigger than a chunk do not disappear if you touch a border 2021-09-01 18:11:01 +02:00
Leonardo 32e587d536 Small fix to the index of vanillaRenderedChunks 2021-09-01 17:27:37 +02:00
Leonardo e3dfe658f5 Fixed chunkPos being created multiple time in the buffer 2021-09-01 17:20:52 +02:00
Leonardo 4e249e943a Revert "Added LevelPosUtil, now the node are added using it and not with the LevelPos object"
LevelPos are useful and the small stutter in the buffer builder is probably caused by the creation of ChunkPos
2021-09-01 16:33:34 +02:00
Leonardo 1360edb459 Added LevelPosUtil, now the node are added using it and not with the LevelPos object 2021-09-01 15:15:23 +02:00
James Seibel 4c7ca395c6 Add the buffer rebuild timeouts to ClientProxy.applyConfigOverrides() 2021-08-31 21:14:19 -05:00
James Seibel a1c720d588 Fix a issue where the projection matrix was given a depth of 0
This caused the depth buffer to stop working.
2021-08-31 21:05:53 -05:00
James Seibel 7b09840d02 Organize inputs 2021-08-31 19:26:17 -05:00
Leonardo e65579f346 temporary fix to the missing region bug 2021-08-31 18:08:02 +02:00
Leonardo 78d6481a49 Another small fix 2021-08-31 12:55:42 +02:00
Leonardo 1428e72d46 small fix to the generation 2021-08-31 11:47:18 +02:00
James Seibel 2c2c6d6785 Add configs for buffer building timeouts and small refactors 2021-08-30 23:16:27 -05:00
Leonardo d5d48f2448 now the vanillaRenderedChunk is reset if the player goes to high 2021-08-30 23:41:56 +02:00
Leonardo 536de1a22d fixed a small error with the timer 2021-08-30 23:25:37 +02:00
Leonardo 193c579712 changed the generation. Added re-use of levelPos 2021-08-30 23:03:22 +02:00
Leonardo cdba7b20f5 Buffer that does not change won't be rebuilt 2021-08-30 17:55:34 +02:00
Leonardo 5467d007b8 preparing the mod for future buffer caching 2021-08-30 12:36:07 +02:00
Leonardo b24d691d8a Removed a useless temp Object in the getNodeToRender 2021-08-30 10:36:15 +02:00
James Seibel f68e6a9a13 Add a config option to disable the F4 keybinding 2021-08-29 21:23:16 -05:00
James Seibel 2dcdc854e3 Improve stone color 2021-08-29 21:09:30 -05:00
James Seibel 42da213ea9 Update the mod meta info 2021-08-29 16:35:59 -05:00
James Seibel dfea2f561a Replace the old logo files with the new logo files 2021-08-29 14:32:19 -05:00
James Seibel d8b4730ee0 Remove a unneeded depreciation suppression warning 2021-08-29 14:20:18 -05:00
Leonardo 74cbf794a1 the culling in templace can be disabled using the disableCulling boolean 2021-08-29 18:22:41 +02:00
Leonardo 812fa65054 divided the time checker for the regen 2021-08-29 17:18:21 +02:00
Leonardo ba63b44288 small change 2021-08-29 16:44:36 +02:00
Leonardo b19a80f411 Optimized the regen 2021-08-29 16:42:44 +02:00
Leonardo 450f15ad36 Finally fixed the regen problem 2021-08-29 10:56:14 +02:00
James Seibel a6ed4968f5 Add a config option for the number of buffer builder threads 2021-08-28 23:38:51 -05:00
James Seibel 65dc629771 Remove a unsettable configOverride 2021-08-28 23:38:16 -05:00
James Seibel 80aa49e28b Update 1.4 release notes.txt 2021-08-28 23:37:34 -05:00
James Seibel 2c3149ef30 Fix a potential issue with compiling to the wrong Java version 2021-08-28 17:15:38 -05:00
James Seibel cd792d7045 Fix a potential crash where Setupbuffers isn't called fast enough for the BufferBuilder 2021-08-28 17:13:17 -05:00
Leonardo 3ade43651f small Optimization to the buffer 2021-08-28 20:55:18 +02:00
Leonardo f4c3ad8bb5 Fixed the garbage collector being called too much 2021-08-28 20:32:58 +02:00
James Seibel 13d2c7b421 Create the comment for issue #62 2021-08-28 12:10:19 -05:00
James Seibel c54c2c6612 Remove the unused parameter in getBufferMemoryForSingleLod() 2021-08-28 11:55:48 -05:00
James Seibel 13878b7387 auto-format 2021-08-28 11:27:20 -05:00
James Seibel 2f20fc6b77 Update the default config options 2021-08-28 11:18:19 -05:00
James Seibel d4ada067c5 auto-indent 2021-08-28 11:05:33 -05:00
James Seibel 9277b3ad38 Add different debug modes (off, detail, detail_wireframe) 2021-08-28 11:04:59 -05:00
James Seibel c48d409015 remove the unused enum LodQuality 2021-08-28 10:18:23 -05:00
James Seibel ccdebb4242 auto-indent 2021-08-28 10:18:05 -05:00
James Seibel 18c94cea46 Update known issues 2021-08-28 10:09:32 -05:00
James Seibel fe381fc207 Rearrange ClientProxy and fix a potential saving issues 2021-08-28 10:07:20 -05:00
James Seibel acc73af666 Remove some debugging 2021-08-28 10:00:11 -05:00
Leonardo 685284f131 removed some e.printStack for the release 2021-08-28 13:40:39 +02:00
Leonardo f803bd58af fixed server not overriding lower quality 2021-08-28 13:21:50 +02:00
Leonardo 26fbdfc92c fixed memory use method and put F4 as debug key 2021-08-28 12:41:54 +02:00
Leonardo e3e8ef705a geneartionType is no longer used in LodRegion. Every region has a generationMode (+ server) 2021-08-28 12:22:09 +02:00
Leonardo e1a425dbcc fixed a small generation errore,
Now cut and gen tree are automatic
2021-08-28 11:15:34 +02:00
Leonardo d8bd4e2347 Fixed a small loading bug,
made the getDataToGenerate fully automatic, added an option to update the DetailDistanceUtil values
2021-08-28 10:38:44 +02:00
James Seibel 49cdd5702f Add 1.4 release notes
This also includes bugs that need to be fixed before 1.4 can be released
2021-08-27 21:25:26 -05:00
James Seibel 32c19eab7f move a comment 2021-08-27 20:59:41 -05:00
James Seibel a32b66aaab organize imports 2021-08-27 18:05:27 -05:00
James Seibel 425f4948dc Remove unneeded imports and a unneeded cast 2021-08-27 18:05:02 -05:00
James Seibel d05908af32 Auto-formatting 2021-08-27 18:04:50 -05:00
Leonardo 822a088096 fixed loading 2021-08-28 00:36:45 +02:00
Leonardo 36079e1624 fix to the Rendering holes 2021-08-28 00:16:44 +02:00
Leonardo 8db782a406 Now nodeToRender is fully automatic 2021-08-27 23:05:37 +02:00
Leonardo dd018f90d3 Small change 2021-08-27 18:47:42 +02:00
Leonardo af4e30588f new z fix 2021-08-27 18:27:37 +02:00
Leonardo 2630d50147 temporary z fix 2021-08-27 17:43:17 +02:00
Leonardo db2410e7fe changed indent 2021-08-27 14:34:43 +02:00
Leonardo 9990132db2 small changes 2021-08-27 14:31:13 +02:00
Leonardo 21069d6479 Optimization to getLodToRender 2021-08-27 12:02:02 +02:00
Leonardo b27afbb18c Optimized the getDataToGenerate 2021-08-27 11:34:55 +02:00
Leonardo 783c0c97a1 Preparing the BufferBuilder for new system 2021-08-27 11:28:29 +02:00
Leonardo 3dfa2d778a Fixed end bug 2021-08-27 10:59:24 +02:00
James Seibel b44a641d96 Add a TODO 2021-08-26 22:59:55 -05:00
James Seibel 8139b83a01 Fix heights saving higher then they are 2021-08-26 21:01:59 -05:00
James Seibel 456ba183da Fix updating regions where LODs contain no blocks 2021-08-26 20:28:48 -05:00
James Seibel 7525c1b257 Fix the "ffffff" error when reading files 2021-08-26 19:37:38 -05:00
James Seibel 5d4d634537 Re-add the Number Of World Generation Threads config option 2021-08-26 19:31:33 -05:00
James Seibel e1149be7c1 add a missing closing comment "/" 2021-08-26 18:14:49 -05:00
Leonardo fc0aaac69f added better shading + small changes 2021-08-27 00:54:46 +02:00
Leonardo 9786a12273 Fixed a small bug with getDataToGenerate 2021-08-26 23:34:14 +02:00
Leonardo c169cb6b7f Changed how color are calculated 2021-08-26 23:02:32 +02:00
Leonardo afcdce4667 Small fix to LevelPos 2021-08-26 20:17:00 +02:00
Leonardo ab7ed9a4c5 Optimized getDataToGenerate 2021-08-26 20:13:32 +02:00
Leonardo 120e8e5f6d small fixes and changed settings 2021-08-26 19:33:59 +02:00
Leonardo 65824a6fed fixed fog 2021-08-26 19:33:32 +02:00
Leonardo 114aaf9fe4 Update doesn't use temp object anymore 2021-08-26 19:33:15 +02:00
Leonardo 347b149037 The generation is working now 2021-08-26 17:41:01 +02:00
Leonardo 70317a37cb fixed LevelPos and colors 2021-08-26 14:28:27 +02:00
Leonardo 74e4744ff7 Correctly removed LodDataPoint and optimized the LevelPos use 2021-08-26 13:18:18 +02:00
Leonardo 98cbc30709 Small changes to how number of thread is chosen and returned to old LINEAR system 2021-08-25 16:12:18 +02:00
Leonardo b44900e3f0 Added new render/generation distance calculator 2021-08-25 13:44:53 +02:00
Leonardo 1755a252b1 Fixed how request works 2021-08-25 13:13:48 +02:00
Leonardo afcedd0c6d Improved how LINEAR is determined 2021-08-25 13:13:27 +02:00
Leonardo 525005bcb6 small changes to how the node to render are chosen 2021-08-25 12:26:16 +02:00
Leonardo 360294d37c fixed the generation Request 2021-08-25 12:24:59 +02:00
Leonardo ea05e3f9e6 fixed the cull 2021-08-25 12:24:01 +02:00
Leonardo 70a75f0543 added an offset to the cull 2021-08-25 11:09:49 +02:00
Leonardo 488d520b8f Improved the template, shared faces are not rendered 2021-08-25 10:55:05 +02:00
Leonardo 30bb175ea0 small changes 2021-08-25 08:17:39 +02:00
Leonardo 500a68e0fc Merge remote-tracking branch 'origin/1.16.5' into 1.16.5
# Conflicts:
#	src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
#	src/main/java/com/seibel/lod/handlers/LodDimensionFileHandler.java
#	src/main/java/com/seibel/lod/proxy/ClientProxy.java
2021-08-25 07:59:57 +02:00
James Seibel 0cd9bfaef2 Put all LOD save files in the same folder 2021-08-24 21:48:09 -05:00
James Seibel a464176a25 Close #32 (make distance generation independent of the buffer builder) 2021-08-24 21:47:51 -05:00
James Seibel a0dcde48ae Remove unneeded TODOs and unused code 2021-08-24 18:31:42 -05:00
Leonardo 8ae81d3aac added some debugging comments 2021-08-24 23:11:14 +02:00
Leonardo c4f864f0e3 changed how the distance generation mode is determined and added
zFix boolean in node to render to disable the zFighting fix
2021-08-24 23:10:29 +02:00
Leonardo cddd239fc5 Introduced try and catch were needed and fixed some small bugs 2021-08-24 14:58:22 +02:00
Leonardo 189b0ec878 Now the system work stable with SINGLE 2021-08-24 02:35:25 +02:00
Leonardo bd305a0269 small fixes to tree generator new tree cutter 2021-08-24 01:54:01 +02:00
Leonardo bbf99ed145 fixed tree generator new tree cutter 2021-08-24 00:33:46 +02:00
Leonardo cac4807986 Added tree generator and new tree cutter 2021-08-23 23:44:55 +02:00
Leonardo 181539b83b small fixes 2021-08-23 16:05:21 +02:00
Leonardo 4795ddd1ff Fixed circle generation bug 2021-08-23 15:33:51 +02:00
Leonardo c1c6680d04 small changes 2021-08-23 14:20:09 +02:00
Leonardo 81cbc7a12b added the big update function 2021-08-23 12:36:32 +02:00
Leonardo 4c6185556f Small fixes 2021-08-23 12:10:55 +02:00
Leonardo b0ed460230 small fix to the tree cutter 2021-08-23 11:45:15 +02:00
Leonardo 38e323a12f small fix to the tree cutter 2021-08-23 11:24:06 +02:00
Leonardo 9840c594e6 Added the tree cutter 2021-08-23 11:12:23 +02:00
James Seibel fdd8204a46 Add multi-threaded buffer building 2021-08-22 22:54:16 -05:00
James Seibel fb188e4819 auto indentation 2021-08-22 18:46:47 -05:00
James Seibel 9b3d9cbba3 javadoc formatting 2021-08-22 18:46:22 -05:00
James Seibel a2aa1dd081 add a lock to the buffer builder when the buffers are being used
Hopefully this should prevent some crashes and errors when generating buffers
2021-08-22 18:42:27 -05:00
James Seibel cb889d7430 auto formatting 2021-08-22 18:26:59 -05:00
James Seibel 2a88b2e746 Remove a unused method 2021-08-22 18:25:58 -05:00
James Seibel 93dd441708 Close #60 (LODs rendering on top of the player) and improve get Lod pos to skip 2021-08-22 18:24:41 -05:00
James Seibel a81ce6c28a auto reformat 2021-08-22 17:55:24 -05:00
James Seibel 967627c57e Move getRenderedChunks to LodUtil 2021-08-22 17:54:10 -05:00
Leonardo 31cb684bec Added different generation detail option 2021-08-22 19:54:10 +02:00
Leonardo d5112be385 small fixes 2021-08-22 19:18:14 +02:00
Leonardo 547d54aab1 Fixed the near clipping 2021-08-22 16:54:09 +02:00
Leonardo 397573bc08 removed lodChunkRadiusMultiplier from proxy, config and renderer 2021-08-22 16:46:55 +02:00
Leonardo b52d7e4f20 small fix to the Near fog 2021-08-22 16:33:20 +02:00
Leonardo a450f44aa7 small fix to the fog 2021-08-22 16:20:27 +02:00
Leonardo a4e8e9ef60 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5
# Conflicts:
#	src/main/java/com/seibel/lod/proxy/ClientProxy.java
2021-08-22 16:09:07 +02:00
Leonardo 3c28ed5601 small fix to fog 2021-08-22 16:06:30 +02:00
James Seibel c5ec41eb2d Add buffer recreation when changing worlds 2021-08-22 08:42:55 -05:00
Leonardo d1bb96c2dc small fix 2021-08-22 14:46:16 +02:00
James Seibel d72ba5bb82 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-08-22 07:40:09 -05:00
James Seibel baba54bdb8 Add error reporting and handling when unable to access the save folder 2021-08-22 07:40:00 -05:00
Leonardo aa7ea85cde New config 2021-08-22 14:34:02 +02:00
Leonardo a1f01bef78 Fixed game chunk not overriding lod chunk 2021-08-22 11:51:26 +02:00
Leonardo 1a7655e752 Added DetailUtil and it's use in the buffer builder +
small fixes
2021-08-22 11:27:40 +02:00
James Seibel e2a983e4ac comment grammar change 2021-08-21 21:54:40 -05:00
James Seibel e2f0263643 Remove synchronized from getters 2021-08-21 21:54:23 -05:00
James Seibel b280303f8f Improve vine colors 2021-08-21 20:06:22 -05:00
James Seibel ff3b2aee6b Add error catching and improve the None distance generation mode 2021-08-21 20:02:30 -05:00
James Seibel 804f830a10 fix third person backwards culling the wrong regions 2021-08-21 19:57:03 -05:00
James Seibel 68b5978135 Change the color of Mycelium to better match its block color 2021-08-21 19:45:43 -05:00
James Seibel 9ebb84bf9c Make air and Cave air act the same when generating LODs 2021-08-21 19:25:31 -05:00
James Seibel a08e08856a Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into
1.16.5

# Conflicts:
#	src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
2021-08-21 18:57:39 -05:00
James Seibel 8d5c8bf7b8 Finish adding simple frustum culling 2021-08-21 18:54:20 -05:00
Leonardo 168eb537cb Improved generation 2021-08-21 22:21:41 +02:00
James Seibel ca57c15d46 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into
1.16.5

# Conflicts:
#	src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
2021-08-21 15:19:04 -05:00
James Seibel 5aea9877e0 re-organize RenderUtil 2021-08-21 15:11:13 -05:00
Leonardo c20ec4ef59 added commented use of biomeUtils and terrainUtils 2021-08-21 22:01:52 +02:00
James Seibel 32fb349621 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-08-21 13:05:35 -05:00
James Seibel c5b4e20787 Add simple partially functioning frustum culling 2021-08-21 13:05:32 -05:00
James Seibel a246dd7561 improve a few comments 2021-08-21 13:02:21 -05:00
James Seibel 615e29451a add conversions to chunk and block pos 2021-08-21 13:01:39 -05:00
James Seibel bcac2bd7ba Update a few comments 2021-08-21 13:01:24 -05:00
Leonardo a02c232f5f improved getDataToGenerate and changed how it's used in the buffer builder 2021-08-21 17:28:11 +02:00
James Seibel d27dbbb64e Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into
1.16.5

# Conflicts:
#	src/main/java/com/seibel/lod/builders/LodBufferBuilder.java
2021-08-21 10:06:44 -05:00
James Seibel fdfbee108a minor client proxy debug setting changes/commenting 2021-08-21 09:57:14 -05:00
James Seibel de54c37cf1 Optimize Buffer Builder chunk generator queuing 2021-08-21 09:55:04 -05:00
Leonardo d4580806d1 minor fixes, fixed z fighting 2021-08-21 16:25:09 +02:00
James Seibel 5a856c65fa Update the debug colors to work up to region size 2021-08-21 08:03:35 -05:00
James Seibel 75d6da98dc Remove invalid imports (again) 2021-08-21 07:36:49 -05:00
Leonardo 7654cac01d minor fixes 2021-08-21 14:33:11 +02:00
James Seibel cbe242cd2f Remove invalid import 2021-08-21 07:23:55 -05:00
Leonardo 7f69b11ae4 minor fixes 2021-08-21 12:43:38 +02:00
Leonardo 426c9edb05 new generation system fixed 2021-08-21 12:25:49 +02:00
James Seibel 88fb9b5b21 Add debug code to the LodNodeGenWorker 2021-08-20 21:32:57 -05:00
James Seibel 163f8ca979 Remove Node from the names of LodRenderer, BufferBuilder, LodTemplates, and LodBuilder 2021-08-20 20:28:37 -05:00
James Seibel ee416a10ec Add null checking to the BufferBuilder 2021-08-20 20:24:33 -05:00
James Seibel c5ef03aa0e Add null checks and minor formatting changes 2021-08-20 20:19:46 -05:00
James Seibel 25cb08f541 Eclipse auto-formating 2021-08-20 20:19:05 -05:00
Leonardo fcd06bde87 fixed getDataToGenerate use in buffer builder,
Fixed buffers indexing
2021-08-21 02:57:57 +02:00
Leonardo 00f50a2e60 Added getNodeToGenerate to the buffer builder 2021-08-20 19:46:46 +02:00
Leonardo 550c0f1bf2 Added getDataToRender to the bufferBuilder 2021-08-20 19:02:11 +02:00
Leonardo 0f0179bd19 Various fix 2021-08-20 17:06:41 +02:00
Leonardo 7885d14a91 getDataToRender and getDataToGenerate added to dimension 2021-08-20 16:35:38 +02:00
Leonardo bd9c3bba3f added getDataTeRender 2021-08-20 16:07:27 +02:00
Leonardo 04f8cd653a getDataToGenerate should work correctly 2021-08-20 15:03:28 +02:00
James Seibel 02bfc20ae6 Fix small mushrooms using the grass color 2021-08-20 07:34:14 -05:00
James Seibel d65017366a comment out the buffer building time console printing 2021-08-20 07:25:52 -05:00
James Seibel 05d17ba9fa Close #57 (Add support for night vision) 2021-08-20 07:25:22 -05:00
Leonardo 967aab3b3b new line brackets 2021-08-20 11:46:41 +02:00
Leonardo 9f77bf4e61 Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-08-20 11:32:21 +02:00
James Seibel 6aa096de57 Remove an incorrect import 2021-08-19 19:41:56 -05:00
Leonardo d312d60cd9 Fixed loading not working, started the creation of dataToGenerate and dataToRender 2021-08-20 00:50:08 +02:00
Leonardo 65fde550cb Small fix to the position 2021-08-19 15:49:36 +02:00
Leonardo 736b5ba625 new enum for render distance and quality of lods 2021-08-19 12:47:54 +02:00
Leonardo b2227688bc Merge remote-tracking branch 'origin/1.16.5' into 1.16.5 2021-08-19 11:31:40 +02:00
Leonardo cbe8b647b1 New fast save system 2021-08-19 11:31:26 +02:00
James Seibel 0b0f0eab2f Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-08-18 17:37:38 -05:00
James Seibel ffb63ce8ef Move the setupBuffers method to the ClientProxy 2021-08-18 17:37:23 -05:00
Leonardo 0e6f5d9805 Changed the save system
Now lod render distance and quality are not dependent on game render distance
2021-08-18 23:54:13 +02:00
Leonardo a0bd9648dc Conversion to new quad tree LodRegion 2021-08-18 19:46:56 +02:00
James Seibel aa1778cf82 Remove the direct memory Buffer limit
Now the LOD multiplier won't be lowered when the detail is increased.
2021-08-17 22:44:50 -05:00
Leonardo 10d66a4775 LodRegion now works (might still have bugs) 2021-08-16 23:03:21 +02:00
Leonardo 4082c97e0e LodRegion update (not yet complete) 2021-08-16 18:45:42 +02:00
Leonardo 665f979e82 LodRegion update (not yet complete) 2021-08-16 14:23:26 +02:00
Leonardo 911205ce0a Create the new LodRegion class that will replace the quadTrees 2021-08-16 12:24:49 +02:00
James Seibel 51078fde5b Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-08-15 19:39:55 -05:00
James Seibel adde7e8d67 Add a ThreadFactory to name executor threads 2021-08-15 19:38:51 -05:00
Leonardo 582e38eec5 Added the ability to change the save type to bin (slower method at the moment) 2021-08-16 00:05:24 +02:00
James Seibel e987e679d0 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into
1.16.5

# Conflicts:
#	src/main/java/com/seibel/lod/builders/LodNodeBufferBuilder.java
2021-08-15 15:14:43 -05:00
James Seibel 6d776407a4 Optimize the BufferBuilder 2021-08-15 14:52:17 -05:00
Leonardo 8a61a5f0e7 Slightly optimize addLodToBuffer 2021-08-15 16:40:13 +02:00
James Seibel 49a9ff8640 Re-add the render.drawLODs method to clientProxy
Ops.
2021-08-15 08:32:00 -05:00
James Seibel 47ebdb4aee Remove BiomeContainer from BufferBuilder
Having it prevents server use
2021-08-15 08:19:00 -05:00
James Seibel 2b10a9d977 Remove objectSizeCalculator Java Mission Control is much better 2021-08-15 07:50:31 -05:00
James Seibel 247b7d5633 Add toString methods 2021-08-14 21:01:27 -05:00
James Seibel ae9eba0608 Add distanceGenerationMode when generating nodes 2021-08-14 19:56:16 -05:00
James Seibel 7983681b70 Update the config 2021-08-14 18:13:08 -05:00
James Seibel 85d4106f28 Add a try catch to LodQuadTreeDimension 2021-08-14 18:08:47 -05:00
James Seibel 22d329b8aa remove illegal state exception in LodQuadTreeWorld
This fixes an exception being thrown when leaving the world.
2021-08-14 18:02:25 -05:00
James Seibel 004d36ffa7 Remove old commented out code 2021-08-14 18:01:35 -05:00
James Seibel 231340d979 Comment out debug code 2021-08-14 17:38:40 -05:00
James Seibel f55f5b881f Optimize the region distance logic 2021-08-14 17:26:47 -05:00
James Seibel 03ac090e06 Refactor and improve the comments in LodNodeBufferBuilder 2021-08-14 17:26:28 -05:00
James Seibel 3b375e9c1b minor spacing change 2021-08-14 17:22:59 -05:00
James Seibel e44157fae5 Update / Fix RegionPos 2021-08-14 17:22:44 -05:00
James Seibel 997513231c Improve variable naming in LodNodeRenderer 2021-08-14 16:00:12 -05:00
James Seibel 64c3ba297b Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-08-14 09:34:01 -05:00
James Seibel 3ae9c49de4 Improve file writing logic 2021-08-14 09:33:46 -05:00
Leonardo 5692f9fa69 Added the cutTreeAtLevel method 2021-08-14 15:52:14 +02:00
Leonardo 72ba9f5699 Added the cutTreeAtLevel method 2021-08-14 15:50:44 +02:00
James Seibel 696be6f796 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-08-14 08:20:09 -05:00
James Seibel 5198335948 Improve LOD saving logic 2021-08-14 08:19:44 -05:00
Leonardo 8102063850 Added the cutTreeAtLevel method 2021-08-14 15:17:03 +02:00
Leonardo 86bf551de8 Lod not saving fix 2021-08-14 15:04:54 +02:00
Leonardo ec2933f23c Fixed generation detail not being used 2021-08-14 14:14:26 +02:00
James Seibel f6daf62c7d Add a Size calculator class 2021-08-13 23:35:41 -05:00
James Seibel 50988db28c Use a lower level biome generation method 2021-08-13 23:34:53 -05:00
James Seibel 047cef184d Update TODO comment 2021-08-13 23:34:23 -05:00
James Seibel ee5b8662d1 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-08-13 18:01:25 -05:00
James Seibel 9470ee2507 Add KaptainWutax TerrainUtils to build.gradle 2021-08-13 18:00:06 -05:00
James Seibel 8f63e755be Rename saveRegionToDisk to saveRegionToFile 2021-08-13 17:59:33 -05:00
Leonardo b0d62da7fe Remove QuadTreeImage and remove the start, center and end field from the LodNode 2021-08-13 20:25:28 +02:00
James Seibel 7a4347b288 Fix the try catch block in LodNodeGenWorker
Try catch finally blocks need catch to work properly, who knew.
2021-08-12 21:00:35 -05:00
James Seibel bbaa583a6d Fix a config typo 2021-08-12 19:41:09 -05:00
James Seibel c3709f726c Improve how distance based quality is determined 2021-08-11 21:52:16 -05:00
James Seibel d1417069d9 Remove the old LOD objects 2021-08-11 07:33:51 -05:00
James Seibel 412f1bead0 Start removing the old LOD objects 2021-08-11 07:29:51 -05:00
James Seibel 1095f63832 Remove unneeded code in LodDetail 2021-08-10 21:19:14 -05:00
James Seibel 89d0317c7f Add full detail to the LodNodeBufferBuilder 2021-08-10 21:15:34 -05:00
James Seibel 4f489a5272 Change the distance debug colors 2021-08-10 21:14:52 -05:00
James Seibel 8c843ba4b5 Fix the Full detail mode 2021-08-10 21:14:33 -05:00
James Seibel 77401cbfa0 Auto Reformat 2021-08-10 21:14:04 -05:00
James Seibel b983692fc1 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-08-10 20:49:42 -05:00
James Seibel e1a40c6868 Add a comment to LodNodeBufferBuilder 2021-08-10 20:47:28 -05:00
James Seibel 9c2add4e3b Clean up distance based detail and change debugMode 2021-08-10 20:34:06 -05:00
Leonardo 8cede4760e reduced quality to improve performance 2021-08-11 01:46:11 +02:00
Leonardo bceab238d5 Small fix to the offset 2021-08-11 01:45:18 +02:00
James Seibel 121676e661 Remove a unneeded offset in LodNodeBufferBuilder 2021-08-10 17:44:44 -05:00
Leonardo 9ec3be8a48 Added different level 2021-08-10 17:23:43 +02:00
Leonardo bb61cdad70 Added different LodDetail support 2021-08-10 17:11:36 +02:00
Leonardo 2e32e4d768 LodNodeBuilder and LodNodeGenWorker now support correctly LodDetail 2021-08-10 13:07:59 +02:00
Leonardo d4ee641362 Fixed file saving not working 2021-08-10 12:28:32 +02:00
James Seibel 953c2b2e92 Improve color generation and fix Biome Only generation 2021-08-09 22:25:49 -05:00
James Seibel 2cc78c874b Remove comment for issue #54 2021-08-09 22:23:47 -05:00
Leonardo f6f0ecb21b Fixed negative region not showing 2021-08-09 17:54:04 +02:00
Leonardo 190fef934c Added getNodeAtPos for generic node level 2021-08-09 17:01:31 +02:00
James Seibel 52608a9f3f Create issue #54 2021-08-08 22:06:45 -05:00
James Seibel 54e5fd30ab Refactor and comment 2021-08-08 22:04:13 -05:00
James Seibel 89115fd5d5 Add a text reminder when overriding the config file 2021-08-08 21:48:13 -05:00
James Seibel 5631ae52be Refactoring and Commenting 2021-08-08 16:41:25 -05:00
James Seibel 6520cdb184 Refactoring and commenting 2021-08-08 16:30:04 -05:00
James Seibel ce5f8708cd Remove unused code in LodNodeBuilder
I don't think using a 3rd party generator is a good idea; even if it is much faster than vanilla MC.
For a couple of reasons:
1. we could run into issues where the 3rd party isn't updated fast enough
2. the 3rd party generator may not generate the same terrain/biomes/etc.
3.  we wouldn't be able to generate mod terrain
2021-08-08 16:25:42 -05:00
James Seibel 270a83ddbc Refactoring and Commenting 2021-08-08 09:58:55 -05:00
James Seibel 64b8cb3556 Refactoring, reformatting, and commenting
I removed the getters from LodQuadTreeNode since they were public variables anyway.
2021-08-08 00:09:12 -05:00
James Seibel 7f7884c130 update LodNodeBufferBuilder version date 2021-08-07 23:38:14 -05:00
James Seibel 5a95613cee spacing reformatting 2021-08-07 23:38:00 -05:00
James Seibel 9a58800499 Refactoring and commenting 2021-08-07 23:31:40 -05:00
James Seibel d68e46a2d0 Refactoring 2021-08-07 19:31:31 -05:00
James Seibel 20d1ff6d49 revert LodQuadTree region to LodQuadTree and other refactors 2021-08-07 18:30:36 -05:00
James Seibel ed188448f2 Fix LodNodeBufferBuilder queueing the same chunk for generation multiple times 2021-08-07 18:29:20 -05:00
James Seibel 87c803e4c6 Minor refactoring 2021-08-07 13:40:04 -05:00
James Seibel 58f51aae91 reword a TODO 2021-08-07 13:36:15 -05:00
James Seibel 97a773176d Refactoring fixes 2021-08-07 13:30:03 -05:00
James Seibel f6d92021ed Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-08-07 13:29:05 -05:00
James Seibel 026cbd5da3 add fix from 2d70e8eb 2021-08-07 12:33:34 -05:00
James Seibel 3538e79a6b Reformat, Refactor, and add comments 2021-08-07 12:22:49 -05:00
Leonardo d520fb8535 previus fix was not correct 2021-08-07 19:03:56 +02:00
Leonardo d7dbf8b994 Fixed the repeating region bug 2021-08-07 18:56:51 +02:00
Leonardo 2d70e8ebe2 Fixed the repeating region bug 2021-08-07 18:54:10 +02:00
James Seibel 5eafe8f818 Improve formatting and a few variable names 2021-08-05 21:42:58 -05:00
James Seibel e875c664fd fix LODs generating multiple times (at least in single threaded gen) 2021-08-05 21:41:08 -05:00
James Seibel e313a03410 Fix/improve rendering again 2021-08-05 20:40:12 -05:00
James Seibel 781aa339bc Partially fix LodNode rendering 2021-08-05 07:56:00 -05:00
James Seibel 73e318ee38 Merge branch '1.16.5' of gitlab.com:jeseibel/minecraft-lod-mod into 1.16.5 2021-08-04 23:07:12 -05:00
James Seibel 337853cdfa Start merging in 1.16.5_QuadTree
The mod does compile and render, however distance LODs don't generate or render correctly and there are other problems as well.
2021-08-04 23:07:03 -05:00
James Seibel afe4e111c3 Add release version a1.3.2 2021-08-04 22:58:06 -05:00
James Seibel 3675c5da46 Add deprecation suppressions in LodRenderer 2021-07-29 07:20:22 -05:00
James Seibel a4cc39dbac Add 400 px icons 2021-07-27 22:32:18 -05:00
James Seibel e3787079b7 Add icon files 2021-07-27 21:24:11 -05:00
James Seibel b2f98e2d92 Improve grass colors (#36) 2021-07-26 22:27:20 -05:00
James Seibel e1edd01069 Implement a few small features in LodServerWorld 2021-07-26 22:20:00 -05:00
James Seibel eb3455452b Fix getting the GPU's fancy fog capabilities 2021-07-26 20:26:24 -05:00
James Seibel 34baf923b2 Fix #45 (Half and Full qualities checkerboard) 2021-07-26 07:56:00 -05:00
James Seibel 499308870d fix a typo 2021-07-25 20:55:15 -05:00
James Seibel f852a79a0e Fix LODs rendering with an offset 2021-07-25 20:52:30 -05:00
James Seibel fa98454151 Hopefully reduce the chance of index out of bounds exceptions 2021-07-25 20:51:52 -05:00
James Seibel 286fc91db6 Slightly improve gamma lighting 2021-07-25 20:51:18 -05:00
James Seibel 99209f920d Fix a few truncation and off by 1 errors 2021-07-25 18:48:25 -05:00
James Seibel 19fd1aff98 Close #36 (Improve foliage colors)
While the colors could still be improved, I'm not sure what else to do with them to do so.
2021-07-25 18:20:34 -05:00
James Seibel 9ebc5aeb32 Improve comments in CublicLodTemplate 2021-07-25 18:06:42 -05:00
James Seibel 7c890a4627 Add a config option to change LOD brightness and saturation
Related to issue #36
2021-07-25 18:00:39 -05:00
James Seibel ccc661225e Improve the DARKEN_SIDES shading mode 2021-07-25 17:58:46 -05:00
James Seibel d7b13a2e0b fix a typo 2021-07-25 15:49:18 -05:00
James Seibel c53ce15f7d Hopefully fix #38 (teleporting causing regions to save in the wrong place) 2021-07-25 14:14:07 -05:00
James Seibel 35ac6fc756 Fix a typo 2021-07-25 14:10:08 -05:00
James Seibel 6bcf58959b Fix #46 (MC crashing when joining a server) 2021-07-25 13:18:47 -05:00
James Seibel 5051508e42 Fix #48 (Lava showing up as water) 2021-07-25 12:29:40 -05:00
James Seibel 196e02e61a Partially close #43 (add SSAO)
I am surprised how much this small change improves how things look. I may still implement SSAO in the future but for the time being this is a big improvement for how things look.
2021-07-25 12:19:14 -05:00
Leonardo bc8188beb0 Added important TODOs 2021-07-21 10:43:51 +02:00
Leonardo 0fc4c5532b Minor fixes 2021-07-19 17:00:40 +02:00
Leonardo 98586d6af9 now different generation setting can be used in the same Dimension without conflict 2021-07-19 16:23:14 +02:00
Leonardo bdd1e2410a Updated the guide 2021-07-19 11:47:26 +02:00
Leonardo c0240c71bf Updated the guide 2021-07-19 11:46:22 +02:00
Leonardo 65ffc93e0f Updated the guide 2021-07-19 11:35:38 +02:00
Leonardo 01183be383 getLevelToGenerate has been renamed getNodesToGenerate. Now it return node and not the complete level 2021-07-19 11:32:20 +02:00
Leonardo 359791ea58 Fixed getLevelToGenerate. Now it works correctly 2021-07-19 11:26:05 +02:00
Leonardo 5b3aa82817 Updated the image creation 2021-07-14 15:08:10 +02:00
Leonardo d77bb48da1 Updated the guide 2021-07-14 15:07:09 +02:00
Leonardo 8b941cb95c Updated the guide 2021-07-14 14:41:03 +02:00
Leonardo b9d991db63 Updated the guide 2021-07-14 14:37:48 +02:00
Leonardo 1a8a7be494 Updated the guide 2021-07-14 14:33:58 +02:00
Leonardo d054ac91b1 Fixed all negative coords bug 2021-07-14 14:33:17 +02:00
Leonardo e40ee20460 Added GUIDE to Readme.txt 2021-07-14 11:14:44 +02:00
Leonardo 29b3e9fadc The lodQuadTree is now correctly converted to use LodDataPoint and DistanceGenerationMode 2021-07-13 20:40:55 +02:00
Leonardo 3cc78c62a0 The lodQuadTree is now correctly converted to use LodDataPoint and DistanceGenerationMode 2021-07-13 15:38:20 +02:00
Leonardo 2c719c41d9 Various change to support LodDataPoint and the DistanceGenerationMode enum 2021-07-13 11:38:08 +02:00
Leonardo cd06b42b02 changed pc 2021-07-13 00:53:24 +02:00
Leonardo e8b46a6fd2 Converting the quadTree to use the LodDataPoint class 2021-07-13 00:52:24 +02:00
James Seibel 814ac5df84 Change distanceBiomeOnlyGeneration to distanceGenerationMode in the configHandler 2021-07-11 18:41:38 -05:00
Morippi 7854f659a3 various change 2021-07-10 15:02:26 +02:00
Morippi 6cb1d2f8f4 second fix for negative coordinate 2021-07-10 13:36:15 +02:00
Morippi f95d57ab6d Several chages to converto to quadTree + first fix for negative coordinate 2021-07-10 12:43:23 +02:00
James Seibel 55f9d142e6 Add 1.16.5 a1.3.1 to the compiled Jars 2021-07-09 23:10:36 -05:00
James Seibel 58607ab1fc Update the version to a1.3.1 2021-07-09 23:09:32 -05:00
James Seibel 433ab4f92f Fix #37 (Z fighting far from the world's origin) 2021-07-09 23:08:30 -05:00
James Seibel 8840973a1e Fix #41 (leaving a world causing Lod generation to break) 2021-07-09 22:57:32 -05:00
Morippi f91479829d Several chages to converto to quadTree 2021-07-09 21:07:00 +02:00
Morippi 829c9531fa Several chages to converto to quadTree 2021-07-09 21:01:37 +02:00
Morippi f9bb248eef Several chages to converto to quadTree 2021-07-09 21:01:17 +02:00
Morippi 03ce4d9c42 Several chages to converto to quadTree 2021-07-09 19:23:14 +02:00
Morippi f181d073a3 fixed LodQuadTreeDimension 2021-07-09 17:56:44 +02:00
Morippi 63b01f3ec7 fixed LodQuadTreeDimension 2021-07-09 15:53:32 +02:00
Morippi 14f1b6db54 fixed LodQuadTreeDimension 2021-07-09 15:26:03 +02:00
Morippi 604089cfa8 fixed LodQuadTreeDimension 2021-07-09 15:08:48 +02:00
Morippi 712d9db2fa fixed LodQuadTreeDimension 2021-07-09 14:58:48 +02:00
Morippi 2b5b023472 fixed LodQuadTreeDimension 2021-07-09 13:33:11 +02:00
Morippi 4a9bc7ca74 fixed LodQuadTreeDimension 2021-07-09 13:11:25 +02:00
Morippi 804f910584 added region in image + various fix 2021-07-08 19:31:27 +02:00
Morippi d5b2512e27 various fix 2021-07-08 13:00:29 +02:00
Morippi 280d281604 various fix 2021-07-08 12:52:50 +02:00
Morippi 95bcc71d23 various fix 2021-07-08 12:40:36 +02:00
Morippi b623f1581f various fix 2021-07-07 23:12:45 +02:00
Morippi 62b6d9ea30 Modified to used getNodeToRender 2021-07-07 22:44:53 +02:00
Morippi 6c8d0f98a6 Added circular rendering,
Fixed get node to render
2021-07-07 22:43:44 +02:00
Morippi dc353cd029 Map works correctly 2021-07-07 21:16:18 +02:00
Morippi 86e4ab7e83 Map works correctly 2021-07-07 20:22:05 +02:00
Morippi c6a96ae710 Fixed QuadTreeImage 2021-07-07 19:44:10 +02:00
Morippi 9e24ee0ef7 Fixed LodQuadTree
Added QuadTreeImage to visualize how the quadTree is builded
2021-07-07 00:53:32 +02:00
Morippi 72bcc87de7 QuadTree version, still doesn't work 2021-07-05 14:46:51 +02:00
76 changed files with 4051 additions and 6518 deletions
+1
View File
@@ -20,6 +20,7 @@ build
# other
eclipse
run
**/src/generated/
# Files from Forge MDK
logs
+3
View File
@@ -0,0 +1,3 @@
[submodule "core"]
path = core
url = https://gitlab.com/jeseibel/distant-horizons-core.git
+68
View File
@@ -0,0 +1,68 @@
# Distant Horizons
This mod adds a Level Of Detail (LOD) system to Minecraft.\
This implementation renders simplified chunks outside the normal render distance\
allowing for an increased view distance without harming performance.
Or in other words: this mod lets you see farther without turning your game into a slide show.\
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.4](https://i.ytimg.com/vi_webp/H2tnvEVbO1c/mqdefault.webp)</a>
Forge version: 1.16.5-36.1.0
Notes:\
This version has been confirmed to work in Eclipse and Retail Minecraft.\
(Retail running forge version 1.16.5-36.1.0)
## source code installation
See the Forge Documentation online for more detailed instructions:\
http://mcforge.readthedocs.io/en/latest/gettingstarted/
1. Create a system variable called "JAVA_MC_HOME" with the location of the JDK 1.8.0_251 (This is needed for gradle to work correctly)
2. replace JAVA_HOME with JAVA_MC_HOME in gradle.bat
3. open a command line in the project folder
**If using Ecplise:**
1. run the command: `./gradlew geneclipseruns`
2. run the command: `./gradlew eclipse`
3. Make sure eclipse has the JDK 1.8.0_251 installed. (This is needed so that eclipse can run minecraft)
4. Import the project into eclipse
**If using IntelliJ:**
1. open IDEA and import the build.gradle
2. run the command: `./gradlew genIntellijRuns`
3. refresh the Gradle project in IDEA if required
## Compiling
1. open a command line in the project folder
2. run the command: `./gradlew build`
3. the compiled jar file will be in the folder `build\libs`
## Other commands
`./gradlew --refresh-dependencies` to refresh local dependencies.
`./gradlew clean` to reset everything (this does not affect your code) and then start the process again.
## Note to self
The Minecraft source code is NOT added to your workspace in an editable way. Minecraft is treated like a normal Library. Sources are there for documentation and research purposes only.
Source code uses Mojang mappings.
The source code can be 'created' with the `./eclipse` command and can be found in the following path:\
`minecraft-lod-mod\build\fg_cache\mcp\ VERSION \joined\ RANDOM_STRING \patch\output.jar`
## Open Source Acknowledgements
XZ for Java (data compression)\
https://tukaani.org/xz/java.html
-70
View File
@@ -1,70 +0,0 @@
This mod adds a Level Of Detail (LOD) system to Minecraft.
This implementation renders simplified chunks outside the normal render distance
allowing for an increased view distance without harming performance.
Or in other words: this mod let's you see farther without turning your game into a slide show.
If you want to see a quick demo, check out the video I made here:
https://youtu.be/CCT-3s02tYA
Forge version: 1.16.5-36.1.0
Notes:
This version has been confirmed to work in Eclipse and Retail Minecraft.
(Retail running forge version 1.16.5-36.1.0)
========================
source code installation
========================
See the Forge Documentation online for more detailed instructions:
http://mcforge.readthedocs.io/en/latest/gettingstarted/
Step 1: Create a system variable called "JAVA_MC_HOME" with the location of the JDK 1.8.0_251 (This is needed for gradle to work correctly)
Step 2: replace JAVA_HOME with JAVA_MC_HOME in gradle.bat
Step 3: open a command line in the project folder
Step 4: run the command: "./gradlew geneclipseruns"
Step 5: run the command: "./gradlew eclipse"
Step 6: Make sure the eclipse has the JDK 1.8.0_251 installed. (This is needed so that eclipse can run minecraft)
Step 7: Import the project into eclipse
=========
compiling
=========
Step 1: open a command line in the project folder
Step 2: run the command: "./gradlew build"
Step 3: the compiled jar file will be in the folder "build\libs"
==============
Other commands
==============
"./gradlew --refresh-dependencies" to refresh local dependencies.
"./gradlew clean" to reset everything (this does not affect your code) and then start the process again.
============
Note to self
============
The Minecraft source code is NOT added to your workspace in a editable way. Minecraft is treated like a normal Library. Sources are there for documentation and research purposes only.
Source code uses mcp mappings not Mojangs.
The source code can be 'created' with the ./eclipse command and can be found in the following path:
minecraft-lod-mod\build\fg_cache\mcp\ VERSION \joined\ RANDOM_STRING \patch\output.jar
Binary file not shown.
Binary file not shown.
+104 -28
View File
@@ -1,26 +1,36 @@
buildscript {
repositories {
maven { url = 'https://files.minecraftforge.net/maven' }
jcenter()
maven { url = 'https://files.minecraftforge.net' }
mavenCentral()
// potential replacement in case of problems: https://dist.creeper.host/Sponge/maven
maven { url = 'https://repo.spongepowered.org/maven/' }
// potential replacement in case of problems:
// https://dist.creeper.host/Sponge/maven
// used to download and compile dependencies from git repos
maven { url 'https://jitpack.io' }
gradlePluginPortal()
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
// Note to self: Don't try to update ForgeGradle!
// As of 11-27-2021 Mixins don't work on Gradle 7,
// which the newer versions of ForgeGradle use
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3+', changing: true
classpath group: 'org.spongepowered', name: 'mixingradle', version: '0.7-SNAPSHOT'
}
}
plugins {
id "com.github.johnrengelman.shadow" version "4.0.4"
}
apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'org.spongepowered.mixin'
// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
apply plugin: 'eclipse'
apply plugin: 'maven-publish'
version = 'a1.3'
group = 'com.backsun.lod'
archivesBaseName = 'lod_1.16.5'
version = 'a1.5.3'
group = 'com.seibel.lod'
archivesBaseName = 'Distant-Horizons_1.16.5'
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
@@ -32,7 +42,7 @@ minecraft {
// Use non-default mappings at your own risk. they may not always work.
// Simply re-run your setup task after changing the mappings to update your workspace.
mappings channel: 'official', version: '1.16.5'
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
@@ -113,8 +123,32 @@ minecraft {
}
}
// Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' }
sourceSets {
main {
java {
// add Distant Horizon's Core source folders
srcDirs("core/src/main/java");
srcDirs("core/src/main/resources")
}
resources {
// Include resources generated by data generators.
srcDir("src/generated/resources")
}
}
}
// this is required so that we can use
// jitpack in the dependencies section below
repositories {
mavenCentral()
// used to download and compile dependencies from git repos
maven { url 'https://jitpack.io' }
}
configurations {
shadowMe
compileOnly.extendsFrom(embed)
}
dependencies {
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
@@ -122,20 +156,27 @@ dependencies {
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
minecraft 'net.minecraftforge:forge:1.16.5-36.1.0'
// required to generate the mixin refmap
annotationProcessor 'org.spongepowered:mixin:0.8:processor'
// these were added to hopefully allow for cloning
// configuredFeatures to allow for safe
// multi threaded feature generation. Sadly I couldn't find
// a way to duplicate lambda functions (which features use)
// so for now I'm not sure what to do.
//implementation 'io.github.kostaskougios:cloning:1.10.3'
//
//implementation ('com.esotericsoftware:kryo:5.1.1') {
// exclude group: "org.objenesis"
//}
//implementation 'org.objenesis:objenesis:3.2'
implementation 'org.tukaani:xz:1.9'
shadowMe 'org.tukaani:xz:1.9'
implementation 'org.apache.commons:commons-compress:1.21'
shadowMe 'org.apache.commons:commons-compress:1.21'
// these were added to hopefully allow for cloning
// configuredFeatures to allow for safe
// multi threaded feature generation. Sadly I couldn't find
// a way to duplicate lambda functions (which features use)
// so for now I'm not sure what to do.
//implementation 'io.github.kostaskougios:cloning:1.10.3'
//
//implementation ('com.esotericsoftware:kryo:5.1.1') {
// exclude group: "org.objenesis"
//}
//implementation 'org.objenesis:objenesis:3.2'
// You may put jars on which you depend on in ./libs or you may define them like so..
// compile "some.group:artifact:version:classifier"
// compile "some.group:artifact:version"
@@ -153,26 +194,59 @@ dependencies {
// For more info...
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.html
}
task copyCoreResources(type: Copy) {
from file("core/src/main/resources/shaders")
into file("src/generated/resources/shaders")
}
task copyCoreResourcesAtRuntime(type: Copy) {
from file("core/src/main/resources/shaders")
into file("build/resources/main/shaders")
}
compileJava.dependsOn(copyCoreResources).dependsOn(copyCoreResourcesAtRuntime)
jar {
classifier 'withoutDependencies'
}
shadowJar {
duplicatesStrategy = DuplicatesStrategy.INCLUDE
configurations = [project.configurations.getByName("shadowMe")]
relocate 'org.tukaani', 'shaded.tukaani'
relocate 'org.apache.commons.compress', 'shaded.apache.commons.compress'
classifier ''
}
reobf {
shadowJar {
dependsOn tasks.createMcpToSrg
mappings = tasks.createMcpToSrg.outputs.files.singleFile
}
}
artifacts {
archives tasks.shadowJar
}
// Example for how to get properties into the manifest for reading by the runtime..
jar {
manifest {
attributes([
"Specification-Title": "Level of Detail",
"Specification-Title": "LOD",
"Specification-Version": "1", // We are version 1 of ourselves
"Implementation-Title": project.name,
"Implementation-Version": "{version}",
"Implementation-Version": "1",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
"MixinConfigs": "lod.mixins.json",
])
}
}
// Example configuration to allow publishing using the maven-publish task
// This is the preferred method to reobfuscate your jar file
jar.finalizedBy('reobfJar')
jar.finalizedBy('reobfJar')
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
//publish.dependsOn('reobfJar')
@@ -191,4 +265,6 @@ publishing {
mixin {
add sourceSets.main, "lod.refmap.json"
config "lod.mixins.json"
}
Submodule
+1
Submodule core added at 73c041e02f
+1 -1
View File
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
Binary file not shown.
-101
View File
@@ -1,101 +0,0 @@
/*
* This file is part of 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;
import org.lwjgl.opengl.GL;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.proxy.ClientProxy;
import com.seibel.lod.render.LodRenderer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DeferredWorkQueue;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
/**
* Initialize and setup the Mod.
* <br>
* If you are looking for the real start of the mod
* check out the ClientProxy.
*
* @author James Seibel
* @version 7-3-2021
*/
@Mod(ModInfo.MODID)
public class LodMain
{
public static LodMain instance;
public static ClientProxy client_proxy;
@SuppressWarnings("deprecation")
private void init(final FMLCommonSetupEvent event)
{
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, LodConfig.clientSpec);
Thread setFancyFog = new Thread(() ->
{
LodRenderer.fancyFogAvailable = GL.getCapabilities().GL_NV_fog_distance;
if (!LodRenderer.fancyFogAvailable)
{
ClientProxy.LOGGER.info("This GPU does not support GL_NV_fog_distance. This means that fancy fog options will not be available.");
}
});
// This will be run on the main thread when it is able.
// If it wasn't run on the main thread GL.getCapabilities()
// would fail.
DeferredWorkQueue.runLater(setFancyFog);
}
public LodMain()
{
// Register the methods
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::init);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientStart);
// Register ourselves for server and other game events we are interested in
MinecraftForge.EVENT_BUS.register(this);
}
private void onClientStart(final FMLClientSetupEvent event)
{
client_proxy = new ClientProxy();
MinecraftForge.EVENT_BUS.register(client_proxy);
}
@SubscribeEvent
public void onServerStarting(FMLServerStartingEvent event)
{
// this is called when the server starts
}
}
-32
View File
@@ -1,32 +0,0 @@
/*
* This file is part of 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;
/**
* This file is similar to mcmod.info
*
* @author James Seibel
* @version 05-31-2021
*/
public final class ModInfo
{
public static final String MODID = "lod";
public static final String MODNAME = "Level of Detail";
public static final String MODAPI = "LodAPI";
public static final String VERSION = "a1.3";
}
@@ -1,437 +0,0 @@
/*
* This file is part of 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.builders;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import org.lwjgl.opengl.GL11;
import com.seibel.lod.builders.worldGeneration.LodChunkGenWorker;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.NearFarBuffer;
import com.seibel.lod.render.LodRenderer;
import com.seibel.lod.util.LodUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.biome.BiomeContainer;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.WorldWorkerManager;
/**
* This object is used to create NearFarBuffer objects.
*
* @author James Seibel
* @version 06-19-2021
*/
public class LodBufferBuilder
{
private Minecraft mc;
/** This holds the thread used to generate new LODs off the main thread. */
private ExecutorService genThread = Executors.newSingleThreadExecutor();
private LodChunkBuilder lodChunkBuilder;
/** The buffers that are used to create LODs using near fog */
public volatile BufferBuilder buildableNearBuffer;
/** The buffers that are used to create LODs using far fog */
public volatile BufferBuilder buildableFarBuffer;
/** if this is true the LOD buffers are currently being
* regenerated. */
public volatile boolean generatingBuffers = false;
/** if this is true new LOD buffers have been generated
* and are waiting to be swapped with the drawable buffers*/
private volatile boolean switchBuffers = false;
/** This keeps track of how many chunk generation requests are on going.
* This is to prevent chunks from being generated for a long time in an area
* the player is no longer in. */
public volatile AtomicInteger numberOfChunksWaitingToGenerate = new AtomicInteger(0);
/** how many chunks to generate outside of the player's
* view distance at one time. (or more specifically how
* many requests to make at one time).
* I multiply by 8 to make sure there is always a buffer of chunk requests,
* to make sure the CPU is always busy and we can generate LODs as quickly as
* possible. */
public int maxChunkGenRequests = LodConfig.CLIENT.numberOfWorldGenerationThreads.get() * 8;
public LodBufferBuilder(LodChunkBuilder newLodBuilder)
{
mc = Minecraft.getInstance();
lodChunkBuilder = newLodBuilder;
}
private BiomeContainer biomeContainer = null;
private LodDimension previousDimension = null;
/**
* Create a thread to asynchronously generate LOD buffers
* centered around the given camera X and Z.
* <br>
* This method will write to the drawableNearBuffers and drawableFarBuffers.
* <br>
* After the buildable buffers have been generated they must be
* swapped with the drawable buffers in the LodRenderer to be drawn.
*/
public void generateLodBuffersAsync(LodRenderer renderer, LodDimension lodDim,
double playerX, double playerZ, int numbChunksWide)
{
// only allow one generation process to happen at a time
if (generatingBuffers)
return;
if (buildableNearBuffer == null || buildableFarBuffer == null)
throw new IllegalStateException("generateLodBuffersAsync was called before the buildableNearBuffer and buildableFarBuffer were created.");
if (previousDimension != lodDim)
{
biomeContainer = LodUtil.getServerWorldFromDimension(lodDim.dimension).getChunk(0, 0, ChunkStatus.EMPTY).getBiomes();
previousDimension = lodDim;
}
generatingBuffers = true;
// this seemingly useless math is required,
// just using (int) playerX/Z doesn't work
int playerXChunkOffset = ((int) playerX / LodChunk.WIDTH) * LodChunk.WIDTH;
int playerZChunkOffset = ((int) playerZ / LodChunk.WIDTH) * LodChunk.WIDTH;
// this is where we will start drawing squares
// (exactly half the total width)
int startX = (-LodChunk.WIDTH * (numbChunksWide / 2)) + playerXChunkOffset;
int startZ = (-LodChunk.WIDTH * (numbChunksWide / 2)) + playerZChunkOffset;
Thread thread = new Thread(()->
{
// index of the chunk currently being added to the
// generation list
int chunkGenIndex = 0;
ChunkPos[] chunksToGen = new ChunkPos[maxChunkGenRequests];
// if we don't have a full number of chunks to generate in chunksToGen
// we can top it off from the reserve
ChunkPos[] chunksToGenReserve = new ChunkPos[maxChunkGenRequests];
int minChunkDist = Integer.MAX_VALUE;
ChunkPos playerChunkPos = new ChunkPos((int)playerX / LodChunk.WIDTH, (int)playerZ / LodChunk.WIDTH);
// generate our new buildable buffers
buildableNearBuffer.begin(GL11.GL_QUADS, LodRenderer.LOD_VERTEX_FORMAT);
buildableFarBuffer.begin(GL11.GL_QUADS, LodRenderer.LOD_VERTEX_FORMAT);
// x axis
for (int i = 0; i < numbChunksWide; i++)
{
// z axis
for (int j = 0; j < numbChunksWide; j++)
{
int chunkX = i + (startX / LodChunk.WIDTH);
int chunkZ = j + (startZ / LodChunk.WIDTH);
// skip any chunks that Minecraft is going to render
if(isCoordInCenterArea(i, j, (numbChunksWide / 2))
&& renderer.vanillaRenderedChunks.contains(new ChunkPos(chunkX, chunkZ)))
{
continue;
}
// set where this square will be drawn in the world
double xOffset = (LodChunk.WIDTH * i) + // offset by the number of LOD blocks
startX; // offset so the center LOD block is centered underneath the player
double yOffset = 0;
double zOffset = (LodChunk.WIDTH * j) + startZ;
LodChunk lod = lodDim.getLodFromCoordinates(chunkX, chunkZ);
if (lod == null || lod.isLodEmpty())
{
// generate a new chunk if no chunk currently exists
// and we aren't waiting on any other chunks to generate
if (lod == null && numberOfChunksWaitingToGenerate.get() < maxChunkGenRequests)
{
ChunkPos pos = new ChunkPos(chunkX, chunkZ);
// can be used for debugging
// if (chunksToGen == null)
// {
// chunkGenIndex = 0;
// chunksToGen = new ChunkPos[maxChunkGenRequests];
// }
//
// if (chunkGenIndex < maxChunkGenRequests)
// {
// chunksToGen[chunkGenIndex] = pos;
// chunkGenIndex++;
// }
// determine if this position is closer to the player
// than the previous
int newDistance = playerChunkPos.getChessboardDistance(pos);
// issue #40
// TODO optimize this code,
// using the purely optimized code above we can achieve close to
// 100% CPU utilization, this code generally achieves 40 - 50 %
// I'm sure there is a better data structure for this.
if (newDistance < minChunkDist)
{
// this chunk is closer, clear any previous
// positions and update the new minimum distance
minChunkDist = newDistance;
// move all the old chunks into the reserve
ChunkPos[] newReserve = new ChunkPos[maxChunkGenRequests];
int oldToGenIndex = 0;
int oldReserveIndex = 0;
for(int tmpIndex = 0; tmpIndex < newReserve.length; tmpIndex++)
{
// we don't check if the boundaries are good since
// the tmp array will always be the same length
// as chunksToGen and chunksToGenReserve
if (chunksToGen[oldToGenIndex] != null)
{
// add all the closest chunks...
newReserve[tmpIndex] = chunksToGen[oldToGenIndex];
oldToGenIndex++;
}
else if (chunksToGenReserve[oldReserveIndex] != null)
{
// ...then add all the previous reserve chunks
// (which are farther away)
newReserve[tmpIndex] = chunksToGenReserve[oldToGenIndex];
oldReserveIndex++;
}
else
{
// we have moved all the items from
// the old chunksToGen and reserve
break;
}
}
chunksToGenReserve = newReserve;
chunkGenIndex = 0;
chunksToGen = new ChunkPos[maxChunkGenRequests];
chunksToGen[chunkGenIndex] = pos;
chunkGenIndex++;
}
else if (newDistance <= minChunkDist)
{
// this chunk position is as close or closers than the
// minimum distance
if(chunkGenIndex < maxChunkGenRequests)
{
// we are still under the number of chunks to generate
// add this position to the list
chunksToGen[chunkGenIndex] = pos;
chunkGenIndex++;
}
}
}
// don't render this null chunk
continue;
}
BufferBuilder currentBuffer = null;
if (isCoordinateInNearFogArea(i, j, numbChunksWide / 2))
currentBuffer = buildableNearBuffer;
else
currentBuffer = buildableFarBuffer;
// get the desired LodTemplate and
// add this LOD to the buffer
LodConfig.CLIENT.lodTemplate.get().
template.addLodToBuffer(currentBuffer, lodDim, lod,
xOffset, yOffset, zOffset, renderer.debugging);
}
}
// TODO add a way for a server side mod to generate chunks requested here
if(mc.hasSingleplayerServer())
{
ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(lodDim.dimension);
// make sure we have as many chunks to generate as we are allowed
if (chunkGenIndex < maxChunkGenRequests)
{
for(int i = chunkGenIndex, j = 0; i < maxChunkGenRequests; i++, j++)
{
chunksToGen[i] = chunksToGenReserve[j];
}
}
// start chunk generation
for(ChunkPos chunkPos : chunksToGen)
{
if(chunkPos == null)
break;
// make sure we don't generate this chunk again
lodDim.addLod(new LodChunk(chunkPos));
numberOfChunksWaitingToGenerate.addAndGet(1);
LodChunkGenWorker genWorker = new LodChunkGenWorker(chunkPos, renderer, lodChunkBuilder, this, lodDim, serverWorld, biomeContainer);
WorldWorkerManager.addWorker(genWorker);
}
}
// finish the buffer building
buildableNearBuffer.end();
buildableFarBuffer.end();
// mark that the buildable buffers as ready to swap
generatingBuffers = false;
switchBuffers = true;
});
genThread.execute(thread);
return;
}
//====================//
// generation helpers //
//====================//
/**
* Returns if the given coordinate is in the loaded area of the world.
* @param centerCoordinate the center of the loaded world
*/
private boolean isCoordInCenterArea(int i, int j, int centerCoordinate)
{
return (i >= centerCoordinate - mc.options.renderDistance
&& i <= centerCoordinate + mc.options.renderDistance)
&&
(j >= centerCoordinate - mc.options.renderDistance
&& j <= centerCoordinate + mc.options.renderDistance);
}
/**
* Find the coordinates that are in the center half of the given
* 2D matrix, starting at (0,0) and going to (2 * lodRadius, 2 * lodRadius).
*/
private static boolean isCoordinateInNearFogArea(int chunkX, int chunkZ, int lodRadius)
{
int halfRadius = lodRadius / 2;
return (chunkX >= lodRadius - halfRadius
&& chunkX <= lodRadius + halfRadius)
&&
(chunkZ >= lodRadius - halfRadius
&& chunkZ <= lodRadius + halfRadius);
}
//===============================//
// BufferBuilder related methods //
//===============================//
/**
* Called from the LodRenderer to create the
* BufferBuilders at the right size.
*
* @param bufferMaxCapacity
*/
public void setupBuffers(int bufferMaxCapacity)
{
buildableNearBuffer = new BufferBuilder(bufferMaxCapacity);
buildableFarBuffer = new BufferBuilder(bufferMaxCapacity);
}
/**
* Swap the drawable and buildable buffers and return
* the old drawable buffers.
* @param drawableNearBuffer
* @param drawableFarBuffer
*/
public NearFarBuffer swapBuffers(BufferBuilder drawableNearBuffer, BufferBuilder drawableFarBuffer)
{
// swap the BufferBuilders
BufferBuilder tmp = buildableNearBuffer;
buildableNearBuffer = drawableNearBuffer;
drawableNearBuffer = tmp;
tmp = buildableFarBuffer;
buildableFarBuffer = drawableFarBuffer;
drawableFarBuffer = tmp;
// the buffers have been swapped
switchBuffers = false;
return new NearFarBuffer(drawableNearBuffer, drawableFarBuffer);
}
/**
* If this is true the buildable near and far
* buffers have been generated and are ready to be
* sent to the LodRenderer.
*/
public boolean newBuffersAvaliable()
{
return switchBuffers;
}
}
@@ -1,61 +0,0 @@
/*
* This file is part of 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.builders;
/**
* This is used to easily configure how LodChunks are generated.
* Generally this will only be used if we want to generate a
* LodChunk using a incomplete Chunk, otherwise the defaults
* work best for a fully generated chunk (IE has correct surface blocks).
*
* @author James Seibel
* @version 6-27-2021
*/
public class LodBuilderConfig
{
/** default false */
public boolean useHeightmap;
/** default false */
public boolean useBiomeColors;
/** default true */
public boolean useSolidBlocksInColorGen;
/** default settings for a normal chunk
* useHeightmap = false
* useBiomeColors = false
* useSolidBlocksInColorGen = true
*/
public LodBuilderConfig()
{
useHeightmap = false;
useBiomeColors = false;
useSolidBlocksInColorGen = true;
}
/**
* @param newUseHeightmap default = false
* @param newUseBiomeColors default = false
* @param newUseSolidBlocksInBiomeColor default = true
*/
public LodBuilderConfig(boolean newUseHeightmap, boolean newUseBiomeColors, boolean newUseSolidBlocksInBiomeColor)
{
useHeightmap = newUseHeightmap;
useBiomeColors = newUseBiomeColors;
useSolidBlocksInColorGen = newUseSolidBlocksInBiomeColor;
}
}
@@ -1,527 +0,0 @@
/*
* This file is part of 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.builders;
import java.awt.Color;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDataPoint;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.LodWorld;
import com.seibel.lod.util.LodUtil;
import net.minecraft.block.AbstractPlantBlock;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.BushBlock;
import net.minecraft.block.FlowingFluidBlock;
import net.minecraft.block.GrassBlock;
import net.minecraft.block.IGrowable;
import net.minecraft.block.LeavesBlock;
import net.minecraft.world.DimensionType;
import net.minecraft.world.IWorld;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.Heightmap;
/**
* This object is in charge of creating Lod
* related objects.
* (specifically: Lod World, Dimension, Region, and Chunk objects)
*
* @author James Seibel
* @version 6-27-2021
*/
public class LodChunkBuilder
{
private ExecutorService lodGenThreadPool = Executors.newSingleThreadExecutor();
/** Default size of any LOD regions we use */
public int regionWidth = 5;
public static final int CHUNK_DATA_WIDTH = LodChunk.WIDTH;
public static final int CHUNK_SECTION_HEIGHT = LodChunk.WIDTH;
public LodChunkBuilder()
{
}
public void generateLodChunkAsync(IChunk chunk, LodWorld lodWorld, IWorld world)
{
generateLodChunkAsync(chunk, new LodBuilderConfig(), lodWorld, world);
}
public void generateLodChunkAsync(IChunk chunk, LodBuilderConfig config, LodWorld lodWorld, IWorld world)
{
if (lodWorld == null || !lodWorld.getIsWorldLoaded())
return;
// don't try to create an LOD object
// if for some reason we aren't
// given a valid chunk object
if (chunk == null)
return;
Thread thread = new Thread(() ->
{
try
{
DimensionType dim = world.dimensionType();
LodChunk lod = generateLodFromChunk(chunk, config);
LodDimension lodDim;
if (lodWorld.getLodDimension(dim) == null)
{
lodDim = new LodDimension(dim, lodWorld, regionWidth);
lodWorld.addLodDimension(lodDim);
}
else
{
lodDim = lodWorld.getLodDimension(dim);
}
lodDim.addLod(lod);
}
catch(IllegalArgumentException | NullPointerException e)
{
// if the world changes while LODs are being generated
// they will throw errors as they try to access things that no longer
// exist.
}
});
lodGenThreadPool.execute(thread);
return;
}
/**
* Creates a LodChunk for a chunk in the given world.
*
* @throws IllegalArgumentException
* thrown if either the chunk or world is null.
*/
public LodChunk generateLodFromChunk(IChunk chunk) throws IllegalArgumentException
{
return generateLodFromChunk(chunk, new LodBuilderConfig());
}
/**
* Creates a LodChunk for a chunk in the given world.
*
* @throws IllegalArgumentException
* thrown if either the chunk or world is null.
*/
public LodChunk generateLodFromChunk(IChunk chunk, LodBuilderConfig config) throws IllegalArgumentException
{
if(chunk == null)
throw new IllegalArgumentException("generateLodFromChunk given a null chunk");
LodDetail detail = LodConfig.CLIENT.lodDetail.get();
LodDataPoint[][] dataPoints = new LodDataPoint[detail.dataPointLengthCount][detail.dataPointLengthCount];
for(int i = 0; i < detail.dataPointLengthCount * detail.dataPointLengthCount; i++)
{
int startX = detail.startX[i];
int startZ = detail.startZ[i];
int endX = detail.endX[i];
int endZ = detail.endZ[i];
Color color;
color = generateLodColorForArea(chunk, config, startX, startZ, endX, endZ);
short height;
short depth;
if (!config.useHeightmap)
{
height = determineHeightPointForArea(chunk.getSections(), startX, startZ, endX, endZ);
depth = determineBottomPointForArea(chunk.getSections(), startX, startZ, endX, endZ);
}
else
{
height = determineHeightPoint(chunk.getOrCreateHeightmapUnprimed(LodChunk.DEFAULT_HEIGHTMAP), startX, startZ, endX, endZ);
depth = 0;
}
int x = i / detail.dataPointLengthCount;
int z = i % detail.dataPointLengthCount;
dataPoints[x][z] = new LodDataPoint(height, depth, color);
}
return new LodChunk(chunk.getPos(), dataPoints, detail);
}
//=====================//
// constructor helpers //
//=====================//
/**
* Find the lowest valid point from the bottom.
* @param chunkSections
* @param startX
* @param startZ
* @param endX
* @param endZ
*/
private short determineBottomPointForArea(ChunkSection[] chunkSections,
int startX, int startZ, int endX, int endZ)
{
int numberOfBlocksRequired = ((endX-startX) * (endZ-startZ) / 2);
// search from the bottom up
for(int section = 0; section < CHUNK_DATA_WIDTH; section++)
{
for(int y = 0; y < CHUNK_SECTION_HEIGHT; y++)
{
int numberOfBlocksFound = 0;
for(int x = startX; x < endX; x++)
{
for(int z = startZ; z < endZ; z++)
{
if(isLayerValidLodPoint(chunkSections, section, y, x, z))
{
numberOfBlocksFound++;
if (numberOfBlocksFound >= numberOfBlocksRequired)
{
// we found
// enough blocks in this
// layer to count as an
// LOD point
return (short) (y + (section * CHUNK_SECTION_HEIGHT));
}
}
}
}
}
}
// we never found a valid LOD point
return -1;
}
/**
* Find the lowest valid point from the bottom.
*/
@SuppressWarnings("unused")
private short determineBottomPoint(Heightmap heightmap)
{
// the heightmap only shows how high the blocks go, it
// doesn't have any info about how low they go
return 0;
}
/**
* Find the highest valid point from the Top
* @param chunkSections
* @param startX
* @param startZ
* @param endX
* @param endZ
*/
private short determineHeightPointForArea(ChunkSection[] chunkSections,
int startX, int startZ, int endX, int endZ)
{
int numberOfBlocksRequired = ((endX-startX) * (endZ-startZ) / 2);
// search from the top down
for(int section = chunkSections.length - 1; section >= 0; section--)
{
for(int y = CHUNK_DATA_WIDTH - 1; y >= 0; y--)
{
int numberOfBlocksFound = 0;
for(int x = startX; x < endX; x++)
{
for(int z = startZ; z < endZ; z++)
{
if(isLayerValidLodPoint(chunkSections, section, y, x, z))
{
numberOfBlocksFound++;
if (numberOfBlocksFound >= numberOfBlocksRequired)
{
// we found
// enough blocks in this
// layer to count as an
// LOD point
return (short) (y + (section * CHUNK_SECTION_HEIGHT));
}
}
}
}
}
}
// we never found a valid LOD point
return -1;
}
/**
* Find the highest point from the Top
*/
private short determineHeightPoint(Heightmap heightmap,
int startX, int startZ, int endX, int endZ)
{
short highest = 0;
for(int x = startX; x < endX; x++)
{
for(int z = startZ; z < endZ; z++)
{
short newHeight = (short) heightmap.getFirstAvailable(x, z);
if (newHeight > highest)
highest = newHeight;
}
}
return highest;
}
/**
* Generate the color for the given chunk using biome
* water color, foliage color, and grass color.
*
* @param config_useSolidBlocksInColorGen <br>
* If true we look down from the top of the <br>
* chunk until we find a non-invisible block, and then use <br>
* its color. If false we generate the color immediately for <br>
* each x and z.
* @param config_useBiomeColors <br>
* If true use biome foliage, water, and grass colors, <br>
* otherwise only use the block's material color
*/
private Color generateLodColorForArea(IChunk chunk, LodBuilderConfig config, int startX, int startZ, int endX, int endZ)
{
ChunkSection[] chunkSections = chunk.getSections();
int numbOfBlocks = 0;
int red = 0;
int green = 0;
int blue = 0;
for(int x = startX; x < endX; x++)
{
for(int z = startZ; z < endZ; z++)
{
boolean foundBlock = false;
// go top down
for(int i = chunkSections.length - 1; !foundBlock && i >= 0; i--)
{
if( !foundBlock && (chunkSections[i] != null || !config.useSolidBlocksInColorGen))
{
for(int y = CHUNK_SECTION_HEIGHT - 1; !foundBlock && y >= 0; y--)
{
int colorInt = 0;
BlockState blockState = null;
if (chunkSections[i] != null)
{
blockState = chunkSections[i].getBlockState(x, y, z);
colorInt = blockState.materialColor.col;
}
if(colorInt == 0 && config.useSolidBlocksInColorGen)
{
// skip air or invisible blocks
continue;
}
if (config.useBiomeColors)
{
Biome biome = chunk.getBiomes().getNoiseBiome(x, y + i * chunkSections.length, z);
if (biome.getBiomeCategory() == Biome.Category.OCEAN ||
biome.getBiomeCategory() == Biome.Category.RIVER)
{
if (config.useSolidBlocksInColorGen &&
blockState != Blocks.WATER.defaultBlockState())
{
// non-water block
colorInt = getColorForBlock(x, z, blockState, biome);
}
else
{
// water block
colorInt = biome.getWaterColor();
}
}
else if (biome.getBiomeCategory() == Biome.Category.EXTREME_HILLS)
{
colorInt = Blocks.STONE.defaultMaterialColor().col;
}
else if (biome.getBiomeCategory() == Biome.Category.ICY)
{
colorInt = LodUtil.colorToInt(Color.WHITE);
}
else if (biome.getBiomeCategory() == Biome.Category.THEEND)
{
colorInt = Blocks.END_STONE.defaultBlockState().materialColor.col;
}
else if (config.useSolidBlocksInColorGen)
{
colorInt = getColorForBlock(x, z, blockState, biome);
}
else
{
colorInt = biome.getGrassColor(x, z);
}
}
else
{
Biome biome = chunk.getBiomes().getNoiseBiome(x, y + i * chunkSections.length, z);
colorInt = getColorForBlock(x,z, blockState, biome);
}
Color c = LodUtil.intToColor(colorInt);
red += c.getRed();
green += c.getGreen();
blue += c.getBlue();
numbOfBlocks++;
// we found a valid block, skip to the
// next x and z
foundBlock = true;
}
}
}
}
}
if(numbOfBlocks == 0)
numbOfBlocks = 1;
red /= numbOfBlocks;
green /= numbOfBlocks;
blue /= numbOfBlocks;
return new Color(red, green, blue);
}
/**
* Returns a color int for a given block.
*/
private int getColorForBlock(int x, int z, BlockState blockState, Biome biome)
{
int colorInt = 0;
if (blockState == Blocks.AIR.defaultBlockState())
{
colorInt = biome.getGrassColor(x, z);
}
else if (blockState.getBlock() instanceof LeavesBlock)
{
Color leafColor = LodUtil.intToColor(biome.getFoliageColor()).darker();
colorInt = LodUtil.colorToInt(leafColor);
}
else if (blockState.getBlock() instanceof GrassBlock ||
blockState.getBlock() instanceof AbstractPlantBlock ||
blockState.getBlock() instanceof BushBlock ||
blockState.getBlock() instanceof IGrowable)
{
colorInt = biome.getGrassColor(x, z);
}
else if (blockState.getBlock() instanceof FlowingFluidBlock)
{
colorInt = biome.getWaterColor();
}
else
{
colorInt = blockState.materialColor.col;
}
return colorInt;
}
/**
* Is the layer between the given X, Z, and dataIndex
* values a valid LOD point?
*/
private boolean isLayerValidLodPoint(
ChunkSection[] chunkSections,
int sectionIndex, int y,
int x, int z)
{
if(chunkSections[sectionIndex] == null)
{
// this section doesn't have any blocks,
// it is not a valid section
return false;
}
else
{
if(chunkSections[sectionIndex].getBlockState(x, y, z) != null &&
chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.AIR)
{
return true;
}
}
return false;
}
}
@@ -1,54 +0,0 @@
/*
* This file is part of 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.builders.lodTemplates;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import net.minecraft.client.renderer.BufferBuilder;
/**
* This is the abstract class used to create different
* BufferBuilders.
*
* @author James Seibel
* @version 06-16-2021
*/
public abstract class AbstractLodTemplate
{
public abstract void addLodToBuffer(BufferBuilder buffer,
LodDimension lodDim, LodChunk lod,
double xOffset, double yOffset, double zOffset,
boolean debugging);
/** add the given position and color to the buffer */
protected void addPosAndColor(BufferBuilder buffer,
double x, double y, double z,
int red, int green, int blue, int alpha)
{
buffer.vertex(x, y, z).color(red, green, blue, alpha).endVertex();
}
/** Returns in bytes how much buffer memory is required
* for one LOD object */
public abstract int getBufferMemoryForSingleLod(LodDetail detail);
}
@@ -1,191 +0,0 @@
/*
* This file is part of 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.builders.lodTemplates;
import java.awt.Color;
import com.seibel.lod.enums.ColorDirection;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.util.math.AxisAlignedBB;
/**
* Builds LODs as rectangular prisms.
*
* @author James Seibel
* @version 06-16-2021
*/
public class CubicLodTemplate extends AbstractLodTemplate
{
public CubicLodTemplate()
{
}
@Override
public void addLodToBuffer(BufferBuilder buffer,
LodDimension lodDim, LodChunk centerLod,
double xOffset, double yOffset, double zOffset,
boolean debugging)
{
AxisAlignedBB bbox;
// Add this LOD to the BufferBuilder
// using the quality setting set by the config
LodDetail detail = LodConfig.CLIENT.lodDetail.get();
int halfWidth = detail.dataPointWidth / 2;
for(int i = 0; i < detail.dataPointLengthCount * detail.dataPointLengthCount; i++)
{
int startX = detail.startX[i];
int startZ = detail.startZ[i];
int endX = detail.endX[i];
int endZ = detail.endZ[i];
// returns null if the lod is empty at the given location
bbox = generateBoundingBox(
centerLod.getAverageHeightOverArea(startX, startZ, endX, endZ),
centerLod.getAverageDepthOverArea(startX, startZ, endX, endZ),
detail.dataPointWidth,
xOffset - (halfWidth / 2) + detail.startX[i],
yOffset,
zOffset - (halfWidth / 2) + detail.startZ[i]);
if (bbox != null)
{
addBoundingBoxToBuffer(buffer, bbox, centerLod.getAverageColorOverArea(startX, startZ, endX, endZ, debugging));
}
}
}
private AxisAlignedBB generateBoundingBox(int height, int depth, int width, double xOffset, double yOffset, double zOffset)
{
// don't add an LOD if it is empty
if (height == -1 && depth == -1)
return null;
if (depth == height)
{
// if the top and bottom points are at the same height
// render this LOD as 1 block thick
height++;
}
return new AxisAlignedBB(0, depth, 0, width, height, width).move(xOffset, yOffset, zOffset);
}
private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, Color c)
{
// top (facing up)
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
// bottom (facing down)
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
// south (facing -Z)
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
// north (facing +Z)
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
// west (facing -X)
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
// east (facing +X)
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
}
@SuppressWarnings("unused")
private void addBoundingBoxToBuffer(BufferBuilder buffer, AxisAlignedBB bb, Color[] c)
{
// top (facing up)
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c[ColorDirection.TOP.value].getRed(), c[ColorDirection.TOP.value].getGreen(), c[ColorDirection.TOP.value].getBlue(), c[ColorDirection.TOP.value].getAlpha());
// bottom (facing down)
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c[ColorDirection.BOTTOM.value].getRed(), c[ColorDirection.BOTTOM.value].getGreen(), c[ColorDirection.BOTTOM.value].getBlue(), c[ColorDirection.BOTTOM.value].getAlpha());
// south (facing -Z)
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c[ColorDirection.SOUTH.value].getRed(), c[ColorDirection.SOUTH.value].getGreen(), c[ColorDirection.SOUTH.value].getBlue(), c[ColorDirection.SOUTH.value].getAlpha());
// north (facing +Z)
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.NORTH.value].getRed(), c[ColorDirection.NORTH.value].getGreen(), c[ColorDirection.NORTH.value].getBlue(), c[ColorDirection.NORTH.value].getAlpha());
// west (facing -X)
addPosAndColor(buffer, bb.minX, bb.minY, bb.minZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.minY, bb.maxZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.maxZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
addPosAndColor(buffer, bb.minX, bb.maxY, bb.minZ, c[ColorDirection.WEST.value].getRed(), c[ColorDirection.WEST.value].getGreen(), c[ColorDirection.WEST.value].getBlue(), c[ColorDirection.WEST.value].getAlpha());
// east (facing +X)
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.minZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.maxY, bb.maxZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.maxZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
addPosAndColor(buffer, bb.maxX, bb.minY, bb.minZ, c[ColorDirection.EAST.value].getRed(), c[ColorDirection.EAST.value].getGreen(), c[ColorDirection.EAST.value].getBlue(), c[ColorDirection.EAST.value].getAlpha());
}
@Override
public int getBufferMemoryForSingleLod(LodDetail detail)
{
// (sidesOnACube * pointsInASquare * (positionPoints + colorPoints))) * howManyPointsPerLodChunk
return (6 * 4 * (3 + 4)) * detail.dataPointLengthCount * detail.dataPointLengthCount;
}
}
@@ -1,51 +0,0 @@
/*
* This file is part of 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.builders.lodTemplates;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import net.minecraft.client.renderer.BufferBuilder;
/**
* TODO DynamicLodTemplate
* Chunks smoothly transition between
* each other, unless a neighboring chunk
* is at a significantly different height.
*
* @author James Seibel
* @version 06-16-2021
*/
public class DynamicLodTemplate extends AbstractLodTemplate
{
@Override
public void addLodToBuffer(BufferBuilder buffer,
LodDimension lodDim, LodChunk lod,
double xOffset, double yOffset, double zOffset,
boolean debugging)
{
System.err.println("DynamicLodTemplate not implemented!");
}
@Override
public int getBufferMemoryForSingleLod(LodDetail detail) {
// TODO Auto-generated method stub
return 0;
}
}
@@ -1,49 +0,0 @@
/*
* This file is part of 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.builders.lodTemplates;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import net.minecraft.client.renderer.BufferBuilder;
/**
* TODO #21 TriangularLodTemplate
* Builds each LOD chunk as a singular rectangular prism.
*
* @author James Seibel
* @version 06-16-2021
*/
public class TriangularLodTemplate extends AbstractLodTemplate
{
@Override
public void addLodToBuffer(BufferBuilder buffer,
LodDimension lodDim, LodChunk lod,
double xOffset, double yOffset, double zOffset,
boolean debugging)
{
System.err.println("DynamicLodTemplate not implemented!");
}
@Override
public int getBufferMemoryForSingleLod(LodDetail detail) {
// TODO Auto-generated method stub
return 0;
}
}
@@ -1,602 +0,0 @@
/*
* This file is part of 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.builders.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.builders.LodBufferBuilder;
import com.seibel.lod.builders.LodBuilderConfig;
import com.seibel.lod.builders.LodChunkBuilder;
import com.seibel.lod.enums.DistanceGenerationMode;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.LodRegion;
import com.seibel.lod.proxy.ClientProxy;
import com.seibel.lod.render.LodRenderer;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.util.WeightedList.Entry;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.palette.UpgradeData;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.biome.BiomeContainer;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.blockstateprovider.WeightedBlockStateProvider;
import net.minecraft.world.gen.feature.BlockClusterFeatureConfig;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.DecoratedFeatureConfig;
import net.minecraft.world.gen.feature.FeatureSpread;
import net.minecraft.world.gen.feature.FeatureSpreadConfig;
import net.minecraft.world.gen.feature.IceAndSnowFeature;
import net.minecraft.world.gen.feature.NoFeatureConfig;
import net.minecraft.world.gen.placement.ConfiguredPlacement;
import net.minecraft.world.gen.placement.DecoratedPlacementConfig;
import net.minecraft.world.gen.placement.IPlacementConfig;
import net.minecraft.world.gen.placement.NoiseDependant;
import net.minecraft.world.server.ServerChunkProvider;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.server.ServerWorldLightManager;
import net.minecraftforge.common.WorldWorkerManager.IWorker;
/**
* This is used to generate a LodChunk at a given ChunkPos.
*
* @author James Seibel
* @version 7-5-2021
*/
public class LodChunkGenWorker implements IWorker
{
public static final ExecutorService genThreads = Executors.newFixedThreadPool(LodConfig.CLIENT.numberOfWorldGenerationThreads.get());
private boolean threadStarted = false;
private LodChunkGenThread thread;
/** If a configured feature fails for whatever reason,
* add it to this list, this is to hopefully remove any
* features that could cause issues down the line. */
private static ConcurrentHashMap<Integer, ConfiguredFeature<?, ?>> configuredFeaturesToAvoid = new ConcurrentHashMap<>();
public LodChunkGenWorker(ChunkPos newPos, LodRenderer newLodRenderer,
LodChunkBuilder newLodBuilder, LodBufferBuilder newLodBufferBuilder,
LodDimension newLodDimension, ServerWorld newServerWorld,
BiomeContainer newBiomeContainer)
{
if (newServerWorld == null)
throw new IllegalArgumentException("LodChunkGenWorker must have a non-null ServerWorld");
thread = new LodChunkGenThread(newPos, newLodRenderer,
newLodBuilder, newLodBufferBuilder,
newLodDimension, newServerWorld);
}
@Override
public boolean doWork()
{
if (!threadStarted)
{
thread.lodBufferBuilder.numberOfChunksWaitingToGenerate.addAndGet(-1);
if (LodConfig.CLIENT.distanceGenerationMode.get() == DistanceGenerationMode.SERVER)
{
// if we are using SERVER generation that has to be done
// synchronously to prevent crashing and harmful
// interactions with the normal world generator
thread.run();
}
else
{
// Every other method can
// be done asynchronously
genThreads.execute(thread);
}
threadStarted = true;
// useful for debugging
// ClientProxy.LOGGER.info(thread.lodDim.getNumberOfLods());
}
return false;
}
@Override
public boolean hasWork()
{
return !threadStarted;
}
private class LodChunkGenThread implements Runnable
{
public final ServerWorld serverWorld;
public final LodDimension lodDim;
public final LodChunkBuilder lodChunkBuilder;
public final LodRenderer lodRenderer;
private LodBufferBuilder lodBufferBuilder;
private ChunkPos pos;
public LodChunkGenThread(ChunkPos newPos, LodRenderer newLodRenderer,
LodChunkBuilder newLodBuilder, LodBufferBuilder newLodBufferBuilder,
LodDimension newLodDimension, ServerWorld newServerWorld)
{
pos = newPos;
lodRenderer = newLodRenderer;
lodChunkBuilder = newLodBuilder;
lodBufferBuilder = newLodBufferBuilder;
lodDim = newLodDimension;
serverWorld = newServerWorld;
}
@Override
public void run()
{
// only generate LodChunks if they can
// be added to the current LodDimension
if (lodDim.regionIsInRange(pos.x / LodRegion.SIZE, pos.z / LodRegion.SIZE))
{
// long startTime = System.currentTimeMillis();
switch(LodConfig.CLIENT.distanceGenerationMode.get())
{
case BIOME_ONLY:
case BIOME_ONLY_SIMULATE_HEIGHT:
// fastest
generateUsingBiomesOnly();
break;
case SURFACE:
// faster
generateUsingSurface();
break;
case FEATURES:
// fast
generateUsingFeatures();
break;
case SERVER:
// very slow
generateWithServer();
break;
}
lodRenderer.regenerateLODsNextFrame();
// if (lodDim.getLodFromCoordinates(pos.x, pos.z) != null)
// ClientProxy.LOGGER.info(pos.x + " " + pos.z + " Success!");
// else
// ClientProxy.LOGGER.info(pos.x + " " + pos.z);
// long endTime = System.currentTimeMillis();
// System.out.println(endTime - startTime);
}// if in range
}// run
/**
* takes about 2-5 ms
*/
private void generateUsingBiomesOnly()
{
List<IChunk> chunkList = new LinkedList<>();
ChunkPrimer chunk = new ChunkPrimer(pos, UpgradeData.EMPTY);
chunkList.add(chunk);
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
ChunkGenerator chunkGen = chunkSource.generator;
// generate the terrain (this is thread safe)
ChunkStatus.EMPTY.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
// override the chunk status so we can run the next generator stage
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
ChunkStatus.BIOMES.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
// generate fake height data for this LOD
int seaLevel = serverWorld.getSeaLevel();
boolean simulateHeight = LodConfig.CLIENT.distanceGenerationMode.get() == 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, LodChunk.DEFAULT_HEIGHTMAP);
for(int x = 0; x < LodChunk.WIDTH && !inTheEnd; x++)
{
for(int z = 0; z < LodChunk.WIDTH && !inTheEnd; z++)
{
if (simulateHeight)
{
// TODO use the biomes around each block to smooth out the transition
// 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, seaLevel, z).getBiomeCategory())
{
case NETHER:
heightmap.setHeight(x, z, serverWorld.getHeight() / 2);
break;
case EXTREME_HILLS:
heightmap.setHeight(x, z, seaLevel + 30);
break;
case MESA:
heightmap.setHeight(x, z, seaLevel + 20);
break;
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(LodChunk.DEFAULT_HEIGHTMAP, heightmap.getRawData());
LodChunk lod;
if (!inTheEnd)
{
lod = lodChunkBuilder.generateLodFromChunk(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 really bad.
lod = new LodChunk(chunk.getPos().x, chunk.getPos().z);
}
lodDim.addLod(lod);
}
/**
* takes about 10 - 20 ms
*/
private void generateUsingSurface()
{
List<IChunk> chunkList = new LinkedList<>();
ChunkPrimer chunk = new ChunkPrimer(pos, UpgradeData.EMPTY);
chunkList.add(chunk);
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
ChunkGenerator chunkGen = chunkSource.generator;
// generate the terrain (this is thread safe)
ChunkStatus.EMPTY.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
// override the chunk status so we can run the next generator stage
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
ChunkStatus.BIOMES.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
ChunkStatus.NOISE.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
ChunkStatus.SURFACE.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
// this feature has proved to be thread safe
// so we will add it
IceAndSnowFeature snowFeature = new IceAndSnowFeature(NoFeatureConfig.CODEC);
snowFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition(), null);
LodChunk lod = lodChunkBuilder.generateLodFromChunk(chunk);
lodDim.addLod(lod);
}
/**
* takes about 15 - 20 ms
*
* Causes concurrentModification Exceptions,
* which could cause instability or world generation bugs
*/
private void generateUsingFeatures()
{
List<IChunk> chunkList = new LinkedList<>();
ChunkPrimer chunk = new ChunkPrimer(pos, UpgradeData.EMPTY);
chunkList.add(chunk);
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
ChunkGenerator chunkGen = chunkSource.generator;
// generate the terrain (this is thread safe)
ChunkStatus.EMPTY.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
// override the chunk status so we can run the next generator stage
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
ChunkStatus.BIOMES.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
ChunkStatus.NOISE.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
ChunkStatus.SURFACE.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
// get all the biomes in the chunk
HashSet<Biome> biomes = new HashSet<>();
for (int x = 0; x < LodChunk.WIDTH; x++)
{
for (int z = 0; z < LodChunk.WIDTH; z++)
{
Biome biome = chunk.getBiomes().getNoiseBiome(x, serverWorld.getSeaLevel(), z);
// 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.Category.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 = LodConfig.CLIENT.allowUnstableFeatureGeneration.get();
// 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(int featureStateToGenerate = 0; featureStateToGenerate < featuresForState.size(); featureStateToGenerate++)
{
for(Supplier<ConfiguredFeature<?, ?>> featureSupplier : featuresForState.get(featureStateToGenerate))
{
ConfiguredFeature<?, ?> configuredFeature = featureSupplier.get();
if (!allowUnstableFeatures &&
configuredFeaturesToAvoid.containsKey(configuredFeature.hashCode()))
continue;
try
{
configuredFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition());
}
catch(ConcurrentModificationException e)
{
// This will happen. I'm not sure what to do about it
// except pray that it doesn't effect 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)
configuredFeaturesToAvoid.put(configuredFeature.hashCode(), configuredFeature);
// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
}
catch(UnsupportedOperationException e)
{
// This will happen when the LodServerWorld
// isn't able to return something that a feature
// generator needs
if (!allowUnstableFeatures)
configuredFeaturesToAvoid.put(configuredFeature.hashCode(), configuredFeature);
// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
}
catch(Exception e)
{
// I'm not sure what happened, print to the log
System.out.println();
System.out.println();
e.printStackTrace();
System.out.println();
System.out.println();
if (!allowUnstableFeatures)
configuredFeaturesToAvoid.put(configuredFeature.hashCode(), configuredFeature);
// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
}
}
}
}
// generate a Lod like normal
LodChunk lod = lodChunkBuilder.generateLodFromChunk(chunk);
lodDim.addLod(lod);
}
/**
* on pre generated chunks 0 - 1 ms
* on un generated chunks 0 - 50 ms
* with the median seeming to hover around 15 - 30 ms
* and outliers in the 100 - 200 ms range
*
* Note this should not be multithreaded and does cause server/simulation lag
* (Higher lag for generating than loading)
*/
private void generateWithServer()
{
lodChunkBuilder.generateLodChunkAsync(serverWorld.getChunk(pos.x, pos.z, ChunkStatus.FEATURES), ClientProxy.getLodWorld(), serverWorld);
}
//================//
// Unused methods //
//================//
// Sadly I wasn't able to get these to work,
// they are here for documentation purposes
@SuppressWarnings({ "rawtypes", "unchecked", "unused" })
private DecoratedFeatureConfig cloneDecoratedFeatureConfig(DecoratedFeatureConfig config)
{
IPlacementConfig placementConfig = null;
Class oldConfigClass = config.decorator.config().getClass();
if (oldConfigClass == FeatureSpreadConfig.class)
{
FeatureSpreadConfig oldPlacementConfig = (FeatureSpreadConfig) config.decorator.config();
FeatureSpread oldSpread = oldPlacementConfig.count();
placementConfig = new FeatureSpreadConfig(oldSpread);
}
else if(oldConfigClass == DecoratedPlacementConfig.class)
{
DecoratedPlacementConfig oldPlacementConfig = (DecoratedPlacementConfig) config.decorator.config();
placementConfig = new DecoratedPlacementConfig(oldPlacementConfig.inner(), oldPlacementConfig.outer());
}
else if(oldConfigClass == NoiseDependant.class)
{
NoiseDependant oldPlacementConfig = (NoiseDependant) config.decorator.config();
placementConfig = new NoiseDependant(oldPlacementConfig.noiseLevel, oldPlacementConfig.belowNoise, oldPlacementConfig.aboveNoise);
}
else
{
// ClientProxy.LOGGER.debug("unkown decorated placement config: \"" + config.decorator.config().getClass() + "\"");
return config;
}
ConfiguredPlacement<?> newPlacement = new ConfiguredPlacement(config.decorator.decorator, placementConfig);
return new DecoratedFeatureConfig(config.feature, newPlacement);
}
@SuppressWarnings("unused")
private BlockClusterFeatureConfig cloneBlockClusterFeatureConfig(BlockClusterFeatureConfig config)
{
WeightedBlockStateProvider provider = new WeightedBlockStateProvider();
for(Entry<BlockState> state : ((WeightedBlockStateProvider) config.stateProvider).weightedList.entries)
provider.weightedList.entries.add(state);
HashSet<Block> whitelist = new HashSet<>();
for(Block block : config.whitelist)
whitelist.add(block);
HashSet<BlockState> blacklist = new HashSet<>();
for(BlockState state : config.blacklist)
blacklist.add(state);
BlockClusterFeatureConfig.Builder builder = new BlockClusterFeatureConfig.Builder(provider, config.blockPlacer);
builder.whitelist(whitelist);
builder.blacklist(blacklist);
builder.xspread(config.xspread);
builder.yspread(config.yspread);
builder.zspread(config.zspread);
if(config.canReplace) { builder.canReplace(); }
if(config.needWater) { builder.needWater(); }
if(config.project) { builder.noProjection(); }
builder.tries(config.tries);
return builder.build();
}
}
/*
* 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 is needed to make biomes distinct)
Otherwise if snow/trees aren't necessary SURFACE is the next fastest (although not by much)
*/
}
@@ -1,51 +0,0 @@
/*
* This file is part of 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.enums;
/**
* TOP, NORTH, SOUTH, EAST, WEST, BOTTOM
*
* @author James Seibel
* @version 10-17-2020
*/
public enum ColorDirection
{
// used for colors
/** +Y */
TOP(0),
/** -Z */
NORTH(1),
/** +Z */
SOUTH(2),
/** +X */
EAST(3),
/** -X */
WEST(4),
/** -Y */
BOTTOM(5);
public final int value;
private ColorDirection(int newValue)
{
value = newValue;
}
}
@@ -1,68 +0,0 @@
/*
* This file is part of 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.enums;
/**
* BIOME_ONLY <br>
* BIOME_ONLY_SIMULATE_HEIGHT <br>
* SURFACE <br>
* FEATURES <br>
* SERVER <br><br>
*
* In order of fastest to slowest.
*
* @author James Seibel
* @version 6-27-2021
*/
public enum DistanceGenerationMode
{
/** Only generate the biomes and use biome
* grass/foliage color, water color, or ice color
* to generate the color.
* Doesn't generate height, everything is shown at sea level.
* Multithreaded - Fastest (2-5 ms) */
BIOME_ONLY,
/**
* Same as BIOME_ONLY, except instead
* of always using sea level as the LOD height
* different biome types (mountain, ocean, forest, etc.)
* use predetermined heights to simulate having height data.
*/
BIOME_ONLY_SIMULATE_HEIGHT,
/** Generate the world surface,
* this does NOT include caves, trees,
* or structures.
* Multithreaded - Faster (10-20 ms) */
SURFACE,
/** Generate everything except structures.
* NOTE: This may cause world generation bugs or instability,
* since some features cause concurrentModification exceptions.
* Multithreaded - Fast (15-20 ms) */
FEATURES,
/** Ask the server to generate/load each chunk.
* This is the most compatible, but causes server/simulation lag.
* This will also show player made structures if you
* are adding the mod to a pre-existing world.
* Singlethreaded - Slow (15-50 ms, with spikes up to 200 ms) */
SERVER;
}
@@ -1,36 +0,0 @@
/*
* This file is part of 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.enums;
/**
* NEAR, FAR, or NEAR_AND_FAR.
*
* @author James Seibel
* @version 02-14-2021
*/
public enum FogDistance
{
/** good for fast or fancy fog qualities. */
NEAR,
/** good for fast or fancy fog qualities. */
FAR,
/** only looks good if the fog quality is set to Fancy. */
NEAR_AND_FAR;
}
@@ -1,43 +0,0 @@
/*
* This file is part of 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.enums;
/**
* USE_OPTIFINE_FOG_SETTING, <br>
* NEVER_DRAW_FOG, <br>
* ALWAYS_DRAW_FOG_FAST, <br>
* ALWAYS_DRAW_FOG_FANCY <br>
*
* @author James Seibel
* @version 7-03-2021
*/
public enum FogDrawOverride
{
/** Use whatever Fog setting optifine is using.
* If optifine isn't installed this defaults to ALWAYS_DRAW_FOG. */
USE_OPTIFINE_FOG_SETTING,
/** Never draw fog on the LODs */
NEVER_DRAW_FOG,
/** Always draw fog on the LODs */
ALWAYS_DRAW_FOG_FAST,
/** Always draw fog on the LODs */
ALWAYS_DRAW_FOG_FANCY;
}
@@ -1,31 +0,0 @@
/*
* This file is part of 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.enums;
/**
* fast, fancy, or off
*
* @author James Seibel
* @version 02-14-2021
*/
public enum FogQuality
{
FAST,
FANCY,
OFF;
}
@@ -1,43 +0,0 @@
/*
* This file is part of 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.enums;
/**
* NE, SE, SW, NW
*
* @author James Seibel
* @version 1-20-2020
*/
public enum LodCorner
{
/** -Z, +X */
NE(0),
/** +Z, +X */
SE(1),
/** +Z, -X */
SW(2),
/** -Z, -X */
NW(3);
public final int value;
private LodCorner(int newValue)
{
value = newValue;
}
}
@@ -1,114 +0,0 @@
/*
* This file is part of 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.enums;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDataPoint;
/**
* single, double, quad, half, full
*
* @author James Seibel
* @version 06-13-2021
*/
public enum LodDetail
{
/** render 1 LOD for each chunk */
SINGLE(1),
/** render 4 LODs for each chunk */
DOUBLE(2),
/** render 16 LODs for each chunk */
QUAD(4),
/** render 64 LODs for each chunk */
HALF(8),
/** render 256 LODs for each chunk */
FULL(16);
/** How many DataPoints should
* be drawn per side per LodChunk */
public final int dataPointLengthCount;
/** How wide each LOD DataPoint is */
public final int dataPointWidth;
/* Start/End X/Z give the block positions
* for each individual dataPoint in a LodChunk */
public final int[] startX;
public final int[] startZ;
public final int[] endX;
public final int[] endZ;
/** This is how many pieces of data should be expected
* when creating a LodChunk with this detail level */
public final int lodChunkStringDelimiterCount;
private LodDetail(int newLengthCount)
{
dataPointLengthCount = newLengthCount;
dataPointWidth = 16 / dataPointLengthCount;
if(newLengthCount == LodChunk.WIDTH)
{
// this is to prevent overflow
newLengthCount = LodChunk.WIDTH - 1;
}
startX = new int[dataPointLengthCount * dataPointLengthCount];
endX = new int[dataPointLengthCount * dataPointLengthCount];
startZ = new int[dataPointLengthCount * dataPointLengthCount];
endZ = new int[dataPointLengthCount * dataPointLengthCount];
int index = 0;
for(int x = 0; x < newLengthCount; x++)
{
for(int z = 0; z < newLengthCount; z++)
{
startX[index] = x * dataPointWidth;
startZ[index] = z * dataPointWidth;
// special case for FULL
if(dataPointWidth != 1)
{
endX[index] = (x*dataPointWidth) + dataPointWidth - 1;
endZ[index] = (z*dataPointWidth) + dataPointWidth - 1;
}
else
{
endX[index] = (x*dataPointWidth) + dataPointWidth;
endZ[index] = (z*dataPointWidth) + dataPointWidth;
}
index++;
}
}
lodChunkStringDelimiterCount = 2 + (dataPointLengthCount * dataPointLengthCount * LodDataPoint.NUMBER_OF_DELIMITERS);
}// constructor
}
@@ -1,61 +0,0 @@
/*
* This file is part of 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.enums;
import com.seibel.lod.builders.lodTemplates.AbstractLodTemplate;
import com.seibel.lod.builders.lodTemplates.CubicLodTemplate;
import com.seibel.lod.builders.lodTemplates.DynamicLodTemplate;
import com.seibel.lod.builders.lodTemplates.TriangularLodTemplate;
/**
* Cubic, Triangular, Dynamic
*
* @author James Seibel
* @version 06-16-2021
*/
public enum LodTemplate
{
// used for position
/** Chunks are rendered as
* rectangular prisms. */
CUBIC(new CubicLodTemplate()),
/** Chunks smoothly transition between
* each other. */
TRIANGULAR(new TriangularLodTemplate()),
/** Chunks smoothly transition between
* each other, unless a neighboring chunk
* is at a significantly different height. */
DYNAMIC(new DynamicLodTemplate());
public final AbstractLodTemplate template;
private LodTemplate(AbstractLodTemplate newTemplate)
{
template = newTemplate;
}
public int getBufferMemoryForSingleLod(LodDetail detail)
{
return template.getBufferMemoryForSingleLod(detail);
}
}
@@ -1,86 +0,0 @@
/*
* This file is part of 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.enums;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.EnumSet;
/**
* NE, SE, SW, NW <br>
* NORTH, SOUTH, EAST, WEST, <br>
* CENTER
*
* @author James Seibel
* @version 05-30-2021
*/
public enum RelativeChunkPos
{
/** +X, -Z */
NE(0, 1,-1),
/** +X, +Z */
SE(1, 1,1),
/** -X, +Z */
SW(2, -1,1),
/** -X, -Z */
NW(3, -1,-1),
/** -Z */
NORTH(4, 0,-1),
/** +Z */
SOUTH(5, 0,1),
/** +X */
EAST(6, 1,0),
/** -X */
WEST(7, -1,0),
CENTER(8, 0,0);
/** index used when referencing objects in an array */
public final int index;
/** position relative to X CENTER */
public final int x;
/** position relative to Z CENTER */
public final int z;
/** NORTH, SOUTH, EAST, WEST */
public static EnumSet<RelativeChunkPos> ADJACENT = EnumSet.of(NORTH, SOUTH, EAST, WEST);
/** NE, NW, SE, SW */
public static EnumSet<RelativeChunkPos> DIAGONAL = EnumSet.of(NE, NW, SE, SW);
public static EnumSet<RelativeChunkPos> NW_CORNER = EnumSet.of(WEST, NW, NORTH);
public static EnumSet<RelativeChunkPos> NE_CORNER = EnumSet.of(EAST, NE, NORTH);
public static EnumSet<RelativeChunkPos> SW_CORNER = EnumSet.of(WEST, SW, SOUTH);
public static EnumSet<RelativeChunkPos> SE_CORNER = EnumSet.of(EAST, SE, SOUTH);
/** NW_CORNER, NE_CORNER, SW_CORNER, SE_CORNER <br>
* Contains the 3 points surrounding a corner. */
public static ArrayList<EnumSet<RelativeChunkPos>> CORNERS = new ArrayList<EnumSet<RelativeChunkPos>>( Arrays.asList(NW_CORNER, NE_CORNER, SW_CORNER, SE_CORNER) );
private RelativeChunkPos(int newIndex, int newX, int newZ)
{
index = newIndex;
x = newX;
z = newZ;
}
}
@@ -0,0 +1,105 @@
/*
* 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.forge;
import com.seibel.lod.core.api.EventApi;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.forge.wrappers.world.DimensionTypeWrapper;
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
/**
* This handles all events sent to the client,
* and is the starting point for most of the mod.
*
* @author James_Seibel
* @version 11-12-2021
*/
public class ForgeClientProxy
{
private final EventApi eventApi = EventApi.INSTANCE;
@SubscribeEvent
public void serverTickEvent(TickEvent.ServerTickEvent event)
{
eventApi.serverTickEvent();
}
@SubscribeEvent
public void chunkLoadEvent(ChunkEvent.Load event)
{
eventApi.chunkLoadEvent(new ChunkWrapper(event.getChunk()), DimensionTypeWrapper.getDimensionTypeWrapper(event.getWorld().dimensionType()));
}
@SubscribeEvent
public void worldSaveEvent(WorldEvent.Save event)
{
eventApi.worldSaveEvent();
}
/** This is also called when a new dimension loads */
@SubscribeEvent
public void worldLoadEvent(WorldEvent.Load event)
{
eventApi.worldLoadEvent(WorldWrapper.getWorldWrapper(event.getWorld()));
}
@SubscribeEvent
public void worldUnloadEvent(WorldEvent.Unload event)
{
eventApi.worldUnloadEvent();
}
@SubscribeEvent
public void blockChangeEvent(BlockEvent event)
{
// we only care about certain block events
if (event.getClass() == BlockEvent.BreakEvent.class ||
event.getClass() == BlockEvent.EntityPlaceEvent.class ||
event.getClass() == BlockEvent.EntityMultiPlaceEvent.class ||
event.getClass() == BlockEvent.FluidPlaceBlockEvent.class ||
event.getClass() == BlockEvent.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);
}
}
@SubscribeEvent
public void onKeyInput(InputEvent.KeyInputEvent event)
{
eventApi.onKeyInput(event.getKey(), event.getAction());
}
}
@@ -0,0 +1,444 @@
/*
* 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.forge;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.electronwill.nightconfig.core.io.WritingMode;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.enums.config.BlocksToAvoid;
import com.seibel.lod.core.enums.config.BufferRebuildTimes;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.enums.config.GenerationPriority;
import com.seibel.lod.core.enums.config.GpuUploadMethod;
import com.seibel.lod.core.enums.config.HorizontalQuality;
import com.seibel.lod.core.enums.config.HorizontalResolution;
import com.seibel.lod.core.enums.config.HorizontalScale;
import com.seibel.lod.core.enums.config.LodTemplate;
import com.seibel.lod.core.enums.config.VanillaOverdraw;
import com.seibel.lod.core.enums.config.VerticalQuality;
import com.seibel.lod.core.enums.rendering.DebugMode;
import com.seibel.lod.core.enums.rendering.FogColorMode;
import com.seibel.lod.core.enums.rendering.FogDistance;
import com.seibel.lod.core.enums.rendering.FogDrawMode;
import com.seibel.lod.core.objects.MinDefaultMax;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IBuffers;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IDebugging;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IThreading;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IAdvancedGraphics;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IFogQuality;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IQuality;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IWorldGenerator;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
/**
* This handles any configuration the user has access to.
* @author Leonardo Amato
* @author James Seibel
* @version 11-16-2021
*/
@Mod.EventBusSubscriber
public class ForgeConfig
{
// CONFIG STRUCTURE
// -> Client
// |
// |-> Graphics
// | |-> QualityOption
// | |-> FogQualityOption
// | |-> AdvancedGraphicsOption
// |
// |-> World Generation
// |
// |-> Advanced Mod Option
// |-> Threads
// |-> Buffers
// |-> Debugging
public static class Client
{
public final Graphics graphics;
public final WorldGenerator worldGenerator;
public final AdvancedModOptions advancedModOptions;
//================//
// Client Configs //
//================//
public Client(ForgeConfigSpec.Builder builder)
{
builder.push(this.getClass().getSimpleName());
{
graphics = new Graphics(builder);
worldGenerator = new WorldGenerator(builder);
advancedModOptions = new AdvancedModOptions(builder);
}
builder.pop();
}
//==================//
// Graphics Configs //
//==================//
public static class Graphics
{
public final QualityOption qualityOption;
public final FogQualityOption fogQuality;
public final AdvancedGraphicsOption advancedGraphicsOption;
Graphics(ForgeConfigSpec.Builder builder)
{
builder.comment(IGraphics.DESC).push("Graphics");
{
qualityOption = new QualityOption(builder);
advancedGraphicsOption = new AdvancedGraphicsOption(builder);
fogQuality = new FogQualityOption(builder);
}
builder.pop();
}
public static class QualityOption
{
public final ForgeConfigSpec.EnumValue<HorizontalResolution> drawResolution;
public final ForgeConfigSpec.IntValue lodChunkRenderDistance;
public final ForgeConfigSpec.EnumValue<VerticalQuality> verticalQuality;
public final ForgeConfigSpec.EnumValue<HorizontalScale> horizontalScale;
public final ForgeConfigSpec.EnumValue<HorizontalQuality> horizontalQuality;
QualityOption(ForgeConfigSpec.Builder builder)
{
builder.comment(IQuality.DESC).push(this.getClass().getSimpleName());
verticalQuality = builder
.comment("\n\n"
+ IQuality.VERTICAL_QUALITY_DESC)
.defineEnum("Vertical Quality", IQuality.VERTICAL_QUALITY_DEFAULT);
horizontalScale = builder
.comment("\n\n"
+ IQuality.HORIZONTAL_SCALE_DESC)
.defineEnum("Horizontal Scale", IQuality.HORIZONTAL_SCALE_DEFAULT);
horizontalQuality = builder
.comment("\n\n"
+ IQuality.HORIZONTAL_QUALITY_DESC)
.defineEnum("Horizontal Quality", IQuality.HORIZONTAL_QUALITY_DEFAULT);
drawResolution = builder
.comment("\n\n"
+ IQuality.DRAW_RESOLUTION_DESC)
.defineEnum("Block size", IQuality.DRAW_RESOLUTION_DEFAULT);
MinDefaultMax<Integer> minDefaultMax = IQuality.LOD_CHUNK_RENDER_DISTANCE_MIN_DEFAULT_MAX;
lodChunkRenderDistance = builder
.comment("\n\n"
+ IQuality.LOD_CHUNK_RENDER_DISTANCE_DESC)
.defineInRange("Lod Render Distance", minDefaultMax.defaultValue, minDefaultMax.minValue, minDefaultMax.maxValue);
builder.pop();
}
}
public static class FogQualityOption
{
public final ForgeConfigSpec.EnumValue<FogDistance> fogDistance;
public final ForgeConfigSpec.EnumValue<FogDrawMode> fogDrawMode;
public final ForgeConfigSpec.EnumValue<FogColorMode> fogColorMode;
public final ForgeConfigSpec.BooleanValue disableVanillaFog;
FogQualityOption(ForgeConfigSpec.Builder builder)
{
builder.comment(IFogQuality.DESC).push(this.getClass().getSimpleName());
fogDistance = builder
.comment("\n\n"
+ IFogQuality.FOG_DISTANCE_DESC)
.defineEnum("Fog Distance", IFogQuality.FOG_DISTANCE_DEFAULT);
fogDrawMode = builder
.comment("\n\n"
+ IFogQuality.FOG_DRAW_MODE_DESC)
.defineEnum("Fog Draw Mode", IFogQuality.FOG_DRAW_MODE_DEFAULT);
fogColorMode = builder
.comment("\n\n"
+ IFogQuality.FOG_COLOR_MODE_DESC)
.defineEnum("Fog Color Mode", IFogQuality.FOG_COLOR_MODE_DEFAULT);
disableVanillaFog = builder
.comment("\n\n"
+ IFogQuality.DISABLE_VANILLA_FOG_DESC)
.define("Experimental Disable Vanilla Fog", IFogQuality.DISABLE_VANILLA_FOG_DEFAULT);
builder.pop();
}
}
public static class AdvancedGraphicsOption
{
public final ForgeConfigSpec.EnumValue<LodTemplate> lodTemplate;
public final ForgeConfigSpec.BooleanValue disableDirectionalCulling;
public final ForgeConfigSpec.BooleanValue alwaysDrawAtMaxQuality;
public final ForgeConfigSpec.EnumValue<VanillaOverdraw> vanillaOverdraw;
public final ForgeConfigSpec.EnumValue<GpuUploadMethod> gpuUploadMethod;
public final ForgeConfigSpec.BooleanValue useExtendedNearClipPlane;
AdvancedGraphicsOption(ForgeConfigSpec.Builder builder)
{
builder.comment(IAdvancedGraphics.DESC).push(this.getClass().getSimpleName());
lodTemplate = builder
.comment("\n\n"
+ IAdvancedGraphics.LOD_TEMPLATE_DESC)
.defineEnum("LOD Template", IAdvancedGraphics.LOD_TEMPLATE_DEFAULT);
disableDirectionalCulling = builder
.comment("\n\n"
+ IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DESC)
.define("Disable Directional Culling", IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DEFAULT);
alwaysDrawAtMaxQuality = builder
.comment("\n\n"
+ IAdvancedGraphics.ALWAYS_DRAW_AT_MAD_QUALITY_DESC)
.define("Always Use Max Quality", IAdvancedGraphics.ALWAYS_DRAW_AT_MAD_QUALITY_DEFAULT);
vanillaOverdraw = builder
.comment("\n\n"
+ IAdvancedGraphics.VANILLA_OVERDRAW_DESC)
.defineEnum("Vanilla Overdraw", IAdvancedGraphics.VANILLA_OVERDRAW_DEFAULT);
gpuUploadMethod = builder
.comment("\n\n"
+ IAdvancedGraphics.GPU_UPLOAD_METHOD_DESC)
.defineEnum("GPU Upload Method", IAdvancedGraphics.GPU_UPLOAD_METHOD_DEFAULT);
// This is a temporary fix (like vanilla overdraw)
// hopefully we can remove both once we get individual chunk rendering figured out
useExtendedNearClipPlane = builder
.comment("\n\n"
+ IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DESC)
.define("Use Extended Near Clip Plane", IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DEFAULT);
builder.pop();
}
}
}
//========================//
// WorldGenerator Configs //
//========================//
public static class WorldGenerator
{
public final ForgeConfigSpec.EnumValue<GenerationPriority> generationPriority;
public final ForgeConfigSpec.EnumValue<DistanceGenerationMode> distanceGenerationMode;
public final ForgeConfigSpec.BooleanValue allowUnstableFeatureGeneration;
public final ForgeConfigSpec.EnumValue<BlocksToAvoid> blocksToAvoid;
//public final ForgeConfigSpec.BooleanValue useExperimentalPreGenLoading;
WorldGenerator(ForgeConfigSpec.Builder builder)
{
builder.comment(IWorldGenerator.DESC).push("Generation");
generationPriority = builder
.comment("\n\n"
+ IWorldGenerator.GENERATION_PRIORITY_DESC)
.defineEnum("Generation Priority", IWorldGenerator.GENERATION_PRIORITY_DEFAULT);
distanceGenerationMode = builder
.comment("\n\n"
+ IWorldGenerator.DISTANCE_GENERATION_MODE_DESC)
.defineEnum("Distance Generation Mode", IWorldGenerator.DISTANCE_GENERATION_MODE_DEFAULT);
allowUnstableFeatureGeneration = builder
.comment("\n\n"
+ IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DESC)
.define("Allow Unstable Feature Generation", IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT);
blocksToAvoid = builder
.comment("\n\n"
+ IWorldGenerator.BLOCKS_TO_AVOID_DESC)
.defineEnum("Blocks to avoid", IWorldGenerator.BLOCKS_TO_AVOID_DEFAULT);
/*useExperimentalPreGenLoading = builder
.comment("\n\n"
+ " if a chunk has been pre-generated, then the mod would use the real chunk for the \n"
+ "fake chunk creation. May require a deletion of the lod file to see the result. \n")
.define("Use pre-generated chunks", false);*/
builder.pop();
}
}
//============================//
// AdvancedModOptions Configs //
//============================//
public static class AdvancedModOptions
{
public final Threading threading;
public final Debugging debugging;
public final Buffers buffers;
public AdvancedModOptions(ForgeConfigSpec.Builder builder)
{
builder.comment(IAdvanced.DESC).push(this.getClass().getSimpleName());
{
threading = new Threading(builder);
debugging = new Debugging(builder);
buffers = new Buffers(builder);
}
builder.pop();
}
public static class Threading
{
public final ForgeConfigSpec.IntValue numberOfWorldGenerationThreads;
public final ForgeConfigSpec.IntValue numberOfBufferBuilderThreads;
Threading(ForgeConfigSpec.Builder builder)
{
builder.comment(IThreading.DESC).push(this.getClass().getSimpleName());
MinDefaultMax<Integer> minDefaultMax = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DEFAULT;
numberOfWorldGenerationThreads = builder
.comment("\n\n"
+ IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DESC)
.defineInRange("numberOfWorldGenerationThreads", minDefaultMax.defaultValue, minDefaultMax.minValue, minDefaultMax.maxValue);
minDefaultMax = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX;
numberOfBufferBuilderThreads = builder
.comment("\n\n"
+ IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX)
.defineInRange("numberOfBufferBuilderThreads", minDefaultMax.defaultValue, minDefaultMax.minValue, minDefaultMax.maxValue);
builder.pop();
}
}
//===============//
// Debug Options //
//===============//
public static class Debugging
{
public final ForgeConfigSpec.BooleanValue drawLods;
public final ForgeConfigSpec.EnumValue<DebugMode> debugMode;
public final ForgeConfigSpec.BooleanValue enableDebugKeybindings;
Debugging(ForgeConfigSpec.Builder builder)
{
builder.comment(IDebugging.DESC).push(this.getClass().getSimpleName());
drawLods = builder
.comment("\n\n"
+ IDebugging.DRAW_LODS_DESC)
.define("Enable Rendering", IDebugging.DRAW_LODS_DEFAULT);
debugMode = builder
.comment("\n\n"
+ IDebugging.DEBUG_MODE_DESC)
.defineEnum("Debug Mode", IDebugging.DEBUG_MODE_DEFAULT);
enableDebugKeybindings = builder
.comment("\n\n"
+ IDebugging.DEBUG_KEYBINDINGS_ENABLED_DESC)
.define("Enable Debug Keybinding", IDebugging.DEBUG_KEYBINDINGS_ENABLED_DEFAULT);
builder.pop();
}
}
public static class Buffers
{
public final ForgeConfigSpec.EnumValue<BufferRebuildTimes> rebuildTimes;
Buffers(ForgeConfigSpec.Builder builder)
{
builder.comment(IBuffers.DESC).push(this.getClass().getSimpleName());
rebuildTimes = builder
.comment("\n\n"
+ IBuffers.REBUILD_TIMES_DESC)
.defineEnum("rebuildFrequency", IBuffers.REBUILD_TIMES_DEFAULT);
builder.pop();
}
}
}
}
/** {@link Path} to the configuration file of this mod */
private static final Path CONFIG_PATH = Paths.get("config", ModInfo.NAME + ".toml");
public static final ForgeConfigSpec CLIENT_SPEC;
public static final Client CLIENT;
static
{
final Pair<Client, ForgeConfigSpec> specPair = new ForgeConfigSpec.Builder().configure(Client::new);
CLIENT_SPEC = specPair.getRight();
CLIENT = specPair.getLeft();
CommentedFileConfig clientConfig = CommentedFileConfig.builder(CONFIG_PATH)
.writingMode(WritingMode.REPLACE)
.build();
clientConfig.load();
clientConfig.save();
CLIENT_SPEC.setConfig(clientConfig);
}
@SubscribeEvent
public static void onLoad(final ModConfig.Loading configEvent)
{
LogManager.getLogger().debug(ModInfo.NAME, "Loaded forge config file {}", configEvent.getConfig().getFileName());
}
@SubscribeEvent
public static void onFileChange(final ModConfig.Reloading configEvent)
{
LogManager.getLogger().debug(ModInfo.NAME, "Forge config just got changed on the file system!");
}
}
@@ -0,0 +1,80 @@
/*
* 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.forge;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.forge.wrappers.ForgeDependencySetup;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
/**
* Initialize and setup the Mod. <br>
* If you are looking for the real start of the mod
* check out the ClientProxy.
*
* @author James Seibel
* @version 11-16-2021
*/
@Mod(ModInfo.ID)
public class ForgeMain
{
public static ForgeClientProxy forgeClientProxy;
private void init(final FMLCommonSetupEvent event)
{
// make sure the dependencies are set up before the mod needs them
ForgeDependencySetup.createInitialBindings();
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.CLIENT_SPEC);
}
public ForgeMain()
{
// Register the methods
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::init);
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientStart);
// Register ourselves for server and other game events we are interested in
MinecraftForge.EVENT_BUS.register(this);
}
private void onClientStart(final FMLClientSetupEvent event)
{
forgeClientProxy = new ForgeClientProxy();
MinecraftForge.EVENT_BUS.register(forgeClientProxy);
}
@SubscribeEvent
public void onServerStarting(FMLServerStartingEvent event)
{
// this is called when the server starts
}
}
@@ -1,5 +1,6 @@
/*
* This file is part of the LOD Mod, licensed under the GNU GPL v3 License.
* 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
*
@@ -15,16 +16,19 @@
* 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.mixin;
package com.seibel.lod.forge.mixins;
import org.lwjgl.opengl.GL15;
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.matrix.MatrixStack;
import com.seibel.lod.LodMain;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.forge.wrappers.McObjectConverter;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.WorldRenderer;
@@ -32,18 +36,19 @@ import net.minecraft.client.renderer.WorldRenderer;
/**
* This class is used to mix in my rendering code
* before Minecraft starts rendering blocks.
* If this wasn't done the LODs would render on top
* If this wasn't done, and we used Forge's
* render last event, the LODs would render on top
* of the normal terrain.
*
* @author James Seibel
* @version 05-29-2021
* @version 9-19-2021
*/
@Mixin(WorldRenderer.class)
public class MixinWorldRenderer
{
private static float previousPartialTicks = 0;
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V", cancellable = false)
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V")
private void renderSky(MatrixStack matrixStackIn, float partialTicks, CallbackInfo callback)
{
// get the partial ticks since renderBlockLayer doesn't
@@ -51,12 +56,24 @@ public class MixinWorldRenderer
previousPartialTicks = partialTicks;
}
@Inject(at = @At("HEAD"), method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/matrix/MatrixStack;DDD)V", cancellable = false)
@Inject(at = @At("HEAD"), method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/matrix/MatrixStack;DDD)V")
private void renderChunkLayer(RenderType renderType, MatrixStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
{
// only render if LODs are enabled and
// only render before solid blocks
if (LodConfig.CLIENT.drawLODs.get() && renderType.equals(RenderType.solid()))
LodMain.client_proxy.renderLods(previousPartialTicks);
if (renderType.equals(RenderType.solid()))
{
// get MC's current projection matrix
float[] mcProjMatrixRaw = new float[16];
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
// OpenGl outputs their matrices in col,row form instead of row,col
// (or maybe vice versa I have no idea :P)
mcProjectionMatrix.transpose();
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
}
}
}
@@ -0,0 +1,37 @@
package com.seibel.lod.forge.wrappers;
import com.seibel.lod.core.handlers.IReflectionHandler;
import com.seibel.lod.core.handlers.ReflectionHandler;
import com.seibel.lod.core.util.SingletonHandler;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import com.seibel.lod.forge.wrappers.block.BlockColorSingletonWrapper;
import com.seibel.lod.forge.wrappers.config.LodConfigWrapperSingleton;
import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.lod.forge.wrappers.minecraft.MinecraftWrapper;
/**
* Binds all necessary dependencies so we
* can access them in Core. <br>
* This needs to be called before any Core classes
* are loaded.
*
* @author James Seibel
* @version 11-20-2021
*/
public class ForgeDependencySetup
{
public static void createInitialBindings()
{
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);
SingletonHandler.bind(IBlockColorSingletonWrapper.class, BlockColorSingletonWrapper.INSTANCE);
SingletonHandler.bind(IMinecraftWrapper.class, MinecraftWrapper.INSTANCE);
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
SingletonHandler.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftWrapper.INSTANCE.getOptions()));
}
}
@@ -0,0 +1,56 @@
/*
* 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.forge.wrappers;
import java.nio.FloatBuffer;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.objects.math.Mat4f;
import net.minecraft.util.Direction;
import net.minecraft.util.math.vector.Matrix4f;
/**
* This class converts to and from Minecraft objects (Ex: Matrix4f)
* and objects we created (Ex: Mat4f).
*
* @author James Seibel
* @version 11-20-2021
*/
public class McObjectConverter
{
/** 4x4 float matrix converter */
public static Mat4f Convert(Matrix4f mcMatrix)
{
FloatBuffer buffer = FloatBuffer.allocate(16);
mcMatrix.store(buffer);
Mat4f matrix = new Mat4f(buffer);
matrix.transpose();
return matrix;
}
public static Direction Convert(LodDirection lodDirection)
{
return Direction.byName(lodDirection.name());
}
}
@@ -0,0 +1,91 @@
/*
* 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.forge.wrappers;
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
import com.seibel.lod.core.objects.lod.LodDimension;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.forge.wrappers.worldGeneration.WorldGeneratorWrapper;
/**
* This handles creating abstract wrapper objects.
*
* @author James Seibel
* @version 11-20-2021
*/
public class WrapperFactory implements IWrapperFactory
{
public static final WrapperFactory INSTANCE = new WrapperFactory();
@Override
public AbstractBlockPosWrapper createBlockPos()
{
return new BlockPosWrapper();
}
@Override
public AbstractBlockPosWrapper createBlockPos(int x, int y, int z)
{
return new BlockPosWrapper(x,y,z);
}
@Override
public AbstractChunkPosWrapper createChunkPos()
{
return new ChunkPosWrapper();
}
@Override
public AbstractChunkPosWrapper createChunkPos(int x, int z)
{
return new ChunkPosWrapper(x, z);
}
@Override
public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos)
{
return new ChunkPosWrapper(newChunkPos);
}
@Override
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos)
{
return new ChunkPosWrapper(blockPos);
}
@Override
public AbstractWorldGeneratorWrapper createWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
{
return new WorldGeneratorWrapper(newLodBuilder, newLodDimension, worldWrapper);
}
}
@@ -1,5 +1,6 @@
/*
* This file is part of the LOD Mod, licensed under the GNU GPL v3 License.
* 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
*
@@ -15,34 +16,20 @@
* 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.objects;
package com.seibel.lod.forge.wrappers;
import net.minecraft.world.gen.Heightmap;
/**
* This object is similar to ChunkPos or BlockPos.
* Stores any variables or code that
* may be shared between wrapper objects.
*
* @author James Seibel
* @version 03-19-2021
* @version 11-20-2021
*/
public class RegionPos
public class WrapperUtil
{
public int x;
public int z;
/**
* Default Constructor <br>
*
* Sets x and z to 0
*/
public RegionPos()
{
x = 0;
z = 0;
}
public RegionPos(int newX, int newZ)
{
x = newX;
z = newZ;
}
/** If we ever need to use a heightmap for any reason, use this one. */
public static final Heightmap.Type DEFAULT_HEIGHTMAP = Heightmap.Type.WORLD_SURFACE_WG;
}
@@ -0,0 +1,46 @@
/*
* 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.forge.wrappers.block;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import net.minecraft.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);
}
}
@@ -0,0 +1,332 @@
/*
* 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.forge.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.core.util.ColorUtil;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import com.seibel.lod.forge.wrappers.minecraft.MinecraftWrapper;
import net.minecraft.block.AbstractPlantBlock;
import net.minecraft.block.AbstractTopPlantBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.BushBlock;
import net.minecraft.block.FlowerBlock;
import net.minecraft.block.GrassBlock;
import net.minecraft.block.IGrowable;
import net.minecraft.block.LeavesBlock;
import net.minecraft.block.TallGrassBlock;
import net.minecraft.client.renderer.model.BakedQuad;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraftforge.client.model.data.ModelDataMap;
/**
* @author ??
* @version 11-17-2021
*/
public class BlockColorWrapper implements IBlockColorWrapper
{
//set of block which require tint
public static final ConcurrentMap<Block, BlockColorWrapper> blockColorWrapperMap = new ConcurrentHashMap<>();
public static final ModelDataMap dataMap = new ModelDataMap.Builder().build();
public static final BlockPos blockPos = new BlockPos(0, 0, 0);
public static final 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 final Block block;
private int color;
private boolean isColored;
private boolean toTint;
private boolean foliageTint;
private boolean grassTint;
private boolean waterTint;
/**Constructor only require for the block instance we are wrapping**/
public BlockColorWrapper(Block block)
{
this.block = block;
this.color = 0;
this.isColored = true;
this.toTint = false;
this.foliageTint = false;
this.grassTint = false;
this.waterTint = false;
setupColorAndTint();
/*StringBuilder s = new StringBuilder();
s.append(block + "\n"
+ Integer.toHexString(
Minecraft.getInstance().getBlockColors().createDefault().getColor(
block.defaultBlockState(),
(World) MinecraftWrapper.INSTANCE.getWrappedServerLevel().getLevel(),
blockPosWrapper.getBlockPos())) + "\n"
);
for(Property x : Minecraft.getInstance().getBlockColors().getColoringProperties(block))
s.append(x.getName() + " " + x.getPossibleValues() + '\n');
System.out.println(s);*/
//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 block object of the block to wrap
*/
public static IBlockColorWrapper getBlockColorWrapper(Block block)
{
//first we check if the block has already been wrapped
if (blockColorWrapperMap.containsKey(block) && blockColorWrapperMap.get(block) != null)
return blockColorWrapperMap.get(block);
//if it hasn't been created yet, we create it and save it in the map
BlockColorWrapper blockWrapper = new BlockColorWrapper(block);
blockColorWrapperMap.put(block, 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 = block.defaultBlockState();
BlockPosWrapper blockPosWrapper = new 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)
{
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
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)
{
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
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().getTexture(block.defaultBlockState(), mc.getClientWorld(), blockPosWrapper.getBlockPos());
}
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++)
{
// 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++)
{
tempColor = texture.getPixelRGBA(frameIndex, u, v);
if (ColorUtil.getAlpha(texture.getPixelRGBA(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.foliageTint = 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 IGrowable
|| block instanceof AbstractPlantBlock
|| block instanceof AbstractTopPlantBlock
|| 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 foliageTint;
}
@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,102 @@
/*
* 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.forge.wrappers.block;
import java.util.Objects;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import net.minecraft.util.math.BlockPos;
/**
* @author James Seibel
* @version 11-20-2021
*/
public class BlockPosWrapper extends AbstractBlockPosWrapper
{
private final BlockPos.Mutable blockPos;
public BlockPosWrapper()
{
this.blockPos = new BlockPos.Mutable(0, 0, 0);
}
public BlockPosWrapper(int x, int y, int z)
{
this.blockPos = new BlockPos.Mutable(x, y, z);
}
@Override
public void set(int x, int y, int z)
{
blockPos.set(x, y, z);
}
@Override
public int getX()
{
return blockPos.getX();
}
@Override
public int getY()
{
return blockPos.getY();
}
@Override
public int getZ()
{
return blockPos.getZ();
}
@Override
public int get(LodDirection.Axis axis)
{
return axis.choose(getX(), getY(), getZ());
}
public BlockPos.Mutable getBlockPos()
{
return blockPos;
}
@Override
public boolean equals(Object o)
{
return blockPos.equals(o);
}
@Override
public int hashCode()
{
return Objects.hash(blockPos);
}
@Override
public BlockPosWrapper offset(int x, int y, int z)
{
blockPos.set(blockPos.getX() + x, blockPos.getY() + y, blockPos.getZ() + z);
return this;
}
}
@@ -0,0 +1,179 @@
/*
* 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.forge.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.forge.wrappers.chunk.ChunkWrapper;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.block.SixWayBlock;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.IBlockReader;
/**
* @author ??
* @version 11-18-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 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) chunkWrapper, (BlockPosWrapper) 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, IChunkWrapper 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(ChunkWrapper chunkWrapper, BlockPosWrapper blockPosWrapper)
{
IBlockReader chunk = chunkWrapper.getChunk();
BlockPos blockPos = 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())
{
AxisAlignedBB 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)
|| block.equals(Blocks.VOID_AIR);
}
//-----------------//
//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,135 @@
/*
* 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.forge.wrappers.chunk;
import java.util.Objects;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
/**
* @author James Seibel
* @version 11-18-2021
*/
public class ChunkPosWrapper extends AbstractChunkPosWrapper
{
private final ChunkPos chunkPos;
public ChunkPosWrapper(ChunkPos newChunkPos)
{
this.chunkPos = newChunkPos;
}
public ChunkPosWrapper(BlockPos blockPos)
{
this.chunkPos = new ChunkPos(blockPos);
}
public ChunkPosWrapper(AbstractChunkPosWrapper newChunkPos)
{
this.chunkPos = ((ChunkPosWrapper) newChunkPos).chunkPos;
}
public ChunkPosWrapper(AbstractBlockPosWrapper blockPos)
{
this.chunkPos = new ChunkPos(((BlockPosWrapper) blockPos).getBlockPos());
}
public ChunkPosWrapper(int chunkX, int chunkZ)
{
this.chunkPos = new ChunkPos(chunkX, chunkZ);
}
public ChunkPosWrapper()
{
this.chunkPos = new ChunkPos(0, 0);
}
@Override
public int getX()
{
return chunkPos.x;
}
@Override
public int getZ()
{
return chunkPos.z;
}
@Override
public int getMinBlockX()
{
return chunkPos.getMinBlockX();
}
@Override
public int getMinBlockZ()
{
return chunkPos.getMinBlockZ();
}
@Override
public int getRegionX()
{
return chunkPos.getRegionX();
}
@Override
public int getRegionZ()
{
return chunkPos.getRegionZ();
}
public ChunkPos getChunkPos()
{
return chunkPos;
}
@Override
public boolean equals(Object o)
{
return chunkPos.equals(o);
}
@Override
public int hashCode()
{
return Objects.hash(chunkPos);
}
@Override
public BlockPosWrapper getWorldPosition()
{
BlockPos blockPos = chunkPos.getWorldPosition();
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
}
}
@@ -0,0 +1,125 @@
/*
* 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.forge.wrappers.chunk;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.lod.forge.wrappers.WrapperUtil;
import com.seibel.lod.forge.wrappers.block.BlockColorWrapper;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import com.seibel.lod.forge.wrappers.block.BlockShapeWrapper;
import com.seibel.lod.forge.wrappers.world.BiomeWrapper;
import net.minecraft.block.BlockState;
import net.minecraft.block.ILiquidContainer;
import net.minecraft.block.IWaterLoggable;
import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.world.chunk.IChunk;
/**
* @author ??
* @version 11-17-2021
*/
public class ChunkWrapper implements IChunkWrapper
{
private final IChunk chunk;
private final ChunkPosWrapper chunkPos;
@Override
public int getHeight()
{
return chunk.getMaxBuildHeight();
}
@Override
public boolean isPositionInWater(AbstractBlockPosWrapper blockPos)
{
BlockState blockState = chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos());
//This type of block is always in water
return ((blockState.getBlock() instanceof ILiquidContainer) && !(blockState.getBlock() instanceof IWaterLoggable))
|| (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED));
}
@Override
public int getHeightMapValue(int xRel, int zRel)
{
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
}
@Override
public BiomeWrapper getBiome(int xRel, int yAbs, int zRel)
{
return BiomeWrapper.getBiomeWrapper(chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2));
}
@Override
public IBlockColorWrapper getBlockColorWrapper(AbstractBlockPosWrapper blockPos)
{
return BlockColorWrapper.getBlockColorWrapper(chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos()).getBlock());
}
@Override
public IBlockShapeWrapper getBlockShapeWrapper(AbstractBlockPosWrapper blockPos)
{
return BlockShapeWrapper.getBlockShapeWrapper(chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos()).getBlock(), this, blockPos);
}
public ChunkWrapper(IChunk chunk)
{
this.chunk = chunk;
this.chunkPos = new ChunkPosWrapper(chunk.getPos());
}
public IChunk getChunk()
{
return chunk;
}
@Override
public ChunkPosWrapper getPos()
{
return chunkPos;
}
@Override
public boolean isLightCorrect()
{
return chunk.isLightCorrect();
}
@Override
public boolean isWaterLogged(AbstractBlockPosWrapper blockPos)
{
BlockState blockState = chunk.getBlockState(((BlockPosWrapper)blockPos).getBlockPos());
//This type of block is always in water
return ((blockState.getBlock() instanceof ILiquidContainer) && !(blockState.getBlock() instanceof IWaterLoggable))
|| (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED));
}
@Override
public int getEmittedBrightness(AbstractBlockPosWrapper blockPos)
{
return chunk.getLightEmission(((BlockPosWrapper)blockPos).getBlockPos());
}
}
@@ -0,0 +1,504 @@
/*
* 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.forge.wrappers.config;
import com.seibel.lod.core.enums.config.BlocksToAvoid;
import com.seibel.lod.core.enums.config.BufferRebuildTimes;
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
import com.seibel.lod.core.enums.config.GenerationPriority;
import com.seibel.lod.core.enums.config.GpuUploadMethod;
import com.seibel.lod.core.enums.config.HorizontalQuality;
import com.seibel.lod.core.enums.config.HorizontalResolution;
import com.seibel.lod.core.enums.config.HorizontalScale;
import com.seibel.lod.core.enums.config.LodTemplate;
import com.seibel.lod.core.enums.config.VanillaOverdraw;
import com.seibel.lod.core.enums.config.VerticalQuality;
import com.seibel.lod.core.enums.rendering.DebugMode;
import com.seibel.lod.core.enums.rendering.FogColorMode;
import com.seibel.lod.core.enums.rendering.FogDistance;
import com.seibel.lod.core.enums.rendering.FogDrawMode;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.forge.ForgeConfig;
/**
* @author James Seibel
* @version 11-16-2021
*/
public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
{
public static final LodConfigWrapperSingleton INSTANCE = new LodConfigWrapperSingleton();
private static final Client client = new Client();
@Override
public IClient client()
{
return client;
}
public static class Client implements IClient
{
public final IGraphics graphics;
public final IWorldGenerator worldGenerator;
public final IAdvanced advanced;
@Override
public IGraphics graphics()
{
return graphics;
}
@Override
public IWorldGenerator worldGenerator()
{
return worldGenerator;
}
@Override
public IAdvanced advanced()
{
return advanced;
}
//================//
// Client Configs //
//================//
public Client()
{
graphics = new Graphics();
worldGenerator = new WorldGenerator();
advanced = new Advanced();
}
//==================//
// Graphics Configs //
//==================//
public static class Graphics implements IGraphics
{
public final IQuality quality;
public final IFogQuality fogQuality;
public final IAdvancedGraphics advancedGraphics;
@Override
public IQuality quality()
{
return quality;
}
@Override
public IFogQuality fogQuality()
{
return fogQuality;
}
@Override
public IAdvancedGraphics advancedGraphics()
{
return advancedGraphics;
}
Graphics()
{
quality = new Quality();
advancedGraphics = new AdvancedGraphics();
fogQuality = new FogQuality();
}
public static class Quality implements IQuality
{
@Override
public HorizontalResolution getDrawResolution()
{
return ForgeConfig.CLIENT.graphics.qualityOption.drawResolution.get();
}
@Override
public void setDrawResolution(HorizontalResolution newHorizontalResolution)
{
ForgeConfig.CLIENT.graphics.qualityOption.drawResolution.set(newHorizontalResolution);
}
@Override
public int getLodChunkRenderDistance()
{
return ForgeConfig.CLIENT.graphics.qualityOption.lodChunkRenderDistance.get();
}
@Override
public void setLodChunkRenderDistance(int newLodChunkRenderDistance)
{
ForgeConfig.CLIENT.graphics.qualityOption.lodChunkRenderDistance.set(newLodChunkRenderDistance);
}
@Override
public VerticalQuality getVerticalQuality()
{
return ForgeConfig.CLIENT.graphics.qualityOption.verticalQuality.get();
}
@Override
public void setVerticalQuality(VerticalQuality newVerticalQuality)
{
ForgeConfig.CLIENT.graphics.qualityOption.verticalQuality.set(newVerticalQuality);
}
@Override
public HorizontalScale getHorizontalScale()
{
return ForgeConfig.CLIENT.graphics.qualityOption.horizontalScale.get();
}
@Override
public void setHorizontalScale(HorizontalScale newHorizontalScale)
{
ForgeConfig.CLIENT.graphics.qualityOption.horizontalScale.set(newHorizontalScale);
}
@Override
public HorizontalQuality getHorizontalQuality()
{
return ForgeConfig.CLIENT.graphics.qualityOption.horizontalQuality.get();
}
@Override
public void setHorizontalQuality(HorizontalQuality newHorizontalQuality)
{
ForgeConfig.CLIENT.graphics.qualityOption.horizontalQuality.set(newHorizontalQuality);
}
}
public static class FogQuality implements IFogQuality
{
@Override
public FogDistance getFogDistance()
{
return ForgeConfig.CLIENT.graphics.fogQuality.fogDistance.get();
}
@Override
public void setFogDistance(FogDistance newFogDistance)
{
ForgeConfig.CLIENT.graphics.fogQuality.fogDistance.set(newFogDistance);
}
@Override
public FogDrawMode getFogDrawMode()
{
return ForgeConfig.CLIENT.graphics.fogQuality.fogDrawMode.get();
}
@Override
public void setFogDrawMode(FogDrawMode newFogDrawMode)
{
ForgeConfig.CLIENT.graphics.fogQuality.fogDrawMode.set(newFogDrawMode);
}
@Override
public FogColorMode getFogColorMode()
{
return ForgeConfig.CLIENT.graphics.fogQuality.fogColorMode.get();
}
@Override
public void setFogColorMode(FogColorMode newFogColorMode)
{
ForgeConfig.CLIENT.graphics.fogQuality.fogColorMode.set(newFogColorMode);
}
@Override
public boolean getDisableVanillaFog()
{
return ForgeConfig.CLIENT.graphics.fogQuality.disableVanillaFog.get();
}
@Override
public void setDisableVanillaFog(boolean newDisableVanillaFog)
{
ForgeConfig.CLIENT.graphics.fogQuality.disableVanillaFog.set(newDisableVanillaFog);
}
}
public static class AdvancedGraphics implements IAdvancedGraphics
{
@Override
public LodTemplate getLodTemplate()
{
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.lodTemplate.get();
}
@Override
public void setLodTemplate(LodTemplate newLodTemplate)
{
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.lodTemplate.set(newLodTemplate);
}
@Override
public boolean getDisableDirectionalCulling()
{
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.disableDirectionalCulling.get();
}
@Override
public void setDisableDirectionalCulling(boolean newDisableDirectionalCulling)
{
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.disableDirectionalCulling.set(newDisableDirectionalCulling);
}
@Override
public boolean getAlwaysDrawAtMaxQuality()
{
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.alwaysDrawAtMaxQuality.get();
}
@Override
public void setAlwaysDrawAtMaxQuality(boolean newAlwaysDrawAtMaxQuality)
{
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.alwaysDrawAtMaxQuality.set(newAlwaysDrawAtMaxQuality);
}
@Override
public VanillaOverdraw getVanillaOverdraw()
{
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.vanillaOverdraw.get();
}
@Override
public void setVanillaOverdraw(VanillaOverdraw newVanillaOverdraw)
{
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.vanillaOverdraw.set(newVanillaOverdraw);
}
@Override
public GpuUploadMethod getGpuUploadMethod()
{
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.get();
}
@Override
public void setGpuUploadMethod(GpuUploadMethod newDisableVanillaFog)
{
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.gpuUploadMethod.set(newDisableVanillaFog);
}
@Override
public boolean getUseExtendedNearClipPlane()
{
return ForgeConfig.CLIENT.graphics.advancedGraphicsOption.useExtendedNearClipPlane.get();
}
@Override
public void setUseExtendedNearClipPlane(boolean newUseExtendedNearClipPlane)
{
ForgeConfig.CLIENT.graphics.advancedGraphicsOption.useExtendedNearClipPlane.set(newUseExtendedNearClipPlane);
}
}
}
//========================//
// WorldGenerator Configs //
//========================//
public static class WorldGenerator implements IWorldGenerator
{
@Override
public GenerationPriority getGenerationPriority()
{
return ForgeConfig.CLIENT.worldGenerator.generationPriority.get();
}
@Override
public void setGenerationPriority(GenerationPriority newGenerationPriority)
{
ForgeConfig.CLIENT.worldGenerator.generationPriority.set(newGenerationPriority);
}
@Override
public DistanceGenerationMode getDistanceGenerationMode()
{
return ForgeConfig.CLIENT.worldGenerator.distanceGenerationMode.get();
}
@Override
public void setDistanceGenerationMode(DistanceGenerationMode newDistanceGenerationMode)
{
ForgeConfig.CLIENT.worldGenerator.distanceGenerationMode.set(newDistanceGenerationMode);
}
@Override
public boolean getAllowUnstableFeatureGeneration()
{
return ForgeConfig.CLIENT.worldGenerator.allowUnstableFeatureGeneration.get();
}
@Override
public void setAllowUnstableFeatureGeneration(boolean newAllowUnstableFeatureGeneration)
{
ForgeConfig.CLIENT.worldGenerator.allowUnstableFeatureGeneration.set(newAllowUnstableFeatureGeneration);
}
@Override
public BlocksToAvoid getBlocksToAvoid()
{
return ForgeConfig.CLIENT.worldGenerator.blocksToAvoid.get();
}
@Override
public void setBlockToAvoid(BlocksToAvoid newBlockToAvoid)
{
ForgeConfig.CLIENT.worldGenerator.blocksToAvoid.set(newBlockToAvoid);
}
}
//============================//
// AdvancedModOptions Configs //
//============================//
public static class Advanced implements IAdvanced
{
public final IThreading threading;
public final IDebugging debugging;
public final IBuffers buffers;
@Override
public IThreading threading()
{
return threading;
}
@Override
public IDebugging debugging()
{
return debugging;
}
@Override
public IBuffers buffers()
{
return buffers;
}
public Advanced()
{
threading = new Threading();
debugging = new Debugging();
buffers = new Buffers();
}
public static class Threading implements IThreading
{
@Override
public int getNumberOfWorldGenerationThreads()
{
return ForgeConfig.CLIENT.advancedModOptions.threading.numberOfWorldGenerationThreads.get();
}
@Override
public void setNumberOfWorldGenerationThreads(int newNumberOfWorldGenerationThreads)
{
ForgeConfig.CLIENT.advancedModOptions.threading.numberOfWorldGenerationThreads.set(newNumberOfWorldGenerationThreads);
}
@Override
public int getNumberOfBufferBuilderThreads()
{
return ForgeConfig.CLIENT.advancedModOptions.threading.numberOfBufferBuilderThreads.get();
}
@Override
public void setNumberOfBufferBuilderThreads(int newNumberOfWorldBuilderThreads)
{
ForgeConfig.CLIENT.advancedModOptions.threading.numberOfBufferBuilderThreads.set(newNumberOfWorldBuilderThreads);
}
}
//===============//
// Debug Options //
//===============//
public static class Debugging implements IDebugging
{
@Override
public boolean getDrawLods()
{
return ForgeConfig.CLIENT.advancedModOptions.debugging.drawLods.get();
}
@Override
public void setDrawLods(boolean newDrawLods)
{
ForgeConfig.CLIENT.advancedModOptions.debugging.drawLods.set(newDrawLods);
}
@Override
public DebugMode getDebugMode()
{
return ForgeConfig.CLIENT.advancedModOptions.debugging.debugMode.get();
}
@Override
public void setDebugMode(DebugMode newDebugMode)
{
ForgeConfig.CLIENT.advancedModOptions.debugging.debugMode.set(newDebugMode);
}
@Override
public boolean getDebugKeybindingsEnabled()
{
return ForgeConfig.CLIENT.advancedModOptions.debugging.enableDebugKeybindings.get();
}
@Override
public void setDebugKeybindingsEnabled(boolean newEnableDebugKeybindings)
{
ForgeConfig.CLIENT.advancedModOptions.debugging.enableDebugKeybindings.set(newEnableDebugKeybindings);
}
}
public static class Buffers implements IBuffers
{
@Override
public BufferRebuildTimes getRebuildTimes()
{
return ForgeConfig.CLIENT.advancedModOptions.buffers.rebuildTimes.get();
}
@Override
public void setRebuildTimes(BufferRebuildTimes newBufferRebuildTimes)
{
ForgeConfig.CLIENT.advancedModOptions.buffers.rebuildTimes.set(newBufferRebuildTimes);
}
}
}
}
}
@@ -0,0 +1,165 @@
package com.seibel.lod.forge.wrappers.minecraft;
import java.awt.Color;
import java.util.HashSet;
import org.lwjgl.opengl.GL15;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.objects.math.Vec3d;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.lod.forge.wrappers.McObjectConverter;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
import net.minecraft.potion.Effects;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
/**
* A singleton that contains everything
* related to rendering in Minecraft.
*
* @author James Seibel
* @version 11-26-2021
*/
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
{
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
private final GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer;
private final static Minecraft mc = Minecraft.getInstance();
@Override
public Vec3f getLookAtVector()
{
ActiveRenderInfo camera = gameRenderer.getMainCamera();
Vector3f cameraDir = camera.getLookVector();
return new Vec3f(cameraDir.x(), cameraDir.y(), cameraDir.z());
}
@Override
public AbstractBlockPosWrapper getCameraBlockPosition()
{
ActiveRenderInfo camera = gameRenderer.getMainCamera();
BlockPos blockPos = camera.getBlockPosition();
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
}
@Override
public boolean playerHasBlindnessEffect()
{
return mc.player.getActiveEffectsMap().get(Effects.BLINDNESS) != null;
}
@Override
public Vec3d getCameraExactPosition()
{
ActiveRenderInfo camera = gameRenderer.getMainCamera();
Vector3d projectedView = camera.getPosition();
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
}
@Override
public Mat4f getDefaultProjectionMatrix(float partialTicks)
{
return McObjectConverter.Convert(gameRenderer.getProjectionMatrix(gameRenderer.getMainCamera(), partialTicks, true));
}
@Override
public double getGamma()
{
return mc.options.gamma;
}
@Override
public Color getFogColor()
{
float[] colorValues = new float[4];
GL15.glGetFloatv(GL15.GL_FOG_COLOR, colorValues);
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
}
@Override
public Color getSkyColor()
{
if (mc.level.dimensionType().hasSkyLight())
{
Vector3d colorValues = mc.level.getSkyColor(mc.gameRenderer.getMainCamera().getBlockPosition(), 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 gameRenderer.getFov(gameRenderer.getMainCamera(), partialTicks, true);
}
/** Measured in chunks */
@Override
public int getRenderDistance()
{
return mc.options.renderDistance;
}
@Override
public int getScreenWidth()
{
return mc.getWindow().getWidth();
}
@Override
public int getScreenHeight()
{
return mc.getWindow().getHeight();
}
/**
* This method returns the ChunkPos of all chunks that Minecraft
* is going to render this frame. <br><br>
* <p>
* Note: This isn't perfect. It will return some chunks that are outside
* 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!
// go through every RenderInfo to get the compiled chunks
WorldRenderer renderer = mc.levelRenderer;
for (WorldRenderer.LocalRenderInformationContainer 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;
}
}
@@ -0,0 +1,397 @@
/*
* 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.forge.wrappers.minecraft;
import java.awt.Color;
import java.io.File;
import java.util.ArrayList;
import com.seibel.lod.core.ModInfo;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.LodDirection;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.forge.wrappers.McObjectConverter;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.forge.wrappers.misc.LightMapWrapper;
import com.seibel.lod.forge.wrappers.world.DimensionTypeWrapper;
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
import net.minecraft.client.GameSettings;
import net.minecraft.client.MainWindow;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.client.network.play.ClientPlayNetHandler;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.model.ModelManager;
import net.minecraft.client.renderer.texture.NativeImage;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.crash.CrashReport;
import net.minecraft.entity.Entity;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.DimensionType;
import net.minecraft.world.server.ServerWorld;
import javax.annotation.Nullable;
/**
* A singleton that wraps the Minecraft class
* to allow for easier movement between Minecraft versions.
*
* @author James Seibel
* @version 9-16-2021
*/
public class MinecraftWrapper implements IMinecraftWrapper
{
public static final MinecraftWrapper INSTANCE = new MinecraftWrapper();
private final Minecraft mc = Minecraft.getInstance();
/**
* The lightmap for the current:
* Time, dimension, brightness setting, etc.
*/
private NativeImage lightMap = null;
private ProfilerWrapper profilerWrapper;
private MinecraftWrapper()
{
}
//================//
// helper methods //
//================//
/**
* This should be called at the beginning of every frame to
* clear any Minecraft data that becomes out of date after a frame. <br> <br>
* <p>
* LightMaps and other time sensitive objects fall in this category. <br> <br>
* <p>
* This doesn't affect OpenGL objects in any way.
*/
@Override
public void clearFrameObjectCache()
{
lightMap = null;
}
//=================//
// method wrappers //
//=================//
@Override
public float getShade(LodDirection lodDirection)
{
Direction mcDir = McObjectConverter.Convert(lodDirection);
return mc.level.getShade(mcDir, true);
}
@Override
public boolean hasSinglePlayerServer()
{
return mc.hasSingleplayerServer();
}
@Override
public String getCurrentServerName()
{
return mc.getCurrentServer().name;
}
@Override
public String getCurrentServerIp()
{
return mc.getCurrentServer().ip;
}
@Override
public String getCurrentServerVersion()
{
return mc.getCurrentServer().version.getString();
}
/** Returns the dimension the player is currently in */
@Override
public IDimensionTypeWrapper getCurrentDimension()
{
return DimensionTypeWrapper.getDimensionTypeWrapper(mc.player.level.dimensionType());
}
@Override
public String getCurrentDimensionId()
{
return LodUtil.getDimensionIDFromWorld(WorldWrapper.getWorldWrapper(mc.level));
}
/** This texture changes every frame */
@Override
public ILightMapWrapper getCurrentLightMap()
{
// get the current lightMap if the cache is empty
if (lightMap == null)
{
LightTexture tex = mc.gameRenderer.lightTexture();
lightMap = tex.lightPixels;
}
return new LightMapWrapper(lightMap);
}
/**
* Returns the color int at the given pixel coordinates
* from the current lightmap.
* @param u x location in texture space
* @param v z location in texture space
*/
@Override
public int getColorIntFromLightMap(int u, int v)
{
if (lightMap == null)
{
// make sure the lightMap is up-to-date
getCurrentLightMap();
}
return lightMap.getPixelRGBA(u, v);
}
/**
* Returns the Color at the given pixel coordinates
* from the current lightmap.
* @param u x location in texture space
* @param v z location in texture space
*/
@Override
public Color getColorFromLightMap(int u, int v)
{
return LodUtil.intToColor(lightMap.getPixelRGBA(u, v));
}
//=============//
// Simple gets //
//=============//
public ClientPlayerEntity getPlayer()
{
return mc.player;
}
@Override
public boolean playerExists()
{
return mc.player != null;
}
@Override
public BlockPosWrapper getPlayerBlockPos()
{
BlockPos playerPos = getPlayer().blockPosition();
return new BlockPosWrapper(playerPos.getX(), playerPos.getY(), playerPos.getZ());
}
@Override
public ChunkPosWrapper getPlayerChunkPos()
{
return new ChunkPosWrapper(getPlayer().xChunk, getPlayer().zChunk);
}
public GameSettings getOptions()
{
return mc.options;
}
public ModelManager getModelManager()
{
return mc.getModelManager();
}
public ClientWorld getClientWorld()
{
return mc.level;
}
/**
* Attempts to get the ServerWorld for the dimension
* the user is currently in.
* @returns null if no ServerWorld is available
*/
@Override
public IWorldWrapper getWrappedServerWorld()
{
if (mc.level == null)
return null;
DimensionType dimension = mc.level.dimensionType();
IntegratedServer server = mc.getSingleplayerServer();
if (server == null)
return null;
ServerWorld serverWorld = null;
Iterable<ServerWorld> worlds = server.getAllLevels();
for (ServerWorld world : worlds)
{
if (world.dimensionType() == dimension)
{
serverWorld = world;
break;
}
}
return WorldWrapper.getWorldWrapper(serverWorld);
}
@Nullable
@Override
public IWorldWrapper getWrappedClientWorld()
{
return WorldWrapper.getWorldWrapper(mc.level);
}
@Override
public File getGameDirectory()
{
return mc.gameDirectory;
}
@Override
public IProfilerWrapper getProfiler()
{
if (profilerWrapper == null)
profilerWrapper = new ProfilerWrapper(mc.getProfiler());
else if (mc.getProfiler() != profilerWrapper.profiler)
profilerWrapper.profiler = mc.getProfiler();
return profilerWrapper;
}
public ClientPlayNetHandler getConnection()
{
return mc.getConnection();
}
public GameRenderer getGameRenderer()
{
return mc.gameRenderer;
}
public Entity getCameraEntity()
{
return mc.cameraEntity;
}
public MainWindow getWindow()
{
return mc.getWindow();
}
@Override
public float getSkyDarken(float partialTicks)
{
return mc.level.getSkyDarken(partialTicks);
}
public IntegratedServer getSinglePlayerServer()
{
return mc.getSingleplayerServer();
}
@Override
public boolean connectedToServer()
{
return mc.getCurrentServer() != null;
}
public ServerData getCurrentServer()
{
return mc.getCurrentServer();
}
public WorldRenderer getLevelRenderer()
{
return mc.levelRenderer;
}
/** Returns all worlds available to the server */
@Override
public ArrayList<IWorldWrapper> getAllServerWorlds()
{
ArrayList<IWorldWrapper> worlds = new ArrayList<IWorldWrapper>();
Iterable<ServerWorld> serverWorlds = mc.getSingleplayerServer().getAllLevels();
for (ServerWorld world : serverWorlds)
{
worlds.add(WorldWrapper.getWorldWrapper(world));
}
return worlds;
}
@Override
public void sendChatMessage(String string)
{
getPlayer().sendMessage(new StringTextComponent(string), getPlayer().getUUID());
}
/**
* Crashes Minecraft, displaying the given errorMessage <br> <br>
* In the following format: <br>
*
* The game crashed whilst <strong>errorMessage</strong> <br>
* Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br>
* Exit Code: -1 <br>
*/
@Override
public void crashMinecraft(String errorMessage, Throwable exception)
{
ClientApi.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
CrashReport report = new CrashReport(errorMessage, exception);
Minecraft.crash(report);
}
}
@@ -0,0 +1,43 @@
package com.seibel.lod.forge.wrappers.minecraft;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import net.minecraft.profiler.IProfiler;
/**
*
*
* @author James Seibel
* @version 11-20-2021
*/
public class ProfilerWrapper implements IProfilerWrapper
{
public IProfiler profiler;
public ProfilerWrapper(IProfiler newProfiler)
{
profiler = newProfiler;
}
/** starts a new section inside the currently running section */
@Override
public void push(String newSection)
{
profiler.push(newSection);
}
/** ends the currently running section and starts a new one */
@Override
public void popPush(String newSection)
{
profiler.popPush(newSection);
}
/** ends the currently running section */
@Override
public void pop()
{
profiler.pop();
}
}
@@ -0,0 +1,31 @@
package com.seibel.lod.forge.wrappers.misc;
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
import net.minecraft.client.renderer.texture.NativeImage;
/**
*
* @author Leonardo Amato
* @version 11-13-2021
*/
public class LightMapWrapper implements ILightMapWrapper
{
private NativeImage lightMap = null;
public LightMapWrapper(NativeImage newlightMap)
{
lightMap = newlightMap;
}
public void setLightMap(NativeImage newlightMap)
{
lightMap = newlightMap;
}
@Override
public int getLightValue(int skyLight, int blockLight)
{
return lightMap.getPixelRGBA(skyLight, blockLight);
}
}
@@ -0,0 +1,60 @@
/*
* 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.forge.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.forge.wrappers.block.BlockPosWrapper;
import net.minecraft.world.biome.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());
}
}
@@ -0,0 +1,157 @@
package com.seibel.lod.forge.wrappers.world;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.util.ColorUtil;
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.lod.forge.wrappers.block.BlockColorSingletonWrapper;
import com.seibel.lod.forge.wrappers.block.BlockColorWrapper;
import net.minecraft.block.Blocks;
import net.minecraft.world.biome.Biome;
/**
* @author James Seibel
* @version 11-15-2021
*/
public class BiomeWrapper implements IBiomeWrapper
{
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
private final Biome biome;
public BiomeWrapper(Biome biome)
{
this.biome = biome;
}
static public BiomeWrapper getBiomeWrapper(Biome biome)
{
//first we check if the biome has already been wrapped
if(biomeWrapperMap.containsKey(biome) && biomeWrapperMap.get(biome) != null)
return biomeWrapperMap.get(biome);
//if it hasn't been created yet, we create it and save it in the map
BiomeWrapper biomeWrapper = new BiomeWrapper(biome);
biomeWrapperMap.put(biome, biomeWrapper);
//we return the newly created wrapper
return biomeWrapper;
}
/** Returns a color int for the given biome. */
@Override
public int getColorForBiome(int x, int z)
{
int colorInt;
int tintValue = 0;
switch (biome.getBiomeCategory())
{
case NETHER:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.NETHERRACK).getColor();
break;
case THEEND:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.END_STONE).getColor();
break;
case BEACH:
case DESERT:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.SAND).getColor();
break;
case EXTREME_HILLS:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.STONE).getColor();
break;
case MUSHROOM:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.MYCELIUM).getColor();
break;
case ICY:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.SNOW).getColor();
break;
case MESA:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.RED_SAND).getColor();
break;
case OCEAN:
case RIVER:
colorInt = BlockColorSingletonWrapper.INSTANCE.getWaterColor().getColor();
tintValue = biome.getWaterColor();
break;
case PLAINS:
case SAVANNA:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.GRASS_BLOCK).getColor();
tintValue = biome.getGrassColor(x, z);
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
break;
case TAIGA:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.SPRUCE_LEAVES).getColor();
tintValue = biome.getFoliageColor();
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
break;
case JUNGLE:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.JUNGLE_LEAVES).getColor();
tintValue = biome.getFoliageColor();
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
break;
case NONE:
default:
case SWAMP:
case FOREST:
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.OAK_LEAVES).getColor();
tintValue = biome.getFoliageColor();
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
break;
}
return colorInt;
}
@Override
public int getGrassTint(int x, int z)
{
return biome.getGrassColor(x, z);
}
@Override
public int getFolliageTint()
{
return biome.getFoliageColor();
}
@Override
public int getWaterTint()
{
return biome.getWaterColor();
}
@Override public boolean equals(Object o)
{
if (this == o)
return true;
if (!(o instanceof BiomeWrapper))
return false;
BiomeWrapper that = (BiomeWrapper) o;
return Objects.equals(biome, that.biome);
}
@Override public int hashCode()
{
return Objects.hash(biome);
}
}
@@ -0,0 +1,56 @@
package com.seibel.lod.forge.wrappers.world;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
import net.minecraft.world.DimensionType;
/**
* @author ??
* @version 11-15-2021
*/
public class DimensionTypeWrapper implements IDimensionTypeWrapper
{
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
private final DimensionType dimensionType;
public DimensionTypeWrapper(DimensionType dimensionType)
{
this.dimensionType = dimensionType;
}
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
{
//first we check if the biome has already been wrapped
if(dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null)
return dimensionTypeWrapperMap.get(dimensionType);
//if it hasn't been created yet, we create it and save it in the map
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
dimensionTypeWrapperMap.put(dimensionType, dimensionTypeWrapper);
//we return the newly created wrapper
return dimensionTypeWrapper;
}
@Override
public String getDimensionName()
{
return dimensionType.effectsLocation().getPath();
}
@Override
public boolean hasCeiling()
{
return dimensionType.hasCeiling();
}
@Override
public boolean hasSkyLight()
{
return dimensionType.hasSkyLight();
}
}
@@ -0,0 +1,155 @@
package com.seibel.lod.forge.wrappers.world;
import java.io.File;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import com.seibel.lod.core.enums.WorldType;
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.world.IWorld;
import net.minecraft.world.LightType;
import net.minecraft.world.server.ServerChunkProvider;
import net.minecraft.world.server.ServerWorld;
import javax.annotation.Nullable;
/**
* @author James Seibel
* @author ??
* @version 11-20-2021
*/
public class WorldWrapper implements IWorldWrapper
{
private static final ConcurrentMap<IWorld, WorldWrapper> worldWrapperMap = new ConcurrentHashMap<>();
private final IWorld world;
public final WorldType worldType;
public WorldWrapper(IWorld newWorld)
{
world = newWorld;
if (world.getClass() == ServerWorld.class)
worldType = WorldType.ServerWorld;
else if (world.getClass() == ClientWorld.class)
worldType = WorldType.ClientWorld;
else
worldType = WorldType.Unknown;
}
@Nullable
public static WorldWrapper getWorldWrapper(IWorld world)
{
if (world == null) return null;
//first we check if the biome has already been wrapped
if(worldWrapperMap.containsKey(world) && worldWrapperMap.get(world) != null)
return worldWrapperMap.get(world);
//if it hasn't been created yet, we create it and save it in the map
WorldWrapper worldWrapper = new WorldWrapper(world);
worldWrapperMap.put(world, worldWrapper);
//we return the newly created wrapper
return worldWrapper;
}
public static void clearMap()
{
worldWrapperMap.clear();
}
@Override
public WorldType getWorldType()
{
return worldType;
}
@Override
public DimensionTypeWrapper getDimensionType()
{
return DimensionTypeWrapper.getDimensionTypeWrapper(world.dimensionType());
}
@Override
public int getBlockLight(AbstractBlockPosWrapper blockPos)
{
return world.getBrightness(LightType.BLOCK, ((BlockPosWrapper) blockPos).getBlockPos());
}
@Override
public int getSkyLight(AbstractBlockPosWrapper blockPos)
{
return world.getBrightness(LightType.SKY, ((BlockPosWrapper) blockPos).getBlockPos());
}
@Override
public BiomeWrapper getBiome(AbstractBlockPosWrapper blockPos)
{
return BiomeWrapper.getBiomeWrapper(world.getBiome(((BlockPosWrapper) blockPos).getBlockPos()));
}
public IWorld getWorld()
{
return world;
}
@Override
public boolean hasCeiling()
{
return world.dimensionType().hasCeiling();
}
@Override
public boolean hasSkyLight()
{
return world.dimensionType().hasSkyLight();
}
@Override
public boolean isEmpty()
{
return world == null;
}
@Override
public int getHeight()
{
return world.getHeight();
}
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
@Override
public File getSaveFolder() throws UnsupportedOperationException
{
if (worldType != WorldType.ServerWorld)
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
ServerChunkProvider chunkSource = ((ServerWorld) world).getChunkSource();
return chunkSource.dataStorage.dataFolder;
}
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
public ServerWorld getServerWorld() throws UnsupportedOperationException
{
if (worldType != WorldType.ServerWorld)
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
return (ServerWorld) world;
}
@Override
public int getSeaLevel()
{
// TODO this is depreciated, what should we use instead?
return world.getSeaLevel();
}
}
@@ -1,5 +1,6 @@
/*
* This file is part of the LOD Mod, licensed under the GNU GPL v3 License.
* 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
*
@@ -15,7 +16,8 @@
* 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.builders.worldGeneration;
package com.seibel.lod.forge.wrappers.worldGeneration;
import java.util.HashMap;
import java.util.List;
@@ -23,7 +25,8 @@ import java.util.Random;
import java.util.function.Predicate;
import java.util.stream.Stream;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.forge.wrappers.WrapperUtil;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@@ -52,7 +55,6 @@ import net.minecraft.world.chunk.AbstractChunkProvider;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.Heightmap.Type;
import net.minecraft.world.gen.feature.structure.Structure;
import net.minecraft.world.gen.feature.structure.StructureStart;
import net.minecraft.world.lighting.WorldLightManager;
@@ -62,20 +64,21 @@ import net.minecraft.world.storage.IWorldInfo;
/**
* This is a fake ServerWorld used when generating features.
* This allows us to keep each LodChunk generation independent
* of the actual ServerWorld, allowing us
* to multithread generation.
* It allows us to keep each LodChunk generation independent
* of the actual ServerWorld, allowing
* multithread generation.
*
* @author James Seibel
* @version 7-4-2021
* @version 7-26-2021
*/
public class LodServerWorld implements ISeedReader {
public class LodServerWorld implements ISeedReader
{
public HashMap<Heightmap.Type, Heightmap> heightmaps = new HashMap<>();
public IChunk chunk;
public final IChunk chunk;
public ServerWorld serverWorld;
public final ServerWorld serverWorld;
public LodServerWorld(ServerWorld newServerWorld, IChunk newChunk)
{
@@ -84,24 +87,23 @@ public class LodServerWorld implements ISeedReader {
}
@Override
public int getHeight(Type heightmapType, int x, int z)
public int getHeight(Heightmap.Type heightmapType, int x, int z)
{
// make sure the block position is set relative to the chunk
x = x % LodChunk.WIDTH;
x = x % LodUtil.CHUNK_WIDTH;
x = (x < 0) ? x + 16 : x;
z = z % LodChunk.WIDTH;
z = z % LodUtil.CHUNK_WIDTH;
z = (z < 0) ? z + 16 : z;
return chunk.getOrCreateHeightmapUnprimed(LodChunk.DEFAULT_HEIGHTMAP).getFirstAvailable(x, z);
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(x, z);
}
@Override
public Biome getBiome(BlockPos pos)
{
return chunk.getBiomes().getNoiseBiome(pos.getX(), pos.getY(), pos.getZ());
return chunk.getBiomes().getNoiseBiome(pos.getX() >> 2, pos.getY() >> 2, pos.getZ() >> 2);
}
@Override
@@ -123,7 +125,6 @@ public class LodServerWorld implements ISeedReader {
}
@Override
public boolean isStateAtPosition(BlockPos pos, Predicate<BlockState> state)
{
@@ -160,161 +161,171 @@ public class LodServerWorld implements ISeedReader {
return new WorldLightManager(null, false, false);
}
@Override
public long getSeed()
{
return serverWorld.getSeed();
}
@Override
public DynamicRegistries registryAccess()
{
return serverWorld.registryAccess();
}
/**
*
* All methods below shouldn't be needed
* and thus have been left unimplemented.
*
* and thus have been left unimplemented.
*/
@Override
public Random getRandom() {
public Random getRandom()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public void playSound(PlayerEntity player, BlockPos pos, SoundEvent soundIn, SoundCategory category, float volume,
float pitch) {
float pitch)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public void addParticle(IParticleData particleData, double x, double y, double z, double xSpeed, double ySpeed,
double zSpeed) {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public DynamicRegistries registryAccess() {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public BiomeManager getBiomeManager() {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public int getSeaLevel() {
double zSpeed)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public float getShade(Direction p_230487_1_, boolean p_230487_2_) {
public BiomeManager getBiomeManager()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public WorldBorder getWorldBorder() {
public int getSeaLevel()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public boolean removeBlock(BlockPos pos, boolean isMoving) {
public float getShade(Direction p_230487_1_, boolean p_230487_2_)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public boolean destroyBlock(BlockPos pos, boolean dropBlock, Entity entity, int recursionLeft) {
public WorldBorder getWorldBorder()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public long getSeed() {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public ServerWorld getLevel() {
public boolean removeBlock(BlockPos pos, boolean isMoving)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public AbstractChunkProvider getChunkSource() {
public boolean destroyBlock(BlockPos pos, boolean dropBlock, Entity entity, int recursionLeft)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public DifficultyInstance getCurrentDifficultyAt(BlockPos arg0) {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public IWorldInfo getLevelData() {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public void levelEvent(PlayerEntity arg0, int arg1, BlockPos arg2, int arg3) {
public ServerWorld getLevel()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public AbstractChunkProvider getChunkSource()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public DifficultyInstance getCurrentDifficultyAt(BlockPos arg0)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public IWorldInfo getLevelData()
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public void levelEvent(PlayerEntity arg0, int arg1, BlockPos arg2, int arg3)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public List<Entity> getEntities(Entity arg0, AxisAlignedBB arg1, Predicate<? super Entity> arg2) {
public List<Entity> getEntities(Entity arg0, AxisAlignedBB arg1, Predicate<? super Entity> arg2)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public <T extends Entity> List<T> getEntitiesOfClass(Class<? extends T> arg0, AxisAlignedBB arg1,
Predicate<? super T> arg2) {
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public List<? extends PlayerEntity> 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() {
Predicate<? super T> arg2)
{
throw new UnsupportedOperationException("Not Implemented");
}
@Override
public TileEntity getBlockEntity(BlockPos p_175625_1_) {
public List<? extends PlayerEntity> 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 TileEntity getBlockEntity(BlockPos p_175625_1_)
{
throw new UnsupportedOperationException("Not Implemented");
}
@@ -0,0 +1,389 @@
package com.seibel.lod.forge.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.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.forge.wrappers.WrapperUtil;
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
import com.seibel.lod.forge.wrappers.chunk.ChunkWrapper;
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
import net.minecraft.util.palette.UpgradeData;
import net.minecraft.util.registry.Registry;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.chunk.ChunkPrimer;
import net.minecraft.world.chunk.ChunkStatus;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.gen.ChunkGenerator;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.feature.ConfiguredFeature;
import net.minecraft.world.gen.feature.IceAndSnowFeature;
import net.minecraft.world.gen.feature.NoFeatureConfig;
import net.minecraft.world.gen.feature.template.TemplateManager;
import net.minecraft.world.server.ServerChunkProvider;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.server.ServerWorldLightManager;
/**
* @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<>();
public final ServerWorld 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<IChunk> chunkList = new LinkedList<>();
ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
chunkList.add(chunk);
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
ChunkGenerator chunkGen = chunkSource.generator;
// generate the terrain (this is thread safe)
ChunkStatus.EMPTY.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) 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<IChunk> chunkList = new LinkedList<>();
ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
chunkList.add(chunk);
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
ServerWorldLightManager lightEngine = (ServerWorldLightManager) serverWorld.getLightEngine();
TemplateManager templateManager = serverWorld.getStructureManager();
ChunkGenerator chunkGen = chunkSource.generator;
// generate the terrain (this is thread safe)
ChunkStatus.EMPTY.generate(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(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
ChunkStatus.SURFACE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
// this feature has been proven to be thread safe,
// so we will add it
IceAndSnowFeature snowFeature = new IceAndSnowFeature(NoFeatureConfig.CODEC);
snowFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition(), null);
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<IChunk> chunkList = new LinkedList<>();
ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
chunkList.add(chunk);
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
ServerWorldLightManager lightEngine = (ServerWorldLightManager) serverWorld.getLightEngine();
TemplateManager templateManager = serverWorld.getStructureManager();
ChunkGenerator chunkGen = chunkSource.generator;
// generate the terrain (this is thread safe)
ChunkStatus.EMPTY.generate(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(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
ChunkStatus.SURFACE.generate(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.Category.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)
*/
}
@@ -1,258 +0,0 @@
/*
* This file is part of 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.handlers;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.logging.log4j.LogManager;
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
import com.electronwill.nightconfig.core.io.WritingMode;
import com.seibel.lod.ModInfo;
import com.seibel.lod.enums.DistanceGenerationMode;
import com.seibel.lod.enums.FogDistance;
import com.seibel.lod.enums.FogDrawOverride;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.enums.LodTemplate;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
/**
*
* @author James Seibel
* @version 7-5-2021
*/
@Mod.EventBusSubscriber
public class LodConfig
{
public static class Client
{
public ForgeConfigSpec.BooleanValue drawLODs;
public ForgeConfigSpec.EnumValue<FogDistance> fogDistance;
public ForgeConfigSpec.EnumValue<FogDrawOverride> fogDrawOverride;
public ForgeConfigSpec.BooleanValue debugMode;
public ForgeConfigSpec.EnumValue<LodTemplate> lodTemplate;
public ForgeConfigSpec.EnumValue<LodDetail> lodDetail;
public ForgeConfigSpec.EnumValue<DistanceGenerationMode> distanceGenerationMode;
public ForgeConfigSpec.BooleanValue allowUnstableFeatureGeneration;
public ForgeConfigSpec.IntValue numberOfWorldGenerationThreads;
/** this is multiplied by the default view distance
* to determine how far out to generate/render LODs */
public ForgeConfigSpec.IntValue lodChunkRadiusMultiplier;
Client(ForgeConfigSpec.Builder builder)
{
builder.comment(ModInfo.MODNAME + " configuration settings").push("client");
drawLODs = builder
.comment("\n\n"
+ " If false LODs will not be drawn, \n"
+ " however they will still be generated \n"
+ " and saved to file for later use. \n")
.define("drawLODs", true);
fogDistance = builder
.comment("\n\n"
+ " At what distance should Fog be drawn on the LODs? \n"
+ " If the fog cuts off ubruptly or you are using Optifine's \"fast\" \n"
+ " fog option set this to " + FogDistance.NEAR.toString() + " or " + FogDistance.FAR.toString() + ". \n")
.defineEnum("fogDistance", FogDistance.NEAR_AND_FAR);
fogDrawOverride = builder
.comment("\n\n"
+ " When should fog be drawn? \n"
+ " " + FogDrawOverride.USE_OPTIFINE_FOG_SETTING.toString() + ": Use whatever Fog setting Optifine is using. If Optifine isn't installed this defaults to " + FogDrawOverride.ALWAYS_DRAW_FOG_FANCY.toString() + ". \n"
+ " " + FogDrawOverride.NEVER_DRAW_FOG.toString() + ": Never draw fog on the LODs \n"
+ " " + FogDrawOverride.ALWAYS_DRAW_FOG_FAST.toString() + ": Always draw fast fog on the LODs \n"
+ " " + FogDrawOverride.ALWAYS_DRAW_FOG_FANCY.toString() + ": Always draw fancy fog on the LODs (if your graphics card supports it) \n")
.defineEnum("fogDrawOverride", FogDrawOverride.USE_OPTIFINE_FOG_SETTING);
debugMode = builder
.comment("\n\n"
+ " If false the LODs will draw with their normal world colors. \n"
+ " If true they will draw as a black and white checkerboard. \n"
+ " This can be used for debugging or imagining you are playing a \n"
+ " giant game of chess ;) \n")
.define("drawCheckerBoard", false);
lodTemplate = builder
.comment("\n\n"
+ " How should the LODs be drawn? \n"
+ " NOTE: Currently only " + LodTemplate.CUBIC.toString() + " is implemented! \n"
+ " \n"
+ " " + LodTemplate.CUBIC.toString() + ": LOD Chunks are drawn as rectangular prisms (boxes). \n"
+ " " + LodTemplate.TRIANGULAR.toString() + ": LOD Chunks smoothly transition between other. \n"
+ " " + LodTemplate.DYNAMIC.toString() + ": LOD Chunks smoothly transition between other, \n"
+ " " + " unless a neighboring chunk is at a significantly different height. \n")
.defineEnum("lodTemplate", LodTemplate.CUBIC);
lodDetail = builder
.comment("\n\n"
+ " How detailed should the LODs be? \n"
+ " " + LodDetail.SINGLE.toString() + ": render 1 LOD for each Chunk. \n"
+ " " + LodDetail.DOUBLE.toString() + ": render 4 LODs for each Chunk. \n"
+ " " + LodDetail.QUAD.toString() + ": render 16 LODs for each Chunk. \n"
+ " " + LodDetail.HALF.toString() + ": render 64 LODs for each Chunk. \n")
.defineEnum("lodGeometryQuality", LodDetail.DOUBLE);
lodChunkRadiusMultiplier = builder
.comment("\n\n"
+ " This is multiplied by the default view distance \n"
+ " to determine how far out to generate/render LODs. \n"
+ " A value of 2 means that there is 1 render distance worth \n"
+ " of LODs in each cardinal direction. \n")
.defineInRange("lodChunkRadiusMultiplier", 8, 2, 16);
distanceGenerationMode = builder
.comment("\n\n"
+ " Note: The times listed here are the amount of time it took \n"
+ " the developer's PC to generate 1 chunk, \n"
+ " and are included so you can compare the \n"
+ " different generation options. Your mileage may vary. \n"
+ "\n"
+ " " + DistanceGenerationMode.BIOME_ONLY.toString() + " \n"
+ " Only generate the biomes and use biome \n"
+ " grass/foliage color, water color, or snow color \n"
+ " to generate the color. \n"
+ " Doesn't generate height, everything is shown at sea level. \n"
+ " Multithreaded - Fastest (2-5 ms) \n"
+ "\n"
+ " " + DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT.toString() + " \n"
+ " Same as BIOME_ONLY, except instead \n"
+ " of always using sea level as the LOD height \n"
+ " different biome types (mountain, ocean, forest, etc.) \n"
+ " use predetermined heights to simulate having height data. \n"
+ " Multithreaded - Fastest (2-5 ms) \n"
+ "\n"
+ " " + DistanceGenerationMode.SURFACE.toString() + " \n"
+ " Generate the world surface, \n"
+ " this does NOT include caves, trees, \n"
+ " or structures. \n"
+ " Multithreaded - Faster (10-20 ms) \n"
+ "\n"
+ " " + DistanceGenerationMode.FEATURES.toString() + " \n"
+ " Generate everything except structures. \n"
+ " WARNING: This may cause world generation bugs or instability! \n"
+ " Multithreaded - Fast (15-20 ms) \n"
+ "\n"
+ " " + DistanceGenerationMode.SERVER.toString() + " \n"
+ " Ask the server to generate/load each chunk. \n"
+ " This is the most compatible, but causes server/simulation lag. \n"
+ " This will also show player made structures if you \n"
+ " are adding the mod to a pre-existing world. \n"
+ " Singlethreaded - Slow (15-50 ms, with spikes up to 200 ms) \n")
.defineEnum("distanceBiomeOnlyGeneration", DistanceGenerationMode.SURFACE);
allowUnstableFeatureGeneration = builder
.comment("\n\n"
+ " When using the " + DistanceGenerationMode.FEATURES.toString() + "generation mode \n"
+ " some features may not be thread safe, which could \n"
+ " cause instability and crashes. \n"
+ " By default (false) those features are skipped, \n"
+ " improving stability, but decreasing how many features are \n"
+ " actually generated. \n"
+ " (for example: some tree generation is unstable, \n"
+ " so some trees may not be generated.) \n"
+ " By setting this to true, all features will be generated, \n"
+ " but your game will be more unstable and crashes may occur. \n"
+ " \n"
+ " I would love to remove this option and always generate everything, \n"
+ " but I'm not sure how to do that. \n"
+ " If you are a Java wizard, check out the git issue here: \n"
+ " https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/35 \n")
.define("allowUnstableFeatureGeneration", false);
numberOfWorldGenerationThreads = builder
.comment("\n\n"
+ " This is how many threads are used when generating terrain. \n"
+ " If you experience stuttering when generating terrain, decrease \n"
+ " this number. If you want to increase LOD generation speed, \n"
+ " increase the number. \n"
+ " The max is the number of processors on your CPU. \n"
+ "\n"
+ " Requires a restart to take effect. \n"
)
.defineInRange("numberOfWorldGenerationThreads", Runtime.getRuntime().availableProcessors(), 1, Runtime.getRuntime().availableProcessors());
builder.pop();
}
}
/**
* {@link Path} to the configuration file of this mod
*/
private static final Path CONFIG_PATH =
Paths.get("config", ModInfo.MODID + ".toml");
public static final ForgeConfigSpec clientSpec;
public static final Client CLIENT;
static {
final Pair<Client, ForgeConfigSpec> specPair = new ForgeConfigSpec.Builder().configure(Client::new);
clientSpec = specPair.getRight();
CLIENT = specPair.getLeft();
// setup the config file
CommentedFileConfig config = CommentedFileConfig.builder(CONFIG_PATH)
.writingMode(WritingMode.REPLACE)
.build();
config.load();
config.save();
clientSpec.setConfig(config);
}
@SubscribeEvent
public static void onLoad(final ModConfig.Loading configEvent)
{
LogManager.getLogger().debug(ModInfo.MODNAME, "Loaded forge config file {}", configEvent.getConfig().getFileName());
}
@SubscribeEvent
public static void onFileChange(final ModConfig.Reloading configEvent)
{
LogManager.getLogger().debug(ModInfo.MODNAME, "Forge config just got changed on the file system!");
}
}
@@ -1,361 +0,0 @@
/*
* This file is part of 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.handlers;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.LodRegion;
import com.seibel.lod.proxy.ClientProxy;
/**
* This object handles creating LodRegions
* from files and saving LodRegion objects
* to file.
*
* @author James Seibel
* @version 6-27-2021
*/
public class LodDimensionFileHandler
{
/** This is what separates each piece of data */
public static final char DATA_DELIMITER = ',';
private LodDimension loadedDimension = null;
public long regionLastWriteTime[][];
private File dimensionDataSaveFolder;
/** lod */
private final String FILE_NAME_PREFIX = "lod";
/** .txt */
private final String FILE_EXTENSION = ".txt";
/** This is the file version currently accepted by this
* file handler, older versions (smaller numbers) will be deleted and overwritten,
* newer versions (larger numbers) will be ignored and won't be read. */
public static final int LOD_SAVE_FILE_VERSION = 2;
/** This is the string written before the file version */
private static final String LOD_FILE_VERSION_PREFIX = "lod_save_file_version";
/** Allow saving asynchronously, but never try to save multiple regions
* at a time */
private ExecutorService fileWritingThreadPool = Executors.newSingleThreadExecutor();
public LodDimensionFileHandler(File newSaveFolder, LodDimension newLoadedDimension)
{
if (newSaveFolder == null)
throw new IllegalArgumentException("LodDimensionFileHandler requires a valid File location to read and write to.");
dimensionDataSaveFolder = newSaveFolder;
loadedDimension = newLoadedDimension;
// these two variable are used in sync with the LodDimension
regionLastWriteTime = new long[loadedDimension.getWidth()][loadedDimension.getWidth()];
for(int i = 0; i < loadedDimension.getWidth(); i++)
for(int j = 0; j < loadedDimension.getWidth(); j++)
regionLastWriteTime[i][j] = -1;
}
//================//
// read from file //
//================//
/**
* Return the LodRegion at the given coordinates.
* (null if the file doesn't exist)
*/
public LodRegion loadRegionFromFile(int regionX, int regionZ)
{
String fileName = getFileNameAndPathForRegion(regionX, regionZ, LodConfig.CLIENT.lodDetail.get());
File f = new File(fileName);
if (!f.exists())
{
// there wasn't a file, don't
// return anything
return null;
}
LodRegion region = new LodRegion(regionX, regionZ);
try
{
BufferedReader br = new BufferedReader(new FileReader(f));
String s = br.readLine();
int fileVersion = -1;
if(s != null && !s.isEmpty())
{
// try to get the file version
try
{
fileVersion = Integer.parseInt(s.substring(s.indexOf(' ')).trim());
}
catch(NumberFormatException | StringIndexOutOfBoundsException e)
{
// this file doesn't have a version
// keep the version as -1
fileVersion = -1;
}
// check if this file can be read by this file handler
if(fileVersion < LOD_SAVE_FILE_VERSION)
{
// the file we are reading is an older version,
// close the reader and delete the file.
br.close();
f.delete();
ClientProxy.LOGGER.info("Outdated LOD region file for region: (" + regionX + "," + regionZ + ") version: " + fileVersion +
", version requested: " + LOD_SAVE_FILE_VERSION +
" File was been deleted.");
return null;
}
else if(fileVersion > LOD_SAVE_FILE_VERSION)
{
// the file we are reading is a newer version,
// close the reader and ignore the file, we don't
// want to accidently delete anything the user may want.
br.close();
ClientProxy.LOGGER.info("Newer LOD region file for region: (" + regionX + "," + regionZ + ") version: " + fileVersion +
", version requested: " + LOD_SAVE_FILE_VERSION +
" this region will not be written to in order to protect the newer file.");
return null;
}
}
else
{
// there is no data in this file
br.close();
return null;
}
// this file is a readable version, begin reading the file
s = br.readLine();
while(s != null && !s.isEmpty())
{
try
{
// convert each line into an LOD object and add it to the region
LodChunk lod = new LodChunk(s, LodConfig.CLIENT.lodDetail.get());
region.addLod(lod);
}
catch(IllegalArgumentException e)
{
// we were unable to create this chunk
// for whatever reason.
// skip to the next chunk
ClientProxy.LOGGER.warn(e.getMessage());
}
s = br.readLine();
}
br.close();
}
catch (IOException e)
{
// the buffered reader encountered a
// problem reading the file
return null;
}
return region;
}
//==============//
// Save to File //
//==============//
/**
* Save all dirty regions in this LodDimension to file.
*/
public void saveDirtyRegionsToFileAsync()
{
fileWritingThreadPool.execute(saveDirtyRegionsThread);
}
private Thread saveDirtyRegionsThread = new Thread(() ->
{
for(int i = 0; i < loadedDimension.getWidth(); i++)
{
for(int j = 0; j < loadedDimension.getWidth(); j++)
{
if(loadedDimension.isRegionDirty[i][j] && loadedDimension.regions[i][j] != null)
{
saveRegionToDisk(loadedDimension.regions[i][j]);
loadedDimension.isRegionDirty[i][j] = false;
}
}
}
});
/**
* Save a specific region to disk.<br>
* Note: <br>
* 1. If a file already exists for a newer version
* the file won't be written.<br>
* 2. This will save to the LodDimension that this
* handler is associated with.
*/
private void saveRegionToDisk(LodRegion region)
{
// convert chunk coordinates to region
// coordinates
int x = region.x;
int z = region.z;
File f = new File(getFileNameAndPathForRegion(x, z, LodConfig.CLIENT.lodDetail.get()));
try
{
// make sure the file and folder exists
if (!f.exists())
{
// the file doesn't exist,
// create it and the folder if need be
if(!f.getParentFile().exists())
f.getParentFile().mkdirs();
f.createNewFile();
}
else
{
// the file exists, make sure it
// is the correct version.
// (to make sure we don't overwrite a newer
// version file if it exists)
BufferedReader br = new BufferedReader(new FileReader(f));
String s = br.readLine();
int fileVersion = LOD_SAVE_FILE_VERSION;
if(s != null && !s.isEmpty())
{
// try to get the file version
try
{
fileVersion = Integer.parseInt(s.substring(s.indexOf(' ')).trim());
}
catch(NumberFormatException | StringIndexOutOfBoundsException e)
{
// this file doesn't have a correctly formated version
// just overwrite the file
}
}
br.close();
// check if this file can be written to by the file handler
if(fileVersion <= LOD_SAVE_FILE_VERSION)
{
// we are good to continue and overwrite the old file
}
else //if(fileVersion > LOD_SAVE_FILE_VERSION)
{
// the file we are reading is a newer version,
// don't write anything, we don't want to accidently
// delete anything the user may want.
return;
}
}
FileWriter fw = new FileWriter(f);
// add the version of this file
fw.write(LOD_FILE_VERSION_PREFIX + " " + LOD_SAVE_FILE_VERSION + "\n");
// add each LodChunk to the file
for(LodChunk[] chunkArray : region.getAllLods())
for(LodChunk chunk : chunkArray)
if(chunk != null && !chunk.isPlaceholder())
fw.write(chunk.toData() + "\n");
fw.close();
}
catch(Exception e)
{
ClientProxy.LOGGER.error("LOD file write error: " + e.getMessage());
}
}
//================//
// helper methods //
//================//
/**
* Return the name of the file that should contain the
* region at the given x and z. <br>
* Returns null if this object isn't ready to read and write. <br><br>
*
* example: "lod.FULL.0.0.txt"
*/
private String getFileNameAndPathForRegion(int regionX, int regionZ, LodDetail detail)
{
try
{
// saveFolder is something like
// ".\Super Flat\DIM-1\data"
// or
// ".\Super Flat\data"
return dimensionDataSaveFolder.getCanonicalPath() + File.separatorChar +
FILE_NAME_PREFIX + "." + detail.toString() + "." + regionX + "." + regionZ + FILE_EXTENSION;
}
catch(IOException e)
{
return null;
}
}
}
@@ -1,119 +0,0 @@
/*
* This file is part of 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.handlers;
import java.lang.reflect.Field;
import com.seibel.lod.enums.FogQuality;
import net.minecraft.client.Minecraft;
/**
* This object is used to get variables from methods
* where they are private. Specifically the fog setting
* in Optifine.
*
* @author James Seibel
* @version 7-03-2021
*/
public class ReflectionHandler
{
private Minecraft mc = Minecraft.getInstance();
public Field ofFogField = null;
public ReflectionHandler()
{
setupFogField();
}
/**
* Similar to setupFovMethod.
*/
private void setupFogField()
{
// get every variable from the entity renderer
Field[] optionFields = mc.options.getClass().getDeclaredFields();
// try and find the ofFogType variable in gameSettings
for(Field field : optionFields)
{
if(field.getName().equals("ofFogType"))
{
ofFogField = field;
return;
}
}
// we didn't find the field,
// either optifine isn't installed, or
// optifine changed the name of the variable
ofFogField = null;
}
/**
* Get what type of fog optifine is currently set to render.
*/
public FogQuality getFogQuality()
{
if (ofFogField == null)
{
// either optifine isn't installed,
// the variable name was changed, or
// the setup method wasn't called yet.
return FogQuality.FANCY;
}
int returnNum = 0;
try
{
returnNum = (int)ofFogField.get(mc.options);
}
catch (IllegalArgumentException | IllegalAccessException e)
{
e.printStackTrace();
}
switch (returnNum)
{
// optifine's "default" option,
// it should never be called in this case
case 0:
return FogQuality.FAST;
// normal options
case 1:
return FogQuality.FAST;
case 2:
return FogQuality.FANCY;
case 3:
return FogQuality.OFF;
default:
return FogQuality.FAST;
}
}
}
@@ -1,503 +0,0 @@
/*
* This file is part of 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.objects;
import java.awt.Color;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.handlers.LodDimensionFileHandler;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.gen.Heightmap;
/**
* This object contains position
* and color data for an LOD object.
*
* @author James Seibel
* @version 6-27-2021
*/
public class LodChunk
{
/** This is what separates each piece of data in the toData method */
private static final char DATA_DELIMITER = LodDimensionFileHandler.DATA_DELIMITER;
/** Width of a Minecraft Chunk */
public static final int WIDTH = 16;
/** alpha used when drawing chunks in debug mode */
private static final int DEBUG_ALPHA = 255; // 0 - 255
private static final Color DEBUG_BLACK = new Color(0, 0, 0, DEBUG_ALPHA);
private static final Color DEBUG_WHITE = new Color(255, 255, 255, DEBUG_ALPHA);
private static final Color INVISIBLE = new Color(0,0,0,0);
/** If we ever have to use a heightmap for any reason, use this one. */
public static final Heightmap.Type DEFAULT_HEIGHTMAP = Heightmap.Type.WORLD_SURFACE_WG;
public LodDetail detail = LodDetail.SINGLE;
/** If this is set to true then toData will return
* the empty string */
public boolean dontSave = false;
// TODO store the DistanceGenerationMethod used for this chunk (so we can upgrade old chunks if we want to)
/** The x coordinate of the chunk. */
public int x = 0;
/** The z coordinate of the chunk. */
public int z = 0;
/** This stores the height and color for each data point in the LodChunk */
public LodDataPoint dataPoints[][];
/** If true then this LodChunk contains no data */
private boolean empty = false;
/**
* Create an empty, invisible, non-saving LodChunk at (0,0)
*/
public LodChunk()
{
dontSave = true;
empty = true;
x = 0;
z = 0;
detail = LodDetail.SINGLE;
dataPoints = new LodDataPoint[detail.dataPointLengthCount][detail.dataPointLengthCount];
// fill with dummy data, to prevent null pointers
for(int i = 0; i < detail.dataPointLengthCount; i++)
for(int j = 0; j < detail.dataPointLengthCount; j++)
dataPoints[i][j] = new LodDataPoint();
}
/**
* Create an empty, invisible, non-saving LodChunk at the given ChunkPos
*/
public LodChunk(ChunkPos pos)
{
this();
x = pos.x;
z = pos.z;
}
/**
* Create an empty, invisible, non-saving LodChunk at the given ChunkPos
*/
public LodChunk(int newX, int newZ)
{
this();
x = newX;
z = newZ;
}
/**
* Creates an LodChunk from the string
* generated by the toData method.
*
* @throws IllegalArgumentException if the data isn't valid to create a LodChunk
* @throws NumberFormatException if any piece of data can't be converted at any point
*/
public LodChunk(String data, LodDetail newDetail) throws IllegalArgumentException, NumberFormatException
{
/*
* data format:
* x, z, dataPoint[0][0], dataPoint[0][1], ...
* x, z, height, depth, rgb color data, height, depth, rgb....
*
* example:
* 5,8, 4, 0, 255,255,255, 4, 0, 255, 255, 255, ...
*/
dontSave = false;
// make sure there are the correct number of entries
// in the data string
int count = 0;
detail = newDetail;
for(int i = 0; i < data.length(); i++)
if(data.charAt(i) == DATA_DELIMITER)
count++;
if(count != detail.lodChunkStringDelimiterCount)
throw new IllegalArgumentException("LodChunk constructor givin an invalid string. The data given had " + count + " delimiters when it should have had " + detail.lodChunkStringDelimiterCount + ".");
dataPoints = new LodDataPoint[detail.dataPointLengthCount][detail.dataPointLengthCount];
// index we will use when going through the String
int index = 0;
int lastIndex = 0;
// x and z position
index = data.indexOf(DATA_DELIMITER, 0);
this.x = Integer.parseInt(data.substring(0,index));
lastIndex = index;
index = data.indexOf(DATA_DELIMITER, lastIndex+1);
this.z = Integer.parseInt(data.substring(lastIndex+1,index));
// LodDataPoints
for(int blockX = 0; blockX < detail.dataPointLengthCount; blockX++)
{
for(int blockZ = 0; blockZ < detail.dataPointLengthCount; blockZ++)
{
// height
lastIndex = index;
index = data.indexOf(DATA_DELIMITER, lastIndex+1);
int height = Short.parseShort(data.substring(lastIndex+1,index));
// depth
lastIndex = index;
index = data.indexOf(DATA_DELIMITER, lastIndex+1);
int depth = Short.parseShort(data.substring(lastIndex+1,index));
// color
int red = 0;
int green = 0;
int blue = 0;
// get r,g,b
for(int i = 0; i < 3; i++)
{
lastIndex = index;
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
String raw = "";
switch(i)
{
case 0:
raw = data.substring(lastIndex+1,index);
red = Short.parseShort(raw);
break;
case 1:
raw = data.substring(lastIndex+1,index);
green = Short.parseShort(raw);
break;
case 2:
raw = data.substring(lastIndex+1,index);
blue = Short.parseShort(raw);
break;
}
}
dataPoints[blockX][blockZ] = new LodDataPoint((short)height, (short)depth, new Color(red, green, blue));
}
}
empty = determineIfEmtpy();
}
/**
* Create a LodChunk from the given values.
*/
public LodChunk(ChunkPos pos, LodDataPoint[][] newDataPoints, LodDetail newDetail)
{
x = pos.x;
z = pos.z;
dataPoints = newDataPoints;
dontSave = false;
detail = newDetail;
empty = determineIfEmtpy();
}
//================//
// misc functions //
//================//
/**
* Returns true if this LodChunk is an emptyPlaceholder
*/
public boolean isPlaceholder()
{
return empty;
}
public boolean isLodEmpty()
{
return empty;
}
/**
* Returns true if this LOD is either invisible
* from every direction or doesn't have a valid height.
*/
private boolean determineIfEmtpy()
{
for(LodDataPoint[] dataPointArray : dataPoints)
{
for(LodDataPoint dataPoint : dataPointArray)
{
if (dataPoint == null)
continue;
// we don't check the depth since the
// height should always be greater than or equal
// to the depth
if(dataPoint.height >= 0)
{
// the height is valid,
if (dataPoint.color == INVISIBLE)
continue;
// the color and height are valid
// this LodChunk isn't empty
return false;
}
}
}
// we checked everywhere, this LodChunk is empty
return true;
}
//========//
// output //
//========//
/**
* Returns the data point for the given relative block position.
*/
public LodDataPoint getDataPointForBlockPos(int blockX, int blockZ)
{
return dataPoints[blockX / detail.dataPointWidth][blockZ / detail.dataPointWidth];
}
public Color getColorForBlockPos(int blockX, int blockZ)
{
return getDataPointForBlockPos(blockX, blockZ).color;
}
public short getHeightForBlockPos(int blockX, int blockZ)
{
return getDataPointForBlockPos(blockX, blockZ).height;
}
public short getDepthForBlockPos(int blockX, int blockZ)
{
return getDataPointForBlockPos(blockX, blockZ).depth;
}
public Color getColor(int xIndex, int zIndex)
{
return dataPoints[xIndex][zIndex].color;
}
public short getHeight(int xIndex, int zIndex)
{
return dataPoints[xIndex][zIndex].height;
}
public short getDepth(int xIndex, int zIndex)
{
return dataPoints[xIndex][zIndex].depth;
}
public short calculateHighestPoint()
{
short highest = 0;
for(int x = 0; x < detail.dataPointLengthCount; x++)
{
for(int z = 0; z < detail.dataPointLengthCount; z++)
{
if (getHeight(x,z) > highest)
highest = getHeight(x,z);
}
}
return highest;
}
/**
* @param startX
* @param startZ
* @param endX
* @param endZ
* @return
*/
public short getAverageHeightOverArea(int startX, int startZ, int endX, int endZ)
{
if (startX == endX || startZ == endZ)
// we were given an area with 0 blocks in it
return getHeightForBlockPos(startX,startZ);
int average = 0;
for(int x = startX; x < endX; x++)
for(int z = startZ; z < endZ; z++)
average += getHeightForBlockPos(x,z);
return (short) (average / ((endX - startX) * (endZ - startZ)));
}
/**
* @param startX
* @param startZ
* @param endX
* @param endZ
* @return
*/
public short getAverageDepthOverArea(int startX, int startZ, int endX, int endZ)
{
if (startX == endX || startZ == endZ)
// we were given an area with 0 blocks in it
return getDepthForBlockPos(startX,startZ);
int average = 0;
for(int x = startX; x < endX; x++)
for(int z = startZ; z < endZ; z++)
average += getDepthForBlockPos(x,z);
return (short) (average / ((endX - startX) * (endZ - startZ)));
}
/**
* Determine the color of this LOD.
*/
public Color getAverageColorOverArea(int startX, int startZ, int endX, int endZ, boolean debugging)
{
if (startX == endX || startZ == endZ)
// we were given an area with 0 blocks in it
return getColorForBlockPos(startX,startZ);
int[] colorComponents = new int[3];
if (debugging)
{
// draw the squares as a black and white,
// like a checker board
// only return 1 color to prevent
// getting back gray
if ((startX + startZ) % 2 == 0)
return DEBUG_WHITE;
else
return DEBUG_BLACK;
}
for(int x = startX; x < endX; x++)
{
for(int z = startZ; z < endZ; z++)
{
colorComponents = addColorToColorAverages(colorComponents, getColorForBlockPos(x,z));
}
}
int numbPoints = ((endX - startX) * (endZ - startZ));
return new Color(colorComponents[0]/numbPoints, colorComponents[1]/numbPoints, colorComponents[2]/numbPoints);
}
private int[] addColorToColorAverages(int[] colorAverages, Color colorToAdd)
{
// convert the colorToAdd to an int array
float[] colorCompoments = new float[4];
colorCompoments = colorToAdd.getColorComponents(colorCompoments);
// add each color component to the array
for(int rgbIndex = 0; rgbIndex < 3; rgbIndex++)
{
// * 255 + 0.5 taken from the Color java class
colorAverages[rgbIndex] += (int) (colorCompoments[rgbIndex] * 255 + 0.5);
}
return colorAverages;
}
/**
* Outputs all data in a csv format
* with the given delimiter, if
* dontSave is false. <br><br>
*
* data format: <br>
* x, z, dataPoint[0][0], dataPoint[0][1], ... <br>
* x, z, height, depth, rgb color data, height, depth, rgb.... <br><br>
*
* example: <br>
* 5,8, 4, 0, 255,255,255, 4, 0, 255, 255, 255, ...
*/
public String toData()
{
if (dontSave)
return "";
String s = "";
s += Integer.toString(x) + DATA_DELIMITER + Integer.toString(z) + DATA_DELIMITER;
for (int i = 0; i < dataPoints.length; i++)
for (int j = 0; j < dataPoints[i].length; j++)
s += dataPoints[i][j].toData();
return s;
}
@Override
public String toString()
{
String s = "";
s += "x: " + x + " z: " + z + "\t";
return s;
}
}
@@ -1,112 +0,0 @@
/*
* This file is part of 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.objects;
import java.awt.Color;
import com.seibel.lod.handlers.LodDimensionFileHandler;
/**
* This stores the height and color
* for a specific area in a LodChunk.
*
* @author James Seibel
* @version 6-19-2021
*/
public class LodDataPoint
{
/** This is what separates each piece of data in the toData method */
private static final char DATA_DELIMITER = LodDimensionFileHandler.DATA_DELIMITER;
/** this is how many pieces of data are exported when toData is called */
public static final int NUMBER_OF_DELIMITERS = 5;
private static final Color INVISIBLE = new Color(0,0,0,0);
/** highest point */
public short height;
/** lowest point */
public short depth;
/** The average color for the 6 cardinal directions */
public Color color;
/**
* Creates and empty LodDataPoint
*/
public LodDataPoint()
{
height = -1;
depth = -1;
color = INVISIBLE;
}
public LodDataPoint(short newHeight, short newDepth, Color newColor)
{
height = newHeight;
depth = newDepth;
color = newColor;
}
public LodDataPoint(int newHeight, int newDepth, Color newColor)
{
height = (short) newHeight;
depth = (short) newDepth;
color = newColor;
}
/**
* Outputs all data in a csv format
* with the given delimiter.
* <br>
* Exports data in the form:
* <br>
* height, depth, rgb color data
*
* <br>
* example output:
* <br>
* 4, 0, 255,255,255,
*/
public String toData()
{
String s = Short.toString(height) + DATA_DELIMITER;
s += Short.toString(depth) + DATA_DELIMITER;
s += Integer.toString(color.getRed()) + DATA_DELIMITER + Integer.toString(color.getGreen()) + DATA_DELIMITER + Integer.toString(color.getBlue()) + DATA_DELIMITER;
return s;
}
@Override
public String toString()
{
String s = Short.toString(height) + DATA_DELIMITER;
s += Short.toString(depth) + DATA_DELIMITER;
s += Integer.toString(color.getRed()) + DATA_DELIMITER + Integer.toString(color.getGreen()) + DATA_DELIMITER + Integer.toString(color.getBlue()) + DATA_DELIMITER;
return s;
}
}
@@ -1,424 +0,0 @@
/*
* This file is part of 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.objects;
import java.io.File;
import java.io.IOException;
import com.seibel.lod.handlers.LodDimensionFileHandler;
import com.seibel.lod.util.LodUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.DimensionType;
import net.minecraft.world.server.ServerChunkProvider;
import net.minecraft.world.server.ServerWorld;
/**
* This object holds all loaded LOD regions
* for a given dimension.
*
* @author James Seibel
* @version 06-27-2021
*/
public class LodDimension
{
public final DimensionType dimension;
private volatile int width;
private volatile int halfWidth;
public volatile LodRegion regions[][];
public volatile boolean isRegionDirty[][];
private int centerX;
private int centerZ;
private LodDimensionFileHandler fileHandler;
public LodDimension(DimensionType newDimension, LodWorld lodWorld, int newMaxWidth)
{
dimension = newDimension;
width = newMaxWidth;
try
{
Minecraft mc = Minecraft.getInstance();
File saveDir;
if(mc.hasSingleplayerServer())
{
// local world
ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(newDimension);
// provider needs a separate variable to prevent
// the compiler from complaining
ServerChunkProvider provider = serverWorld.getChunkSource();
saveDir = new File(provider.dataStorage.dataFolder.getCanonicalFile().getPath() + File.separatorChar + "lod");
}
else
{
// connected to server
saveDir = new File(mc.gameDirectory.getCanonicalFile().getPath() +
File.separatorChar + "lod server data" + File.separatorChar + LodUtil.getDimensionIDFromWorld(mc.level));
}
fileHandler = new LodDimensionFileHandler(saveDir, this);
}
catch(IOException e)
{
// the file handler wasn't able to be created
// we won't be able to read or write any files
}
regions = new LodRegion[width][width];
isRegionDirty = new boolean[width][width];
// populate isRegionDirty
for(int i = 0; i < width; i++)
for(int j = 0; j < width; j++)
isRegionDirty[i][j] = false;
centerX = 0;
centerZ = 0;
halfWidth = (int)Math.floor(width / 2);
}
/**
* Move the center of this LodDimension and move all owned
* regions over by the given x and z offset.
*/
public void move(int xOffset, int zOffset)
{
// if the x or z offset is equal to or greater than
// the total size, just delete the current data
// and update the centerX and/or centerZ
if (Math.abs(xOffset) >= width || Math.abs(zOffset) >= width)
{
for(int x = 0; x < width; x++)
{
for(int z = 0; z < width; z++)
{
regions[x][z] = null;
}
}
// update the new center
centerX += xOffset;
centerZ += zOffset;
return;
}
// X
if(xOffset > 0)
{
// move everything over to the left (as the center moves to the right)
for(int x = 0; x < width; x++)
{
for(int z = 0; z < width; z++)
{
if(x + xOffset < width)
regions[x][z] = regions[x + xOffset][z];
else
regions[x][z] = null;
}
}
}
else
{
// move everything over to the right (as the center moves to the left)
for(int x = width - 1; x >= 0; x--)
{
for(int z = 0; z < width; z++)
{
if(x + xOffset >= 0)
regions[x][z] = regions[x + xOffset][z];
else
regions[x][z] = null;
}
}
}
// Z
if(zOffset > 0)
{
// move everything up (as the center moves down)
for(int x = 0; x < width; x++)
{
for(int z = 0; z < width; z++)
{
if(z + zOffset < width)
regions[x][z] = regions[x][z + zOffset];
else
regions[x][z] = null;
}
}
}
else
{
// move everything down (as the center moves up)
for(int x = 0; x < width; x++)
{
for(int z = width - 1; z >= 0; z--)
{
if(z + zOffset >= 0)
regions[x][z] = regions[x][z + zOffset];
else
regions[x][z] = null;
}
}
}
// update the new center
centerX += xOffset;
centerZ += zOffset;
}
/**
* Gets the region at the given X and Z
* <br>
* Returns null if the region doesn't exist
* or is outside the loaded area.
*/
public LodRegion getRegion(int regionX, int regionZ)
{
int xIndex = (regionX - centerX) + halfWidth;
int zIndex = (regionZ - centerZ) + halfWidth;
if (!regionIsInRange(regionX, regionZ))
// out of range
return null;
if (regions[xIndex][zIndex] == null)
{
regions[xIndex][zIndex] = getRegionFromFile(regionX, regionZ);
if (regions[xIndex][zIndex] == null)
{
regions[xIndex][zIndex] = new LodRegion(regionX, regionZ);
}
}
return regions[xIndex][zIndex];
}
/**
* Overwrite the LodRegion at the location of newRegion with newRegion.
* @throws ArrayIndexOutOfBoundsException if newRegion is outside what can be stored in this LodDimension.
*/
public void setRegion(LodRegion newRegion) throws ArrayIndexOutOfBoundsException
{
int xIndex = (newRegion.x - centerX) + halfWidth;
int zIndex = (centerZ - newRegion.z) + halfWidth;
if (!regionIsInRange(newRegion.x, newRegion.z))
// out of range
throw new ArrayIndexOutOfBoundsException();
regions[xIndex][zIndex] = newRegion;
}
/**
* Add the given LOD to this dimension at the coordinate
* stored in the LOD. If an LOD already exists at the given
* coordinates it will be overwritten.
*/
public void addLod(LodChunk lod)
{
RegionPos pos = LodUtil.convertChunkPosToRegionPos(new ChunkPos(lod.x, lod.z));
// don't continue if the region can't be saved
if (!regionIsInRange(pos.x, pos.z))
{
return;
}
LodRegion region = getRegion(pos.x, pos.z);
if (region == null)
{
// if no region exists, create it
region = new LodRegion(pos.x, pos.z);
setRegion(region);
}
region.addLod(lod);
// don't save empty place holders to disk
if (!lod.isPlaceholder() && fileHandler != null)
{
// mark the region as dirty so it will be saved to disk
int xIndex = (pos.x - centerX) + halfWidth;
int zIndex = (pos.z - centerZ) + halfWidth;
isRegionDirty[xIndex][zIndex] = true;
fileHandler.saveDirtyRegionsToFileAsync();
}
}
/**
* Get the LodChunk at the given X and Z coordinates
* in this dimension.
* <br>
* Returns null if the LodChunk doesn't exist or
* is outside the loaded area.
*/
public LodChunk getLodFromCoordinates(int chunkX, int chunkZ)
{
RegionPos pos = LodUtil.convertChunkPosToRegionPos(new ChunkPos(chunkX, chunkZ));
LodRegion region = getRegion(pos.x, pos.z);
if(region == null)
return null;
return region.getLod(chunkX, chunkZ);
}
/**
* Get the region at the given X and Z coordinates from the
* RegionFileHandler.
*/
public LodRegion getRegionFromFile(int regionX, int regionZ)
{
if (fileHandler != null)
return fileHandler.loadRegionFromFile(regionX, regionZ);
else
return null;
}
/**
* Returns whether the region at the given X and Z coordinates
* is within the loaded range.
*/
public boolean regionIsInRange(int regionX, int regionZ)
{
int xIndex = (regionX - centerX) + halfWidth;
int zIndex = (regionZ - centerZ) + halfWidth;
return xIndex >= 0 && xIndex < width && zIndex >= 0 && zIndex < width;
}
public int getCenterX()
{
return centerX;
}
public int getCenterZ()
{
return centerZ;
}
/**
* Returns how many non-null LodChunks
* are stored in this LodDimension.
*/
public int getNumberOfLods()
{
int numbLods = 0;
for (LodRegion[] regions : regions)
{
if(regions == null)
continue;
for (LodRegion region : regions)
{
if(region == null)
continue;
for(LodChunk[] lods : region.getAllLods())
{
if(lods == null)
continue;
for(LodChunk lod : lods)
{
if (lod != null)
numbLods++;
}
}
}
}
return numbLods;
}
public int getWidth()
{
return width;
}
public void setRegionWidth(int newWidth)
{
width = newWidth;
halfWidth = (int)Math.floor(width / 2);
regions = new LodRegion[width][width];
isRegionDirty = new boolean[width][width];
// populate isRegionDirty
for(int i = 0; i < width; i++)
for(int j = 0; j < width; j++)
isRegionDirty[i][j] = false;
}
@Override
public String toString()
{
String s = "";
s += "dim: " + dimension.toString() + "\t";
s += "(" + centerX + "," + centerZ + ")";
return s;
}
}
@@ -1,104 +0,0 @@
/*
* This file is part of 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.objects;
/**
* A LodRegion is the a 32x32
* 2D array of LodChunk objects.
* Each LodRegion corresponds to
* one file in the file system.
*
* @author James Seibel
* @version 6-12-2021
*/
public class LodRegion
{
/** number of chunks wide */
public static final int SIZE = 32;
/** X coordinate of this region */
public final int x;
/** Z coordinate of this region */
public final int z;
private LodChunk chunks[][];
public LodRegion(int regionX, int regionZ)
{
x = regionX;
z = regionZ;
chunks = new LodChunk[SIZE][SIZE];
}
/**
* Add the given LOD to this region at the coordinate
* stored in the LOD. If an LOD already exists at the given
* coordinates it will be overwritten.
*/
public void addLod(LodChunk lod)
{
// we use ABS since LODs can be negative, but if they are
// the region will negative first, therefore we don't have to
// store the LOD chunks at negative indexes since we search
// LOD the region first
int xIndex = Math.abs(lod.x % SIZE);
int zIndex = Math.abs(lod.z % SIZE);
chunks[xIndex][zIndex] = lod;
}
/**
* Get the LodChunk at the given X and Z coordinates
* in this region.
* <br>
* Returns null if the LodChunk doesn't exist or
* is outside the loaded area.
*/
public LodChunk getLod(int chunkX, int chunkZ)
{
// since we add LOD's with ABS, we get them the same way
int arrayX = Math.abs(chunkX % SIZE);
int arrayZ = Math.abs(chunkZ % SIZE);
return chunks[arrayX][arrayZ];
}
/**
* Returns all LodChunks in this region
*/
public LodChunk[][] getAllLods()
{
return chunks;
}
@Override
public String toString()
{
String s = "";
s += "x: " + x + " z: " + z + "\t";
return s;
}
}
@@ -1,127 +0,0 @@
/*
* This file is part of 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.objects;
import java.util.Hashtable;
import java.util.Map;
import net.minecraft.world.DimensionType;
/**
* This stores all LODs for a given world.
*
* @author James Seibel
* @version 04-01-2021
*/
public class LodWorld
{
private String worldName;
private Map<DimensionType, LodDimension> lodDimensions;
/** If true then the LOD world is setup and ready to use */
private boolean isWorldLoaded = false;
public static final String NO_WORLD_LOADED = "No world loaded";
public LodWorld()
{
worldName = NO_WORLD_LOADED;
}
/**
* Set up the LodWorld with the given newWorldName. <br>
* This should be done whenever loading a new world.
* @param newWorldName
*/
public void selectWorld(String newWorldName)
{
if(newWorldName.isEmpty())
{
deselectWorld();
return;
}
if (worldName.equals(newWorldName))
// don't recreate everything if we
// didn't actually change worlds
return;
worldName = newWorldName;
lodDimensions = new Hashtable<DimensionType, LodDimension>();
isWorldLoaded = true;
}
/**
* Set the worldName to "No world loaded"
* and clear the lodDimensions Map. <br>
* This should be done whenever unloaded a world.
*/
public void deselectWorld()
{
worldName = NO_WORLD_LOADED;
lodDimensions = null;
isWorldLoaded = false;
}
public void addLodDimension(LodDimension newStorage)
{
if (lodDimensions == null)
throw new IllegalStateException("LodWorld hasn't been given a world yet.");
lodDimensions.put(newStorage.dimension, newStorage);
}
public LodDimension getLodDimension(DimensionType dimension)
{
if (lodDimensions == null)
throw new IllegalStateException("LodWorld hasn't been given a world yet.");
return lodDimensions.get(dimension);
}
/**
* Resizes the max width in regions that each LodDimension
* should use.
*/
public void resizeDimensionRegionWidth(int newWidth)
{
if (lodDimensions == null)
throw new IllegalStateException("LodWorld hasn't been given a world yet.");
for(DimensionType key : lodDimensions.keySet())
lodDimensions.get(key).setRegionWidth(newWidth);
}
public boolean getIsWorldLoaded()
{
return isWorldLoaded;
}
public String getWorldName()
{
return worldName;
}
@Override
public String toString()
{
return "World name: " + worldName;
}
}
@@ -1,45 +0,0 @@
/*
* This file is part of 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.objects;
import net.minecraft.client.renderer.BufferBuilder;
/**
* This object is just a replacement for an array
* to make things easier to understand in the LodRenderer
* and BuildBufferThread.
*
* @author James Seibel
* @version 03-25-2021
*/
public class NearFarBuffer
{
public BufferBuilder nearBuffer;
public BufferBuilder farBuffer;
/**
* @param newNearBuffer
* @param newFarBuffer
*/
public NearFarBuffer(BufferBuilder newNearBuffer, BufferBuilder newFarBuffer)
{
nearBuffer = newNearBuffer;
farBuffer = newFarBuffer;
}
}
@@ -1,63 +0,0 @@
/*
* This file is part of 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.objects;
import com.seibel.lod.enums.FogDistance;
import com.seibel.lod.enums.FogQuality;
/**
* This object is just a replacement for an array
* to make things easier to understand in the LodRenderer.
*
* @author James Seibel
* @version 7-03-2021
*/
public class NearFarFogSettings
{
public NearOrFarSetting near = new NearOrFarSetting(FogDistance.NEAR);
public NearOrFarSetting far = new NearOrFarSetting(FogDistance.FAR);
/** If true that means Minecraft is
* rendering fog along side us */
public boolean vanillaIsRenderingFog = true;
public NearFarFogSettings()
{
}
/**
* This holds all relevant data to rendering fog at either
* near or far distances.
*/
public class NearOrFarSetting
{
public FogQuality quality = FogQuality.FANCY;
public FogDistance distance = FogDistance.FAR;
/** If true this section should render with fog */
public boolean enabled = true;
public NearOrFarSetting(FogDistance newFogDistance)
{
distance = newFogDistance;
}
}
}
@@ -1,212 +0,0 @@
/*
* This file is part of 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.proxy;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import com.seibel.lod.builders.LodBufferBuilder;
import com.seibel.lod.builders.LodChunkBuilder;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.LodRegion;
import com.seibel.lod.objects.LodWorld;
import com.seibel.lod.render.LodRenderer;
import com.seibel.lod.util.LodUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.profiler.IProfiler;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
/**
* This handles all events sent to the client,
* and is the starting point for most of this program.
*
* @author James_Seibel
* @version 06-27-2021
*/
public class ClientProxy
{
public static final Logger LOGGER = LogManager.getLogger("LOD");
private static LodWorld lodWorld = new LodWorld();
private static LodChunkBuilder lodChunkBuilder = new LodChunkBuilder();
private static LodBufferBuilder lodBufferBuilder = new LodBufferBuilder(lodChunkBuilder);
private static LodRenderer renderer = new LodRenderer(lodBufferBuilder);
Minecraft mc = Minecraft.getInstance();
public ClientProxy()
{
}
//==============//
// render event //
//==============//
/**
* Do any setup that is required to draw LODs
* and then tell the LodRenderer to draw.
*/
public void renderLods(float partialTicks)
{
if (mc == null || mc.player == null || !lodWorld.getIsWorldLoaded())
return;
// update each regions' width to match the new render distance
int newWidth = Math.max(4,
// TODO is this logic good?
(mc.options.renderDistance * LodChunk.WIDTH * 2 * LodConfig.CLIENT.lodChunkRadiusMultiplier.get()) / LodRegion.SIZE
);
if (lodChunkBuilder.regionWidth != newWidth)
{
lodWorld.resizeDimensionRegionWidth(newWidth);
lodChunkBuilder.regionWidth = newWidth;
// skip this frame, hopefully the lodWorld
// should have everything set up by then
return;
}
LodDimension lodDim = lodWorld.getLodDimension(mc.player.level.dimensionType());
if (lodDim == null)
return;
// offset the regions
double playerX = mc.player.getX();
double playerZ = mc.player.getZ();
int xOffset = ((int)playerX / (LodChunk.WIDTH * LodRegion.SIZE)) - lodDim.getCenterX();
int zOffset = ((int)playerZ / (LodChunk.WIDTH * LodRegion.SIZE)) - lodDim.getCenterZ();
if (xOffset != 0 || zOffset != 0)
{
lodDim.move(xOffset, zOffset);
}
// for testing
// LodConfig.CLIENT.debugMode.set(false);
// LodConfig.CLIENT.lodDetail.set(LodDetail.DOUBLE);
// LodConfig.CLIENT.lodChunkRadiusMultiplier.set(12);
// LodConfig.CLIENT.fogDistance.set(FogDistance.FAR);
// LodConfig.CLIENT.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY);
// LodConfig.CLIENT.distanceGenerationMode.set(DistanceGenerationMode.FEATURES);
// LodConfig.CLIENT.allowUnstableFeatureGeneration.set(false);
// Note to self:
// if "unspecified" shows up in the pie chart, it is
// possibly because the amount of time between sections
// is too small for the profile to measure
IProfiler profiler = mc.getProfiler();
profiler.pop(); // get out of "terrain"
profiler.push("LOD");
renderer.drawLODs(lodDim, partialTicks, mc.getProfiler());
profiler.pop(); // end LOD
profiler.push("terrain"); // restart terrain
}
//==============//
// forge events //
//==============//
@SubscribeEvent
public void chunkLoadEvent(ChunkEvent.Load event)
{
lodChunkBuilder.generateLodChunkAsync(event.getChunk(), lodWorld, event.getWorld());
}
@SubscribeEvent
public void worldLoadEvent(WorldEvent.Load event)
{
// the player just loaded a new world/dimension
lodWorld.selectWorld(LodUtil.getWorldID(event.getWorld()));
// make sure the correct LODs are being rendered
// (if this isn't done the previous world's LODs may be drawn)
renderer.regenerateLODsNextFrame();
}
@SubscribeEvent
public void worldUnloadEvent(WorldEvent.Unload event)
{
// the player just unloaded a world/dimension
if(mc.getConnection().getLevel() == null)
{
lodBufferBuilder.numberOfChunksWaitingToGenerate.set(0);
// the player has disconnected from a server
lodWorld.deselectWorld();
}
}
@SubscribeEvent
public void blockChangeEvent(BlockEvent event)
{
if (event.getClass() == BlockEvent.BreakEvent.class ||
event.getClass() == BlockEvent.EntityPlaceEvent.class ||
event.getClass() == BlockEvent.EntityMultiPlaceEvent.class ||
event.getClass() == BlockEvent.FluidPlaceBlockEvent.class ||
event.getClass() == BlockEvent.PortalSpawnEvent.class)
{
// recreate the LOD where the blocks were changed
lodChunkBuilder.generateLodChunkAsync(event.getWorld().getChunk(event.getPos()), lodWorld, event.getWorld());
}
}
//================//
// public getters //
//================//
public static LodWorld getLodWorld()
{
return lodWorld;
}
public static LodChunkBuilder getLodBuilder()
{
return lodChunkBuilder;
}
public static LodRenderer getRenderer()
{
return renderer;
}
}
@@ -1,865 +0,0 @@
/*
* This file is part of 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.render;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.HashSet;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.NVFogDistance;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem;
import com.seibel.lod.builders.LodBufferBuilder;
import com.seibel.lod.enums.FogDistance;
import com.seibel.lod.enums.FogDrawOverride;
import com.seibel.lod.enums.FogQuality;
import com.seibel.lod.handlers.LodConfig;
import com.seibel.lod.handlers.ReflectionHandler;
import com.seibel.lod.objects.LodChunk;
import com.seibel.lod.objects.LodDimension;
import com.seibel.lod.objects.NearFarBuffer;
import com.seibel.lod.objects.NearFarFogSettings;
import com.seibel.lod.proxy.ClientProxy;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.FogRenderer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.renderer.vertex.VertexBuffer;
import net.minecraft.client.renderer.vertex.VertexFormat;
import net.minecraft.potion.Effects;
import net.minecraft.profiler.IProfiler;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.util.math.vector.Vector3f;
/**
* This is where all the magic happens. <br>
* This is where LODs are draw to the world.
*
* @author James Seibel
* @version 07-4-2021
*/
public class LodRenderer
{
/** this is the light used when rendering the LODs,
* it should be something different than what is used by Minecraft */
private static final int LOD_GL_LIGHT_NUMBER = GL11.GL_LIGHT2;
/**
* 64 MB by default is the maximum amount of memory that
* can be directly allocated. <br><br>
*
* I know there are commands to change that amount
* (specifically "-XX:MaxDirectMemorySize"), but
* I have no idea how to access that amount. <br>
* So I guess this will be the hard limit for now. <br><br>
*
* https://stackoverflow.com/questions/50499238/bytebuffer-allocatedirect-and-xmx
*/
public static final int MAX_ALOCATEABLE_DIRECT_MEMORY = 64 * 1024 * 1024;
/** Does this computer's GPU support fancy fog? */
public static boolean fancyFogAvailable = false;
/** If true the LODs colors will be replaced with
* a checkerboard, this can be used for debugging. */
public boolean debugging = false;
private Minecraft mc;
private GameRenderer gameRender;
private IProfiler profiler;
private float farPlaneDistance;
private ReflectionHandler reflectionHandler;
/** This is used to generate the buildable buffers */
private LodBufferBuilder lodBufferBuilder;
/** The buffers that are used to draw LODs using near fog */
private volatile BufferBuilder drawableNearBuffer;
/** The buffers that are used to draw LODs using far fog */
private volatile BufferBuilder drawableFarBuffer;
/** This is the VertexBuffer used to draw any LODs that use near fog */
private volatile VertexBuffer nearVbo;
/** This is the VertexBuffer used to draw any LODs that use far fog */
private volatile VertexBuffer farVbo;
public static final VertexFormat LOD_VERTEX_FORMAT = DefaultVertexFormats.POSITION_COLOR;
/** This is used to determine if the LODs should be regenerated */
private int previousChunkRenderDistance = 0;
/** This is used to determine if the LODs should be regenerated */
private int prevChunkX = 0;
/** This is used to determine if the LODs should be regenerated */
private int prevChunkZ = 0;
/** This is used to determine if the LODs should be regenerated */
private FogDistance prevFogDistance = FogDistance.NEAR_AND_FAR;
/** if this is true the LOD buffers should be regenerated,
* provided they aren't already being regenerated. */
private volatile boolean regen = false;
/** This HashSet contains every chunk that Vanilla Minecraft
* is going to render */
public HashSet<ChunkPos> vanillaRenderedChunks = new HashSet<>();
public LodRenderer(LodBufferBuilder newLodBufferBuilder)
{
mc = Minecraft.getInstance();
gameRender = mc.gameRenderer;
reflectionHandler = new ReflectionHandler();
lodBufferBuilder = newLodBufferBuilder;
}
/**
* Besides drawing the LODs this method also starts
* the async process of generating the Buffers that hold those LODs.
*
* @param newDimension The dimension to draw, if null doesn't replace the current dimension.
* @param partialTicks how far into the current tick this method was called.
*/
public void drawLODs(LodDimension lodDim, float partialTicks, IProfiler newProfiler)
{
if (lodDim == null)
{
// if there aren't any loaded LodChunks
// don't try drawing anything
return;
}
//===============//
// initial setup //
//===============//
profiler = newProfiler;
profiler.push("LOD setup");
ClientPlayerEntity player = mc.player;
// should LODs be regenerated?
if ((int)player.getX() / LodChunk.WIDTH != prevChunkX ||
(int)player.getZ() / LodChunk.WIDTH != prevChunkZ ||
previousChunkRenderDistance != mc.options.renderDistance ||
prevFogDistance != LodConfig.CLIENT.fogDistance.get())
{
// yes
regen = true;
prevChunkX = (int)player.getX() / LodChunk.WIDTH;
prevChunkZ = (int)player.getZ() / LodChunk.WIDTH;
prevFogDistance = LodConfig.CLIENT.fogDistance.get();
}
else
{
// nope, the player hasn't moved, the
// render distance hasn't changed, and
// the dimension is the same
}
// did the user change the debug setting?
if (LodConfig.CLIENT.debugMode.get() != debugging)
{
debugging = LodConfig.CLIENT.debugMode.get();
regen = true;
}
// determine how far the game's render distance is currently set
int renderDistWidth = mc.options.renderDistance;
farPlaneDistance = renderDistWidth * LodChunk.WIDTH;
// set how big the LODs will be and how far they will go
int totalLength = (int) farPlaneDistance * LodConfig.CLIENT.lodChunkRadiusMultiplier.get() * 2;
int numbChunksWide = (totalLength / LodChunk.WIDTH);
// determine which LODs should not be rendered close to the player
HashSet<ChunkPos> chunkPosToSkip = getNearbyLodChunkPosToSkip(lodDim, player.blockPosition());
// see if the chunks Minecraft is going to render are the
// same as last time
if (!vanillaRenderedChunks.containsAll(chunkPosToSkip))
{
regen = true;
vanillaRenderedChunks = chunkPosToSkip;
}
//=================//
// create the LODs //
//=================//
// only regenerate the LODs if:
// 1. we want to regenerate LODs
// 2. we aren't already regenerating the LODs
// 3. we aren't waiting for the build and draw buffers to swap
// (this is to prevent thread conflicts)
if (regen && !lodBufferBuilder.generatingBuffers && !lodBufferBuilder.newBuffersAvaliable())
{
// this will mainly happen when the view distance is changed
if (drawableNearBuffer == null || drawableFarBuffer == null ||
previousChunkRenderDistance != mc.options.renderDistance)
setupBuffers(numbChunksWide);
// generate the LODs on a separate thread to prevent stuttering or freezing
lodBufferBuilder.generateLodBuffersAsync(this, lodDim, player.getX(), player.getZ(), numbChunksWide);
// the regen process has been started,
// it will be done when lodBufferBuilder.newBuffersAvaliable
// is true
regen = false;
}
// replace the buffers used to draw and build,
// this is only done when the createLodBufferGenerationThread
// has finished executing on a parallel thread.
if (lodBufferBuilder.newBuffersAvaliable())
{
swapBuffers();
}
//===========================//
// GL settings for rendering //
//===========================//
// set the required open GL settings
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glEnable(GL11.GL_CULL_FACE);
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
GL11.glEnable(GL11.GL_DEPTH_TEST);
// disable the lights Minecraft uses
GL11.glDisable(GL11.GL_LIGHT0);
GL11.glDisable(GL11.GL_LIGHT1);
// get the default projection matrix so we can
// reset it after drawing the LODs
float[] defaultProjMatrix = new float[16];
GL11.glGetFloatv(GL11.GL_PROJECTION_MATRIX, defaultProjMatrix);
Matrix4f modelViewMatrix = generateModelViewMatrix(partialTicks);
setupProjectionMatrix(partialTicks);
setupLighting(lodDim, partialTicks);
NearFarFogSettings fogSettings = determineFogSettings();
// determine the current fog settings so they can be
// reset after drawing the LODs
float defaultFogStartDist = GL11.glGetFloat(GL11.GL_FOG_START);
float defaultFogEndDist = GL11.glGetFloat(GL11.GL_FOG_END);
int defaultFogMode = GL11.glGetInteger(GL11.GL_FOG_MODE);
int defaultFogDistance = GL11.glGetInteger(NVFogDistance.GL_FOG_DISTANCE_MODE_NV);
//===========//
// rendering //
//===========//
profiler.popPush("LOD draw");
setupFog(fogSettings.near.distance, fogSettings.near.quality);
sendLodsToGpuAndDraw(nearVbo, modelViewMatrix);
setupFog(fogSettings.far.distance, fogSettings.far.quality);
sendLodsToGpuAndDraw(farVbo, modelViewMatrix);
//=========//
// cleanup //
//=========//
profiler.popPush("LOD cleanup");
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glDisable(LOD_GL_LIGHT_NUMBER);
// re-enable the lights Minecraft uses
GL11.glEnable(GL11.GL_LIGHT0);
GL11.glEnable(GL11.GL_LIGHT1);
RenderSystem.disableLighting();
// this can't be called until after the buffers are built
// because otherwise the buffers may be set to the wrong size
previousChunkRenderDistance = mc.options.renderDistance;
// reset the fog settings so the normal chunks
// will be drawn correctly
cleanupFog(fogSettings, defaultFogStartDist, defaultFogEndDist, defaultFogMode, defaultFogDistance);
// reset the projection matrix so anything drawn after
// the LODs will use the correct projection matrix
Matrix4f mvm = new Matrix4f(defaultProjMatrix);
mvm.transpose();
gameRender.resetProjectionMatrix(mvm);
// clear the depth buffer so anything drawn is drawn
// over the LODs
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT);
// end of internal LOD profiling
profiler.pop();
}
/**
* This is where the actual drawing happens.
*
* @param buffers the buffers sent to the GPU to draw
*/
private void sendLodsToGpuAndDraw(VertexBuffer vbo, Matrix4f modelViewMatrix)
{
if (vbo == null)
return;
vbo.bind();
// 0L is the starting pointer
LOD_VERTEX_FORMAT.setupBufferState(0L);
vbo.draw(modelViewMatrix, GL11.GL_QUADS);
VertexBuffer.unbind();
LOD_VERTEX_FORMAT.clearBufferState();
}
//=================//
// Setup Functions //
//=================//
@SuppressWarnings("deprecation")
private void setupFog(FogDistance fogDistance, FogQuality fogQuality)
{
if(fogQuality == FogQuality.OFF)
{
FogRenderer.setupNoFog();
RenderSystem.disableFog();
return;
}
if(fogDistance == FogDistance.NEAR_AND_FAR)
{
throw new IllegalArgumentException("setupFog doesn't accept the NEAR_AND_FAR fog distance.");
}
// determine the fog distance mode to use
int glFogDistanceMode = NVFogDistance.GL_EYE_RADIAL_NV;
if (fogQuality == FogQuality.FANCY)
{
// fancy fog (fragment distance based fog)
glFogDistanceMode = NVFogDistance.GL_EYE_RADIAL_NV;
}
else
{
// fast fog (frustum distance based fog)
glFogDistanceMode = NVFogDistance.GL_EYE_PLANE_ABSOLUTE_NV;
}
// the multipliers are percentages
// of the regular view distance.
if(fogDistance == FogDistance.NEAR)
{
// the reason that I wrote fogEnd then fogStart backwards
// is because we are using fog backwards to how
// it is normally used, with it hiding near objects
// instead of far objects.
if (fogQuality == FogQuality.FANCY)
{
RenderSystem.fogEnd(farPlaneDistance * 1.75f);
RenderSystem.fogStart(farPlaneDistance * 1.95f);
}
else if(fogQuality == FogQuality.FAST)
{
// for the far fog of the normal chunks
// to start right where the LODs' end use:
// end = 0.8f, start = 1.5f
RenderSystem.fogEnd(farPlaneDistance * 1.5f);
RenderSystem.fogStart(farPlaneDistance * 2.0f);
}
}
else if(fogDistance == FogDistance.FAR)
{
if (fogQuality == FogQuality.FANCY)
{
RenderSystem.fogStart(farPlaneDistance * 0.85f * LodConfig.CLIENT.lodChunkRadiusMultiplier.get());
RenderSystem.fogEnd(farPlaneDistance * 1.0f * LodConfig.CLIENT.lodChunkRadiusMultiplier.get());
}
else if(fogQuality == FogQuality.FAST)
{
RenderSystem.fogStart(farPlaneDistance * 0.5f * LodConfig.CLIENT.lodChunkRadiusMultiplier.get());
RenderSystem.fogEnd(farPlaneDistance * 0.75f * LodConfig.CLIENT.lodChunkRadiusMultiplier.get());
}
}
GL11.glEnable(GL11.GL_FOG);
RenderSystem.enableFog();
RenderSystem.setupNvFogDistance();
RenderSystem.fogMode(GlStateManager.FogMode.LINEAR);
GL11.glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, glFogDistanceMode);
}
/**
* Revert any changes that were made to the fog.
*/
private void cleanupFog(NearFarFogSettings fogSettings,
float defaultFogStartDist, float defaultFogEndDist,
int defaultFogMode, int defaultFogDistance)
{
RenderSystem.fogStart(defaultFogStartDist);
RenderSystem.fogEnd(defaultFogEndDist);
RenderSystem.fogMode(defaultFogMode);
GL11.glFogi(NVFogDistance.GL_FOG_DISTANCE_MODE_NV, defaultFogDistance);
// disable fog if Minecraft wasn't rendering fog
// but we were
if(!fogSettings.vanillaIsRenderingFog &&
(fogSettings.near.quality != FogQuality.OFF ||
fogSettings.far.quality != FogQuality.OFF))
{
GL11.glDisable(GL11.GL_FOG);
}
}
/**
* Create the model view matrix to move the LODs
* from object space into world space.
*/
private Matrix4f generateModelViewMatrix(float partialTicks)
{
// get all relevant camera info
ActiveRenderInfo renderInfo = mc.gameRenderer.getMainCamera();
Vector3d projectedView = renderInfo.getPosition();
// generate the model view matrix
MatrixStack matrixStack = new MatrixStack();
matrixStack.pushPose();
// translate and rotate to the current camera location
matrixStack.mulPose(Vector3f.XP.rotationDegrees(renderInfo.getXRot()));
matrixStack.mulPose(Vector3f.YP.rotationDegrees(renderInfo.getYRot() + 180));
matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z);
return matrixStack.last().pose();
}
/**
* create a new projection matrix and send it over to the GPU
* <br><br>
* A lot of this code is copied from renderLevel (line 567)
* in the GameRender class. The code copied is anything with
* a matrixStack and is responsible for making sure the LOD
* objects distort correctly relative to the rest of the world.
* Distortions are caused by: standing in a nether portal,
* nausea potion effect, walking bobbing.
*
* @param partialTicks how many ticks into the frame we are
*/
private void setupProjectionMatrix(float partialTicks)
{
// Note: if the LOD objects don't distort correctly
// compared to regular minecraft terrain, make sure
// all the transformations in renderWorld are here too
MatrixStack matrixStack = new MatrixStack();
matrixStack.pushPose();
gameRender.bobHurt(matrixStack, partialTicks);
if (this.mc.options.bobView) {
gameRender.bobView(matrixStack, partialTicks);
}
// potion and nausea effects
float f = MathHelper.lerp(partialTicks, this.mc.player.oPortalTime, this.mc.player.portalTime) * this.mc.options.screenEffectScale * this.mc.options.screenEffectScale;
if (f > 0.0F) {
int i = this.mc.player.hasEffect(Effects.CONFUSION) ? 7 : 20;
float f1 = 5.0F / (f * f + 5.0F) - f * 0.04F;
f1 = f1 * f1;
Vector3f vector3f = new Vector3f(0.0F, MathHelper.SQRT_OF_TWO / 2.0F, MathHelper.SQRT_OF_TWO / 2.0F);
matrixStack.mulPose(vector3f.rotationDegrees((gameRender.tick + partialTicks) * i));
matrixStack.scale(1.0F / f1, 1.0F, 1.0F);
float f2 = -(gameRender.tick + partialTicks) * i;
matrixStack.mulPose(vector3f.rotationDegrees(f2));
}
// this projection matrix allows us to see past the normal
// world render distance
Matrix4f projectionMatrix =
Matrix4f.perspective(
getFov(partialTicks, true),
(float)this.mc.getWindow().getScreenWidth() / (float)this.mc.getWindow().getScreenHeight(),
0.5F,
this.farPlaneDistance * LodConfig.CLIENT.lodChunkRadiusMultiplier.get() * 2);
// add the screen space distortions
projectionMatrix.multiply(matrixStack.last().pose());
gameRender.resetProjectionMatrix(projectionMatrix);
return;
}
/**
* setup the lighting to be used for the LODs
*/
private void setupLighting(LodDimension lodDimension, float partialTicks)
{
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.level.getSkyDarken(partialTicks) : 0.2f;
float gammaMultiplyer = (float)mc.options.gamma - 0.5f;
float lightStrength = ((sunBrightness / 2f) - 0.2f) + (gammaMultiplyer * 0.2f);
float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f};
// can be used for debugging
// if (partialTicks < 0.005)
// ClientProxy.LOGGER.debug(lightStrength);
ByteBuffer temp = ByteBuffer.allocateDirect(16);
temp.order(ByteOrder.nativeOrder());
GL11.glLightfv(LOD_GL_LIGHT_NUMBER, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip());
GL11.glEnable(LOD_GL_LIGHT_NUMBER); // Enable the above lighting
RenderSystem.enableLighting();
}
/**
* Create all buffers that will be used.
*/
private void setupBuffers(int numbChunksWide)
{
// calculate the max amount of memory needed (in bytes)
int bufferMemory = RenderUtil.getBufferMemoryForRadiusMultiplier(LodConfig.CLIENT.lodChunkRadiusMultiplier.get());
// if the required memory is greater than the
// MAX_ALOCATEABLE_DIRECT_MEMORY lower the lodChunkRadiusMultiplier
// to fit.
if (bufferMemory > MAX_ALOCATEABLE_DIRECT_MEMORY)
{
int maxRadiusMultiplier = RenderUtil.getMaxRadiusMultiplierWithAvaliableMemory(LodConfig.CLIENT.lodTemplate.get(), LodConfig.CLIENT.lodDetail.get());
ClientProxy.LOGGER.warn("The lodChunkRadiusMultiplier was set too high "
+ "and had to be lowered to fit memory constraints "
+ "from " + LodConfig.CLIENT.lodChunkRadiusMultiplier.get() + " "
+ "to " + maxRadiusMultiplier);
LodConfig.CLIENT.lodChunkRadiusMultiplier.set(
maxRadiusMultiplier);
bufferMemory = RenderUtil.getBufferMemoryForRadiusMultiplier(maxRadiusMultiplier);
}
drawableNearBuffer = new BufferBuilder(bufferMemory);
drawableFarBuffer = new BufferBuilder(bufferMemory);
lodBufferBuilder.setupBuffers(bufferMemory);
}
//======================//
// Other Misc Functions //
//======================//
/**
* If this is called then the next time "drawLODs" is called
* the LODs will be regenerated; the same as if the player moved.
*/
public void regenerateLODsNextFrame()
{
regen = true;
}
/**
* Replace the current drawable buffers with the newly
* created buffers from the lodBufferBuilder.
*/
private void swapBuffers()
{
// replace the drawable buffers with
// the newly created buffers from the lodBufferBuilder
NearFarBuffer newBuffers = lodBufferBuilder.swapBuffers(drawableNearBuffer, drawableFarBuffer);
drawableNearBuffer = newBuffers.nearBuffer;
drawableFarBuffer = newBuffers.farBuffer;
// bind the buffers with their respective VBOs
if (nearVbo != null)
nearVbo.close();
nearVbo = new VertexBuffer(LOD_VERTEX_FORMAT);
nearVbo.upload(drawableNearBuffer);
if (farVbo != null)
farVbo.close();
farVbo = new VertexBuffer(LOD_VERTEX_FORMAT);
farVbo.upload(drawableFarBuffer);
}
private double getFov(float partialTicks, boolean useFovSetting)
{
return mc.gameRenderer.getFov(mc.gameRenderer.getMainCamera(), partialTicks, useFovSetting);
}
/**
* Return what fog settings should be used when rendering.
*/
private NearFarFogSettings determineFogSettings()
{
NearFarFogSettings fogSettings = new NearFarFogSettings();
FogQuality quality = reflectionHandler.getFogQuality();
FogDrawOverride override = LodConfig.CLIENT.fogDrawOverride.get();
if (quality == FogQuality.OFF)
fogSettings.vanillaIsRenderingFog = false;
else
fogSettings.vanillaIsRenderingFog = true;
// use any fog overrides the user may have set
switch(override)
{
case ALWAYS_DRAW_FOG_FANCY:
quality = FogQuality.FANCY;
break;
case NEVER_DRAW_FOG:
quality = FogQuality.OFF;
break;
case ALWAYS_DRAW_FOG_FAST:
quality = FogQuality.FAST;
break;
case USE_OPTIFINE_FOG_SETTING:
// don't override anything
break;
}
// only use fancy fog if the user's GPU can deliver
if (!fancyFogAvailable && quality == FogQuality.FANCY)
{
quality = FogQuality.FAST;
}
// how different distances are drawn depends on the quality set
switch(quality)
{
case FANCY:
fogSettings.near.quality = FogQuality.FANCY;
fogSettings.far.quality = FogQuality.FANCY;
switch(LodConfig.CLIENT.fogDistance.get())
{
case NEAR_AND_FAR:
fogSettings.near.distance = FogDistance.NEAR;
fogSettings.far.distance = FogDistance.FAR;
break;
case NEAR:
fogSettings.near.distance = FogDistance.NEAR;
fogSettings.far.distance = FogDistance.NEAR;
break;
case FAR:
fogSettings.near.distance = FogDistance.FAR;
fogSettings.far.distance = FogDistance.FAR;
break;
}
break;
case FAST:
fogSettings.near.quality = FogQuality.FAST;
fogSettings.far.quality = FogQuality.FAST;
// fast fog setting should only have one type of
// fog, since the LODs are separated into a near
// and far portion; and fast fog is rendered from the
// frustrum's perspective instead of the camera
switch(LodConfig.CLIENT.fogDistance.get())
{
case NEAR_AND_FAR:
fogSettings.near.distance = FogDistance.NEAR;
fogSettings.far.distance = FogDistance.NEAR;
break;
case NEAR:
fogSettings.near.distance = FogDistance.NEAR;
fogSettings.far.distance = FogDistance.NEAR;
break;
case FAR:
fogSettings.near.distance = FogDistance.FAR;
fogSettings.far.distance = FogDistance.FAR;
break;
}
break;
case OFF:
fogSettings.near.quality = FogQuality.OFF;
fogSettings.far.quality = FogQuality.OFF;
break;
}
return fogSettings;
}
/**
* Get a HashSet of all ChunkPos within the normal render distance
* that should not be rendered.
*/
private HashSet<ChunkPos> getNearbyLodChunkPosToSkip(LodDimension lodDim, BlockPos playerPos)
{
int chunkRenderDist = mc.options.renderDistance;
int blockRenderDist = chunkRenderDist * 16;
ChunkPos centerChunk = new ChunkPos(playerPos);
// skip chunks that are already going to be rendered by Minecraft
HashSet<ChunkPos> posToSkip = getRenderedChunks();
// go through each chunk within the normal view distance
for(int x = centerChunk.x - chunkRenderDist; x < centerChunk.x + chunkRenderDist; x++)
{
for(int z = centerChunk.z - chunkRenderDist; z < centerChunk.z + chunkRenderDist; z++)
{
LodChunk lod = lodDim.getLodFromCoordinates(x, z);
if (lod != null)
{
short lodHighestPoint = lod.calculateHighestPoint();
if (playerPos.getY() < lodHighestPoint)
{
// don't draw Lod's that are taller than the player
// to prevent LODs being drawn on top of the player
posToSkip.add(new ChunkPos(x, z));
}
else if (blockRenderDist < Math.abs(playerPos.getY() - lodHighestPoint))
{
// draw Lod's that are lower than the player's view range
posToSkip.remove(new ChunkPos(x, z));
}
}
}
}
return posToSkip;
}
/**
* This method returns the ChunkPos of all chunks that Minecraft
* is going to render this frame. <br><br>
*
* Note: This isn't perfect. It will return some chunks that are outside
* 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).
*/
public static HashSet<ChunkPos> getRenderedChunks()
{
HashSet<ChunkPos> loadedPos = new HashSet<>();
Minecraft mc = Minecraft.getInstance();
// Wow those are some long names!
// go through every RenderInfo to get the compiled chunks
for(WorldRenderer.LocalRenderInformationContainer worldrenderer$localrenderinformationcontainer : mc.levelRenderer.renderChunks)
{
if (!worldrenderer$localrenderinformationcontainer.chunk.getCompiledChunk().hasNoRenderableLayers())
{
// add the ChunkPos for every empty compiled chunk
BlockPos bpos = worldrenderer$localrenderinformationcontainer.chunk.getOrigin();
loadedPos.add(new ChunkPos(bpos.getX() / 16, bpos.getZ() / 16));
}
}
return loadedPos;
}
}
@@ -1,111 +0,0 @@
/*
* This file is part of 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.render;
import com.seibel.lod.enums.LodDetail;
import com.seibel.lod.enums.LodTemplate;
import com.seibel.lod.handlers.LodConfig;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.ChunkPos;
/**
* This holds miscellaneous helper code
* to be used in the rendering process.
*
* @author James Seibel
* @version 6-17-2021
*/
public class RenderUtil
{
private static final Minecraft mc = Minecraft.getInstance();
/**
* Returns if the given ChunkPos is in the loaded area of the world.
* @param centerCoordinate the center of the loaded world (probably the player's ChunkPos)
*/
public static boolean isChunkPosInLoadedArea(ChunkPos pos, ChunkPos center)
{
Minecraft mc = Minecraft.getInstance();
return (pos.x >= center.x - mc.options.renderDistance
&& pos.x <= center.x + mc.options.renderDistance)
&&
(pos.z >= center.z - mc.options.renderDistance
&& pos.z <= center.z + mc.options.renderDistance);
}
/**
* Returns if the given coordinate is in the loaded area of the world.
* @param centerCoordinate the center of the loaded world
*/
public static boolean isCoordinateInLoadedArea(int i, int j, int centerCoordinate)
{
Minecraft mc = Minecraft.getInstance();
return (i >= centerCoordinate - mc.options.renderDistance
&& i <= centerCoordinate + mc.options.renderDistance)
&&
(j >= centerCoordinate - mc.options.renderDistance
&& j <= centerCoordinate + mc.options.renderDistance);
}
/**
* Find the coordinates that are in the center half of the given
* 2D matrix, starting at (0,0) and going to (2 * lodRadius, 2 * lodRadius).
*/
public static boolean isCoordinateInNearFogArea(int i, int j, int lodRadius)
{
int halfRadius = lodRadius / 2;
return (i >= lodRadius - halfRadius
&& i <= lodRadius + halfRadius)
&&
(j >= lodRadius - halfRadius
&& j <= lodRadius + halfRadius);
}
/**
* Get how much buffer memory would be required for the given radius multiplier
*/
public static int getBufferMemoryForRadiusMultiplier(int radiusMultiplier)
{
int numbChunksWide = mc.options.renderDistance *
radiusMultiplier * 2;
// calculate the max amount of buffer memory needed (in bytes)
return numbChunksWide * numbChunksWide *
LodConfig.CLIENT.lodTemplate.get().
getBufferMemoryForSingleLod(LodConfig.CLIENT.lodDetail.get());
}
/**
* Returns the maxViewDistanceMultiplier for the given LodTemplate
* at the given LodDetail level.
*/
public static int getMaxRadiusMultiplierWithAvaliableMemory(LodTemplate lodTemplate, LodDetail lodDetail)
{
int maxNumberOfLods = LodRenderer.MAX_ALOCATEABLE_DIRECT_MEMORY / lodTemplate.getBufferMemoryForSingleLod(lodDetail);
int numbLodsWide = (int) Math.sqrt(maxNumberOfLods);
return numbLodsWide / (2 * mc.options.renderDistance);
}
}
@@ -1,257 +0,0 @@
/*
* This file is part of 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.util;
import java.awt.Color;
import java.io.File;
import com.seibel.lod.objects.LodRegion;
import com.seibel.lod.objects.RegionPos;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.DimensionType;
import net.minecraft.world.IWorld;
import net.minecraft.world.chunk.ChunkSection;
import net.minecraft.world.chunk.IChunk;
import net.minecraft.world.server.ServerChunkProvider;
import net.minecraft.world.server.ServerWorld;
/**
* This class holds methods that may be used in multiple places.
*
* @author James Seibel
* @version 06-27-2021
*/
public class LodUtil
{
private static Minecraft mc = Minecraft.getInstance();
/**
* Gets the first valid ServerWorld.
*
* @return null if there are no ServerWorlds
*/
public static ServerWorld getFirstValidServerWorld()
{
if (mc.hasSingleplayerServer())
return null;
Iterable<ServerWorld> worlds = mc.getSingleplayerServer().getAllLevels();
for (ServerWorld world : worlds)
return world;
return null;
}
/**
* Gets the ServerWorld for the relevant dimension.
*
* @return null if there is no ServerWorld for the given dimension
*/
public static ServerWorld getServerWorldFromDimension(DimensionType dimension)
{
IntegratedServer server = mc.getSingleplayerServer();
if (server == null)
return null;
Iterable<ServerWorld> worlds = server.getAllLevels();
ServerWorld returnWorld = null;
for (ServerWorld world : worlds)
{
if(world.dimensionType() == dimension)
{
returnWorld = world;
break;
}
}
return returnWorld;
}
/**
* Convert the given ChunkPos into a RegionPos.
*/
public static RegionPos convertChunkPosToRegionPos(ChunkPos pos)
{
RegionPos rPos = new RegionPos();
rPos.x = pos.x / LodRegion.SIZE;
rPos.z = pos.z / LodRegion.SIZE;
// prevent issues if X/Z is negative and less than 16
if (pos.x < 0)
{
rPos.x = (Math.abs(rPos.x) * -1) - 1;
}
if (pos.z < 0)
{
rPos.z = (Math.abs(rPos.z) * -1) - 1;
}
return rPos;
}
/**
* Return whether the given chunk
* has any data in it.
*/
public static boolean chunkHasBlockData(IChunk chunk)
{
ChunkSection[] blockStorage = chunk.getSections();
for(ChunkSection section : blockStorage)
{
if(section != null && !section.isEmpty())
{
return true;
}
}
return false;
}
public static String getCurrentDimensionID()
{
Minecraft mc = Minecraft.getInstance();
if(mc.hasSingleplayerServer())
{
// this will return the world save location
// and the dimension folder
if(mc.level == null)
return "";
ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(mc.level.dimensionType());
if(serverWorld == null)
return "";
ServerChunkProvider provider = serverWorld.getChunkSource();
if(provider == null)
return "";
return provider.dataStorage.dataFolder.toString();
}
else
{
ServerData server = mc.getCurrentServer();
return server.name + ", IP " +
server.ip + ", GameVersion " +
server.version.getString() + File.separatorChar
+ "dim_" + mc.level.dimensionType().effectsLocation().getPath() + File.separatorChar;
}
}
/**
* If on single player this will return the name of the user's
* world and the dimensional save folder, if in multiplayer
* it will return the server name, game version, and dimension.<br>
* <br>
* This can be used to determine where to save files for a given
* dimension.
*/
public static String getDimensionIDFromWorld(IWorld world)
{
Minecraft mc = Minecraft.getInstance();
if(mc.hasSingleplayerServer())
{
// this will return the world save location
// and the dimension folder
ServerWorld serverWorld = LodUtil.getServerWorldFromDimension(world.dimensionType());
if(serverWorld == null)
throw new NullPointerException("getDimensionIDFromWorld wasn't able to get the ServerWorld for the dimension " + world.dimensionType().effectsLocation().getPath());
ServerChunkProvider provider = serverWorld.getChunkSource();
if(provider == null)
throw new NullPointerException("getDimensionIDFromWorld wasn't able to get the ServerChunkProvider for the dimension " + world.dimensionType().effectsLocation().getPath());
return provider.dataStorage.dataFolder.toString();
}
else
{
ServerData server = mc.getCurrentServer();
return server.name + ", IP " +
server.ip + ", GameVersion " +
server.version.getString() + File.separatorChar
+ "dim_" + world.dimensionType().effectsLocation().getPath() + File.separatorChar;
}
}
/**
* If on single player this will return the name of the user's
* world, if in multiplayer it will return the server name
* and game version.
*/
public static String getWorldID(IWorld world)
{
if(mc.hasSingleplayerServer())
{
// chop off the dimension ID as it is not needed/wanted
String dimId = getDimensionIDFromWorld(world);
// get the world name
int saveIndex = dimId.indexOf("saves") + 1 + "saves".length();
int slashIndex = dimId.indexOf(File.separatorChar, saveIndex);
dimId = dimId.substring(saveIndex, slashIndex);
return dimId;
}
else
{
ServerData server = mc.getCurrentServer();
return server.name + ", IP " +
server.ip + ", GameVersion " +
server.version.getString();
}
}
/**
* Convert a BlockColors int into a Color object.
*/
public static Color intToColor(int num)
{
int filter = 0b11111111;
int red = (num >> 16 ) & filter;
int green = (num >> 8 ) & filter;
int blue = num & filter;
return new Color(red, green, blue);
}
/**
* Convert a Color into a BlockColors object.
*/
public static int colorToInt(Color color)
{
return color.getRGB();
}
}
@@ -1,43 +0,0 @@
/*
* This file is part of 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.util;
/**
* This holds meta information about the mod.
*
* @author James Seibel
* @version 04-16-2020
*/
public class Reference
{
/** the mod's identifier */
public static final String MOD_ID = "lod";
/** the mod's name */
public static final String NAME = "LOD Mod";
/** the mod's version */
public static final String VERSION = "1.0";
/** the version of minecraft this mod is built for */
public static final String ACCEPTED_VERSIONS = "[1.16.4]";
/** where the client proxy class is */
public static final String CLIENT_PROXY_CLASS = "com.backsun.lod.proxy.ClientProxy";
/** where the common proxy class is*/
public static final String COMMON_PROXY_CLASS = "com.backsun.lod.proxy.CommonProxy";
}
@@ -44,6 +44,13 @@ public net.minecraft.world.lighting.WorldLightManager field_215576_a # blockEngi
public net.minecraft.world.lighting.WorldLightManager field_215577_b # skyEngine
public net.minecraft.world.gen.feature.Feature field_236290_a_ # configuredCodec
# used for uploading vertex buffers off the render thread
public net.minecraft.client.renderer.vertex.VertexBuffer field_177365_a # id
public net.minecraft.client.renderer.vertex.VertexBuffer field_177363_b # format
public net.minecraft.client.renderer.vertex.VertexBuffer field_177364_c # vertexCount
# used for accessing the lightmap
public net.minecraft.client.renderer.LightTexture field_205111_b # lightPixels
#=====================#
+11 -10
View File
@@ -11,10 +11,10 @@ loaderVersion="[36,)" #mandatory This is typically bumped every Minecraft versio
#// The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
#// Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
license="All rights reserved"
license="GNU GPLv3"
#// A URL to refer people to when problems occur with this mod
#//issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
issueTrackerURL="https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues" #optional
#// A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
@@ -24,27 +24,28 @@ modId="lod" #mandatory
#// The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
#//${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
#// see the associated build.gradle script for how to populate this completely automatically during a build
version="a1.3" #mandatory
version="a1.5.3" #mandatory
#// A display name for the mod
displayName="Level of Detail" #mandatory
displayName="Distant Horizons" #mandatory
#// A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
#//updateJSONURL="https://change.me.example.invalid/updates.json" #optional
#// A URL for the "homepage" for this mod, displayed in the mod UI
#//displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
displayURL="https://www.curseforge.com/minecraft/mc-mods/lod-level-of-detail" #optional
#// A file name (in the root of the mod JAR) containing a logo for display
#//logoFile="examplemod.png" #optional
logoFile="logo.png" #optional
#// A file name (in the root of the mod JAR) containing a icon for display by catalogue
catalogueImageIcon="icon.png"
#// A text field displayed in the mod UI
credits="TechnoVision, Vike, and Darkhax for their modding tutorials." #optional
#// A text field displayed in the mod UI
authors="James Seibel" #optional
authors="James Seibel, Leonardo Amato, and Cola" #optional
#// The description text for the mod (multi line!) (#mandatory)
description='''
This mod generates and renders simplified chunks beyond the normal view distance, at a low performance cost.
'''
description='''This mod generates and renders simplified terrain beyond the normal view distance, at a low performance cost.'''
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+1 -1
View File
@@ -1,6 +1,6 @@
{
"required": true,
"package": "com.seibel.lod.mixin",
"package": "com.seibel.lod.forge.mixins",
"compatibilityLevel": "JAVA_8",
"refmap": "lod.refmap.json",
"mixins": [
Binary file not shown.

After

Width:  |  Height:  |  Size: 191 KiB

-16
View File
@@ -1,16 +0,0 @@
[
{
"modid": "lod",
"name": "Level Of Detail",
"description": "Generates and renders simplified chunks beyond the normal view distance, at a low performance cost.",
"version": "a1.3",
"mcversion": "1.16.4",
"url": "",
"updateUrl": "",
"authorList": ["James Seibel"],
"credits": "TechnoVision, Vike, and Darkhax for their modding tutorials.",
"logoFile": "",
"screenshots": [],
"dependencies": []
}
]
+1 -1
View File
@@ -1,6 +1,6 @@
{
"pack": {
"description": "examplemod resources",
"description": "",
"pack_format": 6,
"_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods."
}