Compare commits

...

218 Commits

Author SHA1 Message Date
s809 f12f119ce2 Refactor thread pool handling 2025-01-06 23:32:29 +05:00
s809 fda44c41a8 Add comments to UPDATE_POS_MANAGER.maxSize and refactor 2025-01-04 22:11:26 +05:00
James Seibel 8247f5f215 add comments to DhLitWorldGenRegion.getBlockTicks() 2025-01-04 10:50:56 -06:00
James Seibel 7eba6848bb Merge branch 'distant-horizons-fix/disable-scheduled-ticks' 2025-01-04 10:17:09 -06:00
James Seibel 6e84cac0d2 Fix infinitely growing memory and add warnings if memory isn't enough 2025-01-04 10:12:03 -06:00
s809 2bf96ea781 Update core 2025-01-04 19:25:48 +05:00
James Seibel d5de4a8171 Fix sqlite memory leaks 2025-01-03 14:47:42 -06:00
James Seibel 3cd7c7f1a3 remove pmcVer from forge runClient 2025-01-03 14:47:18 -06:00
ishland 1741ebf8b2 change: remove block and fluid scheduled tick access as it is unneeded 2025-01-03 16:57:34 +08:00
s809 55776f8beb Update core 2025-01-03 01:04:13 +05:00
s809 a469770e5d Check for updates on launch on dedicated servers 2025-01-03 00:30:15 +05:00
s809 851dabc18b Fix 1.16.5 compilation 2025-01-02 20:20:32 +05:00
s809 dccdbaeb73 Rename serversideShortName to chatCommandName 2025-01-02 19:43:01 +05:00
s809 f4126f5378 Add descriptions to config entries in commands 2025-01-01 20:33:01 +05:00
s809 97af075c7d Use correct world folder name in LAN level key prefix 2025-01-01 18:13:25 +05:00
James Seibel 1dfdd422db Potentially fix EXCEPTION_ACCESS_VIOLATION rendering crash 2024-12-31 09:08:25 -06:00
James Seibel 072082c56a handle corrupted data better 2024-12-28 13:45:43 -06:00
James Seibel 43caa2a55c Fix neoforge running in release 2024-12-28 13:45:17 -06:00
James Seibel b8bad9b6bf fix compiling for MC 1.20.4 2024-12-27 18:12:14 -06:00
James Seibel 8afdd6ed2b Fix typo preventing threadpools from running 2024-12-27 18:11:58 -06:00
James Seibel 34968a6945 Add schedule fix mixin to neoforge
also fix old fabric compiling
2024-12-27 09:25:54 -06:00
James Seibel 851a79a77e Fix compiling on older MC versions 2024-12-27 09:18:00 -06:00
James Seibel 1ca1db705f Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2024-12-27 08:48:16 -06:00
James Seibel 8f57c2cce2 Only have a single thread config 2024-12-27 08:47:20 -06:00
s809 942e3093cb Respond to incompatible packets so the client is able to display an error in F3 2024-12-27 17:05:07 +05:00
s809 f3e65010f1 Fix failed counter working incorrectly 2024-12-27 15:51:47 +05:00
s809 b3cfb35fac Update core 2024-12-26 16:09:29 +05:00
s809 b60d778303 Use library provided method for filling *ArrayLists 2024-12-25 23:12:58 +05:00
James Seibel 9ec28aa661 Fix beacons not appearing chunks pulled from distant generation 2024-12-25 09:31:01 -06:00
James Seibel 98400a9d3c Fix mod compat warning chat not hiding with config 2024-12-25 09:17:44 -06:00
James Seibel ae8658ae77 Fix DH preventing server shutdown on close 2024-12-25 09:04:55 -06:00
James Seibel e928fe3ecd Fix not loaded tick schedule warning in world gen
"Trying to schedule tick in not loaded position" can log in MC 1.21.4 when sand or other FallingBlock.class blocks attempt to generate in a DH context (IE the chunk isn't loaded in the server).
2024-12-25 08:23:33 -06:00
James Seibel 963dc4a404 minor DhLitWorldGenregion refactor 2024-12-25 08:21:42 -06:00
James Seibel 04f42999df potentially fix rare null pointer 2024-12-24 08:54:28 -06:00
James Seibel 730d014f13 Fix compiling on for MC before 1.21.1 2024-12-24 08:09:02 -06:00
James Seibel 1f81c50ce1 Fix lag/errors when pulling pre-existing chunks 2024-12-24 08:02:01 -06:00
James Seibel f60c550879 Massively reduce memory use and fix object leaks 2024-12-22 09:17:49 -06:00
James Seibel 0d556b5d95 Attempt to fix stuttering in MC 1.21.4 for pre-existing chunk pulling 2024-12-20 15:36:36 -06:00
James Seibel 70d897f09c add config assumePreExistingChunksAreFinished 2024-12-20 15:27:03 -06:00
James Seibel 9accb6d584 refactor testGenericWorldGen to support hotswapping 2024-12-20 14:02:30 -06:00
James Seibel 843dc580c8 Repo and Obj Pool rewrite
This should provide a significant reduction in garbage generated, reducing GC pressure.
2024-12-20 13:38:47 -06:00
James Seibel 77aa4773ef Fix some bugs and reduce GC load slightly 2024-12-14 23:35:36 -06:00
James Seibel fc3c944e3d remove timeout from chunk IoWorker in world gen 2024-12-14 23:35:29 -06:00
James Seibel 7d6aecc4c7 Merge branch 'distant-horizons-feature/server-backed-distant-gen'
Also remove ChunkWrapper LevelReader parameter
2024-12-14 14:07:16 -06:00
James Seibel 528beb8384 Revert chunky core changes 2024-12-14 12:21:56 -06:00
James Seibel 5f1180a5dd Revert "Fix holes when using Chunky" 2024-12-14 12:21:39 -06:00
James Seibel a9f1e8587c Revert "change the chunky warning message"
This reverts commit 77a366065d.
2024-12-14 12:20:27 -06:00
James Seibel 7a076f5509 re-add full (server) distant generator mode 2024-12-13 07:26:55 -06:00
James Seibel 3349e51655 minor batchGenEnv renaming 2024-12-13 07:25:47 -06:00
James Seibel 77a366065d change the chunky warning message 2024-12-12 21:05:19 -06:00
James Seibel c2d6ecaae6 Fix holes when using Chunky
(at the cost of some server lag)
2024-12-12 20:56:48 -06:00
James Seibel c9bc830058 Fix null pointer in LodRenderSection 2024-12-12 07:46:41 -06:00
James Seibel 6125031d9d Remove world gen timeout config
It didn't work as originally intended. It was originally added to prevent world gen lock-ups if a thread hits and infinite loop, but it didn't do anything for that use case and just ended up being annoying for low-end users.
2024-12-12 06:59:10 -06:00
s809 c041cde574 Show thread preset in config entries in server command 2024-12-10 20:19:03 +05:00
s809 bd946af229 Add player into request group before trying to fulfill 2024-12-09 16:48:24 +05:00
s809 559626456a Prune world gen tasks above limit in multiplayer 2024-12-09 12:03:53 +05:00
s809 c6843c1d95 Revert "Fix gen tasks sometimes not submitting after LOD level changes"
This reverts commit 585a288f
2024-12-08 19:33:20 +05:00
James Seibel 0d32fab434 Fix off-by-one error in DhAPI Terrain Repo
Specifically getting by blockpos
2024-12-07 15:08:40 -06:00
James Seibel 94571de00f Improve Chunk LOD building (thanks builderb0y!) 2024-12-07 11:45:02 -06:00
James Seibel d062eff8b4 Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2024-12-07 11:20:28 -06:00
James Seibel b1e46faf6f Fix GLWrapper compiling for MC 1.16 2024-12-07 11:20:09 -06:00
James Seibel 04ed5b2e03 Replace many GL32 calls with GLMC (IMinecraftGLWrapper) 2024-12-07 09:56:50 -06:00
s809 15d9ff503f Re-add pruning of visitedPositions 2024-12-06 23:32:59 +05:00
s809 64942d77e4 Use N-sized generation on server when available 2024-12-06 23:10:53 +05:00
s809 f287dbd4d3 Merge branch 'NSizedMultiplayerTest' 2024-12-04 23:40:00 +05:00
James Seibel c387f57d9c Add MC 1.21.4 to the CI build script 2024-12-03 20:21:10 -06:00
James Seibel 2dacb91b79 Add MC 1.21.4 support 2024-12-03 20:17:50 -06:00
James Seibel d809568cc3 update Iris/Sodium dependency versions for 1.21.1
Just used for compiling and consistency, shouldn't change anything
2024-12-03 19:44:04 -06:00
James Seibel beee44df14 Add fabric-api >= 0.110.1 requirement for MC 1.21.3 2024-12-03 19:40:29 -06:00
s809 f651fc4b50 Up protocol version 2024-12-03 21:23:41 +05:00
s809 596e4eae0e Fix gen tasks sometimes not submitting after LOD level changes 2024-12-03 21:13:01 +05:00
James Seibel 6e70073ae4 Add visited position removal timer in RemoteFullDataSourceProvider 2024-12-02 07:51:12 -06:00
James Seibel 1beef2b4ad Fix a potential null pointer in world gen chunk loading 2024-12-02 07:18:42 -06:00
James Seibel a0e4ed8371 Fix 1.20.4 compiling 2024-12-01 21:06:30 -06:00
James Seibel f40adfd9c6 Merge !70 (Fix invisible gui button in MC 1.21.3) 2024-12-01 17:52:32 -06:00
James Seibel 7fb5e95809 Add Fabric 1.21.3 support
Also fixes:
`Mod was built with a newer version of Loom (1.8.9), you are using Loom (1.7.415)`
2024-12-01 17:43:09 -06:00
James Seibel 03d5cb9289 Fix compiling for Java 8 2024-12-01 17:06:53 -06:00
James Seibel 3b4b4d6b7e Remove unused world gen MixinData thread local 2024-12-01 17:00:22 -06:00
James Seibel b9a97a0fda Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2024-12-01 15:51:42 -06:00
James Seibel 0dae6942cb Update coreSubProjects 2024-12-01 15:51:27 -06:00
James Seibel 8bb6aeb526 up the manifold version 2024.1.35 -> 37 2024-12-01 15:50:54 -06:00
James Seibel 32ec420248 Merge !68 (Fix slowdown when C2ME is installed)
Thanks ishland for the fix!
2024-12-01 15:50:41 -06:00
s809 1925537da0 Lower log level of out of range warning 2024-11-22 14:54:48 +05:00
James Seibel 3bb4c21fa2 Fix forge compiling for some versions 2024-11-21 19:22:25 -06:00
James Seibel 5b61a98196 Fix race condition when generating terrain extremely quickly 2024-11-21 19:00:57 -06:00
James Seibel 7c6eba983a Fix auto updater attempting to update to "null" 2024-11-19 07:32:54 -06:00
James Seibel 0023ab09ed Fix auto updater not appearing on neoforge 2024-11-19 07:32:27 -06:00
James Seibel c289f5d717 minor format cleanup 2024-11-19 06:58:12 -06:00
watertrainer 6df3ad722c delete done TODO 2024-11-19 11:30:43 +00:00
watertrainer 56f6abd858 ensure clientLevel is loaded, even if player gets redirected (fixes #869) 2024-11-19 11:30:00 +00:00
James Seibel c326e0ba81 Fix a rare error where chunk lighting is set to -1 2024-11-18 07:46:27 -06:00
James Seibel 60b28fcf2e Fix sometimes not loading high-detail LODs when on a server 2024-11-18 07:40:24 -06:00
James Seibel a9ffd3bd3b Forgot to remove all of manifold string gradle 2024-11-18 07:15:33 -06:00
James Seibel bc72e925df Remove manifold string plugin 2024-11-17 08:03:15 -06:00
James Seibel 108df99633 up version number 2.3.0-a -> 2.3.0-b 2024-11-16 22:07:41 -06:00
James Seibel ba245ea266 Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2024-11-16 22:03:48 -06:00
James Seibel ec721ce172 minor build.gradle formatting change 2024-11-16 21:59:28 -06:00
James Seibel 3ad2a95c10 up fabric loader version in 1.21.1 2024-11-16 21:59:15 -06:00
James Seibel e22e241d06 revert accidental change to gradle.properties default version 2024-11-16 21:58:18 -06:00
James Seibel cd70d55b4d comment to remove unused fabricLike gradle references 2024-11-16 21:30:58 -06:00
James Seibel b6c98d3bde Append mod loader to merged jars 2024-11-16 21:25:50 -06:00
s809 5fe605540d Replace Apache's base32 with guava 2024-11-15 09:33:10 +05:00
s809 c232b64f24 Add a comment to #pluginMessageReceived methods 2024-11-14 15:52:46 +05:00
s809 f94b6dbaa5 Replace truncating the hashed seed with encoding it into base32 2024-11-14 15:23:57 +05:00
James Seibel 928bc5df6c Fix setting saturation to 0 crashing the game 2024-11-13 18:26:32 -06:00
James Seibel a5865b3545 Decrease Min mcmeta version from 16 -> 7
should still fix #832
mcmeta files were re-added since forge needs them for certain resource files to load
2024-11-11 07:13:04 -06:00
James Seibel 8f15ab7ccd Revert "Close #832 (remove pack.mcmeta)"
This reverts commit 70550a21a0.
2024-11-11 06:58:15 -06:00
James Seibel 131e4124f3 fix getHashedSeed again from merge 2024-11-09 21:21:21 -06:00
James Seibel ae6333c7b5 Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2024-11-09 21:19:36 -06:00
James Seibel d38c622d9b Fix compiling due to incomplete IDhLevel changes 2024-11-09 21:19:01 -06:00
James Seibel fe625e5b55 Fix ColorUtil impot in ClientLevelWrapper 2024-11-09 21:07:23 -06:00
James Seibel 38a6ad552b Fix height fog 2024-11-09 20:58:59 -06:00
s809 222a008514 Remove seed hash from local & server worlds, and expose DH's level identifier to API 2024-11-09 22:37:05 +05:00
James Seibel 56684bdf4c Fix some render thread tasks not running (causing holes) 2024-11-09 09:53:45 -06:00
James Seibel eb4525c68d Update coreSubProjects 2024-11-09 08:49:23 -06:00
James Seibel 66eb2ed0f9 Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2024-11-09 08:49:05 -06:00
James Seibel 9866842e01 Improve Buffer uploading speed and remove buffer upload thread 2024-11-09 08:48:29 -06:00
coolGi e9487b0481 Updated readme to use the new DH links 2024-11-09 14:40:00 +00:00
James Seibel 82c5aa907b Buffer upload speed test 2024-11-08 07:46:17 -06:00
James Seibel 47b145cb90 up neoforge version 21.3.4 -> 21.3.11 2024-11-07 07:30:46 -06:00
James Seibel ff46b925b2 minor config screen refactoring 2024-11-07 07:30:30 -06:00
James Seibel 8ca7ff5ae0 Fix crashing after server shutdown in serverPlayerDisconnectEvent 2024-11-06 07:08:36 -06:00
James Seibel 70550a21a0 Close #832 (remove pack.mcmeta)
DH doesn't use resource pack files so these files are unnecessary and just cause warnings.
2024-11-06 07:01:55 -06:00
James Seibel 50f911f63c Fix unnecessary logging for JarUtil jarFile getting
Closes #733
2024-11-05 07:32:49 -06:00
James Seibel 4b0dca5823 re-add missing ColorUtil import 2024-11-04 19:34:50 -06:00
James Seibel 0e777f04bc Add hashed seed to server level folders to replace multiverse similarity
Closes !514 and Closes !476
2024-11-04 18:31:04 -06:00
s809 b12f27cc18 Fix Flashback crash on dimension loading 2024-11-03 19:20:20 +05:00
James Seibel 1a66f457af add recalculate heightmap config (disabled by default) 2024-11-02 13:09:03 -05:00
James Seibel b4dca6a1b4 Fix MC_CLIENT.getPlayerCount() null pointer 2024-11-02 13:06:10 -05:00
James Seibel 7759a2f9ea Fix air.isSolid() crash 2024-11-02 13:05:56 -05:00
James Seibel fe9bccb91f add 1.21.3 to nightly builds (still no fabric) 2024-11-02 11:29:55 -05:00
James Seibel fc6fd310f6 use gradle for shared fabric launch config 2024-11-02 11:21:20 -05:00
James Seibel 8be161b381 Add MC 1.21.3 support for Neoforge (no fabric) 2024-11-02 11:21:03 -05:00
James Seibel 8eba8cb40b gradle wrapper 2024-10-30 20:49:22 -05:00
James Seibel 44326344e6 update fabric api dependency for 1.21.1 2024-10-29 20:01:59 -05:00
James Seibel 17b7ee9045 Increase the default render distance 128 -> 256 2024-10-27 16:13:54 -05:00
s809 6a47a2150f Fix too many chunks spam 2024-10-26 00:33:48 +05:00
James Seibel 13728a7540 Closes !825 (Cache arrays used in generic object upload) 2024-10-25 07:40:48 -05:00
James Seibel c51e941413 Fix the update screen logo scaling 2024-10-24 07:07:51 -05:00
James Seibel 2a05c32a2f Fix DH fade corrupting the GL state 2024-10-22 16:28:07 -05:00
James Seibel 353a507914 Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2024-10-22 15:33:16 -05:00
James Seibel f3b73d54f8 Update coreSubProjects 2024-10-22 15:33:13 -05:00
s809 92ed9b8070 Update core 2024-10-22 23:55:50 +05:00
s809 9c3c37bc3e Use earlier event for storing server instance 2024-10-22 23:55:37 +05:00
James Seibel 79fb7c654a Add warning if chunky is installed 2024-10-21 13:27:28 -04:00
James Seibel 520b4e0930 add ClientUtil.argbToInt() 2024-10-21 08:53:26 -04:00
s809 45a07206c9 Update core 2024-10-21 16:43:46 +05:00
s809 ad0b78936a Enable multiplayer in 1.16.5 2024-10-21 16:43:39 +05:00
s809 2babae40de Multiply update queue size by player count 2024-10-20 20:04:35 +05:00
s809 17713a9f93 Make sure data source received from file handler is fully generated before sending to client 2024-10-20 15:15:15 +05:00
s809 48120a4a38 Move commands under /dh, add /dh debug command 2024-10-20 15:14:03 +05:00
s809 69ffd795c9 Split commands into classes 2024-10-20 01:39:16 +05:00
s809 1df5dd5458 Up protocol version 2024-10-18 11:18:34 +05:00
James Seibel b77acaa3b2 Fix javadoc compiling and some Mac lockup issues 2024-10-15 07:47:59 -05:00
s809 d8024ab488 Use version specific caches 2024-10-15 00:33:15 +05:00
James Seibel 064d8b3506 Fix default beacon culling setting 2024-10-14 07:41:13 -05:00
James Seibel 9ca6a2116b Fix Forge compiling 2024-10-14 07:40:24 -05:00
James Seibel 449c87982c Add additional run configurations 2024-10-14 07:12:44 -05:00
James Seibel 7edfc40b9d Split the config file, update the config UI, and remove a few unused configs 2024-10-12 20:39:42 -05:00
James Seibel 9acda97f54 Fix N-sized world gen causing holes when moving 2024-10-12 09:53:46 -05:00
James Seibel 14edd63029 Fix adjacent chunk lighting (thanks CreepermeYT) 2024-10-11 22:14:01 -05:00
James Seibel f3a1235dd3 Fix core standalone jar running (hopefully this doesn't bork Quilt) 2024-10-10 07:44:15 -05:00
James Seibel de93bfee2f Fix 1.16.5 and 1.17 compiling 2024-10-10 06:56:03 -05:00
James Seibel 6eb80ace00 Fix world gen incorrectly returning some data sources to the pool 2024-10-08 20:17:33 -05:00
s809 3ac8d6a8b1 Fix incorrect name of a method 2024-10-08 22:59:00 +05:00
s809 269c8dc4e3 Fix incorrect folder being used without level keys 2024-10-08 22:37:55 +05:00
James Seibel c8173005a7 Decrease vertical quality drop off 2024-10-08 07:51:39 -05:00
James Seibel ed846ea564 merge !67 (Add Mojang Maven repository to fix arm64 MacOS builds) 2024-10-08 07:23:39 -05:00
James Seibel f6a8f5c6b5 Prevent returning out of bounds ColumnArrayView's 2024-10-08 07:07:53 -05:00
s809 3c60a7d842 Fix keyed levels not changing 2024-10-08 09:05:27 +05:00
James Seibel 3c97feeaf8 add comment about spongepowered vanilla gradle versions 2024-10-07 20:16:27 -05:00
James Seibel b2ac91f7db Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2024-10-07 19:45:37 -05:00
James Seibel 1ebad39fc1 Update the API to allow for N-sized world generation requests
This breaks old world generators
2024-10-07 19:45:33 -05:00
James Seibel 38a2edff06 fix batch gen environment exception name 2024-10-07 18:19:39 -05:00
s809 b2cf38798e Fix unhandled message spam in replay mod 2024-10-06 01:47:51 +05:00
s809 ed83e41f19 Use level key prefixes to in LAN multiplayer 2024-10-06 00:20:07 +05:00
s809 6d52cdba0a Prevent server crash on shutdown 2024-10-05 21:30:01 +05:00
s809 05449c9e86 Decouple beacon beam data handling from render handling, send beacon beams to clients 2024-10-05 14:03:08 +05:00
James Seibel 33ef1297ba Close !66 (add IDhApiLevelWrapper.getDhSaveFolder()) 2024-10-04 07:46:09 -05:00
James Seibel 3b13786990 Improve beacon fade rendering 2024-10-03 20:25:26 -05:00
James Seibel 222d06898e Fix zoom mods breaking DH's fade/near clip plane 2024-10-03 17:25:54 -05:00
James Seibel 4438adad24 Improve fade config, add localization, and add fading to the quality presets 2024-10-03 17:10:56 -05:00
James Seibel 986e474657 Add fading to Forge and Neo, fix fading rain, fix old MC compiling 2024-10-03 07:36:11 -05:00
James Seibel e8288a0df9 Fix fade rendering when DH rendering is disabled 2024-10-02 18:16:46 -05:00
James Seibel 74cab8f4ad replace random noise with Bayer for dithering 2024-10-02 18:08:57 -05:00
James Seibel 5e35572de8 Improve overdraw prevention quality 2024-10-02 07:49:46 -05:00
James Seibel 7e0e02bafc Add dithered DH fading, double pass fading, and fix LOD clouds 2024-10-01 22:02:45 -05:00
James Seibel a301532443 merge core changes 2024-09-30 22:00:06 -05:00
James Seibel 940448f219 Add experimental DH/vanilla fading 2024-09-30 21:59:25 -05:00
James Seibel 8510deb6aa Merge branch 'main' of gitlab.com:distant-horizons-team/distant-horizons 2024-09-28 15:28:08 -05:00
s809 0d0ba5d3bf Do not sync sections after generation, fix incorrect timestamp fetch pos range calculation 2024-09-29 01:18:04 +05:00
James Seibel 036371dd76 Remove multiverse similarity percent and add IDhApiSaveStructure
Similarity percent should no longer be needed since the server support was added
2024-09-28 14:30:38 -05:00
James Seibel 5aae584ffe Fix F3 menu showing the same level multiple times 2024-09-28 10:22:47 -05:00
James Seibel 201c619915 Add Api world load/unload events and DhApiWorldProxy.get/setReadOnly() 2024-09-28 08:33:30 -05:00
James Seibel 7cd6a3bb79 Add temporary vertical Quality CUSTOM option
This is temporary since it's just for determining what values we want long term and adding full control will over-complicate the config
2024-09-26 22:34:38 -05:00
James Seibel ca36d4797d Add hashCode() to FullDataPointIdMap 2024-09-26 07:42:31 -05:00
James Seibel b5fe3bcbf9 Up manifold version 2024.1.30 -> 2024.1.32 2024-09-25 21:58:08 -05:00
James Seibel e43f9e76f6 Change FullDataSourceDTO checksum/hash logic to hopefully be more consistent 2024-09-25 21:57:54 -05:00
James Seibel b8901c3edd Fix default generic rendering instanced mode 2024-09-25 18:44:47 -05:00
James Seibel d28938f8af fix readme logo filepaths 2024-09-22 17:25:19 -05:00
James Seibel 9f108220f5 Update readme logos 2024-09-22 17:23:41 -05:00
James Seibel ffe53a7196 Add new logos 2024-09-22 17:19:00 -05:00
James Seibel 9e12849107 Allow toggling generic obj instanced rendering via config 2024-09-22 16:32:51 -05:00
s809 0a8c093682 Fix missing testAnnotationProcessor 2024-09-23 01:18:39 +05:00
s809 60056e1654 Merge branch 'feature/lan-support' 2024-09-23 00:46:56 +05:00
s809 11a752a99d Fix dedicated server failing to send packets 2024-09-23 00:43:00 +05:00
s809 68097f61eb LAN multiplayer kinda works 2024-09-23 00:02:57 +05:00
James Seibel 8b514b07dc Move mod compat warnings into AbstractModInit and add WWOO to the list 2024-09-22 08:09:31 -05:00
s809 8e6010bbe5 Abstract away serverside parts of world & level 2024-09-22 03:29:07 +05:00
James Seibel 95eb07ca79 add commented out attempt at relocating Sqlite 2024-09-21 11:47:40 -05:00
James Seibel e6e03e78ea try upping manifold_version 2024.1.30 -> 2023.1.17 again
Please revert if compiler messages don't appear correctly
2024-09-21 11:47:16 -05:00
James Seibel d2c572414c up Sqlite version 3.43.0.0 -> 3.46.1.0 2024-09-21 11:46:42 -05:00
James Seibel d2e0d5b32b relocate org.slf4j to partially fix old XaeroPlus 2024-09-21 11:46:17 -05:00
James Seibel d4ba227a44 Fix config file handler corruption due to reading/writing concurrently 2024-09-20 07:29:41 -05:00
James Seibel caba007899 Add pshsh, to the author list 2024-09-20 07:08:37 -05:00
James Seibel d5cfe9b8e9 Revert Iris 1.8 requirement since it didn't work correctly 2024-09-19 19:59:52 -05:00
James Seibel f1707236fa Replace incompatible Iris<=1.7.4 with <1.8.0 to hopefully reduce confusion 2024-09-19 07:31:14 -05:00
James Seibel c55cbdb69a Mark Oculus 1.7 and lower as incompatible on forge 2024-09-19 07:30:10 -05:00
144 changed files with 4024 additions and 1567 deletions
+1 -1
View File
@@ -688,7 +688,7 @@ ij_markdown_wrap_text_inside_blockquotes = true
ij_toml_keep_indents_on_empty_lines = false
[{*.yaml,*.yml}]
indent_size = 4
indent_size = 2
ij_yaml_align_values_properties = do_not_align
ij_yaml_autoinsert_sequence_marker = true
ij_yaml_block_mapping_on_new_line = false
+2 -2
View File
@@ -18,7 +18,7 @@ variables:
.build_java:
#image: eclipse-temurin:17
cache:
key: "gradleCache"
key: "gradleCache_$CI_JOB_NAME_SLUG"
policy: pull-push
paths:
- .gradle
@@ -35,7 +35,7 @@ build:
stage: build
parallel:
matrix:
- MC_VER: ["1.16.5", "1.17.1", "1.18.2", "1.19.2", "1.19.4", "1.20.1", "1.20.2", "1.20.4", "1.20.6", "1.21.1"]
- MC_VER: ["1.16.5", "1.17.1", "1.18.2", "1.19.2", "1.19.4", "1.20.1", "1.20.2", "1.20.4", "1.20.6", "1.21.1", "1.21.3", "1.21.4"]
script:
# this both runs the unit tests and assembles the code
- ./gradlew clean -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="distant-horizons [build]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="build" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="distant-horizons [clean]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="clean" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="distant-horizons [core:build]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="core:build" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="distant-horizons [fabric:runClient]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="fabric:runClient" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="distant-horizons [forge:runClient]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="forge:runClient" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="distant-horizons [mergeJars]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="mergeJars" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="distant-horizons [neoforge:runClient]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="neoforge:runClient" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+24
View File
@@ -0,0 +1,24 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="distant-horizons [test]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="test" />
</list>
</option>
<option name="vmOptions" />
</ExternalSystemSettings>
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
<DebugAllEnabled>false</DebugAllEnabled>
<RunAsTest>false</RunAsTest>
<method v="2" />
</configuration>
</component>
+1
View File
@@ -0,0 +1 @@
Distant Horizons logos © 2024 by Pankakes are licensed under CC BY-SA 4.0
+3 -3
View File
@@ -1,4 +1,4 @@
# <img src="https://gitlab.com/jeseibel/distant-horizons-core/-/raw/main/_Misc%20Files/logo%20files/LOD%20logo%20flat%20-%20with%20boarder.png" width="32"> Distant Horizons
# <img src="https://gitlab.com/distant-horizons-team/distant-horizons-core/-/raw/main/_Misc%20Files/logo%20files/new/SVG/Distant-Horizons.svg" height="128px">
_See farther without turning your game into a slide show._
<br>
@@ -131,14 +131,14 @@ Prerequisites:
From the File Explorer:
1. Download and extract the project zip
2. Download the core from https://gitlab.com/jeseibel/distant-horizons-core and extract into a folder called `coreSubProjects`
2. Download the core from https://gitlab.com/distant-horizons-team/distant-horizons-core and extract into a folder called `coreSubProjects`
3. Open a terminal emulator in the project folder (On Windows you can type `cmd` in the title bar)
4. Run the commands: `./gradlew assemble` (You may need to use a `.\` on Windows)
5. Merge the jars with `./gradlew mergeJars`
6. The compiled jar file will be in the folder `Merged`
From the command line:
1. `git clone --recurse-submodules https://gitlab.com/jeseibel/distant-horizons.git`
1. `git clone --recurse-submodules https://gitlab.com/distant-horizons-team/distant-horizons.git`
2. `cd distant-horizons`
3. `./gradlew assemble`
4. `./gradlew mergeJars`
+49 -12
View File
@@ -11,7 +11,7 @@ plugins {
id "systems.manifold.manifold-gradle-plugin" version "0.0.2-alpha"
// Architectury is used here only as a replacement for forge's own loom
id "dev.architectury.loom" version "1.6-SNAPSHOT" apply false
id "dev.architectury.loom" version "1.7-SNAPSHOT" apply false
}
@@ -66,8 +66,11 @@ writeBuildGradlePredefine(rootProject.mcVers, rootProject.mcIndex)
rootProject.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version // + "-" + new Date().format("yyyy_MM_dd_HH_mm")
// Forgix settings (used for merging jars)
forgix {
String loaderHyphenSeparatedList = ((String)gradle.builds_for).replaceAll(",", "-");
group = "com.seibel.distanthorizons"
mergedJarName = "DistantHorizons-${rootProject.versionStr}.jar"
mergedJarName = "DistantHorizons-${rootProject.versionStr}-${loaderHyphenSeparatedList}.jar"
if (findProject(":forge"))
forge {
@@ -159,6 +162,7 @@ subprojects { p ->
if (findProject(":neoforge"))
developmentNeoForge.extendsFrom coreProjects
// TODO remove unused fabricLike
if (findProject(":fabricLike") && p != project(":fabricLike")) {
// Shadow fabricLike
fabricLike
@@ -181,10 +185,19 @@ subprojects { p ->
}
// Log4j
// TODO: Change to shadowMe later to work in the standalone jar
// We cannot do this now as it would break Quilt
implementation("org.apache.logging.log4j:log4j-api:${rootProject.log4j_version}")
implementation("org.apache.logging.log4j:log4j-core:${rootProject.log4j_version}")
if (p == project(":core"))
{
// the standalone core jar needs logging shaded otherwise it won't run
forgeShadowMe("org.apache.logging.log4j:log4j-api:${rootProject.log4j_version}")
forgeShadowMe("org.apache.logging.log4j:log4j-core:${rootProject.log4j_version}")
}
else
{
// When running in MC, MC already includes logging
implementation("org.apache.logging.log4j:log4j-api:${rootProject.log4j_version}")
implementation("org.apache.logging.log4j:log4j-core:${rootProject.log4j_version}")
}
// JOML
if (project.hasProperty("embed_joml") && embed_joml == "true")
@@ -291,9 +304,29 @@ subprojects { p ->
// Compression (LZ4)
relocate "net.jpountz", "${librariesLocation}.jpountz"
// Sqlite Database
//At the moment, there is a bug in this library which doesnt allow it to be relocated
// relocate "org.sqlite", "${librariesLocation}.sqlite"
// Logging
relocate "org.slf4j", "${librariesLocation}.slf4j"
// // Sqlite Database
// // James can't determine how to relocate the library correctly so this is commented out
// relocate ("org.sqlite", "${librariesLocation}.sqlite") {
// exclude("org/sqlite/core/NativeDB/**")
//
// exclude("org/sqlite/native/FreeBSD/**")
// exclude("org/sqlite/native/Linux-Android/**")
// exclude("org/sqlite/native/Linux-Musl/**")
// exclude("org/sqlite/native/Linux/arm/**")
// exclude("org/sqlite/native/Linux/aarch64/**")
// exclude("org/sqlite/native/Linux/armv6/**")
// exclude("org/sqlite/native/Linux/x86/**")
// exclude("org/sqlite/native/Linux/armv7/**")
// exclude("org/sqlite/native/Linux/ppc64/**")
// exclude("org/sqlite/native/Linux/riscv64/**")
// exclude("org/sqlite/native/Windows/armv7/**")
// exclude("org/sqlite/native/Windows/aarch64/**")
// exclude("org/sqlite/native/Windows/armv7/**")
// }
// JOML
if (project.hasProperty("embed_joml") && embed_joml == "true")
@@ -386,7 +419,7 @@ subprojects { p ->
info_build_source : infoBuildSource,
fabric_incompatibility_list : fabric_incompatibility_list,
fabric_recommend_list : fabric_recommend_list,
fabric_recommend_list : fabric_recommend_list,
]
// replace any properties in the sub-projects with the values defined here
@@ -434,7 +467,8 @@ subprojects { p ->
attributes(
'Implementation-Title': rootProject.mod_name,
'Implementation-Version': rootProject.mod_version,
'Main-Class': 'com.seibel.distanthorizons.core.jar.JarMain' // When changing the main of the jar change this line
'Multi-Release': true, // needed for logging in the standalone core jar
'Main-Class': 'com.seibel.distanthorizons.core.jar.JarMain', // When changing the main of the jar change this line
)
}
}
@@ -489,6 +523,9 @@ allprojects { p ->
repositories {
// Mojang overrides (added to fix downloading the wrong LWJGL libs on M1 Mac's and potentially other arm64 based machines)
maven { url "https://libraries.minecraft.net/" }
// The central repo
mavenCentral()
@@ -496,6 +533,7 @@ allprojects { p ->
maven { url "https://repo.enonic.com/public/" }
// For parchment mappings
// versions can be found here: https://ldtteam.jfrog.io/ui/native/parchmentmc-public/org/parchmentmc/data/
maven { url "https://maven.parchmentmc.org" }
// For Architectury API
@@ -617,7 +655,6 @@ allprojects { p ->
tasks.withType(JavaCompile) {
if (isMinecraftSubProject) {
options.release = rootProject.java_version as Integer
options.compilerArgs += ["-Xplugin:Manifold"]
} else {
options.release = 8; // Core & Api should use Java 8 no matter what
//options.release = rootProject.java_version as Integer // But if you want to test some stuff, then this can be enabled
+2 -8
View File
@@ -1,17 +1,11 @@
// TODO can this be removed?
//buildscript {
// configurations.configureEach {
// resolutionStrategy {
// force 'org.spongepowered:vanillagradle:0.2.1-20240507.024226-82'
// }
// }
//}
// temporary fix for broken spongepowered version
buildscript {
configurations.configureEach {
resolutionStrategy {
force 'org.spongepowered:vanillagradle:0.2.1-20240507.024226-82'
// newer versions can be found by going to the link:
// https://repo.spongepowered.org/#browse/browse:maven-public:org%2Fspongepowered%2Fvanillagradle%2F0.2.1-SNAPSHOT
}
}
}
@@ -1,28 +1,21 @@
package com.seibel.distanthorizons.common;
import com.mojang.brigadier.Command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.*;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDhInitEvent;
import com.seibel.distanthorizons.common.commands.CommandInitializer;
import com.seibel.distanthorizons.common.wrappers.DependencySetup;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.ConfigBase;
import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler;
import com.seibel.distanthorizons.core.config.types.AbstractConfigType;
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.jar.ModJarInfo;
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.network.messages.base.CodecCrashMessage;
import com.seibel.distanthorizons.core.util.objects.Pair;
import com.seibel.distanthorizons.core.world.DhServerWorld;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
@@ -33,25 +26,9 @@ import net.minecraft.server.dedicated.DedicatedServer;
import org.apache.logging.log4j.Logger;
import java.lang.invoke.MethodHandles;
import java.util.HashMap;
import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
import static com.mojang.brigadier.arguments.DoubleArgumentType.doubleArg;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static com.seibel.distanthorizons.core.network.messages.MessageRegistry.DEBUG_CODEC_CRASH_MESSAGE;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
#if MC_VER >= MC_1_19_2
import net.minecraft.network.chat.Component;
#else // < 1.19.2
import net.minecraft.network.chat.TranslatableComponent;
#endif
/**
* Base for all mod loader initializers
* and handles most setup.
@@ -60,7 +37,7 @@ public abstract class AbstractModInitializer
{
protected static final Logger LOGGER = DhLoggerBuilder.getLogger(MethodHandles.lookup().lookupClass().getSimpleName());
private CommandDispatcher<CommandSourceStack> commandDispatcher;
private CommandInitializer commandInitializer;
@@ -89,7 +66,7 @@ public abstract class AbstractModInitializer
{
DependencySetup.createClientBindings();
LOGGER.info("Initializing " + ModInfo.READABLE_NAME);
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " client.");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
this.startup();
@@ -100,11 +77,12 @@ public abstract class AbstractModInitializer
this.initializeModCompat();
LOGGER.info(ModInfo.READABLE_NAME + " Initialized");
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
// Client uses config for auto-updater, so it's initialized here instead of post-init stage
this.initConfig();
logModIncompatibilityWarnings(); // needs to be called after config loading
this.subscribeClientStartedEvent(this::postInit);
}
@@ -113,7 +91,7 @@ public abstract class AbstractModInitializer
{
DependencySetup.createServerBindings();
LOGGER.info("Initializing " + ModInfo.READABLE_NAME);
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " server.");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
this.startup();
@@ -128,10 +106,10 @@ public abstract class AbstractModInitializer
this.initializeModCompat();
LOGGER.info(ModInfo.READABLE_NAME + " Initialized");
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized.");
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandDispatcher = dispatcher; });
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer = new CommandInitializer(dispatcher); });
this.subscribeServerStartingEvent(server ->
{
@@ -139,7 +117,9 @@ public abstract class AbstractModInitializer
this.initConfig();
this.postInit();
this.initCommands();
this.commandInitializer.initCommands();
this.checkForUpdates();
LOGGER.info("Dedicated server initialized at " + server.getServerDirectory());
});
@@ -183,10 +163,24 @@ public abstract class AbstractModInitializer
private void initConfig()
{
ConfigBase.INSTANCE = new ConfigBase(ModInfo.ID, ModInfo.NAME, Config.class, 2);
ConfigBase.INSTANCE = new ConfigBase(ModInfo.ID, ModInfo.NAME, Config.class, ModInfo.CONFIG_FILE_VERSION);
Config.completeDelayedSetup();
}
private void checkForUpdates()
{
if (Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get())
{
if (Config.Client.Advanced.AutoUpdater.enableSilentUpdates.get())
{
LOGGER.info("Silent updates are not allowed for dedicated servers; force disabling.");
Config.Client.Advanced.AutoUpdater.enableSilentUpdates.set(false);
}
SelfUpdater.onStart();
}
}
private void postInit()
{
LOGGER.info("Post-Initializing Mod");
@@ -194,135 +188,100 @@ public abstract class AbstractModInitializer
LOGGER.info("Mod Post-Initialized");
}
@SuppressWarnings({"rawtypes", "unchecked"})
private void initCommands()
//==================================//
// mod partial compatibility checks //
//==================================//
/**
* Some mods will work with a few tweaks
* or will partially work but have some known issues we can't solve.
* This method will log (and display to chat if enabled)
* these warnings and potential fixes.
*/
private static void logModIncompatibilityWarnings()
{
LiteralArgumentBuilder<CommandSourceStack> builder = literal("dhconfig")
.requires(source -> source.hasPermission(4));
boolean showChatWarnings = Config.Common.Logging.Warning.showModCompatibilityWarningsOnStartup.get();
IModChecker modChecker = SingletonInjector.INSTANCE.get(IModChecker.class);
for (AbstractConfigType<?, ?> type : ConfigBase.INSTANCE.entries)
String startingString = "Partially Incompatible Distant Horizons mod detected: ";
// Alex's caves
if (modChecker.isModLoaded("alexscaves"))
{
if (!(type instanceof ConfigEntry))
// There've been a few reports about this mod breaking DH at a few different points in time
// the fixes for said breakage changes depending on the version so unfortunately
// all we can do is log a warning so the user can handle it.
if (showChatWarnings)
{
continue;
}
//noinspection PatternVariableCanBeUsed
ConfigEntry configEntry = (ConfigEntry) type;
if (configEntry.getServersideShortName() == null)
{
continue;
String message =
// orange text
"\u00A76" + "Distant Horizons: Alex's Cave detected." + "\u00A7r\n" +
"You may have to change Alex's config for DH to render. ";
ClientApi.INSTANCE.showChatMessageNextFrame(message);
}
Function<
Function<CommandContext<CommandSourceStack>, Object>,
Command<CommandSourceStack>
> makeConfigUpdater = (getter) -> (commandContext) -> {
Object value = getter.apply(commandContext);
commandContext.getSource().sendSuccess(
#if MC_VER >= MC_1_20_1
() -> Component.literal("Changed the value of "+configEntry.getServersideShortName()+" to "+value),
#elif MC_VER >= MC_1_19_2
Component.literal("Changed the value of "+configEntry.getServersideShortName()+" to "+value),
#else
new TranslatableComponent("Changed the value of "+configEntry.getServersideShortName()+" to "+value),
#endif
true);
configEntry.set(value);
return 1;
};
LiteralArgumentBuilder<CommandSourceStack> subcommand = literal(configEntry.getServersideShortName())
.executes((commandContext) -> {
#if MC_VER >= MC_1_20_1
commandContext.getSource().sendSuccess(() -> Component.literal("Current value of "+configEntry.getServersideShortName()+" is "+configEntry.get()), true);
#elif MC_VER >= MC_1_19_2
commandContext.getSource().sendSuccess(Component.literal("Current value of "+configEntry.getServersideShortName()+" is "+configEntry.get()), true);
#else // < 1.19.2
commandContext.getSource().sendSuccess(new TranslatableComponent("Current value of "+configEntry.getServersideShortName()+" is "+configEntry.get()), true);
#endif
return 1;
});
if (Enum.class.isAssignableFrom(configEntry.getType()))
{
for (Object choice : configEntry.getType().getEnumConstants())
{
subcommand.then(
literal(choice.toString())
.executes(makeConfigUpdater.apply(c -> choice))
);
}
}
else
{
boolean setterAdded = false;
for (java.util.Map.Entry<Class<?>, Pair<Supplier<ArgumentType<?>>, BiFunction<CommandContext<?>, String, ?>>> pair : new HashMap<
Class<?>,
Pair<
Supplier<ArgumentType<?>>,
BiFunction<CommandContext<?>, String, ?>>
>() {{
this.put(Integer.class, new Pair<>(() -> integer((int) configEntry.getMin(), (int) configEntry.getMax()), IntegerArgumentType::getInteger));
this.put(Double.class, new Pair<>(() -> doubleArg((double) configEntry.getMin(), (double) configEntry.getMax()), DoubleArgumentType::getDouble));
this.put(Boolean.class, new Pair<>(BoolArgumentType::bool, BoolArgumentType::getBool));
this.put(String.class, new Pair<>(StringArgumentType::string, StringArgumentType::getString));
}}.entrySet())
{
if (!pair.getKey().isAssignableFrom(configEntry.getType()))
{
continue;
}
subcommand.then(argument("value", pair.getValue().first.get())
.executes(makeConfigUpdater.apply(c -> pair.getValue().second.apply(c, "value"))));
setterAdded = true;
break;
}
if (!setterAdded)
{
throw new RuntimeException("Config type of "+type.getName()+" is not supported: "+configEntry.getType().getSimpleName());
}
}
builder.then(subcommand);
LOGGER.warn(startingString + "[Alex's Caves] may require some config changes in order to render Distant Horizons correctly.");
}
this.commandDispatcher.register(builder);
if (DEBUG_CODEC_CRASH_MESSAGE)
// William Wythers' Overhauled Overworld (WWOO)
if (modChecker.isModLoaded("wwoo"))
{
LiteralArgumentBuilder<CommandSourceStack> dhcrash = literal("dhcrash")
.requires(source -> source.hasPermission(4))
.then(literal("encode")
.executes(c -> {
assert SharedApi.getIDhServerWorld() != null;
((DhServerWorld) SharedApi.getIDhServerWorld()).remotePlayerConnectionHandler
#if MC_VER >= MC_1_19_2
.getConnectedPlayer(ServerPlayerWrapper.getWrapper(Objects.requireNonNull(c.getSource().getPlayer())))
#else
.getConnectedPlayer(ServerPlayerWrapper.getWrapper(Objects.requireNonNull(c.getSource().getPlayerOrException())))
#endif
.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.ENCODE));
return 1;
}))
.then(literal("decode")
.executes(c -> {
assert SharedApi.getIDhServerWorld() != null;
((DhServerWorld) SharedApi.getIDhServerWorld()).remotePlayerConnectionHandler
#if MC_VER >= MC_1_19_2
.getConnectedPlayer(ServerPlayerWrapper.getWrapper(Objects.requireNonNull(c.getSource().getPlayer())))
#else
.getConnectedPlayer(ServerPlayerWrapper.getWrapper(Objects.requireNonNull(c.getSource().getPlayerOrException())))
#endif
.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.DECODE));
return 1;
}));
this.commandDispatcher.register(dhcrash);
// WWOO has a bug with it's world gen that can't be fixed by DH or WWOO
// (at least that is what James learned after talking with WWOO)
// WWOO will cause grid lines to appear in the world when DH generates the chunks
// this might be due to how WWOO uses features for everything when generating
// and said features don't always get to the edge of said chunks.
String wwooWarning = "LODs generated by DH may have grid lines between sections. Disabling either WWOO or DH's distant generator will fix the problem.";
if (showChatWarnings)
{
String message =
// orange text
"\u00A76" + "Distant Horizons: WWOO detected." + "\u00A7r\n" +
wwooWarning;
ClientApi.INSTANCE.showChatMessageNextFrame(message);
}
LOGGER.warn(startingString + "[WWOO] "+ wwooWarning);
}
// Chunky
boolean chunkyPresent = false;
try
{
Class.forName("org.popcraft.chunky.api.ChunkyAPI");
chunkyPresent = true;
}
catch (ClassNotFoundException ignore) { }
if (chunkyPresent)
{
// Chunky can generate chunks faster than DH can process them,
// causing holes in the LODs.
// Generally it's better and faster to use DH's world generator.
String chunkyWarning = "Chunky can cause DH LODs to have holes " +
"since Chunky can generate chunks faster than DH can process them. \n" +
"Using DH's distant generator instead of chunky or increasing DH's CPU thread count can resolve the issue.";
if (showChatWarnings)
{
String message =
// orange text
"\u00A76" + "Distant Horizons: Chunky detected." + "\u00A7r\n" +
chunkyWarning;
ClientApi.INSTANCE.showChatMessageNextFrame(message);
}
LOGGER.warn(startingString + "[Chunky] "+ chunkyWarning);
}
}
@@ -15,7 +15,6 @@ import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import org.apache.logging.log4j.LogManager;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.util.Objects;
@@ -23,7 +22,7 @@ import java.util.Objects;
public abstract class AbstractPluginPacketSender implements IPluginPacketSender
{
private static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(),
() -> Config.Client.Advanced.Logging.logNetworkEvent.get());
() -> Config.Common.Logging.logNetworkEvent.get());
#if MC_VER >= MC_1_21_1
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
@@ -0,0 +1,83 @@
package com.seibel.distanthorizons.common.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import net.minecraft.commands.CommandSourceStack;
#if MC_VER >= MC_1_19_2
import net.minecraft.network.chat.Component;
import java.util.Objects;
#else // < 1.19.2
import net.minecraft.network.chat.TranslatableComponent;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
#endif
/**
* Abstract class providing common functionality for DH's commands.
*/
public abstract class AbstractCommand
{
public abstract LiteralArgumentBuilder<CommandSourceStack> buildCommand();
/**
* Sends a success response to the player with the given text.
*
* @param commandContext The command context to send the response to.
* @param text The text to display in the success message.
* @return 1, indicating that the command was successful.
*/
protected int sendSuccessResponse(CommandContext<CommandSourceStack> commandContext, String text)
{
#if MC_VER >= MC_1_20_1
commandContext.getSource().sendSuccess(() -> Component.literal(text), true);
#elif MC_VER >= MC_1_19_2
commandContext.getSource().sendSuccess(Component.literal(text), true);
#else
commandContext.getSource().sendSuccess(new TranslatableComponent(text), true);
#endif
return 1;
}
/**
* Gets the server player from a command context.
*
* @param commandContext The command context to get the server player from.
* @return The server player wrapper for the player who sent the command.
*/
protected IServerPlayerWrapper getSourcePlayer(CommandContext<CommandSourceStack> commandContext) #if MC_VER < MC_1_19_2 throws CommandSyntaxException #endif
{
#if MC_VER >= MC_1_19_2
return ServerPlayerWrapper.getWrapper(Objects.requireNonNull(commandContext.getSource().getPlayer()));
#else
return ServerPlayerWrapper.getWrapper(commandContext.getSource().getPlayerOrException());
#endif
}
/**
* Checks if the source of a command is a player.
*
* @param source The source of the command to check.
* @return True if the source is a player, false otherwise.
*/
protected boolean isPlayerSource(CommandSourceStack source)
{
#if MC_VER >= MC_1_19_2
return source.isPlayer();
#else
try
{
source.getPlayerOrException();
return true;
}
catch (CommandSyntaxException e)
{
return false;
}
#endif
}
}
@@ -0,0 +1,48 @@
package com.seibel.distanthorizons.common.commands;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import static com.seibel.distanthorizons.core.network.messages.MessageRegistry.DEBUG_CODEC_CRASH_MESSAGE;
import static net.minecraft.commands.Commands.literal;
/**
* Initializes commands of the mod.
*/
public class CommandInitializer
{
private final CommandDispatcher<CommandSourceStack> commandDispatcher;
/**
* Constructs a new instance of this class.
*
* @param commandDispatcher The dispatcher to use for registering commands.
*/
public CommandInitializer(CommandDispatcher<CommandSourceStack> commandDispatcher)
{
this.commandDispatcher = commandDispatcher;
}
/**
* Initializes all available commands.
*/
public void initCommands()
{
LiteralArgumentBuilder<CommandSourceStack> builder = literal("dh")
.requires(source -> source.hasPermission(4));
builder.then(new ConfigCommand().buildCommand());
builder.then(new DebugCommand().buildCommand());
if (DEBUG_CODEC_CRASH_MESSAGE)
{
builder.then(new CrashCommand().buildCommand());
}
this.commandDispatcher.register(builder);
}
}
@@ -0,0 +1,146 @@
package com.seibel.distanthorizons.common.commands;
import com.mojang.brigadier.arguments.*;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.mojang.brigadier.context.CommandContext;
import com.seibel.distanthorizons.core.config.ConfigBase;
import com.seibel.distanthorizons.core.config.types.AbstractConfigType;
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import net.minecraft.commands.CommandSourceStack;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.function.ToIntBiFunction;
import static com.mojang.brigadier.arguments.DoubleArgumentType.doubleArg;
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
import static net.minecraft.commands.Commands.argument;
import static net.minecraft.commands.Commands.literal;
/**
* Command for managing config.
*/
public class ConfigCommand extends AbstractCommand
{
private static final List<CommandArgumentData<?>> commandArguments = Arrays.asList(
new CommandArgumentData<>(Integer.class, configEntry -> integer(configEntry.getMin(), configEntry.getMax()), IntegerArgumentType::getInteger),
new CommandArgumentData<>(Double.class, configEntry -> doubleArg(configEntry.getMin(), configEntry.getMax()), DoubleArgumentType::getDouble),
new CommandArgumentData<>(Boolean.class, BoolArgumentType::bool, BoolArgumentType::getBool),
new CommandArgumentData<>(String.class, StringArgumentType::string, StringArgumentType::getString)
);
/**
* Builds a command tree.
*/
@Override
@SuppressWarnings({"rawtypes", "unchecked"})
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
{
LiteralArgumentBuilder<CommandSourceStack> builder = literal("config");
for (AbstractConfigType<?, ?> type : ConfigBase.INSTANCE.entries)
{
// Skip non-config entries
if (!(type instanceof ConfigEntry))
{
continue;
}
//noinspection PatternVariableCanBeUsed
ConfigEntry configEntry = (ConfigEntry) type;
if (configEntry.getChatCommandName() == null)
{
continue;
}
LiteralArgumentBuilder<CommandSourceStack> subcommand = literal(configEntry.getChatCommandName())
.executes(commandContext -> this.sendSuccessResponse(commandContext,
"\n" +
"Description of §l" + configEntry.getChatCommandName() + "§r:\n" +
"§o" + configEntry.getComment().trim() + "§r\n" +
"§7Config file name: §f" + configEntry.name + "§7, category: §f" + configEntry.category + "\n" +
"\n" +
"Current value of " + configEntry.getChatCommandName() + " is §n" + configEntry.get() + "§r"
));
ToIntBiFunction<CommandContext<CommandSourceStack>, Object> updateConfigValue = (commandContext, value) -> {
configEntry.set(value);
return this.sendSuccessResponse(commandContext, "Changed the value of ["+configEntry.getChatCommandName()+"] to ["+value+"]");
};
// Enum type needs a special case since enums aren't represented by existing argument type
// and need literals for each individual value
if (Enum.class.isAssignableFrom(configEntry.getType()))
{
for (Object choice : configEntry.getType().getEnumConstants())
{
subcommand.then(
literal(choice.toString())
.executes(c -> updateConfigValue.applyAsInt(c, choice))
);
}
}
else
{
boolean setterAdded = false;
for (CommandArgumentData<?> commandArgumentData : commandArguments)
{
if (!commandArgumentData.argumentClass.isAssignableFrom(configEntry.getType()))
{
continue;
}
subcommand.then(argument("value", commandArgumentData.getArgumentType(configEntry))
.executes(c -> updateConfigValue.applyAsInt(c, commandArgumentData.getValue(c, "value"))));
setterAdded = true;
break;
}
if (!setterAdded)
{
throw new RuntimeException("Config type of " + type.getName() + " is not supported: " + configEntry.getType().getSimpleName());
}
}
builder.then(subcommand);
}
return builder;
}
private static class CommandArgumentData<T>
{
public final Class<T> argumentClass;
public final Function<ConfigEntry<T>, ArgumentType<T>> argumentTypeFunction;
private final BiFunction<CommandContext<CommandSourceStack>, String, T> valueGetter;
public CommandArgumentData(Class<T> argumentClass, Supplier<ArgumentType<T>> argumentTypeSupplier, BiFunction<CommandContext<CommandSourceStack>, String, T> valueGetter)
{
this(argumentClass, configEntry -> argumentTypeSupplier.get(), valueGetter);
}
public CommandArgumentData(Class<T> argumentClass, Function<ConfigEntry<T>, ArgumentType<T>> argumentTypeFunction, BiFunction<CommandContext<CommandSourceStack>, String, T> valueGetter)
{
this.argumentClass = argumentClass;
this.argumentTypeFunction = argumentTypeFunction;
this.valueGetter = valueGetter;
}
public ArgumentType<T> getArgumentType(ConfigEntry<T> configEntry)
{
return this.argumentTypeFunction.apply(configEntry);
}
public T getValue(CommandContext<CommandSourceStack> commandContext, String argumentName)
{
return this.valueGetter.apply(commandContext, argumentName);
}
}
}
@@ -0,0 +1,44 @@
package com.seibel.distanthorizons.common.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.multiplayer.server.ServerPlayerState;
import com.seibel.distanthorizons.core.network.messages.base.CodecCrashMessage;
import net.minecraft.commands.CommandSourceStack;
import static net.minecraft.commands.Commands.literal;
public class CrashCommand extends AbstractCommand
{
@Override
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
{
return literal("crash")
.requires(this::isPlayerSource)
.then(literal("encode")
.executes(c -> {
assert SharedApi.getIDhServerWorld() != null;
ServerPlayerState serverPlayerState = SharedApi.getIDhServerWorld().getServerPlayerStateManager()
.getConnectedPlayer(this.getSourcePlayer(c));
if (serverPlayerState != null)
{
serverPlayerState.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.ENCODE));
}
return 1;
}))
.then(literal("decode")
.executes(c -> {
assert SharedApi.getIDhServerWorld() != null;
ServerPlayerState serverPlayerState = SharedApi.getIDhServerWorld().getServerPlayerStateManager()
.getConnectedPlayer(this.getSourcePlayer(c));
if (serverPlayerState != null)
{
serverPlayerState.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.DECODE));
}
return 1;
}));
}
}
@@ -0,0 +1,25 @@
package com.seibel.distanthorizons.common.commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
import net.minecraft.commands.CommandSourceStack;
import java.util.ArrayList;
import java.util.List;
import static net.minecraft.commands.Commands.literal;
public class DebugCommand extends AbstractCommand
{
@Override
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
{
return literal("debug")
.executes(c -> {
List<String> lines = new ArrayList<>();
F3Screen.addStringToDisplay(lines);
return this.sendSuccessResponse(c, String.join("\n", lines));
});
}
}
@@ -77,7 +77,7 @@ public class MixinChunkMapCommon
// submit the update event
ServerApi.INSTANCE.serverChunkSaveEvent(
new ChunkWrapper(chunk, level, ServerLevelWrapper.getWrapper(level)),
new ChunkWrapper(chunk, ServerLevelWrapper.getWrapper(level)),
ServerLevelWrapper.getWrapper(level)
);
}
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.common.wrappers;
import com.seibel.distanthorizons.common.wrappers.gui.ClassicConfigGUI;
import com.seibel.distanthorizons.common.wrappers.gui.LangWrapper;
import com.seibel.distanthorizons.common.wrappers.level.KeyedClientLevelManager;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
import com.seibel.distanthorizons.core.wrapperInterfaces.config.IConfigGui;
@@ -32,6 +33,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
@@ -69,6 +71,7 @@ public class DependencySetup
SingletonInjector.INSTANCE.bind(IMinecraftClientWrapper.class, MinecraftClientWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IMinecraftSharedWrapper.class, MinecraftClientWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IMinecraftGLWrapper.class, MinecraftGLWrapper.INSTANCE);
SingletonInjector.INSTANCE.bind(IConfigGui.class, ClassicConfigGUI.CONFIG_CORE_INTERFACE);
}
@@ -25,7 +25,12 @@ public class DependencySetupDoneCheck
{
// TODO move to DependencySetup
public static boolean isDone = false;
// TODO why is this here and what is its purpose?
/**
* This is used so we can override some MC logic when running
* in DH's world generator.
* Specifically so we can redirect threads to run on DH threads instead
* of MC threads.
*/
public static Supplier<Boolean> getIsCurrentThreadDistantGeneratorThread = (() -> { return false; });
}
@@ -174,8 +174,6 @@ public class WrapperFactory implements IWrapperFactory
}
// the level is needed for the DH level wrapper...
Level level = (Level) objectArray[1];
// ...the LevelReader is needed for chunk lighting
LevelReader lightSource = level;
// level wrapper
@@ -184,7 +182,7 @@ public class WrapperFactory implements IWrapperFactory
: ServerLevelWrapper.getWrapper((ServerLevel)level);
return new ChunkWrapper(chunk, lightSource, levelWrapper);
return new ChunkWrapper(chunk, levelWrapper);
}
// incorrect number of parameters from the API
else
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.common.wrappers.block;
import java.io.IOException;
import java.util.HashSet;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -226,8 +227,10 @@ public class BiomeWrapper implements IBiomeWrapper
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome);
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
resourceLocation = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).getKey(this.biome.value());
#else
#elif MC_VER < MC_1_21_3
resourceLocation = registryAccess.registryOrThrow(Registries.BIOME).getKey(this.biome.value());
#else
resourceLocation = registryAccess.lookupOrThrow(Registries.BIOME).getKey(this.biome.value());
#endif
if (resourceLocation == null)
@@ -318,10 +321,24 @@ public class BiomeWrapper implements IBiomeWrapper
Biome unwrappedBiome = registryAccess.registryOrThrow(Registry.BIOME_REGISTRY).get(resourceLocation);
success = (unwrappedBiome != null);
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
#else
#elif MC_VER < MC_1_21_3
Biome unwrappedBiome = registryAccess.registryOrThrow(Registries.BIOME).get(resourceLocation);
success = (unwrappedBiome != null);
Holder<Biome> biome = new Holder.Direct<>(unwrappedBiome);
#else
Holder<Biome> biome;
Optional<Holder.Reference<Biome>> optionalBiomeHolder = registryAccess.lookupOrThrow(Registries.BIOME).get(resourceLocation);
if (optionalBiomeHolder.isPresent())
{
Biome unwrappedBiome = optionalBiomeHolder.get().value();
success = (unwrappedBiome != null);
biome = new Holder.Direct<>(unwrappedBiome);
}
else
{
success = false;
biome = null;
}
#endif
@@ -58,6 +58,7 @@ import net.minecraft.world.level.Level;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.core.Holder;
#endif
public class BlockStateWrapper implements IBlockStateWrapper
@@ -142,10 +143,10 @@ public class BlockStateWrapper implements IBlockStateWrapper
BlockState guessBlockState = (guess == null || guess.isAir()) ? null : (BlockState) guess.getWrappedMcObject();
BlockState inputBlockState = (blockState == null || blockState.isAir()) ? null : blockState;
if (guess instanceof BlockStateWrapper guessWrapper
&& guessBlockState == inputBlockState)
if (guess instanceof BlockStateWrapper
&& guessBlockState == inputBlockState)
{
return guessWrapper;
return (BlockStateWrapper) guess;
}
else
{
@@ -235,7 +236,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
HashSet<String> baseIgnoredBlock = new HashSet<>();
baseIgnoredBlock.add(AIR_STRING);
rendererIgnoredBlocks = getBlockWrappers(Config.Client.Advanced.LodBuilding.ignoredRenderBlockCsv, baseIgnoredBlock, levelWrapper);
rendererIgnoredBlocks = getBlockWrappers(Config.Client.Advanced.Graphics.Culling.ignoredRenderBlockCsv, baseIgnoredBlock, levelWrapper);
return rendererIgnoredBlocks;
}
/**
@@ -252,7 +253,7 @@ public class BlockStateWrapper implements IBlockStateWrapper
HashSet<String> baseIgnoredBlock = new HashSet<>();
baseIgnoredBlock.add(AIR_STRING);
rendererIgnoredCaveBlocks = getBlockWrappers(Config.Client.Advanced.LodBuilding.ignoredRenderCaveBlockCsv, baseIgnoredBlock, levelWrapper);
rendererIgnoredCaveBlocks = getBlockWrappers(Config.Client.Advanced.Graphics.Culling.ignoredRenderCaveBlockCsv, baseIgnoredBlock, levelWrapper);
return rendererIgnoredCaveBlocks;
}
@@ -362,7 +363,11 @@ public class BlockStateWrapper implements IBlockStateWrapper
// +1 to indicate that the block is translucent (in between transparent and opaque)
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT + 1;
}
#if MC_VER < MC_1_21_3
else if (this.blockState.propagatesSkylightDown(EmptyBlockGetter.INSTANCE, BlockPos.ZERO))
#else
else if (this.blockState.propagatesSkylightDown())
#endif
{
opacity = LodUtil.BLOCK_FULLY_TRANSPARENT;
}
@@ -415,6 +420,11 @@ public class BlockStateWrapper implements IBlockStateWrapper
@Override
public boolean isSolid()
{
if (this.isAir())
{
return false;
}
#if MC_VER < MC_1_20_1
return this.blockState.getMaterial().isSolid();
#else
@@ -481,8 +491,10 @@ public class BlockStateWrapper implements IBlockStateWrapper
resourceLocation = Registry.BLOCK.getKey(this.blockState.getBlock());
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
resourceLocation = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).getKey(this.blockState.getBlock());
#else
#elif MC_VER < MC_1_21_3
resourceLocation = registryAccess.registryOrThrow(Registries.BLOCK).getKey(this.blockState.getBlock());
#else
resourceLocation = registryAccess.lookupOrThrow(Registries.BLOCK).getKey(this.blockState.getBlock());
#endif
@@ -571,9 +583,13 @@ public class BlockStateWrapper implements IBlockStateWrapper
#elif MC_VER == MC_1_18_2 || MC_VER == MC_1_19_2
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
block = registryAccess.registryOrThrow(Registry.BLOCK_REGISTRY).get(resourceLocation);
#else
#elif MC_VER < MC_1_21_3
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
block = registryAccess.registryOrThrow(Registries.BLOCK).get(resourceLocation);
#else
net.minecraft.core.RegistryAccess registryAccess = level.registryAccess();
Optional<Holder.Reference<Block>> optionalBlockHolder = registryAccess.lookupOrThrow(Registries.BLOCK).get(resourceLocation);
block = optionalBlockHolder.isPresent() ? optionalBlockHolder.get().value() : null;
#endif
@@ -324,12 +324,12 @@ public class ClientBlockStateColorCache
if (count == 0)
{
// this block is entirely transparent
tempColor = ColorUtil.rgbToInt(0, 255, 255, 255);
tempColor = ColorUtil.argbToInt(0, 255, 255, 255);
}
else
{
// determine the average color
tempColor = ColorUtil.rgbToInt(
tempColor = ColorUtil.argbToInt(
alpha / count,
linearToSrgb((float) (red / (double) alpha)),
linearToSrgb((float) (green / (double) alpha)),
@@ -337,10 +337,10 @@ public class ClientBlockStateColorCache
}
//check if not missing texture
if (tempColor == ColorUtil.rgbToInt(255, 182, 0, 182))
if (tempColor == ColorUtil.argbToInt(255, 182, 0, 182))
{
//make it not render at all
tempColor = ColorUtil.rgbToInt(0, 255, 255, 255);
tempColor = ColorUtil.argbToInt(0, 255, 255, 255);
}
return tempColor;
}
@@ -19,9 +19,15 @@
package com.seibel.distanthorizons.common.wrappers.block;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
#if MC_VER < MC_1_17_1
#elif MC_VER < MC_1_21_3
#else
import com.seibel.distanthorizons.core.util.ColorUtil;
import net.minecraft.client.renderer.texture.SpriteContents;
#endif
/**
* For wrapping/utilizing around TextureAtlasSprite
*
@@ -29,15 +35,6 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
*/
public class TextureAtlasSpriteWrapper
{
/**
* This code is from Minecraft Forge
* Which is licensed under the terms of GNU Lesser General Public License
* as published by the Free Software Foundation version 2.1
* of the License.
*
* The code has been modified to use TextureAtlasSprite
*/
public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y)
{
#if MC_VER < MC_1_17_1
@@ -51,13 +48,29 @@ public class TextureAtlasSpriteWrapper
y += sprite.animatedTexture.getFrameY(frameIndex) * sprite.height;
}
return sprite.mainImage[0].getPixelRGBA(x, y);
#else
#elif MC_VER < MC_1_21_3
if (sprite.contents().animatedTexture != null)
{
x += sprite.contents().animatedTexture.getFrameX(frameIndex) * sprite.contents().width();
y += sprite.contents().animatedTexture.getFrameY(frameIndex) * sprite.contents().width();
}
return sprite.contents().originalImage.getPixelRGBA(x, y);
#else
SpriteContents content = sprite.contents(); // don't close, otherwise MC will be corrupted and you won't be able to re-access the texture
if (content.animatedTexture != null)
{
x += content.animatedTexture.getFrameX(frameIndex) * content.width();
y += content.animatedTexture.getFrameY(frameIndex) * content.width();
}
int abgr = content.originalImage.getPixel(x, y);
// re-pack the color so we can access it normally
int a = (abgr & 0xFF000000) >>> 24;
int b = (abgr & 0x00FF0000) >>> 16;
int g = (abgr & 0x0000FF00) >>> 8;
int r = (abgr & 0x000000FF);
return ColorUtil.argbToInt(a, r, g, b);
#endif
}
@@ -42,15 +42,24 @@ public class TintGetterOverrideFast implements BlockAndTintGetter
{
LevelReader parent;
public TintGetterOverrideFast(LevelReader parent)
{
this.parent = parent;
}
//=============//
// constructor //
//=============//
public TintGetterOverrideFast(LevelReader parent) { this.parent = parent; }
//=========//
// methods //
//=========//
private Biome _getBiome(BlockPos pos)
{
#if MC_VER >= MC_1_18_2
return parent.getBiome(pos).value();
return this.parent.getBiome(pos).value();
#else
return parent.getBiome(pos);
#endif
@@ -63,169 +72,123 @@ public class TintGetterOverrideFast implements BlockAndTintGetter
public float getShade(Direction direction, boolean bl) { return this.parent.getShade(direction, bl); }
@Override
public LevelLightEngine getLightEngine()
{
return parent.getLightEngine();
}
public LevelLightEngine getLightEngine() { return this.parent.getLightEngine(); }
@Override
public int getBrightness(LightLayer lightLayer, BlockPos blockPos)
{
return parent.getBrightness(lightLayer, blockPos);
}
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) { return this.parent.getBrightness(lightLayer, blockPos); }
@Override
public int getRawBrightness(BlockPos blockPos, int i)
{
return parent.getRawBrightness(blockPos, i);
}
public int getRawBrightness(BlockPos blockPos, int i) { return this.parent.getRawBrightness(blockPos, i); }
@Override
public boolean canSeeSky(BlockPos blockPos)
{
return parent.canSeeSky(blockPos);
}
public boolean canSeeSky(BlockPos blockPos) { return this.parent.canSeeSky(blockPos); }
@Override
@Nullable
public BlockEntity getBlockEntity(BlockPos blockPos)
{
return parent.getBlockEntity(blockPos);
}
public BlockEntity getBlockEntity(BlockPos blockPos) { return this.parent.getBlockEntity(blockPos); }
@Override
public BlockState getBlockState(BlockPos blockPos)
{
return parent.getBlockState(blockPos);
}
public BlockState getBlockState(BlockPos blockPos) { return this.parent.getBlockState(blockPos); }
@Override
public FluidState getFluidState(BlockPos blockPos)
{
return parent.getFluidState(blockPos);
}
public FluidState getFluidState(BlockPos blockPos) { return this.parent.getFluidState(blockPos); }
@Override
public int getLightEmission(BlockPos blockPos)
{
return parent.getLightEmission(blockPos);
}
public int getLightEmission(BlockPos blockPos) { return this.parent.getLightEmission(blockPos); }
#if MC_VER < MC_1_21_3
@Override
public int getMaxLightLevel()
{
return parent.getMaxLightLevel();
}
public int getMaxLightLevel() { return parent.getMaxLightLevel(); }
#else
#endif
@Override
public Stream<BlockState> getBlockStates(AABB aABB)
{
return parent.getBlockStates(aABB);
}
{ return this.parent.getBlockStates(aABB); }
@Override
public BlockHitResult clip(ClipContext clipContext)
{
return parent.clip(clipContext);
}
{ return this.parent.clip(clipContext); }
@Override
@Nullable
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState)
{
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
}
{ return this.parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState); }
@Override
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier)
{
return parent.getBlockFloorHeight(voxelShape, supplier);
}
{ return this.parent.getBlockFloorHeight(voxelShape, supplier); }
@Override
public double getBlockFloorHeight(BlockPos blockPos)
{
return parent.getBlockFloorHeight(blockPos);
}
public double getBlockFloorHeight(BlockPos blockPos) { return this.parent.getBlockFloorHeight(blockPos); }
#if MC_VER < MC_1_21_3
@Override
public int getMaxBuildHeight()
{
return parent.getMaxBuildHeight();
}
public int getMaxBuildHeight() { return this.parent.getMaxBuildHeight(); }
#else
@Override
public int getMaxY() { return this.parent.getMaxY(); }
#endif
//==============//
// post MC 1.17 //
//==============//
#if MC_VER >= MC_1_17_1
@Override
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType)
{
return parent.getBlockEntity(blockPos, blockEntityType);
}
{ return this.parent.getBlockEntity(blockPos, blockEntityType); }
@Override
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext)
{
return parent.isBlockInLine(clipBlockStateContext);
}
{ return this.parent.isBlockInLine(clipBlockStateContext); }
@Override
public int getHeight()
{
return parent.getHeight();
}
public int getHeight() { return this.parent.getHeight(); }
#if MC_VER < MC_1_21_3
@Override
public int getMinBuildHeight() { return this.parent.getMinBuildHeight(); }
#else
@Override
public int getMinY() { return this.parent.getMinY(); }
#endif
@Override
public int getMinBuildHeight()
{
return parent.getMinBuildHeight();
}
public int getSectionsCount() { return this.parent.getSectionsCount(); }
#if MC_VER < MC_1_21_3
@Override
public int getMinSection() { return this.parent.getMinSection(); }
#else
@Override
public int getMinSectionY() { return BlockAndTintGetter.super.getMinSectionY(); }
#endif
#if MC_VER < MC_1_21_3
@Override
public int getMaxSection() { return this.parent.getMaxSection(); }
#else
@Override
public int getMaxSectionY() { return this.parent.getMaxSectionY(); }
#endif
@Override
public int getSectionsCount()
{
return parent.getSectionsCount();
}
public boolean isOutsideBuildHeight(BlockPos blockPos) { return this.parent.isOutsideBuildHeight(blockPos); }
@Override
public int getMinSection()
{
return parent.getMinSection();
}
public boolean isOutsideBuildHeight(int i) { return this.parent.isOutsideBuildHeight(i); }
@Override
public int getMaxSection()
{
return parent.getMaxSection();
}
public int getSectionIndex(int i) { return this.parent.getSectionIndex(i); }
@Override
public boolean isOutsideBuildHeight(BlockPos blockPos)
{
return parent.isOutsideBuildHeight(blockPos);
}
public int getSectionIndexFromSectionY(int i) { return this.parent.getSectionIndexFromSectionY(i); }
@Override
public boolean isOutsideBuildHeight(int i)
{
return parent.isOutsideBuildHeight(i);
}
@Override
public int getSectionIndex(int i)
{
return parent.getSectionIndex(i);
}
@Override
public int getSectionIndexFromSectionY(int i)
{
return parent.getSectionIndexFromSectionY(i);
}
@Override
public int getSectionYFromSectionIndex(int i)
{
return parent.getSectionYFromSectionIndex(i);
}
public int getSectionYFromSectionIndex(int i) { return this.parent.getSectionYFromSectionIndex(i); }
#endif
}
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.common.wrappers.block;
import com.seibel.distanthorizons.core.util.LodUtil;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Cursor3D;
import net.minecraft.core.Direction;
@@ -44,16 +45,28 @@ public class TintGetterOverrideSmooth implements BlockAndTintGetter
LevelReader parent;
public int smoothingRange;
//=============//
// constructor //
//=============//
public TintGetterOverrideSmooth(LevelReader parent, int smoothingRange)
{
this.parent = parent;
this.smoothingRange = smoothingRange;
}
//=========//
// methods //
//=========//
private Biome _getBiome(BlockPos pos)
{
#if MC_VER >= MC_1_18_2
return parent.getBiome(pos).value();
return this.parent.getBiome(pos).value();
#else
return parent.getBiome(pos);
#endif
@@ -113,8 +126,11 @@ public class TintGetterOverrideSmooth implements BlockAndTintGetter
@Override
public int getLightEmission(BlockPos blockPos) { return this.parent.getLightEmission(blockPos); }
#if MC_VER < MC_1_21_3
@Override
public int getMaxLightLevel() { return this.parent.getMaxLightLevel(); }
#else
#endif
@Override
public Stream<BlockState> getBlockStates(AABB aABB) { return this.parent.getBlockStates(aABB); }
@@ -135,8 +151,13 @@ public class TintGetterOverrideSmooth implements BlockAndTintGetter
@Override
public double getBlockFloorHeight(BlockPos blockPos) { return this.parent.getBlockFloorHeight(blockPos); }
#if MC_VER < MC_1_21_3
@Override
public int getMaxBuildHeight() { return this.parent.getMaxBuildHeight(); }
#else
@Override
public int getMaxY() { return this.parent.getMaxY(); }
#endif
#if MC_VER >= MC_1_17_1
@Override
@@ -148,17 +169,32 @@ public class TintGetterOverrideSmooth implements BlockAndTintGetter
@Override
public int getHeight() { return this.parent.getHeight(); }
#if MC_VER < MC_1_21_3
@Override
public int getMinBuildHeight() { return this.parent.getMinBuildHeight(); }
#else
@Override
public int getMinY() { return this.parent.getMinY(); }
#endif
@Override
public int getSectionsCount() { return this.parent.getSectionsCount(); }
#if MC_VER < MC_1_21_3
@Override
public int getMinSection() { return this.parent.getMinSection(); }
#else
@Override
public int getMinSectionY() { return BlockAndTintGetter.super.getMinSectionY(); }
#endif
#if MC_VER < MC_1_21_3
@Override
public int getMaxSection() { return this.parent.getMaxSection(); }
#else
@Override
public int getMaxSectionY() { return this.parent.getMaxSectionY(); }
#endif
@Override
public boolean isOutsideBuildHeight(BlockPos blockPos) { return this.parent.isOutsideBuildHeight(blockPos); }
@@ -132,17 +132,27 @@ public class TintWithoutLevelOverrider implements BlockAndTintGetter
}
//==============//
// post MC 1.17 //
//==============//
#if MC_VER >= MC_1_17_1
@Override
public int getHeight()
{
throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
{ throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelOverrider. Object is for tinting only."); }
#if MC_VER < MC_1_21_3
@Override
public int getMinBuildHeight()
{
throw new UnsupportedOperationException("ERROR: getMinBuildHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
{ throw new UnsupportedOperationException("ERROR: getMinBuildHeight() called on TintWithoutLevelOverrider. Object is for tinting only."); }
#else
@Override
public int getMinY()
{ throw new UnsupportedOperationException("ERROR: getMinY() called on TintWithoutLevelOverrider. Object is for tinting only."); }
#endif
#endif
}
@@ -39,11 +39,24 @@ public class TintWithoutLevelSmoothOverrider implements BlockAndTintGetter
final BiomeWrapper biome;
public int smoothingRange;
//=============//
// constructor //
//=============//
public TintWithoutLevelSmoothOverrider(BiomeWrapper biome, int smoothingRange)
{
this.biome = biome;
this.smoothingRange = smoothingRange;
}
//=========//
// methods //
//=========//
@Override
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
{
@@ -57,7 +70,7 @@ public class TintWithoutLevelSmoothOverrider implements BlockAndTintGetter
return biome;
#endif
}
//
// public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
// {
// int i = smoothingRange;
@@ -89,44 +102,43 @@ public class TintWithoutLevelSmoothOverrider implements BlockAndTintGetter
@Override
public float getShade(Direction direction, boolean shade)
{
throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
{ throw new UnsupportedOperationException("ERROR: getShade() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
@Override
public LevelLightEngine getLightEngine()
{
throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
{ throw new UnsupportedOperationException("ERROR: getLightEngine() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos)
{
throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
{ throw new UnsupportedOperationException("ERROR: getBlockEntity() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
@Override
public BlockState getBlockState(BlockPos pos)
{
throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
{ throw new UnsupportedOperationException("ERROR: getBlockState() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
@Override
public FluidState getFluidState(BlockPos pos)
{
throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
{ throw new UnsupportedOperationException("ERROR: getFluidState() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
//==============//
// post MC 1.17 //
//==============//
#if MC_VER >= MC_1_17_1
@Override
public int getHeight()
{
throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
{ throw new UnsupportedOperationException("ERROR: getHeight() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
#if MC_VER < MC_1_21_3
@Override
public int getMinBuildHeight()
{
throw new UnsupportedOperationException("ERROR: getMinBuildHeight() called on TintWithoutLevelOverrider. Object is for tinting only.");
}
{ throw new UnsupportedOperationException("ERROR: getMinBuildHeight() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
#else
@Override
public int getMinY()
{ throw new UnsupportedOperationException("ERROR: getMinY() called on TintWithoutLevelSmoothOverrider. Object is for tinting only."); }
#endif
#endif
}
@@ -22,13 +22,11 @@ package com.seibel.distanthorizons.common.wrappers.chunk;
import com.seibel.distanthorizons.common.wrappers.block.BiomeWrapper;
import com.seibel.distanthorizons.common.wrappers.block.BlockStateWrapper;
import com.seibel.distanthorizons.common.wrappers.misc.MutableBlockPosWrapper;
import com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject.DhLitWorldGenRegion;
import com.seibel.distanthorizons.core.api.internal.SharedApi;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.world.EWorldEnvironment;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
@@ -36,19 +34,14 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IMutableBlockPosWr
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import net.minecraft.client.multiplayer.ClientChunkCache;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.ProtoChunk;
import net.minecraft.world.level.levelgen.Heightmap;
import org.apache.logging.log4j.Logger;
import java.util.*;
import java.util.concurrent.ConcurrentLinkedQueue;
#if MC_VER >= MC_1_17_1
import net.minecraft.core.QuartPos;
@@ -72,8 +65,6 @@ import net.minecraft.world.level.chunk.LevelChunkSection;
#if MC_VER >= MC_1_20_1
import net.minecraft.world.level.chunk.LevelChunkSection;
import net.minecraft.world.level.lighting.LevelLightEngine;
import net.minecraft.core.SectionPos;
#endif
#if MC_VER <= MC_1_20_4
@@ -94,13 +85,10 @@ public class ChunkWrapper implements IChunkWrapper
private final ChunkAccess chunk;
private final DhChunkPos chunkPos;
private final LevelReader lightSource;
private final ILevelWrapper wrappedLevel;
private boolean isDhBlockLightCorrect = false;
private boolean isDhSkyLightCorrect = false;
/** only used when connected to a dedicated server */
private boolean isMcClientLightingCorrect = false;
private ChunkLightStorage blockLightStorage;
private ChunkLightStorage skyLightStorage;
@@ -110,19 +98,36 @@ public class ChunkWrapper implements IChunkWrapper
private int minNonEmptyHeight = Integer.MIN_VALUE;
private int maxNonEmptyHeight = Integer.MAX_VALUE;
/** will be null if we are using MC heightmaps */
private final int[][] solidHeightMap;
/** will be null if we are using MC heightmaps */
private final int[][] lightBlockingHeightMap;
//=============//
// constructor //
//=============//
public ChunkWrapper(ChunkAccess chunk, LevelReader lightSource, ILevelWrapper wrappedLevel)
public ChunkWrapper(ChunkAccess chunk, ILevelWrapper wrappedLevel)
{
this.chunk = chunk;
this.lightSource = lightSource;
this.wrappedLevel = wrappedLevel;
this.chunkPos = new DhChunkPos(chunk.getPos().x, chunk.getPos().z);
// use DH heightmaps if requested
if (Config.Common.LodBuilding.recalculateChunkHeightmaps.get())
{
this.solidHeightMap = new int[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH];
this.lightBlockingHeightMap = new int[LodUtil.CHUNK_WIDTH][LodUtil.CHUNK_WIDTH];
this.recalculateDhHeightMapsIfNeeded();
}
else
{
this.solidHeightMap = null;
this.lightBlockingHeightMap = null;
}
}
@@ -143,19 +148,29 @@ public class ChunkWrapper implements IChunkWrapper
}
@Override
public int getMinBuildHeight() { return getMinBuildHeight(this.chunk); }
public static int getMinBuildHeight(ChunkAccess chunk)
public int getInclusiveMinBuildHeight() { return getInclusiveMinBuildHeight(this.chunk); }
public static int getInclusiveMinBuildHeight(ChunkAccess chunk)
{
#if MC_VER < MC_1_17_1
return 0;
#else
#elif MC_VER < MC_1_21_3
return chunk.getMinBuildHeight();
#else
return chunk.getMinY();
#endif
}
@Override
public int getMaxBuildHeight() { return getMaxBuildHeight(this.chunk); }
public static int getMaxBuildHeight(ChunkAccess chunk) { return chunk.getMaxBuildHeight(); }
public int getExclusiveMaxBuildHeight() { return getExclusiveMaxBuildHeight(this.chunk); }
public static int getExclusiveMaxBuildHeight(ChunkAccess chunk)
{
#if MC_VER < MC_1_21_3
return chunk.getMaxBuildHeight();
#else
// +1 since Minecraft made the max value inclusive
return chunk.getMaxY() + 1;
#endif
}
@Override
public int getMinNonEmptyHeight()
@@ -167,7 +182,7 @@ public class ChunkWrapper implements IChunkWrapper
// default if every section is empty or missing
this.minNonEmptyHeight = this.getMinBuildHeight();
this.minNonEmptyHeight = this.getInclusiveMinBuildHeight();
// determine the lowest empty section (bottom up)
LevelChunkSection[] sections = this.chunk.getSections();
@@ -199,7 +214,7 @@ public class ChunkWrapper implements IChunkWrapper
// default if every section is empty or missing
this.maxNonEmptyHeight = this.getMaxBuildHeight();
this.maxNonEmptyHeight = this.getExclusiveMaxBuildHeight();
// determine the highest empty section (top down)
LevelChunkSection[] sections = this.chunk.getSections();
@@ -232,14 +247,92 @@ public class ChunkWrapper implements IChunkWrapper
return section.hasOnlyAir();
#endif
}
private int getChunkSectionMinHeight(int index) { return (index * 16) + this.getMinBuildHeight(); }
private int getChunkSectionMinHeight(int index) { return (index * 16) + this.getInclusiveMinBuildHeight(); }
/** Will only run if the config says the MC heightmaps shouldn't be trusted. */
public void recalculateDhHeightMapsIfNeeded()
{
// re-calculate the min/max heights for consistency (during world gen these may be wrong)
this.minNonEmptyHeight = Integer.MIN_VALUE;
this.maxNonEmptyHeight = Integer.MAX_VALUE;
// recalculate heightmaps if needed
if (this.solidHeightMap != null)
{
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
{
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
{
int minInclusiveBuildHeight = this.getMinNonEmptyHeight();
// if no blocks are found the height map will be at the bottom of the world
int solidHeight = minInclusiveBuildHeight;
int lightBlockingHeight = minInclusiveBuildHeight;
int y = this.getMaxNonEmptyHeight(); //this.getExclusiveMaxBuildHeight();
IBlockStateWrapper block = this.getBlockState(x, y, z);
while (// go down until we reach the minimum build height
y > minInclusiveBuildHeight
// keep going until we find both height map values
&& (solidHeight == minInclusiveBuildHeight || lightBlockingHeight == minInclusiveBuildHeight))
{
// is this block solid?
if (solidHeight == minInclusiveBuildHeight
&& block.isSolid())
{
solidHeight = y;
}
// is this block light blocking?
if (lightBlockingHeight == minInclusiveBuildHeight
&& block.getOpacity() != LodUtil.BLOCK_FULLY_TRANSPARENT)
{
lightBlockingHeight = y;
}
// get the next block down
y--;
block = this.getBlockState(x, y, z);
}
this.solidHeightMap[x][z] = solidHeight;
this.lightBlockingHeightMap[x][z] = lightBlockingHeight;
}
}
}
}
@Override
public int getSolidHeightMapValue(int xRel, int zRel) { return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE).getFirstAvailable(xRel, zRel); }
public int getSolidHeightMapValue(int xRel, int zRel)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(xRel, zRel);
// will be null if we want to use MC heightmaps
if (this.solidHeightMap == null)
{
return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.WORLD_SURFACE).getFirstAvailable(xRel, zRel);
}
else
{
return this.solidHeightMap[xRel][zRel];
}
}
@Override
public int getLightBlockingHeightMapValue(int xRel, int zRel) { return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING).getFirstAvailable(xRel, zRel); }
public int getLightBlockingHeightMapValue(int xRel, int zRel)
{
this.throwIndexOutOfBoundsIfRelativePosOutsideChunkBounds(xRel, zRel);
if (this.lightBlockingHeightMap == null)
{
return this.chunk.getOrCreateHeightmapUnprimed(Heightmap.Types.MOTION_BLOCKING).getFirstAvailable(xRel, zRel);
}
else
{
return this.lightBlockingHeightMap[xRel][zRel];
}
}
@Override
@@ -276,6 +369,7 @@ public class ChunkWrapper implements IChunkWrapper
blockPos.setY(relY);
blockPos.setZ(relZ);
// TODO copy into pooled array, this isn't thread safe and can cause MC to throw errors if the chunk is loaded
return BlockStateWrapper.fromBlockState(this.chunk.getBlockState(blockPos), this.wrappedLevel);
}
@@ -300,6 +394,20 @@ public class ChunkWrapper implements IChunkWrapper
public ChunkAccess getChunk() { return this.chunk; }
public void trySetStatus(ChunkStatus status) { trySetStatus(this.getChunk(), status); }
/** does nothing if the chunk object doesn't support setting it's status */
public static void trySetStatus(ChunkAccess chunk, ChunkStatus status)
{
if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(status);
#else
((ProtoChunk) chunk).setPersistedStatus(status);
#endif
}
}
public ChunkStatus getStatus() { return getStatus(this.getChunk()); }
public static ChunkStatus getStatus(ChunkAccess chunk)
{
@@ -429,32 +537,6 @@ public class ChunkWrapper implements IChunkWrapper
// other methods //
//===============//
@Override
public boolean doNearbyChunksExist()
{
if (this.lightSource instanceof DhLitWorldGenRegion)
{
return true;
}
for (int dx = -1; dx <= 1; dx++)
{
for (int dz = -1; dz <= 1; dz++)
{
if (dx == 0 && dz == 0)
{
continue;
}
else if (this.lightSource.getChunk(dx + this.chunk.getPos().x, dz + this.chunk.getPos().z, ChunkStatus.BIOMES, false) == null)
{
return false;
}
}
}
return true;
}
@Override
public boolean isStillValid() { return this.wrappedLevel.tryGetChunk(this.chunkPos) == this; }
@@ -16,7 +16,6 @@ import java.util.regex.Pattern;
// Logger (for debug stuff)
import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui;
import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.config.ConfigBase;
import com.seibel.distanthorizons.core.config.types.*;
@@ -119,14 +118,18 @@ public class ClassicConfigGUI
*/
private static void textField(AbstractConfigType info, Function<String, Number> func, Pattern pattern, boolean cast)
{
boolean isNumber = pattern != null;
((EntryInfo) info.guiValue).widget = (BiFunction<EditBox, Button, Predicate<String>>) (editBox, button) -> stringValue ->
{
boolean isNumber = (pattern != null);
stringValue = stringValue.trim();
if (!(stringValue.isEmpty() || !isNumber || pattern.matcher(stringValue).matches()))
{
return false;
}
Number value = 0;
Number value = info.typeIsFloatingPointNumber() ? 0.0 : 0; // different default values are needed so implicit casting works correctly (if not done casting from 0 (an int) to a double will cause an exception)
((EntryInfo) info.guiValue).error = null;
if (isNumber && !stringValue.isEmpty() && !stringValue.equals("-") && !stringValue.equals("."))
{
@@ -143,18 +146,22 @@ public class ClassicConfigGUI
switch (isValid)
{
case 0:
((EntryInfo) info.guiValue).error = null; break;
((EntryInfo) info.guiValue).error = null;
break;
case -1:
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMinimum length is " + ((ConfigEntry) info).getMin())); break;
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMinimum length is " + ((ConfigEntry) info).getMin()));
break;
case 1:
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMaximum length is " + ((ConfigEntry) info).getMax())); break;
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cMaximum length is " + ((ConfigEntry) info).getMax()));
break;
case 2:
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cValue is invalid")); break;
((EntryInfo) info.guiValue).error = new AbstractMap.SimpleEntry<>(editBox, TextOrTranslatable("§cValue is invalid"));
break;
}
}
((EntryInfo) info.guiValue).tempValue = stringValue;
editBox.setTextColor(((ConfigEntry) info).isValid(value) == 0 ? 0xFFFFFFFF : 0xFFFF7777);
editBox.setTextColor(((ConfigEntry) info).isValid(value) == 0 ? 0xFFFFFFFF : 0xFFFF7777); // white and red
// button.active = entries.stream().allMatch(e -> e.inLimits);
@@ -387,9 +394,9 @@ public class ClassicConfigGUI
this.list.addButton(null, null, null, name);
return;
}
if (ConfigLinkedEntry.class.isAssignableFrom(info.getClass()))
if (ConfigUiLinkedEntry.class.isAssignableFrom(info.getClass()))
{
this.addMenuItem(((ConfigLinkedEntry) info).get());
this.addMenuItem(((ConfigUiLinkedEntry) info).get());
return;
}
@@ -438,8 +445,8 @@ public class ClassicConfigGUI
}
// A quick fix for tooltips on linked entries
AbstractConfigType newInfo = ConfigLinkedEntry.class.isAssignableFrom(info.getClass()) ?
((ConfigLinkedEntry) info).get() :
AbstractConfigType newInfo = ConfigUiLinkedEntry.class.isAssignableFrom(info.getClass()) ?
((ConfigUiLinkedEntry) info).get() :
info;
Component name = Translatable(this.translationPrefix + (info.category.isEmpty() ? "" : info.category + ".") + info.getName());
@@ -472,47 +479,47 @@ public class ClassicConfigGUI
private static void initEntry(AbstractConfigType info, String translationPrefix)
private static void initEntry(AbstractConfigType configType, String translationPrefix)
{
info.guiValue = new EntryInfo();
Class<?> fieldClass = info.getType();
configType.guiValue = new EntryInfo();
Class<?> fieldClass = configType.getType();
if (ConfigEntry.class.isAssignableFrom(info.getClass()))
if (ConfigEntry.class.isAssignableFrom(configType.getClass()))
{
if (fieldClass == Integer.class)
{
// For int
textField(info, Integer::parseInt, INTEGER_ONLY_REGEX, true);
textField(configType, Integer::parseInt, INTEGER_ONLY_REGEX, true);
}
else if (fieldClass == Double.class)
{
// For double
textField(info, Double::parseDouble, DECIMAL_ONLY_REGEX, false);
textField(configType, Double::parseDouble, DECIMAL_ONLY_REGEX, false);
}
else if (fieldClass == String.class || fieldClass == List.class)
{
// For string or list
textField(info, String::length, null, true);
textField(configType, String::length, null, true);
}
else if (fieldClass == Boolean.class)
{
// For boolean
Function<Object, Component> func = value -> Translatable("distanthorizons.general."+((Boolean) value ? "true" : "false")).withStyle((Boolean) value ? ChatFormatting.GREEN : ChatFormatting.RED);
((EntryInfo) info.guiValue).widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(button -> {
((ConfigEntry) info).uiSetWithoutSaving(!(Boolean) info.get());
button.setMessage(func.apply(info.get()));
((EntryInfo) configType.guiValue).widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(button -> {
((ConfigEntry) configType).uiSetWithoutSaving(!(Boolean) configType.get());
button.setMessage(func.apply(configType.get()));
}, func);
}
else if (fieldClass.isEnum())
{
// For enum
List<?> values = Arrays.asList(info.getType().getEnumConstants());
Function<Object, Component> func = value -> Translatable(translationPrefix + "enum." + fieldClass.getSimpleName() + "." + info.get().toString());
((EntryInfo) info.guiValue).widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(button -> {
List<?> values = Arrays.asList(configType.getType().getEnumConstants());
Function<Object, Component> func = value -> Translatable(translationPrefix + "enum." + fieldClass.getSimpleName() + "." + configType.get().toString());
((EntryInfo) configType.guiValue).widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(button -> {
// get the currently selected enum and enum index
int startingIndex = values.indexOf(info.get());
int startingIndex = values.indexOf(configType.get());
Enum<?> enumValue = (Enum<?>) values.get(startingIndex);
// search for the next enum that is selectable
@@ -540,12 +547,12 @@ public class ClassicConfigGUI
}
((ConfigEntry<Enum<?>>) info).uiSetWithoutSaving(enumValue);
button.setMessage(func.apply(info.get()));
((ConfigEntry<Enum<?>>) configType).uiSetWithoutSaving(enumValue);
button.setMessage(func.apply(configType.get()));
}, func);
}
}
else if (ConfigCategory.class.isAssignableFrom(info.getClass()))
else if (ConfigCategory.class.isAssignableFrom(configType.getClass()))
{
// if (!info.info.getName().equals(""))
// info.name = new TranslatableComponent(info.info.getName());
@@ -19,31 +19,37 @@
package com.seibel.distanthorizons.common.wrappers.gui;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
#if MC_VER >= MC_1_17_1
import net.minecraft.client.gui.components.Button;
#endif
#if MC_VER < MC_1_17_1
import net.minecraft.client.gui.components.ImageButton;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
#elif MC_VER < MC_1_20_1
import net.minecraft.client.gui.components.ImageButton;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.renderer.GameRenderer;
#elif MC_VER < MC_1_20_2
import net.minecraft.client.gui.components.ImageButton;
import net.minecraft.client.gui.GuiGraphics;
#else
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.renderer.RenderType;
#endif
/**
* Creates a button with a texture on it (and a background) that works with all mc versions
*
* @author coolGi
* @version 2023-10-03
*/
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.components.AbstractButton;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.ImageButton;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
#if MC_VER >= MC_1_17_1
import net.minecraft.client.renderer.GameRenderer;
#endif
#if MC_VER < MC_1_20_1
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft;
#else
import net.minecraft.client.gui.GuiGraphics;
#endif
#if MC_VER < MC_1_20_2
public class TexturedButtonWidget extends ImageButton
#else
@@ -57,20 +63,21 @@ public class TexturedButtonWidget extends Button
private final int v;
private final int hoveredVOffset;
private final ResourceLocation texture;
private final ResourceLocation textureResourceLocation;
private final int textureWidth;
private final int textureHeight;
#endif
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction, Component text) {
this(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, text, true);
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text)
{
this(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text, true);
}
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction, Component text, boolean renderBackground)
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation textureResourceLocation, int textureWidth, int textureHeight, OnPress pressAction, Component text, boolean renderBackground)
{
#if MC_VER < MC_1_20_2
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, text);
super(x, y, width, height, u, v, hoveredVOffset, textureResourceLocation, textureWidth, textureHeight, pressAction, text);
#else
// We don't pass on the text option as otherwise it will render (we normally pass it for narration)
// TODO: Find a fix for it
@@ -80,7 +87,7 @@ public class TexturedButtonWidget extends Button
this.v = v;
this.hoveredVOffset = hoveredVOffset;
this.texture = texture;
this.textureResourceLocation = textureResourceLocation;
this.textureWidth = textureWidth;
this.textureHeight = textureHeight;
@@ -92,7 +99,8 @@ public class TexturedButtonWidget extends Button
#if MC_VER < MC_1_20_2
#if MC_VER < MC_1_19_4
@Override
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta) {
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta)
{
if (this.renderBackground) // Renders the background of the button
{
#if MC_VER < MC_1_17_1
@@ -119,6 +127,7 @@ public class TexturedButtonWidget extends Button
super.renderButton(matrices, mouseX, mouseY, delta);
}
#else
#if MC_VER < MC_1_20_1
@Override
@@ -154,24 +163,49 @@ public class TexturedButtonWidget extends Button
super.renderWidget(matrices, mouseX, mouseY, delta);
}
#endif
#else
@Override
public void renderWidget(GuiGraphics matrices, int mouseX, int mouseY, float delta)
{
if (this.renderBackground)
{
//RenderSystem.enableBlend();
//RenderSystem.enableDepthTest();
#if MC_VER < MC_1_21_3
matrices.blitSprite(SPRITES.get(this.active, this.isHoveredOrFocused()), this.getX(), this.getY(), this.getWidth(), this.getHeight());
#else
matrices.blitSprite(
RenderType::guiTextured,
SPRITES.get(this.active, this.isHoveredOrFocused()),
this.getX(), this.getY(),
this.getWidth(), this.getHeight());
#endif
}
// Renders the sprite
int i = 0;
if (!this.active) i = 2;
else if (this.isHovered) i = 1;
if (!this.active)
{
i = 2;
}
else if (this.isHovered)
{
i = 1;
}
matrices.blit(this.texture, this.getX(), this.getY(), this.u, this.v + (this.hoveredVOffset * i), this.width, this.height, this.textureWidth, this.textureHeight);
#if MC_VER < MC_1_21_3
matrices.blit(this.textureResourceLocation, this.getX(), this.getY(), this.u, this.v + (this.hoveredVOffset * i), this.width, this.height, this.textureWidth, this.textureHeight);
#else
matrices.blit(
RenderType::guiTextured,
this.textureResourceLocation,
this.getX(), this.getY(),
this.u, this.v + (this.hoveredVOffset * i),
this.width, this.height,
this.textureWidth, this.textureHeight);
#endif
}
#endif
}
@@ -161,16 +161,28 @@ public class ChangelogScreen extends DhScreen
#else
this.renderBackground(matrices, mouseX, mouseY, delta); // Render background
#endif
if (!usable)
if (!this.usable)
{
return;
}
int maxScroll;
#if MC_VER <= MC_1_21_3
maxScroll = this.changelogArea.getMaxScroll();
#else
maxScroll = this.changelogArea.maxScrollAmount();
#endif
// Set the scroll position to the mouse height relative to the screen
// This is a bit of a hack as we cannot scroll on this area
double scrollAmount = ((double) mouseY) / ((double) this.height) * 1.1 * this.changelogArea.getMaxScroll();
double scrollAmount = ((double) mouseY) / ((double) this.height) * 1.1 * maxScroll;
#if MC_VER == MC_1_16_5 || MC_VER == MC_1_17_1
this.changelogArea.setScrollAmount(scrollAmount);
#else
#elif MC_VER <= MC_1_21_3
this.changelogArea.scrollAmount = scrollAmount;
#else
this.changelogArea.setScrollAmount(scrollAmount);
#endif
@@ -36,7 +36,7 @@ public class UpdateModScreen extends DhScreen
private String nextVer;
public UpdateModScreen(Screen parent, String newVersionID)
public UpdateModScreen(Screen parent, String newVersionID) throws IllegalArgumentException
{
super(Translatable(ModInfo.ID + ".updater.title"));
this.parent = parent;
@@ -54,6 +54,13 @@ public class UpdateModScreen extends DhScreen
this.currentVer = ModJarInfo.Git_Commit.substring(0,7);
this.nextVer = this.newVersionID.substring(0,7);
}
// done to prevent trying to update to "null"
// (this can happen if no versions are available to check/download from modrinth/gitlab)
if (this.nextVer == null)
{
throw new IllegalArgumentException("No new version found with the ID ["+newVersionID+"].");
}
}
@Override
@@ -69,9 +76,9 @@ public class UpdateModScreen extends DhScreen
// Logo image
this.addBtn(new TexturedButtonWidget(
// Where the button is on the screen
this.width / 2 - 65, this.height / 2 - 110,
this.width / 2 - 95, this.height / 2 - 110,
// Width and height of the button
130, 65,
195, 65,
// Offset
0, 0,
// Some textuary stuff
@@ -81,7 +88,7 @@ public class UpdateModScreen extends DhScreen
#else
ResourceLocation.fromNamespaceAndPath(ModInfo.ID, "logo.png"),
#endif
130, 65,
195, 65,
// Create the button and tell it where to go
// For now it goes to the client option by default
(buttonWidget) -> System.out.println("Nice, you found an easter egg :)"), // TODO: Add a proper easter egg to pressing the logo (maybe with confetti)
@@ -13,6 +13,9 @@ public class KeyedClientLevelManager implements IKeyedClientLevelManager
/** This is set and managed by the ClientApi for servers with support for DH. */
@Nullable
private IServerKeyedClientLevel serverKeyedLevel = null;
/** Allows to keep level manager enabled between loading different keyed levels */
private boolean enabled = false;
@@ -37,12 +40,16 @@ public class KeyedClientLevelManager implements IKeyedClientLevelManager
{
IServerKeyedClientLevel keyedLevel = new ServerKeyedClientLevel((ClientLevel) clientLevel.getWrappedMcObject(), levelKey);
this.serverKeyedLevel = keyedLevel;
this.enabled = true;
return keyedLevel;
}
@Override
public void clearKeyedLevel() { this.serverKeyedLevel = null; }
@Override
public boolean hasLevelSet() { return this.serverKeyedLevel != null; }
public boolean isEnabled() { return this.enabled; }
@Override
public void disable() { this.enabled = false; }
}
@@ -2,6 +2,8 @@ package com.seibel.distanthorizons.common.wrappers.level;
import com.seibel.distanthorizons.common.wrappers.world.ClientLevelWrapper;
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.coreapi.util.StringUtil;
import net.minecraft.client.multiplayer.ClientLevel;
public class ServerKeyedClientLevel extends ClientLevelWrapper implements IServerKeyedClientLevel
@@ -9,16 +11,20 @@ public class ServerKeyedClientLevel extends ClientLevelWrapper implements IServe
/** A unique identifier (generally the level's name) for differentiating multiverse levels */
private final String serverLevelKey;
public ServerKeyedClientLevel(ClientLevel level, String serverLevelKey)
{
super(level);
this.serverLevelKey = serverLevelKey;
}
@Override
public String getServerLevelKey() { return this.serverLevelKey; }
@Override
public String getDimensionName() { return this.getServerLevelKey(); }
public String getDhIdentifier() { return this.getServerLevelKey(); }
}
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.common.wrappers.minecraft;
import java.io.File;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Objects;
import java.util.UUID;
import com.mojang.blaze3d.platform.NativeImage;
@@ -53,10 +54,16 @@ import net.minecraft.core.Direction;
import net.minecraft.network.chat.TextComponent;
#endif
import net.minecraft.server.level.ServerLevel;
import net.minecraft.util.profiling.ProfilerFiller;
import net.minecraft.world.level.ChunkPos;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
#if MC_VER < MC_1_21_3
#else
import net.minecraft.util.profiling.Profiler;
#endif
/**
* A singleton that wraps the Minecraft object.
*
@@ -111,7 +118,7 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@Override
public float getShade(EDhDirection lodDirection)
{
EDhApiLodShading lodShading = Config.Client.Advanced.Graphics.AdvancedGraphics.lodShading.get();
EDhApiLodShading lodShading = Config.Client.Advanced.Graphics.Quality.lodShading.get();
switch (lodShading)
{
default:
@@ -201,6 +208,9 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@Override
public UUID getPlayerUUID() { return this.getPlayer().getUUID(); }
@Override
public String getUsername() { return MINECRAFT.getUser().getName(); }
@Override
public DhBlockPos getPlayerBlockPos()
{
@@ -239,13 +249,20 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
@Override
public IProfilerWrapper getProfiler()
{
ProfilerFiller profiler;
#if MC_VER < MC_1_21_3
profiler = MINECRAFT.getProfiler();
#else
profiler = Profiler.get();
#endif
if (this.profilerWrapper == null)
{
this.profilerWrapper = new ProfilerWrapper(MINECRAFT.getProfiler());
this.profilerWrapper = new ProfilerWrapper(profiler);
}
else if (MINECRAFT.getProfiler() != this.profilerWrapper.profiler)
else if (profiler != this.profilerWrapper.profiler)
{
this.profilerWrapper.profiler = MINECRAFT.getProfiler();
this.profilerWrapper.profiler = profiler;
}
return this.profilerWrapper;
@@ -278,8 +295,10 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
}
#if MC_VER < MC_1_19_2
player.sendMessage(new TextComponent(string), getPlayer().getUUID());
#else
#elif MC_VER < MC_1_21_3
player.sendSystemMessage(net.minecraft.network.chat.Component.translatable(string));
#else
player.displayClientMessage(net.minecraft.network.chat.Component.translatable(string), /*isOverlay*/false);
#endif
}
@@ -316,6 +335,17 @@ public class MinecraftClientWrapper implements IMinecraftClientWrapper, IMinecra
public void executeOnRenderThread(Runnable runnable) { MINECRAFT.execute(runnable); }
@Override
public boolean isWorldNew() { throw new UnsupportedOperationException("Not Implemented"); }
public int getPlayerCount()
{
// can be null if the server hasn't finished booting up yet
if (MINECRAFT.getSingleplayerServer() == null)
{
return 1;
}
else
{
return MINECRAFT.getSingleplayerServer().getPlayerCount();
}
}
}
@@ -0,0 +1,173 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2023 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.common.wrappers.minecraft;
import com.mojang.blaze3d.platform.GlStateManager;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
import org.apache.logging.log4j.Logger;
import org.lwjgl.opengl.GL32;
/**
* A singleton that contains everything
* related to rendering in Minecraft.
*
* @author James Seibel
* @version 12-12-2021
*/
//@Environment(EnvType.CLIENT)
public class MinecraftGLWrapper implements IMinecraftGLWrapper
{
public static final MinecraftGLWrapper INSTANCE = new MinecraftGLWrapper();
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
/*
private static final StencilState STENCIL;
*/
// scissor //
/** @see GL32#GL_SCISSOR_TEST */
@Override
public void enableScissorTest() { GlStateManager._enableScissorTest(); }
/** @see GL32#GL_SCISSOR_TEST */
@Override
public void disableScissorTest() { GlStateManager._disableScissorTest(); }
// stencil //
//
// /** @see GL32#GL_SCISSOR_TEST */
// public void enableScissorTest() { GlStateManager._stencilFunc(); }
// /** @see GL32#GL_SCISSOR_TEST */
// public void disableScissorTest() { GlStateManager._disableScissorTest(); }
// depth //
/** @see GL32#GL_DEPTH_TEST */
@Override
public void enableDepthTest() { GlStateManager._enableDepthTest(); }
/** @see GL32#GL_DEPTH_TEST */
@Override
public void disableDepthTest() { GlStateManager._disableDepthTest(); }
/** @see GL32#glDepthFunc(int) */
@Override
public void glDepthFunc(int func) { GlStateManager._depthFunc(func); }
/** @see GL32#glDepthMask(boolean) */
@Override
public void enableDepthMask() { GlStateManager._depthMask(true); }
/** @see GL32#glDepthMask(boolean) */
@Override
public void disableDepthMask() { GlStateManager._depthMask(false); }
// blending //
/** @see GL32#GL_BLEND */
@Override
public void enableBlend() { GlStateManager._enableBlend(); }
/** @see GL32#GL_BLEND */
@Override
public void disableBlend() { GlStateManager._disableBlend(); }
/** @see GL32#glBlendFunc */
@Override
public void glBlendFunc(int sfactor, int dfactor) { GlStateManager._blendFunc(sfactor, dfactor); }
/** @see GL32#glBlendFuncSeparate */
@Override
public void glBlendFuncSeparate(int sfactorRGB, int dfactorRGB, int sfactorAlpha, int dfactorAlpha)
{ GlStateManager._blendFuncSeparate(sfactorRGB, dfactorRGB, sfactorAlpha, dfactorAlpha); }
// frame buffers //
/** @see GL32#glBindFramebuffer */
@Override
public void glBindFramebuffer(int target, int framebuffer)
{ GlStateManager._glBindFramebuffer(target, framebuffer); }
// buffers //
/** @see GL32#glGenBuffers() */
@Override
public int glGenBuffers()
{ return GlStateManager._glGenBuffers(); }
/** @see GL32#glDeleteBuffers(int) */
@Override
public void glDeleteBuffers(int buffer)
{ GlStateManager._glDeleteBuffers(buffer); }
// culling //
/** @see GL32#GL_CULL_FACE */
@Override
public void enableFaceCulling() { GlStateManager._enableCull(); }
/** @see GL32#GL_CULL_FACE */
@Override
public void disableFaceCulling() { GlStateManager._disableCull(); }
// textures //
/** @see GL32#glGenTextures() */
@Override
public int glGenTextures() { return GlStateManager._genTexture(); }
/** @see GL32#glDeleteTextures(int) */
@Override
public void glDeleteTextures(int texture) { GlStateManager._deleteTexture(texture); }
/** @see GL32#glActiveTexture(int) */
@Override
public void glActiveTexture(int textureId) { GlStateManager._activeTexture(textureId); }
/** only works for textures bound via this system or MC's {@link GlStateManager} */
@Override
public int getActiveTexture()
{
#if MC_VER <= MC_1_16_5
return GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE);
#else
return GlStateManager._getActiveTexture();
#endif
}
/**
* Always binds to {@link GL32#GL_TEXTURE_2D}
* @see GL32#glBindTexture(int, int)
*/
@Override
public void glBindTexture(int texture) { GlStateManager._bindTexture(texture); }
}
@@ -30,6 +30,7 @@ import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.util.ColorUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
#if MC_VER >= MC_1_17_1
@@ -43,7 +44,6 @@ import org.joml.Vector3f;
#else
#endif
#if MC_VER >= MC_1_20_2
import net.minecraft.client.renderer.chunk.SectionRenderDispatcher;
#endif
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
@@ -69,6 +69,7 @@ import net.minecraft.world.level.material.FogType;
#endif
import net.minecraft.world.phys.Vec3;
import org.apache.logging.log4j.Logger;
import org.joml.Vector4f;
/**
@@ -136,16 +137,30 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
#if MC_VER < MC_1_17_1
float[] colorValues = new float[4];
GL15.glGetFloatv(GL15.GL_FOG_COLOR, colorValues);
#else
return new Color(
Math.max(0f, Math.min(colorValues[0], 1f)), // r
Math.max(0f, Math.min(colorValues[1], 1f)), // g
Math.max(0f, Math.min(colorValues[2], 1f)), // b
Math.max(0f, Math.min(colorValues[3], 1f)) // a
);
#elif MC_VER < MC_1_21_3
FogRenderer.setupColor(MC.gameRenderer.getMainCamera(), partialTicks, MC.level, 1, MC.gameRenderer.getDarkenWorldAmount(partialTicks));
float[] colorValues = RenderSystem.getShaderFogColor();
#endif
return new Color(
Math.max(0f, Math.min(colorValues[0], 1f)),
Math.max(0f, Math.min(colorValues[1], 1f)),
Math.max(0f, Math.min(colorValues[2], 1f)),
Math.max(0f, Math.min(colorValues[3], 1f))
Math.max(0f, Math.min(colorValues[0], 1f)), // r
Math.max(0f, Math.min(colorValues[1], 1f)), // g
Math.max(0f, Math.min(colorValues[2], 1f)), // b
Math.max(0f, Math.min(colorValues[3], 1f)) // a
);
#else
Vector4f colorValues = FogRenderer.computeFogColor(MC.gameRenderer.getMainCamera(), partialTicks, MC.level, 1, MC.gameRenderer.getDarkenWorldAmount(partialTicks));
return new Color(
Math.max(0f, Math.min(colorValues.x, 1f)), // r
Math.max(0f, Math.min(colorValues.y, 1f)), // g
Math.max(0f, Math.min(colorValues.z, 1f)), // b
Math.max(0f, Math.min(colorValues.w, 1f)) // a
);
#endif
}
// getSpecialFogColor() is the same as getFogColor()
@@ -157,16 +172,22 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
float frameTime;
#if MC_VER < MC_1_21_1
frameTime = MC.getFrameTime();
#else
#elif MC_VER < MC_1_21_3
frameTime = MC.getTimer().getRealtimeDeltaTicks();
#else
frameTime = MC.deltaTracker.getGameTimeDeltaTicks();
#endif
#if MC_VER < MC_1_17_1
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getBlockPosition(), frameTime);
#else
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), frameTime);
#endif
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
#elif MC_VER < MC_1_21_3
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), frameTime);
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
#else
int argbColorInt = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), frameTime);;
return ColorUtil.toColorObjARGB(argbColorInt); // TODO MC changed color formats
#endif
}
else
{
@@ -246,6 +267,8 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
@Override
public int getDepthTextureId() { return this.getRenderTarget().getDepthTextureId(); }
@Override
public int getColorTextureId() { return this.getRenderTarget().getColorTextureId(); }
@Override
public int getTargetFrameBufferViewportWidth()
@@ -279,6 +302,10 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
#endif
}
/**
* It's better to use {@link MinecraftRenderWrapper#setLightmapId(int, IClientLevelWrapper)} if possible,
* however old MC versions don't support it.
*/
public void updateLightmap(NativeImage lightPixels, IClientLevelWrapper level)
{
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
@@ -289,5 +316,15 @@ public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
wrapper.uploadLightmap(lightPixels);
}
public void setLightmapId(int tetxureId, IClientLevelWrapper level)
{
// Using ClientLevelWrapper as the key would be better, but we don't have a consistent way to create the same
// object for the same MC level and/or the same hash,
// so this will have to do for now
IDimensionTypeWrapper dimensionType = level.getDimensionType();
LightMapWrapper wrapper = this.lightmapByDimensionType.computeIfAbsent(dimensionType, (dimType) -> new LightMapWrapper());
wrapper.setLightmapId(tetxureId);
}
}
@@ -44,7 +44,9 @@ public class MinecraftServerWrapper implements IMinecraftSharedWrapper
}
@Override
public boolean isWorldNew()
{ return this.dedicatedServer.getWorldData().overworldData().isInitialized(); }
public int getPlayerCount()
{
return this.dedicatedServer.getPlayerCount();
}
}
@@ -31,31 +31,19 @@ public class ProfilerWrapper implements IProfilerWrapper
{
public ProfilerFiller profiler;
public ProfilerWrapper(ProfilerFiller newProfiler)
{
profiler = newProfiler;
}
public ProfilerWrapper(ProfilerFiller newProfiler) { this.profiler = newProfiler; }
/** starts a new section inside the currently running section */
@Override
public void push(String newSection)
{
profiler.push(newSection);
}
public void push(String newSection) { this.profiler.push(newSection); }
/** ends the currently running section and starts a new one */
@Override
public void popPush(String newSection)
{
profiler.popPush(newSection);
}
public void popPush(String newSection) { this.profiler.popPush(newSection); }
/** ends the currently running section */
@Override
public void pop()
{
profiler.pop();
}
public void pop() { this.profiler.pop(); }
}
@@ -20,6 +20,8 @@
package com.seibel.distanthorizons.common.wrappers.misc;
import com.mojang.blaze3d.platform.NativeImage;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
import org.lwjgl.opengl.GL32;
@@ -27,9 +29,12 @@ import java.nio.ByteBuffer;
public class LightMapWrapper implements ILightMapWrapper
{
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
private int textureId = 0;
//==============//
// constructors //
//==============//
@@ -38,41 +43,53 @@ public class LightMapWrapper implements ILightMapWrapper
//=========//
// methods //
//=========//
//==================//
// lightmap syncing //
//==================//
public void uploadLightmap(NativeImage image)
{
int currentBind = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
int currentTexture = GLMC.getActiveTexture();
if (this.textureId == 0)
{
this.createLightmap(image);
}
else
{
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId);
GLMC.glBindTexture(this.textureId);
}
image.upload(0, 0, 0, false);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, currentBind);
GLMC.glBindTexture(currentTexture);
}
private void createLightmap(NativeImage image)
{
this.textureId = GL32.glGenTextures();
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId);
this.textureId = GLMC.glGenTextures();
GLMC.glBindTexture(this.textureId);
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, image.format().glFormat(), image.getWidth(), image.getHeight(),
0, image.format().glFormat(), GL32.GL_UNSIGNED_BYTE, (ByteBuffer) null);
}
public void setLightmapId(int minecraftLightmapTetxureId)
{
// just use the MC texture ID
this.textureId = minecraftLightmapTetxureId;
}
//==============//
// lightmap use //
//==============//
@Override
public void bind()
{
GL32.glActiveTexture(GL32.GL_TEXTURE0);
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.textureId);
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
GLMC.glBindTexture(this.textureId);
}
@Override
public void unbind() { GL32.glBindTexture(GL32.GL_TEXTURE_2D, 0); }
public void unbind() { GLMC.glBindTexture(0); }
}
@@ -31,6 +31,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.ConcurrentHashMap;
@@ -40,6 +41,11 @@ import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.status.ChunkStatus;
#endif
#if MC_VER < MC_1_21_3
#else
import com.seibel.distanthorizons.core.util.ColorUtil;
#endif
public class ClientLevelWrapper implements IClientLevelWrapper
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger(ClientLevelWrapper.class.getSimpleName());
@@ -124,6 +130,8 @@ public class ClientLevelWrapper implements IClientLevelWrapper
}
}
//====================//
// base level methods //
//====================//
@@ -188,6 +196,12 @@ public class ClientLevelWrapper implements IClientLevelWrapper
@Override
public String getDimensionName() { return this.level.dimension().location().toString(); }
@Override
public long getHashedSeed() { return this.level.getBiomeManager().biomeZoomSeed; }
@Override
public String getDhIdentifier() { return this.getHashedSeedEncoded() + "@" + this.getDimensionName(); }
@Override
public EDhApiLevelType getLevelType() { return EDhApiLevelType.CLIENT_LEVEL; }
@@ -207,8 +221,10 @@ public class ClientLevelWrapper implements IClientLevelWrapper
{
#if MC_VER < MC_1_17_1
return 0;
#else
#elif MC_VER < MC_1_21_3
return this.level.getMinBuildHeight();
#else
return this.level.getMinY();
#endif
}
@@ -226,7 +242,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
return null;
}
return new ChunkWrapper(chunk, this.level, this);
return new ChunkWrapper(chunk, this);
}
@Override
@@ -238,9 +254,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
@Override
public IBlockStateWrapper getBlockState(DhBlockPos pos)
{
return BlockStateWrapper.fromBlockState(this.level.getBlockState(McObjectConverter.Convert(pos)), this);
}
{ return BlockStateWrapper.fromBlockState(this.level.getBlockState(McObjectConverter.Convert(pos)), this); }
@Override
public IBiomeWrapper getBiome(DhBlockPos pos) { return BiomeWrapper.getBiomeWrapper(this.level.getBiome(McObjectConverter.Convert(pos)), this); }
@@ -255,6 +269,18 @@ public class ClientLevelWrapper implements IClientLevelWrapper
this.parentDhLevel = null;
}
@Override
public File getDhSaveFolder()
{
if (this.parentDhLevel == null)
{
return null;
}
return this.parentDhLevel.getSaveStructure().getSaveFolder(this);
}
//===================//
@@ -278,8 +304,13 @@ public class ClientLevelWrapper implements IClientLevelWrapper
@Override
public Color getCloudColor(float tickDelta)
{
#if MC_VER < MC_1_21_3
Vec3 colorVec3 = this.level.getCloudColor(tickDelta);
return new Color((float)colorVec3.x, (float)colorVec3.y, (float)colorVec3.z);
#else
int argbColor = this.level.getCloudColor(tickDelta);
return ColorUtil.toColorObjARGB(argbColor);
#endif
}
@@ -296,7 +327,7 @@ public class ClientLevelWrapper implements IClientLevelWrapper
return "Wrapped{null}";
}
return "Wrapped{" + this.level.toString() + "@" + this.getDimensionName() + "}";
return "Wrapped{" + this.level.toString() + "@" + this.getDhIdentifier() + "}";
}
}
@@ -47,11 +47,13 @@ import net.minecraft.world.level.chunk.ChunkStatus;
import net.minecraft.world.level.chunk.status.ChunkStatus;
#endif
#if MC_VER < MC_1_21_3
#else
import java.nio.file.Path;
#endif
import org.apache.logging.log4j.Logger;
/**
* @version 2022-9-16
*/
public class ServerLevelWrapper implements IServerLevelWrapper
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -67,12 +69,10 @@ public class ServerLevelWrapper implements IServerLevelWrapper
// constructors //
//==============//
public static ServerLevelWrapper getWrapper(ServerLevel level) { return LEVEL_WRAPPER_BY_SERVER_LEVEL.computeIfAbsent(level, ServerLevelWrapper::new); }
public static ServerLevelWrapper getWrapper(ServerLevel level)
{ return LEVEL_WRAPPER_BY_SERVER_LEVEL.computeIfAbsent(level, ServerLevelWrapper::new); }
public ServerLevelWrapper(ServerLevel level)
{
this.level = level;
}
public ServerLevelWrapper(ServerLevel level) { this.level = level; }
@@ -81,7 +81,24 @@ public class ServerLevelWrapper implements IServerLevelWrapper
//=========//
@Override
public File getSaveFolder() { return this.level.getChunkSource().getDataStorage().dataFolder; }
public File getMcSaveFolder()
{
#if MC_VER < MC_1_21_3
return this.level.getChunkSource().getDataStorage().dataFolder;
#else
return this.level.getChunkSource().getDataStorage().dataFolder.toFile();
#endif
}
@Override
public String getWorldFolderName()
{
#if MC_VER >= MC_1_17_1
return this.level.getServer().getWorldScreenshotFile().get().getParent().getFileName().toString();
#else // <= 1.16.5
return this.level.getServer().getWorldScreenshotFile().getParentFile().getName();
#endif
}
@Override
public DimensionTypeWrapper getDimensionType() { return DimensionTypeWrapper.getDimensionTypeWrapper(this.level.dimensionType()); }
@@ -89,6 +106,12 @@ public class ServerLevelWrapper implements IServerLevelWrapper
@Override
public String getDimensionName() { return this.level.dimension().location().toString(); }
@Override
public long getHashedSeed() { return this.level.getBiomeManager().biomeZoomSeed; }
@Override
public String getDhIdentifier() { return this.getDimensionName(); }
@Override
public EDhApiLevelType getLevelType() { return EDhApiLevelType.SERVER_LEVEL; }
@@ -108,8 +131,10 @@ public class ServerLevelWrapper implements IServerLevelWrapper
{
#if MC_VER < MC_1_17_1
return 0;
#else
#elif MC_VER < MC_1_21_3
return this.level.getMinBuildHeight();
#else
return this.level.getMinY();
#endif
}
@@ -127,7 +152,7 @@ public class ServerLevelWrapper implements IServerLevelWrapper
return null;
}
return new ChunkWrapper(chunk, this.level, this);
return new ChunkWrapper(chunk, this);
}
@Override
@@ -171,6 +196,18 @@ public class ServerLevelWrapper implements IServerLevelWrapper
return this.parentDhLevel.getGenericRenderer();
}
@Override
public File getDhSaveFolder()
{
if (this.parentDhLevel == null)
{
return null;
}
return this.parentDhLevel.getSaveStructure().getSaveFolder(this);
}
//================//
@@ -178,6 +215,6 @@ public class ServerLevelWrapper implements IServerLevelWrapper
//================//
@Override
public String toString() { return "Wrapped{" + this.level.toString() + "@" + this.getDimensionName() + "}"; }
public String toString() { return "Wrapped{" + this.level.toString() + "@" + this.getDhIdentifier() + "}"; }
}
@@ -20,11 +20,10 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration;
import java.lang.invoke.MethodHandles;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.*;
import java.util.function.Consumer;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGenerationStep;
import com.seibel.distanthorizons.core.util.objects.UncheckedInterruptedException;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
@@ -46,6 +45,7 @@ public final class GenerationEvent
/** the number of chunks wide this event is */
public final int size;
public final EDhApiWorldGenerationStep targetGenerationStep;
public final EDhApiDistantGeneratorMode generatorMode;
public EventTimer timer = null;
public long inQueueTime;
public long timeoutTime = -1;
@@ -56,12 +56,13 @@ public final class GenerationEvent
public GenerationEvent(
DhChunkPos minPos, int size, BatchGenerationEnvironment generationGroup,
EDhApiWorldGenerationStep targetGenerationStep, Consumer<IChunkWrapper> resultConsumer)
EDhApiDistantGeneratorMode generatorMode, EDhApiWorldGenerationStep targetGenerationStep, Consumer<IChunkWrapper> resultConsumer)
{
this.inQueueTime = System.nanoTime();
this.id = generationFutureDebugIDs++;
this.minPos = minPos;
this.size = size;
this.generatorMode = generatorMode;
this.targetGenerationStep = targetGenerationStep;
this.threadedParam = ThreadedParameters.getOrMake(generationGroup.params);
this.resultConsumer = resultConsumer;
@@ -71,17 +72,11 @@ public final class GenerationEvent
public static GenerationEvent startEvent(
DhChunkPos minPos, int size, BatchGenerationEnvironment genEnvironment,
EDhApiWorldGenerationStep target, Consumer<IChunkWrapper> resultConsumer,
EDhApiDistantGeneratorMode generatorMode, EDhApiWorldGenerationStep target, Consumer<IChunkWrapper> resultConsumer,
ExecutorService worldGeneratorThreadPool)
{
//if (size % 2 == 0)
//{
// size += 1; // size must be odd for vanilla world gen regions to work
//}
GenerationEvent generationEvent = new GenerationEvent(minPos, size, genEnvironment, target, resultConsumer);
generationEvent.future = CompletableFuture.runAsync(() ->
GenerationEvent generationEvent = new GenerationEvent(minPos, size, genEnvironment, generatorMode, target, resultConsumer);
generationEvent.future = CompletableFuture.supplyAsync(() ->
{
long runStartTime = System.nanoTime();
generationEvent.timeoutTime = runStartTime;
@@ -89,19 +84,75 @@ public final class GenerationEvent
generationEvent.timer = new EventTimer("setup");
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
try
{
//LOGGER.info("generating [{}]", event.minPos);
genEnvironment.generateLodFromList(generationEvent);
genEnvironment.generateLodFromListAsync(generationEvent, (runnable) ->
{
worldGeneratorThreadPool.execute(() ->
{
boolean alreadyMarked = BatchGenerationEnvironment.isCurrentThreadDistantGeneratorThread();
if (!alreadyMarked)
{
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
}
try
{
runnable.run();
}
catch (Throwable throwable)
{
handleWorldGenThrowable(generationEvent, throwable);
}
finally
{
if (!alreadyMarked)
{
BatchGenerationEnvironment.isDistantGeneratorThread.set(false);
}
}
});
});
}
catch (Throwable initialThrowable)
{
handleWorldGenThrowable(generationEvent, initialThrowable);
}
catch (InterruptedException ignored) { }
finally
{
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
}
return null;
}, worldGeneratorThreadPool);
return generationEvent;
}
/** There's probably a better way to handle this, but it'll work for now */
private static void handleWorldGenThrowable(GenerationEvent generationEvent, Throwable initialThrowable)
{
Throwable throwable = initialThrowable;
while (throwable instanceof CompletionException)
{
throwable = throwable.getCause();
}
if (throwable instanceof InterruptedException
|| throwable instanceof UncheckedInterruptedException
|| throwable instanceof RejectedExecutionException)
{
// these exceptions can be ignored, generally they just mean
// the thread is busy so it'll need to try again later.
// FIXME this should cause the world gen task to be re-queued so we can try again later
// however, currently it can cause large gaps in the world gen instead.
// These gaps will generate correctly if the level is reloaded and the world gen is re-queued,
// however this is makes it look like the generator isn't working or skipped something.
}
else
{
generationEvent.future.completeExceptionally(throwable);
}
}
public boolean isComplete() { return this.future.isDone(); }
@@ -50,23 +50,26 @@ import net.minecraft.world.level.storage.WorldData;
public final class GlobalParameters
{
public final ChunkGenerator generator;
#if MC_VER < MC_1_19_2
public final StructureManager structures;
#else
public final StructureTemplateManager structures;
public final RandomState randomState;
#endif
#if MC_VER < MC_1_19_4
public final WorldGenSettings worldGenSettings;
#else
public final WorldOptions worldOptions;
#endif
public final IDhServerLevel lodLevel;
public final ServerLevel level;
public final Registry<Biome> biomes;
public final RegistryAccess registry;
public final long worldSeed;
public final DataFixer fixerUpper;
#if MC_VER < MC_1_19_2
public final StructureManager structures;
#else
public final StructureTemplateManager structures;
public final RandomState randomState;
#endif
#if MC_VER < MC_1_19_4
public final WorldGenSettings worldGenSettings;
#else
public final WorldOptions worldOptions;
#endif
#if MC_VER >= MC_1_18_2
public final BiomeManager biomeManager;
public final ChunkScanAccess chunkScanner; // FIXME: Figure out if this is actually needed
@@ -76,29 +79,34 @@ public final class GlobalParameters
{
this.lodLevel = lodLevel;
level = ((ServerLevelWrapper) lodLevel.getServerLevelWrapper()).getWrappedMcObject();
MinecraftServer server = level.getServer();
this.level = ((ServerLevelWrapper) lodLevel.getServerLevelWrapper()).getWrappedMcObject();
MinecraftServer server = this.level.getServer();
WorldData worldData = server.getWorldData();
registry = server.registryAccess();
this.registry = server.registryAccess();
#if MC_VER < MC_1_19_4
worldGenSettings = worldData.worldGenSettings();
biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
worldSeed = worldGenSettings.seed();
this.worldGenSettings = worldData.worldGenSettings();
this.biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
this.worldSeed = worldGenSettings.seed();
#elif MC_VER < MC_1_21_3
this.worldOptions = worldData.worldGenOptions();
this.biomes = registry.registryOrThrow(Registries.BIOME);
this.worldSeed = worldOptions.seed();
#else
worldOptions = worldData.worldGenOptions();
biomes = registry.registryOrThrow(Registries.BIOME);
worldSeed = worldOptions.seed();
this.worldOptions = worldData.worldGenOptions();
this.biomes = this.registry.lookupOrThrow(Registries.BIOME);
this.worldSeed = this.worldOptions.seed();
#endif
#if MC_VER >= MC_1_18_2
biomeManager = new BiomeManager(level, BiomeManager.obfuscateSeed(worldSeed));
chunkScanner = level.getChunkSource().chunkScanner();
this.biomeManager = new BiomeManager(this.level, BiomeManager.obfuscateSeed(this.worldSeed));
this.chunkScanner = this.level.getChunkSource().chunkScanner();
#endif
structures = server.getStructureManager();
generator = level.getChunkSource().getGenerator();
fixerUpper = server.getFixerUpper();
this.structures = server.getStructureManager();
this.generator = this.level.getChunkSource().getGenerator();
this.fixerUpper = server.getFixerUpper();
#if MC_VER >= MC_1_19_2
randomState = level.getChunkSource().randomState();
this.randomState = this.level.getChunkSource().randomState();
#endif
}
@@ -19,7 +19,6 @@
package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
import com.google.common.collect.Maps;
import com.mojang.serialization.Codec;
import com.mojang.serialization.Dynamic;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@@ -27,21 +26,13 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGeneratio
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.ChunkLightStorage;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import it.unimi.dsi.fastutil.longs.LongSet;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import it.unimi.dsi.fastutil.shorts.ShortList;
import net.minecraft.core.Registry;
import net.minecraft.core.SectionPos;
#if MC_VER >= MC_1_19_4
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
@@ -50,7 +41,6 @@ import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;
import net.minecraft.nbt.NbtOps;
import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.*;
import net.minecraft.world.level.biome.Biome;
@@ -59,20 +49,22 @@ import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.*;
#if MC_VER < MC_1_21_3
import net.minecraft.world.level.chunk.storage.ChunkSerializer;
#else
#endif
import net.minecraft.world.level.levelgen.Heightmap;
#if MC_VER >= MC_1_18_2
import net.minecraft.world.level.levelgen.blending.BlendingData;
#if MC_VER < MC_1_19_2
import net.minecraft.world.level.levelgen.feature.StructureFeature;
#endif
import net.minecraft.world.level.levelgen.structure.StructureStart;
import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext;
import net.minecraft.world.ticks.LevelChunkTicks;
#endif
#if MC_VER >= MC_1_18_2
import net.minecraft.core.Holder;
import net.minecraft.core.RegistryAccess;
#if MC_VER < MC_1_19_2
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
#endif
@@ -238,18 +230,23 @@ public class ChunkLoader
#if MC_VER >= MC_1_18_2
#if MC_VER < MC_1_19_4
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
#else
#elif MC_VER < MC_1_21_3
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registries.BIOME);
#else
Registry<Biome> biomes = level.registryAccess().lookupOrThrow(Registries.BIOME);
#endif
#if MC_VER < MC_1_18_2
Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(
biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
#elif MC_VER < MC_1_19_2
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
#elif MC_VER < MC_1_21_3
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
#else
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codecRW(
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
#endif
#endif
int sectionYIndex = #if MC_VER < MC_1_17_1 16; #else level.getSectionsCount(); #endif
@@ -302,14 +299,28 @@ public class ChunkLoader
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
#else
biomeContainer = tagSection.contains("biomes", 10)
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
if (tagSection.contains("biomes", 10))
{
biomeContainer =
biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logBiomeDeserializationWarning(chunkPos, sectionYIndex, (String) string))
#if MC_VER < MC_1_20_6
.getOrThrow(false, LOGGER::error)
.getOrThrow(false, LOGGER::error);
#else
.getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null))
.getOrThrow((message) -> (RuntimeException) LOGGER.errorAndThrow(message, null));
#endif
: new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(), biomes.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
}
else
{
biomeContainer = new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(),
#if MC_VER < MC_1_21_3
biomes.getHolderOrThrow(Biomes.PLAINS),
#else
biomes.getOrThrow(Biomes.PLAINS),
#endif
PalettedContainer.Strategy.SECTION_BIOMES);
}
#endif
#if MC_VER < MC_1_20_1
@@ -353,12 +364,16 @@ public class ChunkLoader
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
{
ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9);
for (int n = 0; n < tagPostProcessings.size(); ++n)
for (int i = 0; i < tagPostProcessings.size(); ++i)
{
ListTag listTag3 = tagPostProcessings.getList(n);
for (int o = 0; o < listTag3.size(); ++o)
ListTag listTag3 = tagPostProcessings.getList(i);
for (int j = 0; j < listTag3.size(); ++j)
{
chunk.addPackedPostProcess(listTag3.getShort(o), n);
#if MC_VER < MC_1_21_3
chunk.addPackedPostProcess(listTag3.getShort(j), i);
#else
chunk.addPackedPostProcess(ShortList.of(listTag3.getShort(j)), i);
#endif
}
}
}
@@ -370,7 +385,12 @@ public class ChunkLoader
{
@SuppressWarnings({"unchecked", "rawtypes"})
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
#if MC_VER < MC_1_21_3
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null);
#else
blendingData = BlendingData.unpack(BlendingData.Packed.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null));
#endif
}
return blendingData;
}
@@ -392,7 +412,7 @@ public class ChunkLoader
return null;
#else
CombinedChunkLightStorage combinedStorage = new CombinedChunkLightStorage(ChunkWrapper.getMinBuildHeight(chunk), ChunkWrapper.getMaxBuildHeight(chunk));
CombinedChunkLightStorage combinedStorage = new CombinedChunkLightStorage(ChunkWrapper.getInclusiveMinBuildHeight(chunk), ChunkWrapper.getExclusiveMaxBuildHeight(chunk));
ChunkLightStorage blockLightStorage = combinedStorage.blockLightStorage;
ChunkLightStorage skyLightStorage = combinedStorage.skyLightStorage;
@@ -471,7 +491,7 @@ public class ChunkLoader
skyLight = LodUtil.MAX_MC_LIGHT;
}
int y = relY + (sectionIndex * LodUtil.CHUNK_WIDTH) + ChunkWrapper.getMinBuildHeight(chunk);
int y = relY + (sectionIndex * LodUtil.CHUNK_WIDTH) + ChunkWrapper.getInclusiveMinBuildHeight(chunk);
blockLightStorage.set(relX, y, relZ, blockLight);
skyLightStorage.set(relX, y, relZ, skyLight);
}
@@ -5,19 +5,24 @@ package com.seibel.distanthorizons.common.wrappers.worldGeneration.mimicObject;
import net.minecraft.server.level.GenerationChunkHolder;
import net.minecraft.world.level.ChunkPos;
import java.util.concurrent.CompletableFuture;
public class DhGenerationChunkHolder extends GenerationChunkHolder
{
public DhGenerationChunkHolder(ChunkPos pos)
{
super(pos);
}
public DhGenerationChunkHolder(ChunkPos pos) { super(pos); }
@Override
public int getTicketLevel() { return 0; }
@Override
public int getQueueLevel() { return 0; }
#if MC_VER < MC_1_21_3
#else
@Override
protected void addSaveDependency(CompletableFuture<?> completableFuture) { }
#endif
}
#endif
@@ -68,6 +68,13 @@ import com.google.common.collect.ImmutableList;
import net.minecraft.server.level.GenerationChunkHolder;
#endif
#if MC_VER >= MC_1_18_2
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.material.Fluid;
import net.minecraft.world.ticks.BlackholeTickAccess;
import net.minecraft.world.ticks.LevelTickAccess;
#endif
public class DhLitWorldGenRegion extends WorldGenRegion
{
@@ -76,8 +83,9 @@ public class DhLitWorldGenRegion extends WorldGenRegion
private static ChunkStatus debugTriggeredForStatus = null;
public final ServerLevel serverLevel;
public final DummyLightEngine lightEngine;
public final BatchGenerationEnvironment.IEmptyChunkGeneratorFunc generator;
public final BatchGenerationEnvironment.IEmptyChunkRetrievalFunc generator;
public final int writeRadius;
public final int size;
@@ -122,7 +130,7 @@ public class DhLitWorldGenRegion extends WorldGenRegion
ChunkAccess centerChunk,
ServerLevel serverLevel, DummyLightEngine lightEngine,
List<ChunkAccess> chunkList, ChunkStatus chunkStatus, int writeRadius,
BatchGenerationEnvironment.IEmptyChunkGeneratorFunc generator)
BatchGenerationEnvironment.IEmptyChunkRetrievalFunc generator)
{
#if MC_VER == MC_1_16_5
super(serverLevel, chunkList);
@@ -139,9 +147,10 @@ public class DhLitWorldGenRegion extends WorldGenRegion
new ChunkDependencies(ImmutableList.copyOf(ChunkStatus.getStatusList()).reverse()),
writeRadius, (WorldGenContext var1, ChunkStep var2, StaticCache2D<GenerationChunkHolder> var3, ChunkAccess var4) -> null),
centerChunk);
#endif
this.firstPos = chunkList.get(0).getPos();
this.serverLevel = serverLevel;
this.generator = generator;
this.lightEngine = lightEngine;
this.writeRadius = writeRadius;
@@ -170,7 +179,18 @@ public class DhLitWorldGenRegion extends WorldGenRegion
if (center.isUpgrading())
{
LevelHeightAccessor levelHeightAccessor = center.getHeightAccessorForGeneration();
if (blockPos.getY() < levelHeightAccessor.getMinBuildHeight() || blockPos.getY() >= levelHeightAccessor.getMaxBuildHeight())
int minY;
int maxY;
#if MC_VER < MC_1_21_3
minY = levelHeightAccessor.getMinBuildHeight();
maxY = levelHeightAccessor.getMaxBuildHeight();
#else
minY = levelHeightAccessor.getMinY();
maxY = levelHeightAccessor.getMaxY();
#endif
if (blockPos.getY() < minY || blockPos.getY() >= maxY)
{
return false;
}
@@ -180,6 +200,22 @@ public class DhLitWorldGenRegion extends WorldGenRegion
}
#endif
#if MC_VER >= MC_1_18_2
@Override
@NotNull
public LevelTickAccess<Block> getBlockTicks()
{
// DH world gen doesn't need ticking, so return the BlackholeTickAccess list (which causes all ticks to be ignored).
// If this isn't done the server may attempt to tick chunks outside the vanilla render distance,
// which can throw warnings or cause other issues
return BlackholeTickAccess.emptyLevelList();
}
@Override
@NotNull
public LevelTickAccess<Fluid> getFluidTicks() { return BlackholeTickAccess.emptyLevelList(); }
#endif
// TODO Check this
// @Override
// public List<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
@@ -194,7 +230,7 @@ public class DhLitWorldGenRegion extends WorldGenRegion
ChunkAccess chunkAccess = this.getChunk(blockPos);
if (chunkAccess instanceof LevelChunk)
return true;
chunkAccess.setBlockState(blockPos, blockState, false);
chunkAccess.setBlockState(blockPos, blockState, /*isBlockMoving*/false);
// This is for post ticking for water on gen and stuff like that. Not enabled
// for now.
// if (blockState.hasPostProcess(this, blockPos))
@@ -339,7 +375,7 @@ public class DhLitWorldGenRegion extends WorldGenRegion
if (chunk == null)
{
// chunk isn't in memory, generate a new one
chunk = this.generator.generate(chunkX, chunkZ);
chunk = this.generator.getChunk(chunkX, chunkZ);
if (chunk == null)
{
throw new NullPointerException("The provided generator should not return null!");
@@ -390,14 +426,10 @@ public class DhLitWorldGenRegion extends WorldGenRegion
/** Overriding allows us to use our own lighting engine */
@Override
public boolean canSeeSky(@NotNull BlockPos blockPos)
{
return (this.getBrightness(LightLayer.SKY, blockPos) >= this.getMaxLightLevel());
}
{ return (this.getBrightness(LightLayer.SKY, blockPos) >= LodUtil.MAX_MC_LIGHT); }
public int getBlockTint(@NotNull BlockPos blockPos, @NotNull ColorResolver colorResolver)
{
return this.calculateBlockTint(blockPos, colorResolver);
}
{ return this.calculateBlockTint(blockPos, colorResolver); }
private Biome _getBiome(BlockPos pos)
{
@@ -22,11 +22,11 @@ import net.minecraft.world.level.chunk.storage.RegionStorageInfo;
#endif
/**
* @deprecated should be replaced with net.minecraft.world.level.chunk.storage.IOWorker to
* prevent potential file corruption and issues with the C2ME mod.
* Generally this would be done via (MC ServerLevel) level.getChunkSource().chunkMap.worker#loadAsync()
* Shouldn't be used when the C2ME mod is present,
* otherwise there may be potential file corruption.
* When C2ME is present use (via MC ServerLevel) level.getChunkSource().chunkMap.worker#loadAsync()
* instead.
*/
@Deprecated
public class RegionFileStorageExternalCache implements AutoCloseable
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -46,22 +46,11 @@ public class RegionFileStorageExternalCache implements AutoCloseable
static class RegionFileCache
{
public final long pos;
public final RegionFile file;
public RegionFileCache(long pos, RegionFile file)
{
this.pos = pos;
this.file = file;
}
}
private final ConcurrentLinkedQueue<RegionFileCache> regionFileCache = new ConcurrentLinkedQueue<>();
public ConcurrentLinkedQueue<RegionFileCache> regionFileCache = new ConcurrentLinkedQueue<>();
public RegionFileStorageExternalCache(RegionFileStorage storage) { this.storage = storage; }
@@ -150,7 +139,7 @@ public class RegionFileStorageExternalCache implements AutoCloseable
if (retryCount >= maxRetryCount)
{
BatchGenerationEnvironment.LOAD_LOGGER.warn("Concurrency issue detected when getting region file for chunk at " + pos + ".");
BatchGenerationEnvironment.LOAD_LOGGER.warn("Concurrency issue detected when getting region file for chunk at [" + pos + "].");
}
@@ -237,4 +226,22 @@ public class RegionFileStorageExternalCache implements AutoCloseable
}
//================//
// helper classes //
//================//
private static class RegionFileCache
{
public final long pos;
public final RegionFile file;
public RegionFileCache(long pos, RegionFile file)
{
this.pos = pos;
this.file = file;
}
}
}
@@ -68,33 +68,50 @@ public final class StepBiomes
}
else if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
#endif
chunkWrapper.trySetStatus(STATUS);
chunksToDo.add(chunk);
}
}
for (ChunkAccess chunk : chunksToDo)
{
// System.out.println("StepBiomes: "+chunk.getPos());
#if MC_VER < MC_1_18_2
this.environment.params.generator.createBiomes(this.environment.params.biomes, chunk);
#elif MC_VER < MC_1_19_2
chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(this.environment.params.biomes, Runnable::run, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
chunk = this.environment.confirmFutureWasRunSynchronously(
this.environment.params.generator.createBiomes(
this.environment.params.biomes,
Runnable::run,
Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion),
chunk)
);
#elif MC_VER < MC_1_19_4
chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(this.environment.params.biomes, Runnable::run, this.environment.params.randomState, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
chunk = this.environment.confirmFutureWasRunSynchronously(
this.environment.params.generator.createBiomes(
this.environment.params.biomes,
Runnable::run,
this.environment.params.randomState, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion),
chunk)
);
#elif MC_VER < MC_1_21_1
chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(Runnable::run, this.environment.params.randomState, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
chunk = this.environment.confirmFutureWasRunSynchronously(
this.environment.params.generator.createBiomes(
Runnable::run,
this.environment.params.randomState,
Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion),
chunk)
);
#else
chunk = this.environment.joinSync(this.environment.params.generator.createBiomes(this.environment.params.randomState, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
chunk = this.environment.confirmFutureWasRunSynchronously(
this.environment.params.generator.createBiomes(
this.environment.params.randomState,
Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion),
chunk)
);
#endif
}
}
@@ -66,11 +66,7 @@ public final class StepFeatures
}
else if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
#endif
chunkWrapper.trySetStatus(STATUS);
}
@@ -91,7 +87,6 @@ public final class StepFeatures
#endif
Heightmap.primeHeightmaps(chunk, STATUS.heightmapsAfter());
BatchGenerationEnvironment.clearDistantGenerationMixinData();
}
catch (Exception e)
{
@@ -67,32 +67,42 @@ public final class StepNoise
{
continue;
}
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
#endif
chunkWrapper.trySetStatus(STATUS);
chunksToDo.add(chunk);
}
for (ChunkAccess chunk : chunksToDo)
{
// System.out.println("StepNoise: "+chunk.getPos());
#if MC_VER < MC_1_17_1
this.environment.params.generator.fillFromNoise(worldGenRegion, tParams.structFeat, chunk);
#elif MC_VER < MC_1_18_2
chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run,
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
chunk = this.environment.confirmFutureWasRunSynchronously(
this.environment.params.generator.fillFromNoise(
Runnable::run,
tParams.structFeat.forWorldGenRegion(worldGenRegion),
chunk));
#elif MC_VER < MC_1_19_2
chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
chunk = this.environment.confirmFutureWasRunSynchronously(
this.environment.params.generator.fillFromNoise(
Runnable::run,
Blender.of(worldGenRegion),
tParams.structFeat.forWorldGenRegion(worldGenRegion),
chunk));
#elif MC_VER < MC_1_21_1
chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion), this.environment.params.randomState,
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
chunk = this.environment.confirmFutureWasRunSynchronously(
this.environment.params.generator.fillFromNoise(
Runnable::run,
Blender.of(worldGenRegion),
this.environment.params.randomState,
tParams.structFeat.forWorldGenRegion(worldGenRegion),
chunk));
#else
chunk = this.environment.joinSync(this.environment.params.generator.fillFromNoise(Blender.of(worldGenRegion), this.environment.params.randomState,
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
chunk = this.environment.confirmFutureWasRunSynchronously(
this.environment.params.generator.fillFromNoise(
Blender.of(worldGenRegion),
this.environment.params.randomState,
tParams.structFeat.forWorldGenRegion(worldGenRegion),
chunk));
#endif
UncheckedInterruptedException.throwIfInterrupted();
}
@@ -66,12 +66,7 @@ public final class StepStructureReference
}
else if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
#endif
chunksToDo.add(chunk);
chunkWrapper.trySetStatus(STATUS);
}
}
@@ -28,7 +28,9 @@ import com.seibel.distanthorizons.common.wrappers.worldGeneration.BatchGeneratio
import com.seibel.distanthorizons.common.wrappers.worldGeneration.ThreadedParameters;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import net.minecraft.resources.ResourceKey;
import net.minecraft.server.level.WorldGenRegion;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ProtoChunk;
import org.apache.logging.log4j.Logger;
@@ -83,12 +85,7 @@ public final class StepStructureStart
}
else if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
#endif
chunksToDo.add(chunk);
chunkWrapper.trySetStatus(STATUS);
}
}
@@ -96,7 +93,8 @@ public final class StepStructureStart
if (this.environment.params.worldGenSettings.generateFeatures())
{
#elif MC_VER < MC_1_19_4
if (this.environment.params.worldGenSettings.generateStructures()) {
if (this.environment.params.worldGenSettings.generateStructures())
{
#else
if (this.environment.params.worldOptions.generateStructures())
{
@@ -114,15 +112,20 @@ public final class StepStructureStart
STRUCTURE_PLACEMENT_LOCK.lock();
#if MC_VER < MC_1_19_2
environment.params.generator.createStructures(environment.params.registry, tParams.structFeat, chunk, environment.params.structures,
environment.params.worldSeed);
this.environment.params.generator.createStructures(this.environment.params.registry, tParams.structFeat, chunk, this.environment.params.structures,
this.environment.params.worldSeed);
#elif MC_VER < MC_1_19_4
environment.params.generator.createStructures(environment.params.registry, environment.params.randomState, tParams.structFeat, chunk, environment.params.structures,
environment.params.worldSeed);
this.environment.params.generator.createStructures(this.environment.params.registry, this.environment.params.randomState, tParams.structFeat, chunk, this.environment.params.structures,
this.environment.params.worldSeed);
#elif MC_VER <= MC_1_21_3
this.environment.params.generator.createStructures(this.environment.params.registry,
this.environment.params.level.getChunkSource().getGeneratorState(),
tParams.structFeat, chunk, this.environment.params.structures);
#else
environment.params.generator.createStructures(environment.params.registry,
environment.params.level.getChunkSource().getGeneratorState(),
tParams.structFeat, chunk, environment.params.structures);
this.environment.params.generator.createStructures(this.environment.params.registry,
this.environment.params.level.getChunkSource().getGeneratorState(),
tParams.structFeat, chunk, this.environment.params.structures,
this.environment.params.level.dimension());
#endif
#if MC_VER >= MC_1_18_2
@@ -65,12 +65,7 @@ public final class StepSurface
}
else if (chunk instanceof ProtoChunk)
{
#if MC_VER < MC_1_21_1
((ProtoChunk) chunk).setStatus(STATUS);
#else
((ProtoChunk) chunk).setPersistedStatus(STATUS);
#endif
chunkWrapper.trySetStatus(STATUS);
chunksToDo.add(chunk);
}
}
@@ -2,6 +2,8 @@ accessWidener v1 named
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used to help determine what folder a clientLevel is
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
# used when rendering
accessible field com/mojang/blaze3d/vertex/VertexBuffer vertexCount I
@@ -31,6 +33,9 @@ accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecr
#accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Lnet/minecraft/core/Holder;
#accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doCreateBiomes (Lnet/minecraft/core/Registry;Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;)V
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
# lod generation from save file
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
@@ -1,8 +1,9 @@
accessWidener v1 named
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used to help determine what folder a clientLevel is
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
# used when rendering
accessible field com/mojang/blaze3d/vertex/VertexBuffer indexCount I
@@ -31,6 +32,11 @@ accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecr
# accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Lnet/minecraft/core/Holder;
#accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doCreateBiomes (Lnet/minecraft/core/Registry;Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;)V
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
# lod generation from save file
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
@@ -2,6 +2,8 @@ accessWidener v1 named
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used to help determine what folder a clientLevel is
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
# used when rendering
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
@@ -15,6 +17,11 @@ accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chu
# world generation
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
# lod generation from save file
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
@@ -2,6 +2,8 @@ accessWidener v1 named
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used to help determine what folder a clientLevel is
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
# used when rendering
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
@@ -15,6 +17,11 @@ accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chu
# world generation
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
# lod generation from save file
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
@@ -2,6 +2,8 @@ accessWidener v1 named
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used to help determine what folder a clientLevel is
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
# used when rendering
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
@@ -15,6 +17,11 @@ accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chu
# world generation
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
# lod generation from save file
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
@@ -2,6 +2,8 @@ accessWidener v1 named
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used to help determine what folder a clientLevel iss
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
# used when rendering
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
@@ -17,6 +19,11 @@ accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chu
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
# lod generation from save file
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
@@ -2,6 +2,8 @@ accessWidener v1 named
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used to help determine what folder a clientLevel is
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
# used when rendering
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
@@ -16,6 +18,11 @@ accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
# lod generation from save file
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
@@ -2,6 +2,8 @@ accessWidener v1 named
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
# used to help determine what folder a clientLevel is
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
# used when rendering
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
@@ -16,6 +18,11 @@ accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
# lod generation from save file
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
@@ -0,0 +1,53 @@
accessWidener v1 named
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/nio/file/Path;
# used to help determine what folder a clientLevel is
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
# used when rendering
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)F
accessible field net/minecraft/client/Minecraft deltaTracker Lnet/minecraft/client/DeltaTracker$Timer;
# used for grabbing vanilla rendered chunks
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
# world generation
# accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
# lod generation from save file
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
accessible field net/minecraft/world/level/chunk/storage/IOWorker storage Lnet/minecraft/world/level/chunk/storage/RegionFileStorage;
accessible field net/minecraft/world/level/chunk/storage/RegionFileStorage regionCache Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;
accessible field net/minecraft/world/level/chunk/storage/RegionFileStorage folder Ljava/nio/file/Path;
# grabbing textures
accessible class net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture
accessible method net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture getFrameX (I)I
accessible method net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture getFrameY (I)I
accessible field net/minecraft/client/renderer/texture/SpriteContents animatedTexture Lnet/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture;
accessible field net/minecraft/client/renderer/texture/SpriteContents originalImage Lcom/mojang/blaze3d/platform/NativeImage;
# UI stuff
accessible field net/minecraft/client/gui/components/AbstractButton SPRITES Lnet/minecraft/client/gui/components/WidgetSprites;
# Handles inserting the config button
accessible field net/minecraft/client/gui/layouts/HeaderAndFooterLayout headerFrame Lnet/minecraft/client/gui/layouts/FrameLayout;
accessible field net/minecraft/client/gui/layouts/FrameLayout children Ljava/util/List;
accessible class net/minecraft/client/gui/layouts/FrameLayout$ChildContainer
accessible field net/minecraft/client/gui/layouts/LinearLayout wrapped Lnet/minecraft/client/gui/layouts/GridLayout;
# hacky stuff
accessible field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
mutable field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
accessible field net/minecraft/client/gui/components/AbstractSelectionList scrollAmount D # Hack to bypass vanilla's setScrollAmount's clamp
@@ -0,0 +1,52 @@
accessWidener v1 named
# used when determining where to save files to
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/nio/file/Path;
# used to help determine what folder a clientLevel is
accessible field net/minecraft/world/level/biome/BiomeManager biomeZoomSeed J
# used when rendering
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)F
accessible field net/minecraft/client/Minecraft deltaTracker Lnet/minecraft/client/DeltaTracker$Timer;
# used for grabbing vanilla rendered chunks
accessible field net/minecraft/client/renderer/LevelRenderer visibleSections Lit/unimi/dsi/fastutil/objects/ObjectArrayList;
# world generation
# accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
accessible field net/minecraft/world/level/chunk/LevelChunk loaded Z
accessible field net/minecraft/world/level/lighting/LightEngine storage Lnet/minecraft/world/level/lighting/LayerLightSectionStorage;
accessible method net/minecraft/world/level/lighting/LayerLightSectionStorage lightOnInSection (J)Z
accessible field net/minecraft/server/level/ServerChunkCache distanceManager Lnet/minecraft/server/level/DistanceManager;
accessible method net/minecraft/server/level/ChunkMap getUpdatingChunkIfPresent (J)Lnet/minecraft/server/level/ChunkHolder;
accessible method net/minecraft/server/level/ChunkMap tick (Ljava/util/function/BooleanSupplier;)V
accessible field net/minecraft/server/level/ServerLevel entityManager Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
# lod generation from save file
accessible field net/minecraft/world/level/chunk/storage/ChunkStorage worker Lnet/minecraft/world/level/chunk/storage/IOWorker;
accessible field net/minecraft/world/level/chunk/storage/IOWorker storage Lnet/minecraft/world/level/chunk/storage/RegionFileStorage;
accessible field net/minecraft/world/level/chunk/storage/RegionFileStorage regionCache Lit/unimi/dsi/fastutil/longs/Long2ObjectLinkedOpenHashMap;
accessible field net/minecraft/world/level/chunk/storage/RegionFileStorage folder Ljava/nio/file/Path;
# grabbing textures
accessible class net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture
accessible method net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture getFrameX (I)I
accessible method net/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture getFrameY (I)I
accessible field net/minecraft/client/renderer/texture/SpriteContents animatedTexture Lnet/minecraft/client/renderer/texture/SpriteContents$AnimatedTexture;
accessible field net/minecraft/client/renderer/texture/SpriteContents originalImage Lcom/mojang/blaze3d/platform/NativeImage;
# UI stuff
accessible field net/minecraft/client/gui/components/AbstractButton SPRITES Lnet/minecraft/client/gui/components/WidgetSprites;
# Handles inserting the config button
accessible field net/minecraft/client/gui/layouts/HeaderAndFooterLayout headerFrame Lnet/minecraft/client/gui/layouts/FrameLayout;
accessible field net/minecraft/client/gui/layouts/FrameLayout children Ljava/util/List;
accessible class net/minecraft/client/gui/layouts/FrameLayout$ChildContainer
accessible field net/minecraft/client/gui/layouts/LinearLayout wrapped Lnet/minecraft/client/gui/layouts/GridLayout;
# hacky stuff
accessible field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
mutable field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
+10 -2
View File
@@ -1,5 +1,5 @@
plugins {
id "fabric-loom" version "1.6-SNAPSHOT"
id "fabric-loom" version "1.8-SNAPSHOT"
}
loom {
@@ -12,7 +12,15 @@ loom {
setConfigName("Fabric Client")
ideConfigGenerated(true) // When true a run configuration file will be generated for IDE's. By default only set to true for the root project.
runDir("../run/client")
vmArgs("-Dio.netty.leakDetection.level=advanced") // https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
vmArgs(
// https://github.com/FabricMC/fabric-loom/issues/915#issuecomment-1609154390
"-Dminecraft.api.auth.host=https://nope.invalid",
"-Dminecraft.api.account.host=https://nope.invalid",
"-Dminecraft.api.session.host=https://nope.invalid",
"-Dminecraft.api.services.host=https://nope.invalid",
// https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
"-Dio.netty.leakDetection.level=advanced"
)
programArgs("--username", "Dev")
}
server {
@@ -59,6 +59,7 @@ import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
import java.nio.FloatBuffer;
#endif
import java.util.HashSet;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import net.minecraft.client.multiplayer.ClientLevel;
@@ -126,7 +127,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
if (MC.clientConnectedToDedicatedServer())
{
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper(level);
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, level, wrappedLevel), wrappedLevel);
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
}
});
@@ -142,7 +143,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
// executor to prevent locking up the render/event thread
// if the getChunk() takes longer than expected
// (which can be caused by certain mods)
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
@@ -154,7 +155,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
SharedApi.INSTANCE.chunkBlockChangedEvent(
new ChunkWrapper(chunk, level, wrappedLevel),
new ChunkWrapper(chunk, wrappedLevel),
wrappedLevel
);
}
@@ -182,7 +183,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
// executor to prevent locking up the render/event thread
// if the getChunk() takes longer than expected
// (which can be caused by certain mods)
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
@@ -194,7 +195,7 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
IClientLevelWrapper wrappedLevel = ClientLevelWrapper.getWrapper((ClientLevel) level);
SharedApi.INSTANCE.chunkBlockChangedEvent(
new ChunkWrapper(chunk, level, wrappedLevel),
new ChunkWrapper(chunk, wrappedLevel),
wrappedLevel
);
}
@@ -236,6 +237,56 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
);
});
// TODO add to forge and neo
WorldRenderEvents.AFTER_ENTITIES.register((renderContext) ->
{
Mat4f projectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
Mat4f modelViewMatrix;
#if MC_VER < MC_1_20_6
modelViewMatrix = McObjectConverter.Convert(renderContext.matrixStack().last().pose());
#else
modelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
#endif
this.clientApi.renderFadeOpaque(
modelViewMatrix,
projectionMatrix,
#if MC_VER < MC_1_21_1
renderContext.tickDelta(),
#else
renderContext.tickCounter().getGameTimeDeltaTicks(),
#endif
ClientLevelWrapper.getWrapper(renderContext.world())
);
});
// TODO add to forge and neo
WorldRenderEvents.AFTER_TRANSLUCENT.register((renderContext) ->
{
Mat4f projectionMatrix = McObjectConverter.Convert(renderContext.projectionMatrix());
Mat4f modelViewMatrix;
#if MC_VER < MC_1_20_6
modelViewMatrix = McObjectConverter.Convert(renderContext.matrixStack().last().pose());
#else
modelViewMatrix = McObjectConverter.Convert(renderContext.positionMatrix());
#endif
this.clientApi.renderFade(
modelViewMatrix,
projectionMatrix,
#if MC_VER < MC_1_21_1
renderContext.tickDelta(),
#else
renderContext.tickCounter().getGameTimeDeltaTicks(),
#endif
ClientLevelWrapper.getWrapper(renderContext.world())
);
});
// Debug keyboard event
// FIXME: Use better hooks so it doesn't trigger key press events in text boxes
ClientTickEvents.END_CLIENT_TICK.register(client ->
@@ -253,7 +304,6 @@ public class FabricClientProxy implements AbstractModInitializer.IEventProxy
//==================//
#if MC_VER >= MC_1_20_6
PayloadTypeRegistry.playC2S().register(CommonPacketPayload.TYPE, new CommonPacketPayload.Codec());
PayloadTypeRegistry.playS2C().register(CommonPacketPayload.TYPE, new CommonPacketPayload.Codec());
ClientPlayNetworking.registerGlobalReceiver(CommonPacketPayload.TYPE, (payload, context) ->
{
@@ -40,6 +40,7 @@ import net.minecraft.commands.CommandSourceStack;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import org.apache.logging.log4j.Logger;
import org.lwjgl.util.tinyfd.TinyFileDialogs;
#if MC_VER >= MC_1_19_2
import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
@@ -95,10 +96,7 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
String indiumMissingMessage = ModInfo.READABLE_NAME + " needs Indium to work with Sodium.\nPlease download Indium from https://modrinth.com/mod/indium";
LOGGER.fatal(indiumMissingMessage);
if (!GraphicsEnvironment.isHeadless())
{
JOptionPane.showMessageDialog(null, indiumMissingMessage, ModInfo.READABLE_NAME, JOptionPane.INFORMATION_MESSAGE);
}
TinyFileDialogs.tinyfd_messageBox(ModInfo.READABLE_NAME, indiumMissingMessage, "ok", "error", false);
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
String errorMessage = "loading Distant Horizons. Distant Horizons requires Indium in order to run with Sodium.";
@@ -142,7 +140,7 @@ public class FabricMain extends AbstractModInitializer implements ClientModIniti
{
SingletonInjector.INSTANCE.runDelayedSetup();
if (Config.Client.Advanced.Graphics.Fog.disableVanillaFog.get() && SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("bclib"))
if (!Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get() && SingletonInjector.INSTANCE.get(IModChecker.class).isModLoaded("bclib"))
{
ModAccessorInjector.INSTANCE.get(IBCLibAccessor.class).setRenderCustomFog(false); // Remove BCLib's fog
}
@@ -51,7 +51,6 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final boolean isDedicatedServer;
public static Supplier<Boolean> isGenerationThreadChecker = null;
@@ -87,7 +86,6 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
public void registerEvents()
{
LOGGER.info("Registering Fabric Server Events");
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
/* Register the mod needed event callbacks */
@@ -144,7 +142,7 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
if (this.isValidTime())
{
ServerApi.INSTANCE.serverChunkLoadEvent(
new ChunkWrapper(chunk, chunk.getLevel(), level),
new ChunkWrapper(chunk, level),
level);
}
});
@@ -176,32 +174,33 @@ public class FabricServerProxy implements AbstractModInitializer.IEventProxy
}
});
#if MC_VER >= MC_1_20_6
PayloadTypeRegistry.playC2S().register(CommonPacketPayload.TYPE, new CommonPacketPayload.Codec());
if (this.isDedicatedServer)
{
#if MC_VER >= MC_1_20_6
PayloadTypeRegistry.playC2S().register(CommonPacketPayload.TYPE, new CommonPacketPayload.Codec());
PayloadTypeRegistry.playS2C().register(CommonPacketPayload.TYPE, new CommonPacketPayload.Codec());
ServerPlayNetworking.registerGlobalReceiver(CommonPacketPayload.TYPE, (payload, context) ->
{
if (payload.message() == null)
{
return;
}
ServerApi.INSTANCE.pluginMessageReceived(ServerPlayerWrapper.getWrapper(context.player()), payload.message());
});
#else
ServerPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (server, serverPlayer, handler, buffer, packetSender) ->
{
// Forge packet ID
buffer.readByte();
AbstractNetworkMessage message = AbstractPluginPacketSender.decodeMessage(buffer);
if (message != null)
{
ServerApi.INSTANCE.pluginMessageReceived(ServerPlayerWrapper.getWrapper(serverPlayer), message);
}
});
#endif
}
ServerPlayNetworking.registerGlobalReceiver(CommonPacketPayload.TYPE, (payload, context) ->
{
if (payload.message() == null)
{
return;
}
ServerApi.INSTANCE.pluginMessageReceived(ServerPlayerWrapper.getWrapper(context.player()), payload.message());
});
#else
ServerPlayNetworking.registerGlobalReceiver(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE, (server, serverPlayer, handler, buffer, packetSender) ->
{
// Forge packet ID
buffer.readByte();
AbstractNetworkMessage message = AbstractPluginPacketSender.decodeMessage(buffer);
if (message != null)
{
ServerApi.INSTANCE.pluginMessageReceived(ServerPlayerWrapper.getWrapper(serverPlayer), message);
}
});
#endif
}
}
@@ -41,15 +41,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(ClientLevel.class)
public class MixinClientLevel
{
// //Moved to MixinClientPacketListener
// @Inject(method = "<init>", at = @At("TAIL"))
// private void loadWorldEvent(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey resourceKey,
// #if MC_VER >= MC_1_18_2 Holder holder, #else DimensionType dimensionType, #endif int i,
// #if MC_VER >= MC_1_18_2 int j, #endif Supplier supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci)
// {
// ClientApi.INSTANCE.clientLevelLoadEvent(WorldWrapper.getWorldWrapper((ClientLevel)(Object)this));
// }
// Moved to overriding the enableChunkLight(...) method over at ClientPacketListener for 1.20+
#if MC_VER >= MC_1_18_2 && MC_VER < MC_1_20_1 // Only the setLightReady is only available after 1.18. This ensures the light data is ready.
@Inject(method = "setLightReady", at = @At("HEAD"))
@@ -60,7 +51,9 @@ public class MixinClientLevel
if (chunk != null && !chunk.isClientLightReady())
{
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, clientLevel, ClientLevelWrapper.getWrapper(clientLevel)), ClientLevelWrapper.getWrapper(clientLevel));
SharedApi.INSTANCE.chunkLoadEvent(
new ChunkWrapper(chunk, ClientLevelWrapper.getWrapper(clientLevel)),
ClientLevelWrapper.getWrapper(clientLevel));
}
}
#endif
@@ -21,8 +21,15 @@ import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
@Mixin(ClientPacketListener.class)
public class MixinClientPacketListener
{
@Shadow
private ClientLevel level;
@Inject(method = "handleLogin", at = @At("RETURN"))
void onHandleLoginEnd(CallbackInfo ci) { ClientApi.INSTANCE.onClientOnlyConnected(); }
void onHandleLoginEnd(CallbackInfo ci)
{
ClientApi.INSTANCE.onClientOnlyConnected();
ClientApi.INSTANCE.clientLevelLoadEvent(ClientLevelWrapper.getWrapper(this.level, true));
}
#if MC_VER < MC_1_19_4
@Inject(method = "cleanup", at = @At("HEAD"))
@@ -39,7 +46,7 @@ public class MixinClientPacketListener
void onEnableChunkLight(LevelChunk chunk, int x, int z, CallbackInfo ci)
{
IClientLevelWrapper clientLevel = ClientLevelWrapper.getWrapper((ClientLevel) chunk.getLevel());
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, chunk.getLevel(), clientLevel), clientLevel);
SharedApi.INSTANCE.chunkLoadEvent(new ChunkWrapper(chunk, clientLevel), clientLevel);
}
#endif
@@ -23,6 +23,7 @@ import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -35,28 +36,64 @@ import net.minecraft.client.renderer.FogRenderer.FogMode;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
#if MC_VER < MC_1_17_1
import net.minecraft.world.level.material.FluidState;
#elif MC_VER < MC_1_21_3
import net.minecraft.world.level.material.FogType;
#else
import net.minecraft.world.level.material.FogType;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.mojang.blaze3d.shaders.FogShape;
import net.minecraft.client.renderer.FogParameters;
import org.joml.Vector4f;
#endif
@Mixin(FogRenderer.class)
public class MixinFogRenderer
{
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
@Unique
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
@Unique
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
@Inject(at = @At("RETURN"), method = "setupFog")
#if MC_VER < MC_1_19_2
@Inject(at = @At("RETURN"), method = "setupFog")
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback)
{
#else
#elif MC_VER < MC_1_21_3
@Inject(at = @At("RETURN"), method = "setupFog")
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, float g, CallbackInfo callback)
{
#else
@Inject(at = @At("RETURN"), method = "setupFog", cancellable = true)
private static void disableSetupFog(Camera camera, FogMode fogMode, Vector4f vector4f, float f, boolean bl, float g, CallbackInfoReturnable<FogParameters> callback)
#endif
{
boolean cameraNotInFluid = cameraNotInFluid(camera);
Entity entity = camera.getEntity();
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
if (!isSpecialFog && cameraNotInFluid && fogMode == FogMode.FOG_TERRAIN
&& !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial()
&& !Config.Client.Advanced.Graphics.Fog.enableVanillaFog.get())
{
#if MC_VER < MC_1_17_1
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.fogEnd(A_EVEN_LARGER_VALUE);
#elif MC_VER < MC_1_21_3
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
#else
callback.setReturnValue(FogParameters.NO_FOG);
#endif
}
}
@Unique
private static boolean cameraNotInFluid(Camera camera)
{
#if MC_VER < MC_1_17_1
FluidState fluidState = camera.getFluidInCamera();
boolean cameraNotInFluid = fluidState.isEmpty();
@@ -65,20 +102,7 @@ public class MixinFogRenderer
boolean cameraNotInFluid = fogTypes == FogType.NONE;
#endif
Entity entity = camera.getEntity();
boolean isSpecialFog = (entity instanceof LivingEntity) && ((LivingEntity) entity).hasEffect(MobEffects.BLINDNESS);
if (!isSpecialFog && cameraNotInFluid && fogMode == FogMode.FOG_TERRAIN
&& !SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class).isFogStateSpecial()
&& Config.Client.Advanced.Graphics.Fog.disableVanillaFog.get())
{
#if MC_VER < MC_1_17_1
RenderSystem.fogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.fogEnd(A_EVEN_LARGER_VALUE);
#else
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
#endif
}
return cameraNotInFluid;
}
}
@@ -1,58 +0,0 @@
package com.seibel.distanthorizons.fabric.mixins.client;
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
import com.seibel.distanthorizons.core.api.internal.ClientApi;
import net.minecraft.client.renderer.GameRenderer;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
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;
@Mixin(GameRenderer.class)
public class MixinGameRenderer
{
private static final Logger LOGGER = LogManager.getLogger(MixinGameRenderer.class.getSimpleName());
#if MC_VER >= MC_1_17_1
// FIXME: This I think will dup multiple renderStartupEvent calls...
@Inject(method = {"reloadShaders", "preloadUiShader"}, at = @At("TAIL"))
public void onStartupShaders(CallbackInfo ci)
{
LOGGER.info("Starting up renderer (fabric)");
if (!DependencySetupDoneCheck.isDone)
{
LOGGER.warn("Dependency setup is not done yet, skipping renderer this startup event!");
return;
}
ClientApi.INSTANCE.rendererStartupEvent();
}
@Inject(method = "shutdownShaders", at = @At("HEAD"))
public void onShutdownShaders(CallbackInfo ci)
{
LOGGER.info("Shutting down renderer (fabric)");
if (!DependencySetupDoneCheck.isDone)
{
LOGGER.warn("Dependency setup is not done yet, skipping renderer this shutdown event!");
return;
}
ClientApi.INSTANCE.rendererShutdownEvent();
}
#else
// FIXME: on 1.16 we dont have stuff for reloading/shutting down shaders
// FIXME: This I think will dup multiple renderStartupEvent calls...
@Inject(method = {"loadEffect"}, at = @At("TAIL"))
public void onStartupShaders(CallbackInfo ci) {
ClientApi.INSTANCE.rendererStartupEvent();
}
@Inject(method = "shutdownEffect", at = @At("HEAD"))
public void onShutdownShaders(CallbackInfo ci) {
ClientApi.INSTANCE.rendererShutdownEvent();
}
#endif
}
@@ -111,16 +111,22 @@ public class MixinLevelRenderer
mcProjectionMatrix.setIdentity();
#endif
// TODO move this into a common place
float frameTime;
#if MC_VER < MC_1_21_1
frameTime = Minecraft.getInstance().getFrameTime();
#elif MC_VER < MC_1_21_3
frameTime = Minecraft.getInstance().getTimer().getRealtimeDeltaTicks();
#else
frameTime = Minecraft.getInstance().deltaTracker.getRealtimeDeltaTicks();
#endif
if (renderType.equals(RenderType.translucent()))
{
ClientApi.INSTANCE.renderDeferredLods(ClientLevelWrapper.getWrapper(this.level),
mcModelViewMatrix,
mcProjectionMatrix,
#if MC_VER < MC_1_21_1
Minecraft.getInstance().getFrameTime()
#else
Minecraft.getInstance().getTimer().getRealtimeDeltaTicks()
#endif
frameTime
);
}
@@ -19,9 +19,6 @@
package com.seibel.distanthorizons.fabric.mixins.client;
import com.mojang.blaze3d.platform.NativeImage;
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftRenderWrapper;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -35,13 +32,22 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
#if MC_VER < MC_1_21_3
import com.mojang.blaze3d.platform.NativeImage;
#else
import com.mojang.blaze3d.pipeline.TextureTarget;
#endif
@Mixin(LightTexture.class)
public class MixinLightTexture
{
@Shadow
@Final
#if MC_VER < MC_1_21_3
private NativeImage lightPixels;
#else
private TextureTarget target;
#endif
@Inject(method = "updateLightTexture(F)V", at = @At("RETURN"))
public void updateLightTexture(float partialTicks, CallbackInfo ci)
@@ -52,8 +58,14 @@ public class MixinLightTexture
return;
}
IClientLevelWrapper clientLevel = mc.getWrappedClientLevel();
#if MC_VER < MC_1_21_3
MinecraftRenderWrapper.INSTANCE.updateLightmap(this.lightPixels, clientLevel);
#else
MinecraftRenderWrapper.INSTANCE.setLightmapId(this.target.getColorTextureId(), clientLevel);
#endif
}
}
@@ -9,12 +9,14 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.jar.installer.GitlabGetter;
import com.seibel.distanthorizons.core.jar.installer.ModrinthGetter;
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
import com.seibel.distanthorizons.coreapi.ModInfo;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.TitleScreen;
import net.minecraft.client.multiplayer.ClientLevel;
import org.apache.logging.log4j.Logger;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
@@ -31,6 +33,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(Minecraft.class)
public abstract class MixinMinecraft
{
@Unique
private static final Logger LOGGER = DhLoggerBuilder.getLogger(MixinMinecraft.class.getSimpleName());
@Shadow
public abstract boolean isLocalServer();
@@ -89,6 +95,7 @@ public abstract class MixinMinecraft
)
private void buildInitialScreens(Runnable runnable)
{
// TODO merge logic for forge, neo, and fabric
if (
DEBUG_ALWAYS_SHOW_UPDATER ||
(
@@ -111,11 +118,28 @@ public abstract class MixinMinecraft
versionId = GitlabGetter.INSTANCE.projectPipelines.get(0).get("sha");
}
Minecraft.getInstance().setScreen(new UpdateModScreen(
// TODO: Change to runnable, instead of tittle screen
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
versionId
));
if (versionId != null)
{
try
{
Minecraft.getInstance().setScreen(new UpdateModScreen(
// TODO: Change to runnable, instead of tittle screen
new TitleScreen(false), // We don't want to use the vanilla title screen as it would fade the buttons
versionId
));
}
catch (IllegalArgumentException e)
{
// info instead of error since this can be ignored and probably just means
// there isn't a new DH version available
LOGGER.info("Unable to show DH update screen, reason: ["+e.getMessage()+"].");
}
}
else
{
LOGGER.info("Unable to find new DH update for the ["+updateBranch+"] branch. Assuming DH is up to date...");
}
};
}
@@ -91,7 +91,7 @@ public class MixinOptionsScreen extends Screen
@Inject(at = @At("RETURN"), method = "init")
private void lodconfig$init(CallbackInfo ci)
{
if (Config.Client.optionsButton.get())
if (Config.Client.showDhOptionsButtonInMinecraftUi.get())
{
#if MC_VER < MC_1_17_1
this.addButton(this.getOptionsButton());
@@ -19,7 +19,7 @@ public class MixinTextureUtil
at = @At(value = "INVOKE", target = "Lcom/mojang/blaze3d/platform/GlStateManager;_texParameter(IIF)V", #if MC_VER == MC_1_16_5 remap = true #else remap = false #endif))
private static void setLodBias(int target, int pname, float param)
{
float biasValue = Config.Client.Advanced.Graphics.AdvancedGraphics.lodBias.get().floatValue();
float biasValue = Config.Client.Advanced.Graphics.Quality.lodBias.get().floatValue();
if (biasValue != 0)
{
// The target is GL11.GL_TEXTURE_2D
@@ -0,0 +1,55 @@
package com.seibel.distanthorizons.fabric.mixins.server;
#if MC_VER < MC_1_21_3
import net.minecraft.Util;
import net.minecraft.world.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
/**
* {@link MixinUtilBackgroundThread} was used for versions before 1.21.3
* This is just a dummy class/mixin to make the compiler happy.
*
* @see MixinUtilBackgroundThread
*/
//@Mixin(net.minecraft.minecraft.class) // TODO we should allow version specific mixins so we don't have to create dummy mixins that exist for all MC versions
@Mixin(Util.class)
public class MixinLevelTicks
{
}
#else
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
import net.minecraft.world.ticks.LevelTicks;
import net.minecraft.world.ticks.ScheduledTick;
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;
@Mixin(LevelTicks.class)
public class MixinLevelTicks<T>
{
// TODO put in a common location
private static boolean isWorldGenThread()
{ return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get(); }
@Inject(method = "schedule", at = @At(value = "HEAD"), cancellable = true)
private void schedule(ScheduledTick<T> tick, CallbackInfo ci)
{
// In MC 1.21.4 an error check was added to log attempting to schedule ticks for unloaded chunks
// this caused a lot of unnecessary errors when generating sand (FallingBlock.class).
if (isWorldGenThread())
{
ci.cancel();
}
}
}
#endif
@@ -31,8 +31,11 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
#if MC_VER >= MC_1_21_1
#if MC_VER < MC_1_21_1
#elif MC_VER < MC_1_21_3
import net.minecraft.world.level.portal.DimensionTransition;
#else
import net.minecraft.world.level.portal.TeleportTransition;
#endif
@@ -54,23 +57,29 @@ public class MixinServerPlayer implements IMixinServerPlayer
{ this.dimensionChangeDestination = dimensionChangeDestination; }
#endif
#if MC_VER < MC_1_21_1
@Inject(at = @At("HEAD"), method = "changeDimension")
public void changeDimension(ServerLevel destination, CallbackInfoReturnable<Entity> cir)
{ this.dimensionChangeDestination = destination; }
#elif MC_VER < MC_1_21_3
@Inject(at = @At("HEAD"), method = "changeDimension")
#if MC_VER >= MC_1_21_1
public void changeDimension(DimensionTransition dimensionTransition, CallbackInfoReturnable<Entity> cir)
{ this.dimensionChangeDestination = dimensionTransition.newLevel(); }
#else
public void changeDimension(ServerLevel destination, CallbackInfoReturnable<Entity> cir)
{ this.dimensionChangeDestination = destination; }
@Inject(at = @At("HEAD"), method = "teleport")
public void changeDimension(TeleportTransition teleportTransition, CallbackInfoReturnable<ServerPlayer> cir)
{ this.dimensionChangeDestination = teleportTransition.newLevel(); }
#endif
#if MC_VER >= MC_1_20_1
@Inject(at = @At("RETURN"), method = "setServerLevel")
public void setServerLevel(ServerLevel level, CallbackInfo ci)
{ this.dimensionChangeDestination = null; }
#elif MC_VER >= MC_1_17_1
#if MC_VER < MC_1_17_1
#elif MC_VER < MC_1_20_1
@Inject(at = @At("RETURN"), method = "setLevel")
public void setLevel(ServerLevel level, CallbackInfo ci)
{ this.dimensionChangeDestination = null; }
#else
@Inject(at = @At("RETURN"), method = "setServerLevel")
public void setServerLevel(ServerLevel level, CallbackInfo ci)
{ this.dimensionChangeDestination = null; }
#endif
}
@@ -0,0 +1,75 @@
/*
* This file is part of the Distant Horizons mod
* licensed under the GNU LGPL v3 License.
*
* Copyright (C) 2020-2023 James Seibel
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.seibel.distanthorizons.fabric.mixins.server;
import org.spongepowered.asm.mixin.Mixin;
#if MC_VER < MC_1_21_3
/**
* {@link MixinUtilBackgroundThread} was used for versions before 1.21.3
* This is just a dummy class/mixin to make the compiler happy.
*
* @see MixinUtilBackgroundThread
*/
@Mixin(net.minecraft.Util.class) // TODO we should allow version specific mixins so we don't have to create dummy mixins that exist for all MC versions
public class MixinTracingExecutor
{
}
#else
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import net.minecraft.TracingExecutor;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.util.concurrent.Executor;
/**
* This is needed for DH's world gen so we can run
* world gen on our own threads instead of using MC thread pools.
*
* @see MixinUtilBackgroundThread
* @see RunOnThisThreadExecutorService
*/
@Mixin(TracingExecutor.class)
public class MixinTracingExecutor
{
// TODO put in a common location
private static boolean isWorldGenThread()
{ return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get(); }
// replaced with TracingExecutor in MC 1.21.3+
@Inject(method = "forName(Ljava/lang/String;)Ljava/util/concurrent/Executor;", at = @At("HEAD"), cancellable = true)
private void forName(String executorName, CallbackInfoReturnable<Executor> ci)
{
if (isWorldGenThread())
{
// run this task on the current DH thread instead of a new MC thread
ci.setReturnValue(new RunOnThisThreadExecutorService());
}
}
}
#endif
@@ -19,60 +19,81 @@
package com.seibel.distanthorizons.fabric.mixins.server;
import java.util.concurrent.ExecutorService;
import java.util.function.Supplier;
import com.seibel.distanthorizons.fabric.FabricServerProxy;
import com.seibel.distanthorizons.common.wrappers.DependencySetupDoneCheck;
import com.seibel.distanthorizons.core.util.objects.RunOnThisThreadExecutorService;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import com.seibel.distanthorizons.core.util.objects.DummyRunExecutorService;
import net.minecraft.Util;
import java.util.concurrent.ExecutorService;
#if MC_VER < MC_1_16_5
#elif MC_VER < MC_1_21_3
import java.util.function.Supplier;
#else
#endif
/**
* This is needed for DH's world gen so we can run
* world gen on our own threads instead of using MC thread pools.
*
* @see MixinTracingExecutor
* @see RunOnThisThreadExecutorService
*/
@Mixin(Util.class)
public class MixinUtilBackgroundThread
{
private static boolean shouldApplyOverride()
{
return FabricServerProxy.isGenerationThreadChecker != null && FabricServerProxy.isGenerationThreadChecker.get();
}
private static boolean isWorldGenThread()
{ return DependencySetupDoneCheck.isDone && DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread.get(); }
#if MC_VER < MC_1_21_3
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
{
if (shouldApplyOverride())
if (isWorldGenThread())
{
//ApiShared.LOGGER.info("util backgroundExecutor triggered");
ci.setReturnValue(new DummyRunExecutorService());
// run this task on the current DH thread instead of a new MC thread
ci.setReturnValue(new RunOnThisThreadExecutorService());
}
}
#else
// replaced with TracingExecutor in MC 1.21.3+
#endif
#if MC_VER >= MC_1_17_1
#if MC_VER < MC_1_17_1
#elif MC_VER < MC_1_21_3
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/lang/Runnable;)Ljava/lang/Runnable;",
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
{
if (shouldApplyOverride())
if (isWorldGenThread())
{
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
ci.setReturnValue(r);
}
}
#else
// replaced with TracingExecutor in MC 1.21.3+
#endif
#if MC_VER >= MC_1_18_2
#if MC_VER < MC_1_18_2
#elif MC_VER < MC_1_21_3
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/util/function/Supplier;)Ljava/util/function/Supplier;",
at = @At("HEAD"), cancellable = true)
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
{
if (shouldApplyOverride())
if (isWorldGenThread())
{
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
ci.setReturnValue(r);
}
}
#else
// replaced with TracingExecutor in MC 1.21.3+
#endif
}
@@ -9,17 +9,16 @@ import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.Abstrac
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.objects.data.DhApiChunk;
import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.chunk.ChunkAccess;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;
public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
public class TestChunkWorldGenerator extends AbstractDhApiChunkWorldGenerator
{
private final ServerLevel level;
private final IDhApiLevelWrapper levelWrapper;
@@ -30,7 +29,7 @@ public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
// constructor //
//=============//
public TestWorldGenerator(ServerLevel level)
public TestChunkWorldGenerator(ServerLevel level)
{
this.level = level;
this.levelWrapper = ServerLevelWrapper.getWrapper(level);
@@ -46,7 +45,7 @@ public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
public EDhApiWorldGeneratorReturnType getReturnType() { return EDhApiWorldGeneratorReturnType.API_CHUNKS; }
@Override
public boolean runApiChunkValidation() { return true; }
public boolean runApiValidation() { return true; }
@@ -70,8 +69,8 @@ public class TestWorldGenerator extends AbstractDhApiChunkWorldGenerator
ChunkAccess chunk = this.level.getChunk(chunkPosX, chunkPosZ);
int minBuildHeight = this.level.getMinBuildHeight();
int maxBuildHeight = this.level.getMaxBuildHeight();
int minBuildHeight = this.levelWrapper.getMinHeight();
int maxBuildHeight = this.levelWrapper.getMaxHeight();
DhApiChunk apiChunk = DhApiChunk.create(chunkPosX, chunkPosZ, minBuildHeight, maxBuildHeight);
for (int x = 0; x < 16; x++)
@@ -0,0 +1,201 @@
package com.seibel.distanthorizons.fabric.testing;
import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiWorldGeneratorReturnType;
import com.seibel.distanthorizons.api.interfaces.block.IDhApiBiomeWrapper;
import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper;
import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGenerator;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
import com.seibel.distanthorizons.api.objects.data.IDhApiFullDataSource;
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import net.minecraft.server.level.ServerLevel;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.util.ArrayList;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.function.Consumer;
public class TestGenericWorldGenerator implements IDhApiWorldGenerator
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
private final IDhApiLevelWrapper levelWrapper;
//=============//
// constructor //
//=============//
public TestGenericWorldGenerator(IDhApiLevelWrapper levelWrapper)
{ this.levelWrapper = levelWrapper; }
//============//
// properties //
//============//
@Override
public byte getSmallestDataDetailLevel() { return (byte) (EDhApiDetailLevel.BLOCK.detailLevel); }
@Override
public byte getLargestDataDetailLevel()
//{ return (byte) (EDhApiDetailLevel.BLOCK.detailLevel + 12); }
{ return (byte) (EDhApiDetailLevel.BLOCK.detailLevel); }
@Override
public EDhApiWorldGeneratorReturnType getReturnType() { return EDhApiWorldGeneratorReturnType.API_DATA_SOURCES; }
@Override
public boolean runApiValidation() { return true; }
//==================//
// chunk generation //
//==================//
@Override
public CompletableFuture<Void> generateLod(
int chunkPosMinX, int chunkPosMinZ,
int posX, int posZ, byte detailLevel,
IDhApiFullDataSource pooledFullDataSource,
EDhApiDistantGeneratorMode generatorMode, ExecutorService worldGeneratorThreadPool,
Consumer<IDhApiFullDataSource> resultConsumer)
{
return CompletableFuture.runAsync(() ->
this.generateInternal(
chunkPosMinX, chunkPosMinZ,
posX, posZ, detailLevel,
pooledFullDataSource, generatorMode, resultConsumer),
worldGeneratorThreadPool);
}
public void generateInternal(
int chunkPosMinX, int chunkPosMinZ,
int posX, int posZ, byte detailLevel,
IDhApiFullDataSource pooledFullDataSource,
EDhApiDistantGeneratorMode generatorMode,
Consumer<IDhApiFullDataSource> resultConsumer)
{
// this test is only validated for 1.18.2 and up
// (and it is only needed when testing world gen overrides/API chunks, so it isn't normally needed)
#if MC_VER >= MC_1_18_2
IDhApiBiomeWrapper biome;
IDhApiBlockStateWrapper colorBlock;
IDhApiBlockStateWrapper borderBlock;
IDhApiBlockStateWrapper airBlock;
int maxHeight;
try
{
biome = DhApi.Delayed.wrapperFactory.getBiomeWrapper("minecraft:plains", this.levelWrapper);
airBlock = DhApi.Delayed.wrapperFactory.getAirBlockStateWrapper();
borderBlock = DhApi.Delayed.wrapperFactory.getDefaultBlockStateWrapper("minecraft:stone", this.levelWrapper);
String blockResourceLocation;
switch (detailLevel)
{
case 0:
blockResourceLocation = "minecraft:red_wool";
maxHeight = 60;
break;
case 1:
blockResourceLocation = "minecraft:orange_wool";
maxHeight = 70;
break;
case 2:
blockResourceLocation = "minecraft:yellow_wool";
maxHeight = 80;
break;
case 3:
blockResourceLocation = "minecraft:lime_wool";
maxHeight = 90;
break;
case 4:
blockResourceLocation = "minecraft:cyan_wool";
maxHeight = 100;
break;
case 5:
blockResourceLocation = "minecraft:blue_wool";
maxHeight = 100;
break;
case 6:
blockResourceLocation = "minecraft:magenta_wool";
maxHeight = 110;
break;
case 7:
blockResourceLocation = "minecraft:white_wool";
maxHeight = 120;
break;
case 8:
blockResourceLocation = "minecraft:gray_wool";
maxHeight = 120;
break;
default:
blockResourceLocation = "minecraft:black_wool";
maxHeight = 140;
break;
}
colorBlock = DhApi.Delayed.wrapperFactory.getDefaultBlockStateWrapper(blockResourceLocation, this.levelWrapper);
}
catch (IOException e)
{
LOGGER.error("Failed to get biome/block: "+ e.getMessage(), e);
return;
}
ArrayList<DhApiTerrainDataPoint> dataPoints = new ArrayList<>();
int width = pooledFullDataSource.getWidthInDataColumns();
for (int x = 0; x < width; x++)
{
for (int z = 0; z < width; z++)
{
dataPoints.clear();
IDhApiBlockStateWrapper block = colorBlock;
if (x == 0 || x == (width-1)
|| z == 0 || z == (width-1))
{
block = borderBlock;
}
// TODO make mutable dataPoint object
// sky lighting can be ignored. DH will auto light the LODs after they've been submitted
// block lighting however will need to be generated here
dataPoints.add(DhApiTerrainDataPoint.create((byte)0, 0, 0, 0, maxHeight, block, biome));
dataPoints.add(DhApiTerrainDataPoint.create((byte)0, 0, 0, maxHeight, 256, airBlock, biome));
pooledFullDataSource.setApiDataPointColumn(x, z, dataPoints);
}
}
resultConsumer.accept(pooledFullDataSource);
#else
#endif
}
@Override
public void preGeneratorTaskStart() { /* do nothing */ }
//=========//
// cleanup //
//=========//
@Override
public void close() { /* do nothing */ }
}
@@ -8,6 +8,7 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import net.minecraft.server.level.ServerLevel;
import org.apache.logging.log4j.Logger;
// TODO add to API example once Builderb0y has given the all-clear
public class TestWorldGenBindingEvent extends DhApiLevelLoadEvent
{
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
@@ -17,12 +18,20 @@ public class TestWorldGenBindingEvent extends DhApiLevelLoadEvent
{
LOGGER.info("DH Level: ["+event.value.levelWrapper.getDimensionType()+"] loaded.");
// Note: whenever you use a wrapper method on a new Minecraft version it is recommended that you
// call wrapper.getClass() to determine which object the API will return before you try casting it.
ServerLevel level = (ServerLevel) event.value.levelWrapper.getWrappedMcObject();
try
{
// Note: whenever you use a wrapper method on a new Minecraft version it is recommended that you
// call wrapper.getClass() to determine which object the API will return before you try casting it.
ServerLevel level = (ServerLevel) event.value.levelWrapper.getWrappedMcObject();
// override the core DH world generator for this level
IDhApiWorldGenerator exampleWorldGen = new TestWorldGenerator(level);
DhApi.worldGenOverrides.registerWorldGeneratorOverride(event.value.levelWrapper, exampleWorldGen);
// override the core DH world generator for this level
//IDhApiWorldGenerator exampleWorldGen = new TestChunkWorldGenerator(level);
IDhApiWorldGenerator exampleWorldGen = new TestGenericWorldGenerator(event.value.levelWrapper);
DhApi.worldGenOverrides.registerWorldGeneratorOverride(event.value.levelWrapper, exampleWorldGen);
}
catch (ClassCastException e)
{
LOGGER.warn("Unable to add world generator to level wrapper ["+event.value.levelWrapper.getClass()+"] - ["+event.value.levelWrapper.getDimensionType()+"].");
}
}
}
@@ -22,19 +22,20 @@ package com.seibel.distanthorizons.fabric.wrappers.modAccessor;
#if MC_VER >= MC_1_19_4
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
#if MC_VER <= MC_1_20_4
import net.coderbot.iris.Iris;
import net.irisshaders.iris.api.v0.IrisApi;
#else
import net.irisshaders.iris.Iris;
#endif
import net.irisshaders.iris.api.v0.IrisApi;
#endif
public class IrisAccessor implements IIrisAccessor
{
@Override
public String getModName()
{
//return "Iris-Fabric";
return Iris.MODID;
}
@@ -33,11 +33,4 @@ public class OptifineAccessor extends AbstractOptifineAccessor
return "Optifine-Fabric-1.18.X";
}
@Override
public HashSet<DhChunkPos> getNormalRenderedChunks()
{
// TODO: Impl proper methods here
return null;
}
}
@@ -84,7 +84,7 @@ public class SodiumAccessor implements ISodiumAccessor
sodiumPerformanceOptions = optionsClass.getDeclaredField("performance").get(basicOptions);
setFogOcclusionMethod = MethodHandles.lookup()
.findSetter(Class.forName(
"me.jellysquid.mods.sodium.client.gui.SodiumGameOptions$PerformanceSettings"),
"me.jellysquid.mods.sodium.client.gui.SodiumGameOptions$PerformanceSettings"),
"useFogOcclusion", boolean.class);
// alternate option if referencing Sodium 0.5 directly
@@ -101,7 +101,7 @@ public class SodiumAccessor implements ISodiumAccessor
sodiumPerformanceOptions = optionsClass.getDeclaredField("performance").get(basicOptions);
setFogOcclusionMethod = MethodHandles.lookup()
.findSetter(Class.forName(
"net.caffeinemc.mods.sodium.client.gui.SodiumGameOptions$PerformanceSettings"),
"net.caffeinemc.mods.sodium.client.gui.SodiumGameOptions$PerformanceSettings"),
"useFogOcclusion", boolean.class);
}
}
@@ -1,29 +1,30 @@
{
"required": true,
"minVersion": "0.8",
"package": "com.seibel.distanthorizons.fabric.mixins",
"mixins": [
"server.MixinChunkGenerator",
"server.MixinChunkMap",
"server.MixinUtilBackgroundThread",
"server.MixinServerPlayer",
"server.MixinEntity"
],
"client": [
"client.MixinClientLevel",
"client.MixinClientPacketListener",
"client.MixinDebugScreenOverlay",
"client.MixinFogRenderer",
"client.MixinGameRenderer",
"client.MixinLevelRenderer",
"client.MixinLightTexture",
"client.MixinOptionsScreen",
"client.MixinMinecraft",
"client.MixinTextureUtil"
],
"server": [],
"injectors": {
"defaultRequire": 1
},
"plugin": "com.seibel.distanthorizons.fabric.mixins.FabricMixinPlugin"
"required": true,
"minVersion": "0.8",
"package": "com.seibel.distanthorizons.fabric.mixins",
"mixins": [
"server.MixinChunkGenerator",
"server.MixinChunkMap",
"server.MixinEntity",
"server.MixinServerPlayer",
"server.MixinTracingExecutor",
"server.MixinUtilBackgroundThread",
"server.MixinLevelTicks"
],
"client": [
"client.MixinClientLevel",
"client.MixinClientPacketListener",
"client.MixinDebugScreenOverlay",
"client.MixinFogRenderer",
"client.MixinLevelRenderer",
"client.MixinLightTexture",
"client.MixinMinecraft",
"client.MixinOptionsScreen",
"client.MixinTextureUtil"
],
"server": [],
"injectors": {
"defaultRequire": 1
},
"plugin": "com.seibel.distanthorizons.fabric.mixins.FabricMixinPlugin"
}
+9 -1
View File
@@ -39,7 +39,15 @@ loom {
setConfigName("Forge Client")
ideConfigGenerated(false) // When true a run configuration file will be generated for IDE's. By default only set to true for the root project.
runDir("../run/client")
vmArgs("-Dio.netty.leakDetection.level=advanced") // https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
vmArgs(
// https://github.com/FabricMC/fabric-loom/issues/915#issuecomment-1609154390
"-Dminecraft.api.auth.host=https://nope.invalid",
"-Dminecraft.api.account.host=https://nope.invalid",
"-Dminecraft.api.session.host=https://nope.invalid",
"-Dminecraft.api.services.host=https://nope.invalid",
// https://netty.io/wiki/reference-counted-objects.html#leak-detection-levels
"-Dio.netty.leakDetection.level=advanced"
)
programArgs("--username", "Dev")
}
server {
@@ -62,6 +62,7 @@ import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.lwjgl.opengl.GL32;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
/**
@@ -185,7 +186,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
LevelAccessor level = event.getLevel();
#endif
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
@@ -214,7 +215,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
LevelAccessor level = event.getLevel();
#endif
ThreadPoolExecutor executor = ThreadPoolUtil.getFileHandlerExecutor();
AbstractExecutorService executor = ThreadPoolUtil.getFileHandlerExecutor();
if (executor != null)
{
executor.execute(() ->
@@ -228,7 +229,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
private void onBlockChangeEvent(LevelAccessor level, ChunkAccess chunk)
{
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(level);
SharedApi.INSTANCE.chunkBlockChangedEvent(new ChunkWrapper(chunk, level, wrappedLevel), wrappedLevel);
SharedApi.INSTANCE.chunkBlockChangedEvent(new ChunkWrapper(chunk, wrappedLevel), wrappedLevel);
}
@SubscribeEvent
@@ -237,7 +238,7 @@ public class ForgeClientProxy implements AbstractModInitializer.IEventProxy
if (MC.clientConnectedToDedicatedServer())
{
ILevelWrapper wrappedLevel = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), wrappedLevel);
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), wrappedLevel);
SharedApi.INSTANCE.chunkLoadEvent(chunk, wrappedLevel);
}
}
@@ -114,19 +114,6 @@ public class ForgeMain extends AbstractModInitializer
() -> new ConfigScreenHandler.ConfigScreenFactory((client, parent) -> GetConfigScreen.getScreen(parent)));
#endif
if (Config.Client.Advanced.Logging.showModCompatibilityWarningsOnStartup.get())
{
IModChecker modChecker = SingletonInjector.INSTANCE.get(IModChecker.class);
if (modChecker.isModLoaded("alexscaves"))
{
String message =
// orange text
"\u00A76" + "Distant Horizons: Alex's Cave detected." + "\u00A7r\n" +
"You may have to change Alex's config for DH to render. ";
ClientApi.INSTANCE.showChatMessageNextFrame(message);
}
}
}
@Override
@@ -59,7 +59,6 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
private final ServerApi serverApi = ServerApi.INSTANCE;
private final boolean isDedicated;
public static Supplier<Boolean> isGenerationThreadChecker = null;
@@ -82,7 +81,6 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
public ForgeServerProxy(boolean isDedicated)
{
this.isDedicated = isDedicated;
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
}
@@ -148,7 +146,7 @@ public class ForgeServerProxy implements AbstractModInitializer.IEventProxy
{
ILevelWrapper levelWrapper = ProxyUtil.getLevelWrapper(GetEventLevel(event));
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), GetEventLevel(event), levelWrapper);
IChunkWrapper chunk = new ChunkWrapper(event.getChunk(), levelWrapper);
this.serverApi.serverChunkLoadEvent(chunk, levelWrapper);
}

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