Compare commits

...

233 Commits

Author SHA1 Message Date
James Seibel 57c5b2d5fc Up version 2.2.1-dev -> 2.2.1 and API 3.0.0 -> 3.0.1 2024-09-04 06:58:20 -05:00
James Seibel 50c5701836 Fix referencing unavailable GLFW methods for MC 1.18.2 and lower 2024-09-02 08:00:43 -05:00
James Seibel 18e075538d Fix LODs flashing when moving and improve LodQuadTree code 2024-09-01 21:10:22 -05:00
James Seibel b00e8a08e9 add annotations to QuadTree 2024-09-01 21:09:50 -05:00
James Seibel ac4ab11a74 Fix LodRenderSection and QuadNode toString methods 2024-09-01 21:09:17 -05:00
James Seibel c26631db57 Cull beacons based on X/Z distance instead of 3D distance 2024-09-01 17:28:08 -05:00
James Seibel 1daa06fff4 Disable instanced rendering on Mac when Sodium is present
Closes !793 (Generic Rendering crashes with Sodium on M1 Mac)
2024-09-01 17:02:43 -05:00
James Seibel f3ef6f25f4 Fix some beacon rendering/updating issues 2024-09-01 16:36:37 -05:00
James Seibel ec012d9fd6 Fix glass panes not affecting beacon colors 2024-09-01 15:04:24 -05:00
James Seibel fc90cf3377 add disableUnchangedChunkCheck config 2024-08-31 22:11:25 -05:00
James Seibel e1e42d1caf Fix cloud color not matching MC 2024-08-31 21:55:54 -05:00
James Seibel 95ce29e355 Update all pos objects to use getters to match with DhBlockPos
I'd prefer not to need getters/setters since it's cleaner to just call pos.x, but that doesn't allow for immutable/mutable distinction.
2024-08-31 20:50:22 -05:00
James Seibel 0fd818b077 Allow users to re-activate DH rendering if a rendering error is thrown 2024-08-31 20:20:51 -05:00
James Seibel ba59daf747 Add beacon nearby culling 2024-08-31 20:20:24 -05:00
James Seibel b7d94c2ed1 Fix RenderableBoxGroup not supporting clear() 2024-08-31 20:06:04 -05:00
James Seibel 7a057a8d53 fix Lod builder not showing the correct stacktrace in Intellij 2024-08-31 15:04:30 -05:00
James Seibel 49c6ab97a9 Remove unused threadpool 2024-08-31 15:04:12 -05:00
James Seibel ed0d80b37e Reduce deplayed LOD modified save from 2 sec -> 500 ms
This should make some LOD update operations appear faster
2024-08-31 15:01:37 -05:00
James Seibel 9768728c92 Add RollingAverage object 2024-08-31 14:58:08 -05:00
James Seibel 0c68544f2f Fix DhLightingEngine putting lights at relative (0,0) and add debug logic 2024-08-31 12:45:39 -05:00
James Seibel b1f154a0ea Add DhBlockPosMutable and make the original immutable
This is to prevent issues with some methods accidentally mutating shared positions
2024-08-30 07:35:59 -05:00
James Seibel 628c9b071f DhBlockPos cleanup 2024-08-29 20:05:26 -05:00
James Seibel ed39b6181f Fix DH beacon detection logic mutating input block pos
alternate title: Fix DH beacon detection logic breaking the lighting engine
2024-08-29 19:54:36 -05:00
James Seibel 1d6d712483 Fix LODs not updating in the nether or when blocks are changed underground 2024-08-29 07:32:55 -05:00
James Seibel 73c4f0ffcd Add a quick DH cloud UI config 2024-08-28 07:16:20 -05:00
James Seibel 48d1005be6 Up version number 2.2.0 -> 2.2.1-dev 2024-08-20 19:16:18 -05:00
James Seibel e71e8d1966 Up version number 2.1.3-dev -> 2.2.0 2024-08-20 17:44:41 -05:00
James Seibel 489b3d3ae1 Fix Legacy GL causing fog to smear 2024-08-20 17:44:41 -05:00
James Seibel 1b162f10e6 Add sharedApi.isChunkAtChunkPosAlreadyUpdating() 2024-08-18 14:46:12 -05:00
James Seibel 301cce3d11 Remove unused chunkUnloadEvent 2024-08-18 14:25:51 -05:00
James Seibel e68d0d5c45 Fix fog and SSAO being broken by some mods 2024-08-17 22:29:28 -05:00
James Seibel 2cf952fb76 Deprecate IDhApiWorldGenerator.isBusy(), task queuing is now handled internally 2024-08-12 22:20:06 -05:00
James Seibel c7c5ab17bc Add optional DhApiChunk validation for world gen 2024-08-12 21:47:48 -05:00
James Seibel a98955530f Allow adding empty lists to DhApiChunk 2024-08-11 22:01:24 -05:00
James Seibel c63a509f9e Fix DhApiChunk setDataPoints failing for empty lists 2024-08-11 21:55:11 -05:00
James Seibel dac51a9eea Add mod compat warning message config 2024-08-11 09:54:54 -05:00
James Seibel 8d78a1ad74 Rename BeaconBeamDTO.pos -> blockPos 2024-08-09 07:25:49 -05:00
James Seibel 7c11bb4258 Fix beacons not enabling/disabling correctly 2024-08-09 07:25:24 -05:00
James Seibel 0d6ec3d836 Fix frustum culling when the screen is warped 2024-08-07 18:55:02 -05:00
James Seibel 9449433fe8 Fix deleting beacons 2024-08-07 07:47:11 -05:00
James Seibel 2c976c9fb1 Improve fast chunk hash to respect surface block heights 2024-08-07 07:47:02 -05:00
James Seibel 90fdfbbe61 Fix direct memory leak and remove config for GpuUpload 2024-08-07 07:29:52 -05:00
James Seibel a8df13fdd2 Fix LodRenderSection holding onto unnecessary memory 2024-08-06 21:47:03 -05:00
James Seibel f05eac2637 test 2024-08-06 20:47:23 -05:00
James Seibel 4ae30b3d47 Improve LOD detail level detection and hole filling 2024-08-04 08:30:58 -05:00
James Seibel 8abefdcfd5 Attempt to improve LOD building speed and reduce broken lighting on servers 2024-08-03 17:11:18 -05:00
James Seibel 801a126de0 Fix chunk has being saved before LOD update 2024-08-03 16:50:12 -05:00
James Seibel 377d0fbe12 Allow DhApiChunk to accept top down or bottom up data point orders 2024-08-03 09:32:57 -05:00
James Seibel 1ecf968668 Remove unused ChunkToLodBuilder 2024-08-03 09:32:29 -05:00
James Seibel c43b985f4e Fix off by 1 error in Render data transformer 2024-08-02 18:30:55 -05:00
James Seibel b7fea64925 Fix out of bounds exception in Full Data Transformer 2024-08-02 17:56:25 -05:00
James Seibel 116d7f4a3f Fix incorrect comment in DhSectionPos 2024-08-01 06:52:05 -05:00
James Seibel 0c36dc03a5 Fix cave culling affecting floating islands and add LOD reload to some configs 2024-07-31 19:06:44 -05:00
James Seibel c658269eb7 Remove deprecated methods and move method to StringUtil 2024-07-30 17:06:55 -05:00
James Seibel defaea86f0 Remove unused sodium and McRenderWrapper methods
Removed methods were originally used to cull LODs if MC had loaded chunks, however this turned out to be more trouble than it was worth and caused more problems than it solved.
2024-07-30 17:00:59 -05:00
James Seibel f1564cc90b Fix presets only using "custom" after any value was changed 2024-07-30 15:47:48 -05:00
James Seibel 66feb0b9c2 Fix SSAO shader crashing when entering empty config values 2024-07-30 15:35:01 -05:00
James Seibel 79bfa21115 Fix default logging debug to file 2024-07-29 20:40:23 -05:00
James Seibel 5588b0d2fa Add TODO to cleanup LodRenderSection futures 2024-07-29 07:29:48 -05:00
James Seibel e9788acb46 Fix rapidly changing dimensions causing the game to crash 2024-07-29 07:13:06 -05:00
James Seibel 8056a5b8bf Add Buffer Builder/Uploader thread pools to the F3 menu 2024-07-29 07:08:42 -05:00
James Seibel e0ad956e34 Fix incorrect DhApiChunk create constructor parameter order (again) 2024-07-28 20:18:15 -05:00
James Seibel 9546f9cbc8 Close !66 (fix incorrect positions being fed into biome color code) 2024-07-28 09:33:24 -05:00
James Seibel 9834b20a9f Revert and Deprecate DhApiChunk and DhApiTerrainDataPoint constructors 2024-07-28 08:56:18 -05:00
James Seibel 752008e8ac Re-add deprecated IDhApiLevelWrapper.getHeight() 2024-07-28 08:55:54 -05:00
James Seibel fbe81021c0 Update API javadocs 2024-07-28 08:55:35 -05:00
James Seibel 882c5399bd Fix holes in LODs boarding different detail levels 2024-07-27 21:06:50 -05:00
James Seibel dbe0461d5f Fix LOD upload warning 2024-07-27 20:25:55 -05:00
James Seibel d3d166dd02 Undo experimental change to LOD reloading 2024-07-27 20:11:28 -05:00
James Seibel d0dd1f38ff Fix LODs flashing twice when changing configs 2024-07-27 20:11:00 -05:00
James Seibel 53300a3028 Update IDhApiRenderProxy.clearRenderDataCache() to also clear cached block colors 2024-07-27 17:36:40 -05:00
James Seibel 56303dd82a level wrapper renamings 2024-07-27 16:51:08 -05:00
James Seibel 19d8c89bd8 Fix ice/water vertical LOD lighting 2024-07-27 09:30:41 -05:00
James Seibel adba3e4c15 clear testing default debug config values 2024-07-27 08:40:59 -05:00
James Seibel 479ce8093e minor cleanup/refactor 2024-07-27 08:28:31 -05:00
James Seibel 1ed6c619d9 Add localization for new column builder debug options 2024-07-27 08:26:46 -05:00
Builderb0y 825f439ffb fix incorrect positions being fed into biome color code. 2024-07-27 02:32:31 +00:00
James Seibel b1b487e63f Improve RenderDataPointUtil toString() 2024-07-24 06:46:28 -05:00
James Seibel 2763a7ca75 add missing brackets 2024-07-23 20:41:22 -05:00
James Seibel b4b1a2a549 remove deprecated RenderDataPointUtil logic 2024-07-23 20:05:41 -05:00
James Seibel 5865317394 Remove deprecated LodQuadBuilder code 2024-07-23 19:53:13 -05:00
James Seibel b70c090e94 Refactor and cleanup buffer building 2024-07-23 19:39:44 -05:00
James Seibel a9f6b924c2 Move CubicLodTemplate to ColumnRenderBufferBuilder 2024-07-23 07:05:28 -05:00
James Seibel 9c25a6450a comment ColumnArrayView 2024-07-22 20:47:34 -05:00
James Seibel 448982fbaf refactor FullDataToRenderDataTransformer 2024-07-22 19:50:23 -05:00
James Seibel 2ee06c59f1 Add configs for testing the ColumnRenderBufferBuilder 2024-07-22 17:34:04 -05:00
James Seibel d38711ca4b Fix replay mod not showing LODs 2024-07-21 20:05:36 -05:00
James Seibel c9b650fb7f remove unused clientLevelWrapper.getGameDirectory() 2024-07-21 19:27:11 -05:00
James Seibel 3cef8b9a4f Improve cave culling and add config for ignored/cave blocks 2024-07-21 17:27:17 -05:00
James Seibel d9d9f3dad8 minor logging fixes 2024-07-21 17:06:58 -05:00
James Seibel 44fe1eafb1 Fix ConfigEntry String value saving 2024-07-21 16:09:46 -05:00
James Seibel 36fcc46445 Minor DataTransofmer refactor 2024-07-21 07:48:52 -05:00
James Seibel 64895ba521 Remove unnecessary suffix from SectionPos encode method 2024-07-21 07:42:40 -05:00
James Seibel 589340f2db Clean up SectionPos wording for chunk/block pos converters 2024-07-21 07:35:35 -05:00
James Seibel de7d22766a Fix RenderDataPointUtil.toString() ARGB order 2024-07-21 07:19:21 -05:00
James Seibel 568ff40df6 Fix API chunk world gen 2024-07-20 17:57:58 -05:00
James Seibel 17b5ba0ae1 Fix potential issues with WorldGenQueue not being marked as stopped
closes !61
2024-07-20 11:25:00 -05:00
James Seibel 4d4eeacbdd Add IDhApiWrapperFactory resourceLocation string methods for block/biomes 2024-07-20 11:20:48 -05:00
James Seibel 99dc644adf Add AbstractDhApiChunkWorldGenerator.generateApiChunk() 2024-07-20 10:45:43 -05:00
James Seibel f442ab56c0 Remove unnecessary glIsProgram() call 2024-07-18 07:40:04 -05:00
James Seibel 9147b139c7 Increase max VBO size 1 MB -> 10 MB 2024-07-18 07:39:52 -05:00
James Seibel 4f2b8e6d8d VBO handler commenting 2024-07-15 20:22:29 -05:00
James Seibel 7165c086e4 Remove render param from DhApiAfterRenderEvent
This was causing confussion if deferred rendering (iris shaders) was enabled since the render parameters would change.
2024-07-14 09:30:56 -05:00
James Seibel fa22a4f27b Add a optional memory cache to the IDhApiTerrainDataRepo 2024-07-14 08:41:18 -05:00
James Seibel 9c0f5865f6 add missing genericRendering to IDhApiGraphicsConfig 2024-07-14 07:25:45 -05:00
James Seibel 1d0cb048cd Default logging to only write errors to chat 2024-07-13 12:54:21 -05:00
James Seibel 641d399a8e Merge branch 'distant-horizons-core-main' 2024-07-13 12:30:06 -05:00
James Seibel 32861e757d Add shader uniform "u" prefix 2024-07-13 12:04:05 -05:00
James Seibel 634738a1fc Remove minimum near fog distance and rename fog uniforms 2024-07-13 11:35:25 -05:00
James Seibel 859cbb6161 Fix fog reading/writing to the same buffer 2024-07-13 11:09:49 -05:00
James Seibel 6c960a81c0 testDisable beacon SSAO 2024-07-13 11:07:44 -05:00
James Seibel 1695c41ef2 Increase default fog start distance 2024-07-13 08:14:29 -05:00
James Seibel 8eabc6ad4c make clouds smaller and thinner 2024-07-12 21:47:06 -05:00
James Seibel a153ca1fe1 Fix repo connections not getting closed 2024-07-12 20:21:57 -05:00
James Seibel cab9f7c830 Clone API event parameters to reduce listener contamination 2024-07-12 19:22:20 -05:00
James Seibel 6bb832a488 Add renderEventParam to generic rendering shader binding by IMS request 2024-07-12 17:27:17 -05:00
James Seibel e7dda9590a Add generic object setup/cleanup events 2024-07-12 07:15:57 -05:00
James Seibel 0483edd2f3 Fix material typo 2 2024-07-11 22:51:37 -05:00
James Seibel 122ef4dce0 Fix material typo 2024-07-11 22:07:09 -05:00
James Seibel e9d254f8c4 Add generic object materials 2024-07-11 18:12:58 -05:00
James Seibel 17aa85ad24 Add EDhApiBlockMaterial 2024-07-11 17:57:54 -05:00
James Seibel 8e1dfd688e Fix inverting gener rendering event cancling 2024-07-11 17:57:30 -05:00
James Seibel 691d5caded Add api for generic rendering config 2024-07-11 17:38:51 -05:00
James Seibel 31c089f82f Add DhApiBeforeGenericObjectRenderEvent 2024-07-11 17:32:17 -05:00
James Seibel 8eceeb0226 Add namespace/path to generic rendering (including F3 piechart) 2024-07-11 17:20:02 -05:00
James Seibel c178afa4b9 Minor refactoring/renaming 2024-07-11 16:40:32 -05:00
James Seibel 116df0d999 Add IDhApiGenericObjectShaderProgram 2024-07-11 16:35:38 -05:00
James Seibel ef3cd4b43d Add "IP Only" to multiplayer tooltip 2024-07-10 07:45:07 -05:00
James Seibel 4b27f39a04 Fix generic rendering at extreme distances 2024-07-10 07:37:11 -05:00
James Seibel 53a2bf1748 mark ConfigLinkedEntry localization broken 2024-07-09 19:31:14 -05:00
James Seibel edec8bc0a2 Update localization 2024-07-09 19:30:59 -05:00
James Seibel 066b23c785 Add toggleable logging for GL Buffer garbage collection
Will need to be tested by someone who is experiencing issue #718, so far I've been unable to reproduce anything meaningful.
2024-07-09 17:40:21 -05:00
James Seibel 1f74f19cd9 minor cleanup 2024-07-09 07:49:56 -05:00
James Seibel 232c727b4f Move IBlockStateWrapper constants into LodUtil 2024-07-09 07:38:45 -05:00
James Seibel cd5da82d0c Add a TODO to LevelWrapper 2024-07-09 07:33:56 -05:00
James Seibel b762c0561d Add beacon colors 2024-07-09 07:33:17 -05:00
James Seibel f144a9ebc1 Optimize beacon detection 2024-07-08 20:20:48 -05:00
James Seibel 29ef95387c Shrink cloud texture to improve performance 2024-07-08 19:56:20 -05:00
James Seibel 0d79a856b2 Add cloud greedy meshing 2024-07-08 18:45:42 -05:00
James Seibel bd5054e762 re-arrange the generic rendering config 2024-07-08 07:44:41 -05:00
James Seibel 63dea2515e Add generic rendering US localization 2024-07-08 07:42:56 -05:00
James Seibel baa89edd03 Add a few missing items from beacon render handler 2024-07-08 07:35:34 -05:00
James Seibel c45f9f442f Clean up beacon render handling logic 2024-07-08 07:32:29 -05:00
James Seibel 9e13b27197 Fix double unloading beacons 2024-07-07 19:54:17 -05:00
James Seibel 3c173685ea Fix beacons disappearing when unloading LODs 2024-07-07 19:45:27 -05:00
James Seibel 8eb70cbaed fix unloading chunks removing beacon beams 2024-07-07 19:18:40 -05:00
James Seibel 22167081f0 Fix generic render un-binding when moving between levels 2024-07-07 19:16:33 -05:00
James Seibel 23d07aa92d Disable cloud rendering if instanced rendering isn't available 2024-07-07 18:42:11 -05:00
James Seibel 578a9f9309 add directional shading to direct generic rendering 2024-07-07 18:31:43 -05:00
James Seibel bacdfa96e3 rename ILevelWrapper.getHeight -> getMaxHeight 2024-07-07 18:16:00 -05:00
James Seibel c73c3f8490 Add missing generic rendering config options 2024-07-07 18:11:18 -05:00
James Seibel f4a8bfeb0a Add cloud rendering 2024-07-07 18:02:43 -05:00
James Seibel 197e6e8178 add vec3f distance methods 2024-07-07 14:52:30 -05:00
James Seibel c2c8bf8613 minor generic render refactor 2024-07-05 06:56:46 -05:00
James Seibel fce703579f Fix concurrent modification for GenericObjectRenderer 2024-07-04 21:41:57 -05:00
James Seibel e98f17f63b Remove useless IServerLevelWrapper.tryGetClientLevelWrapper() 2024-07-04 16:23:39 -05:00
James Seibel 120dddf844 Fix Api client level not containing the generic renderer 2024-07-04 16:14:32 -05:00
James Seibel ca711bbc72 Instance beacon rendering 2024-07-04 14:34:12 -05:00
James Seibel cc4cb10307 Fix uploading generic objects crashing 2024-07-04 14:34:01 -05:00
James Seibel 88db5c9594 re-add generic rendering to the API 2024-07-03 22:37:52 -05:00
James Seibel 81bfa9a02b Add generic rendering to the F3 menu 2024-07-03 20:46:11 -05:00
James Seibel ae72e627c5 Add a config to use pre-existing lighting 2024-07-03 20:30:49 -05:00
James Seibel 131b2835e5 Make generic renderer level dependent 2024-07-02 22:11:06 -05:00
James Seibel 5b905a9ab3 minor LodRenderer refactor 2024-07-02 19:23:02 -05:00
James Seibel e90c7cd8a0 Add beacon activation logic from merge 60
Closes !60
2024-07-02 17:50:25 -05:00
James Seibel 3b4a0ff4bc test 2024-07-02 17:08:55 -05:00
James Seibel 55cb4595bd Fix beacons un-loading incorrectly in some situations
Specifically neighboring chunks updating and in some cases flying away too fast
2024-07-02 07:50:21 -05:00
James Seibel e91afc17a3 Fix beacon beams for loaded chunks 2024-07-01 19:02:36 -05:00
James Seibel 6a398e6514 Start adding beacon beam repo handling 2024-07-01 07:51:08 -05:00
James Seibel 51de347bdd Add temporary proof-of-concept beacon rendering 2024-06-30 18:08:47 -05:00
James Seibel 72d6cb9697 Disable debug generic object rendering 2024-06-30 18:08:00 -05:00
James Seibel 4a025de9d6 Add generic object sky/block light 2024-06-30 17:45:50 -05:00
James Seibel 6c8060fa87 Up API version 2.1.0 -> 3.0.0 2024-06-30 16:33:54 -05:00
James Seibel 0c0987b66b Replace Vec3f and Mat4f in API with API versions 2024-06-30 16:33:38 -05:00
James Seibel 5a71e4015c Add javadocs to generic rendering objects 2024-06-30 15:28:00 -05:00
James Seibel f68edcbfea Add debug render code toggle 2024-06-30 14:38:35 -05:00
James Seibel aefa0d6797 generic renderable active flag and renaming cube -> box 2024-06-30 14:27:09 -05:00
James Seibel 305a6bb459 Improve generic rendering pos objects 2024-06-30 14:02:44 -05:00
James Seibel 28c8614550 Store generic object instance VBOs if possible 2024-06-30 13:46:03 -05:00
James Seibel f282d78fb9 minor generic obj cleanup 2024-06-30 09:31:45 -05:00
James Seibel 7f8b5579c5 Add generic rendering profilers and move some vertex attribs to uniforms 2024-06-30 09:25:12 -05:00
yeshi db786290e8 tell user to restart the game if the renderer dies 2024-06-29 21:56:38 +02:00
James Seibel 2c71d97c15 fix instanced generic duplicate rendering 2024-06-29 11:00:53 -06:00
James Seibel bf1361c7c3 GenericObjectRenderer forgot cached uniform location 2024-06-29 10:34:58 -06:00
James Seibel f2bba7f3df Add instanced and direct genericObject rendering 2024-06-29 10:29:30 -06:00
James Seibel 62e5183c54 Improve GLProxy creation validation/logging 2024-06-29 10:18:27 -06:00
James Seibel c1a90c9350 Add instanced generic object rendering 2024-06-29 09:11:49 -06:00
James Seibel 0d0826f319 Separate out Generic object rendering 2024-06-28 16:53:05 -06:00
James Seibel 6bfa3a422e Move generic cube rendering into it's own class 2024-06-27 06:36:30 -06:00
James Seibel 352abc40e6 Add proof-of-concept cube rendering 2024-06-27 06:22:15 -06:00
James Seibel 58d26dedd6 Show overloaded message in chat and increase message timeout 5 -> 30 sec 2024-06-26 12:58:18 -05:00
James Seibel 321afa2a9e Up version 2.1.2 -> 2.1.3-dev 2024-06-25 19:25:30 -05:00
James Seibel 71ffbfb7b9 add "warning" to the low memory warning message 2024-06-25 19:24:07 -05:00
James Seibel 2ab7949ce5 Fix database file paths 2024-06-25 19:23:53 -05:00
James Seibel 28e1eaae77 Up version 2.1.1-dev -> 2.1.2 2024-06-24 20:53:36 -05:00
James Seibel 30dda058fe Throw an exception if the file handler can't read/write to the DB 2024-06-23 08:22:35 -05:00
James Seibel 0d16c037f5 Increase default world gen timeout to 3 minutes (from 60 sec) 2024-06-18 07:11:48 -05:00
James Seibel 7f50de17c0 Fix file handler tooltip 2024-06-17 07:40:49 -05:00
James Seibel 67819b30eb Improve F3 menu logic and visuals 2024-06-15 19:20:20 -05:00
James Seibel ad38722304 add a todo to shared api 2024-06-15 11:26:46 -05:00
James Seibel 4da48c4c55 Lower the default CPU presets 2024-06-15 11:26:01 -05:00
James Seibel 6542e9e889 comment out unused showMigrationChatWarning 2024-06-15 11:04:56 -05:00
James Seibel 2f7e3d43d1 Add a startup low memory warning 2024-06-15 11:04:43 -05:00
James Seibel edaafb5cf0 Fix saving the chunk hash incorrectly 2024-06-15 10:37:59 -05:00
James Seibel 81d1ed419e Prevent creating LODs for already processed chunks 2024-06-15 09:42:43 -05:00
James Seibel 385e3dc964 Add ChunkWrapper BlockBiome HashCode 2024-06-15 08:11:16 -05:00
James Seibel 9592cd80f3 Improve position error logging 2024-06-15 07:20:38 -05:00
James Seibel 7b153a8aad Fix SelfUpdater list logging 2024-06-14 07:11:06 -05:00
James Seibel 54c2213eb6 Merge in JustALittleWolf's optimizations 2024-06-13 07:30:17 -05:00
JustAlittleWolf 1274a8e097 Directly access childNodes in LodQuadTree
This changes `LodQuadTree::recursivelyUpdateRenderSectionNode` to directly iterate on the children, instead of creating a childpositerator, and searching for the sectionpos. This lowers memory usage, as the iterators add quite a lot of object garbage (see https://i.imgur.com/r0qlxzc.png)
2024-06-13 13:15:39 +02:00
JustAlittleWolf bd1d0063e5 Change iterator Queue from LinkedList to ArrayDequeue
This improves performance and memory allocation, whenever the iterators are used. See https://docs.oracle.com/javase/8/docs/api/java/util/ArrayDeque.html
2024-06-13 13:14:30 +02:00
James Seibel af9b55ad6c Add lighting engine unit tests 2024-06-11 19:33:08 -05:00
James Seibel 97b86d69c4 Move shared ChunkWrapper code form Main to Core 2024-06-11 18:34:57 -05:00
James Seibel c6b4eacf03 Improve the overloaded chunk loading message 2024-06-11 07:35:28 -05:00
James Seibel e011ce3ee0 Remove OpenGL multithreading 2024-06-08 12:49:08 -05:00
James Seibel 1dd6359c89 Try changing LZMA preset from 4 -> 3 (faster, less compressed) 2024-06-08 11:06:26 -05:00
James Seibel e41abdd176 Improve config comment spacing 2024-06-08 08:33:32 -05:00
James Seibel b7a5bfd274 Add update branch config "auto" 2024-06-08 08:11:09 -05:00
James Seibel c3abfb123d Up the version number 2.1.0-a -> 2.1.1-a-dev 2024-06-07 17:42:36 -05:00
James Seibel 76f28e648c Up the version number 2.0.4-a-dev -> 2.1.0-a 2024-05-30 20:13:55 -05:00
James Seibel f49a79b54a remove unused lightmapBindingIndex in DhApiRenderParam 2024-05-27 17:57:45 -05:00
James Seibel 3cf385c2a2 Potentially fix memory leaks when rendering is disabled 2024-05-27 17:37:52 -05:00
James Seibel 8c91a84795 Fix LZ4 in retail MC 2024-05-21 07:43:33 -05:00
James Seibel 4af63758f2 Add error logging to stream wrappers 2024-05-21 07:42:22 -05:00
James Seibel 969b02dc18 Put config button hide option only in file 2024-05-20 22:15:38 -05:00
Ran 2111ad64c4 Properly shade libraries when using Java version Ω 2024-05-21 02:09:04 +00:00
James Seibel e02deb2fb0 Merge branch 'main' into 'main'
thing part 2 (last mr didn't include core)

See merge request jeseibel/distant-horizons-core!57
2024-05-20 19:57:16 +00:00
Yeshi0 410e34b147 remove unnecessary reference to zstd 2024-05-20 17:53:02 +02:00
James Seibel 9cebd7ee54 Add ConfigBasedLogger.errorAndThrow() 2024-05-18 08:07:41 -05:00
James Seibel cfec32746d Fix shading for MC 1.20.6 IE Java 21 2024-05-18 07:27:17 -05:00
James Seibel fabe5d77ea Merge branch 'SectionPosRewrite' 2024-05-16 22:15:03 -05:00
James Seibel c67712d973 Merge branch 'main' of https://gitlab.com/jeseibel/distant-horizons-core 2024-05-15 18:57:53 -05:00
James Seibel 7e45a98e8f Up the API version 1.1.0 -> 2.0.0
There were several breaking changes and I forgot to up the major version number appropriately.
2024-05-04 18:16:19 -05:00
254 changed files with 11002 additions and 5892 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins { plugins {
id "java" id "java"
id "com.github.johnrengelman.shadow" version '7.1.2' apply false id "com.github.johnrengelman.shadow" version '8.1.1' apply false
} }
@@ -23,7 +23,9 @@ import com.seibel.distanthorizons.api.interfaces.events.IDhApiEventInjector;
import com.seibel.distanthorizons.api.interfaces.factories.IDhApiWrapperFactory; import com.seibel.distanthorizons.api.interfaces.factories.IDhApiWrapperFactory;
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGeneratorOverrideRegister; import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGeneratorOverrideRegister;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
import com.seibel.distanthorizons.api.methods.override.DhApiWorldGeneratorOverrideRegister; import com.seibel.distanthorizons.api.methods.override.DhApiWorldGeneratorOverrideRegister;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
@@ -123,10 +125,16 @@ public class DhApi
/** /**
* Used to create wrappers for Minecraft objects needed by other Distant Horizons API methods. * Used to create wrappers for Minecraft objects needed by other Distant Horizons API methods.
* @since API 1.1.0 * @since API 2.0.0
*/ */
public static IDhApiWrapperFactory wrapperFactory = null; public static IDhApiWrapperFactory wrapperFactory = null;
/**
* Used to create custom renderable objects. <br>
* These objects can be added to the renderer in {@link IDhApiLevelWrapper}
* @since API 3.0.0
*/
public static IDhApiCustomRenderObjectFactory customRenderObjectFactory = null;
} }
@@ -172,7 +180,7 @@ public class DhApi
* This version should be updated whenever non-breaking fixes are added to the Distant Horizons API. * This version should be updated whenever non-breaking fixes are added to the Distant Horizons API.
* @since API 1.0.0 * @since API 1.0.0
*/ */
public static int getApiPatchVersion() { return ModInfo.API_PATH_VERSION; } public static int getApiPatchVersion() { return ModInfo.API_PATCH_VERSION; }
/** /**
* Returns the mod's semantic version number in the format: Major.Minor.Patch * Returns the mod's semantic version number in the format: Major.Minor.Patch
@@ -198,7 +206,7 @@ public class DhApi
/** /**
* Returns true if the thread this method was called from is owned by Distant Horizons. * Returns true if the thread this method was called from is owned by Distant Horizons.
* @since API 1.1.0 * @since API 2.0.0
*/ */
public static boolean isDhThread() { return Thread.currentThread().getName().startsWith(ModInfo.THREAD_NAME_PREFIX); } public static boolean isDhThread() { return Thread.currentThread().getName().startsWith(ModInfo.THREAD_NAME_PREFIX); }
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums;
* CHUNK - Detail Level: 4, width 16 block, <br> * CHUNK - Detail Level: 4, width 16 block, <br>
* REGION - Detail Level: 9, width 512 block <br> <br> * REGION - Detail Level: 9, width 512 block <br> <br>
* *
* Detail levels in Distant Horizons represent how large a section (of either LODs or MC chunks) * Detail levels in Distant Horizons represent how large a LOD
* is, with the smallest being 0 (1 block wide). <br> * is, with the smallest being 0 (1 block wide). <br>
* The width of a detail level can be calculated by putting the detail level to the power of 2. <br> * The width of a detail level can be calculated by putting the detail level to the power of 2. <br>
* Example for the chunk detail level (4): 2^4 = 16 blocks wide <Br><br> * Example for the chunk detail level (4): 2^4 = 16 blocks wide <Br><br>
@@ -23,7 +23,7 @@ package com.seibel.distanthorizons.api.enums.config;
* NONE, <br> * NONE, <br>
* NON_COLLIDING, <br> * NON_COLLIDING, <br>
* *
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiBlocksToAvoid public enum EDhApiBlocksToAvoid
@@ -22,14 +22,13 @@ package com.seibel.distanthorizons.api.enums.config;
/** /**
* UNCOMPRESSED <br> * UNCOMPRESSED <br>
* LZ4 <br> * LZ4 <br>
* ZSTD <br>
* XZ <br><br> * XZ <br><br>
* *
* Note: speed and compression ratios are examples * Note: speed and compression ratios are examples
* and should only be used for estimated comparisons. * and should only be used for estimated comparisons.
* *
* @version 2024-3-16 * @version 2024-3-16
* @since API 1.1.0 * @since API 2.0.0
*/ */
public enum EDhApiDataCompressionMode public enum EDhApiDataCompressionMode
{ {
@@ -20,7 +20,7 @@
package com.seibel.distanthorizons.api.enums.config; package com.seibel.distanthorizons.api.enums.config;
/** /**
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiGLErrorHandlingMode public enum EDhApiGLErrorHandlingMode
@@ -20,7 +20,7 @@
package com.seibel.distanthorizons.api.enums.config; package com.seibel.distanthorizons.api.enums.config;
/** /**
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiGlProfileMode public enum EDhApiGlProfileMode
@@ -23,13 +23,12 @@ package com.seibel.distanthorizons.api.enums.config;
* AUTO, <br> * AUTO, <br>
* BUFFER_STORAGE, <br> * BUFFER_STORAGE, <br>
* SUB_DATA, <br> * SUB_DATA, <br>
* BUFFER_MAPPING, <br>
* DATA <br> * DATA <br>
* *
* @author Leetom * @author Leetom
* @author James Seibel * @author James Seibel
* @version 2024-4-6 * @version 2024-4-6
* @since API 1.1.0 * @since API 3.0.0
*/ */
public enum EDhApiGpuUploadMethod public enum EDhApiGpuUploadMethod
{ {
@@ -49,7 +48,10 @@ public enum EDhApiGpuUploadMethod
* May end up storing buffers in System memory. <br> * May end up storing buffers in System memory. <br>
* Fast rending if in GPU memory, slow if in system memory, <br> * Fast rending if in GPU memory, slow if in system memory, <br>
* but won't stutter when uploading. * but won't stutter when uploading.
*
* @deprecated not currently supported
*/ */
@Deprecated
BUFFER_MAPPING(true, false), BUFFER_MAPPING(true, false),
/** Fast rendering but may stutter when uploading. */ /** Fast rendering but may stutter when uploading. */
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums.config;
* FADE_TO_DIRT <br> * FADE_TO_DIRT <br>
* AS_DIRT <br> * AS_DIRT <br>
* *
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-7 * @version 2024-4-7
*/ */
public enum EDhApiGrassSideRendering public enum EDhApiGrassSideRendering
@@ -26,7 +26,7 @@ package com.seibel.distanthorizons.api.enums.config;
* HIGH <br> * HIGH <br>
* UNLIMITED <br> * UNLIMITED <br>
* *
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiHorizontalQuality public enum EDhApiHorizontalQuality
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums.config;
* ENABLED <br> * ENABLED <br>
* DISABLED <br> * DISABLED <br>
* *
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiLodShading public enum EDhApiLodShading
@@ -22,7 +22,7 @@ package com.seibel.distanthorizons.api.enums.config;
import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Level;
/** /**
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiLoggerMode public enum EDhApiLoggerMode
@@ -33,7 +33,7 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil;
* *
* @author James Seibel * @author James Seibel
* @author Leonardo Amato * @author Leonardo Amato
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiMaxHorizontalResolution public enum EDhApiMaxHorizontalResolution
@@ -30,7 +30,7 @@ package com.seibel.distanthorizons.api.enums.config;
* Determines how the multiplayer folders should be named. * Determines how the multiplayer folders should be named.
* *
* @author James Seibel * @author James Seibel
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiServerFolderNameMode public enum EDhApiServerFolderNameMode
@@ -1,14 +1,41 @@
package com.seibel.distanthorizons.api.enums.config; package com.seibel.distanthorizons.api.enums.config;
import com.seibel.distanthorizons.coreapi.ModInfo;
/** /**
* AUTO, <br>
* STABLE, <br> * STABLE, <br>
* NIGHTLY, <br><br> * NIGHTLY, <br><br>
* *
* @since API 1.1.0 * @since API 2.1.0
* @version 2024-4-6 * @version 2024-6-8
*/ */
public enum EDhApiUpdateBranch public enum EDhApiUpdateBranch
{ {
AUTO,
STABLE, STABLE,
NIGHTLY NIGHTLY;
/**
* If the updateBranch value is {@link EDhApiUpdateBranch#AUTO}
* this method will convert it either to {@link EDhApiUpdateBranch#STABLE} or {@link EDhApiUpdateBranch#NIGHTLY}
* based on this jar's state. <Br><br>
*
* If updateBranch is {@link EDhApiUpdateBranch#STABLE} or {@link EDhApiUpdateBranch#NIGHTLY}
* it just returns.
*/
public static EDhApiUpdateBranch convertAutoToStableOrNightly(EDhApiUpdateBranch updateBranch)
{
if (updateBranch != EDhApiUpdateBranch.AUTO)
{
return updateBranch;
}
else
{
return ModInfo.IS_DEV_BUILD ? EDhApiUpdateBranch.NIGHTLY : EDhApiUpdateBranch.STABLE;
}
}
} }
@@ -28,7 +28,7 @@ package com.seibel.distanthorizons.api.enums.config;
* the vanilla Minecraft terrain. * the vanilla Minecraft terrain.
* *
* @author James Seibel * @author James Seibel
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
@Deprecated // not currently in use, if the config this enum represents is re-implemented, the deprecated flag can be removed @Deprecated // not currently in use, if the config this enum represents is re-implemented, the deprecated flag can be removed
@@ -30,7 +30,7 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil;
* *
* @author Leonardo Amato * @author Leonardo Amato
* @version 2024-4-6 * @version 2024-4-6
* @since API 1.1.0 * @since API 2.0.0
*/ */
public enum EDhApiVerticalQuality public enum EDhApiVerticalQuality
{ {
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums.config;
* VISUALLY_EQUAL <br><br> * VISUALLY_EQUAL <br><br>
* *
* @version 2024-3-27 * @version 2024-3-27
* @since API 1.1.0 * @since API 2.0.0
*/ */
public enum EDhApiWorldCompressionMode public enum EDhApiWorldCompressionMode
{ {
@@ -30,7 +30,7 @@ import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui
* HIGH, <br> * HIGH, <br>
* EXTREME, <br> * EXTREME, <br>
* *
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiQualityPreset public enum EDhApiQualityPreset
@@ -29,7 +29,7 @@ import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui
* BALANCED, <br> * BALANCED, <br>
* AGGRESSIVE, <br> * AGGRESSIVE, <br>
* *
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiThreadPreset public enum EDhApiThreadPreset
@@ -0,0 +1,68 @@
package com.seibel.distanthorizons.api.enums.rendering;
/**
* contains the indices used by shaders to determine
* how different block types should be rendered. <br><br>
*
* UNKNOWN, <br>
* LEAVES, <br>
* STONE, <br>
* WOOD, <br>
* METAL, <br>
* DIRT, <br>
* LAVA, <br>
* DEEPSLATE, <br>
* SNOW, <br>
* SAND, <br>
* TERRACOTTA, <br>
* NETHER_STONE, <br>
* WATER, <br>
* GRASS, <br>
* AIR, <br>
* ILLUMINATED, <br>
*
* @author IMS
* @author James Seibel
* @since API 3.0.0
* @version 2024-7-11
*/
public enum EDhApiBlockMaterial
{
UNKNOWN(0),
LEAVES(1),
STONE(2),
WOOD(3),
METAL(4),
DIRT(5),
LAVA(6),
DEEPSLATE(7),
SNOW(8),
SAND(9),
TERRACOTTA(10),
NETHER_STONE(11),
WATER(12),
GRASS(13),
/** shouldn't normally be needed, but just in case */
AIR(14),
ILLUMINATED(15); // Max value
public final byte index;
EDhApiBlockMaterial(int index) { this.index = (byte)index;}
public static EDhApiBlockMaterial getFromIndex(int index)
{
for(EDhApiBlockMaterial material : EDhApiBlockMaterial.values())
{
if (material.index == index)
{
return material;
}
}
return EDhApiBlockMaterial.UNKNOWN;
}
}
@@ -29,7 +29,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* @author Leetom * @author Leetom
* @author James Seibel * @author James Seibel
* @version 2024-4-6 * @version 2024-4-6
* @since API 1.1.0 * @since API 2.0.0
*/ */
public enum EDhApiDebugRendering public enum EDhApiDebugRendering
{ {
@@ -25,7 +25,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* *
* @author James Seibel * @author James Seibel
* @version 2024-4-6 * @version 2024-4-6
* @since API 1.1.0 * @since API 2.0.0
*/ */
public enum EDhApiFogColorMode public enum EDhApiFogColorMode
{ {
@@ -25,7 +25,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* FOG_DISABLED <br> * FOG_DISABLED <br>
* *
* @author James Seibel * @author James Seibel
* @since API 1.1.0 * @since API 2.0.0
* @version 2022-6-2 * @version 2022-6-2
*/ */
public enum EDhApiFogDrawMode public enum EDhApiFogDrawMode
@@ -26,7 +26,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* *
* @author Leetom * @author Leetom
* @version 2022-6-30 * @version 2022-6-30
* @since API 1.1.0 * @since API 2.0.0
*/ */
public enum EDhApiFogFalloff public enum EDhApiFogFalloff
{ {
@@ -33,7 +33,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* *
* @author Leetom * @author Leetom
* @version 2024-4-6 * @version 2024-4-6
* @since API 1.1.0 * @since API 2.0.0
*/ */
public enum EDhApiHeightFogMixMode public enum EDhApiHeightFogMixMode
{ {
@@ -29,7 +29,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* *
* @author Leetom * @author Leetom
* @version 2024-4-6 * @version 2024-4-6
* @since API 1.1.0 * @since API 2.0.0
*/ */
public enum EDhApiHeightFogMode public enum EDhApiHeightFogMode
{ {
@@ -7,7 +7,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* *
* @author James Seibel * @author James Seibel
* @version 2024-1-30 * @version 2024-1-30
* @since API 1.1.0 * @since API 2.0.0
*/ */
public enum EDhApiRenderPass public enum EDhApiRenderPass
{ {
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* Debug <br> * Debug <br>
* Disabled <br> * Disabled <br>
* *
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiRendererMode public enum EDhApiRendererMode
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* FAKE, <br> * FAKE, <br>
* COMPLETE, <br> * COMPLETE, <br>
* *
* @since API 1.1.0 * @since API 2.0.0
* @version 2024-4-6 * @version 2024-4-6
*/ */
public enum EDhApiTransparency public enum EDhApiTransparency
@@ -31,7 +31,7 @@ import java.util.function.Consumer;
* *
* @author Builderb0y, James Seibel * @author Builderb0y, James Seibel
* @version 2023-12-21 * @version 2023-12-21
* @since API 1.1.0 * @since API 2.0.0
*/ */
public enum EDhApiWorldGeneratorReturnType public enum EDhApiWorldGeneratorReturnType
{ {
@@ -40,7 +40,7 @@ public enum EDhApiWorldGeneratorReturnType
* {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)} * {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)}
* will be used when generating terrain. * will be used when generating terrain.
* *
* @since API 1.1.0 * @since API 2.0.0
*/ */
VANILLA_CHUNKS, VANILLA_CHUNKS,
@@ -49,7 +49,7 @@ public enum EDhApiWorldGeneratorReturnType
* {@link IDhApiWorldGenerator#generateApiChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)} * {@link IDhApiWorldGenerator#generateApiChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)}
* will be used when generating terrain. * will be used when generating terrain.
* *
* @since API 1.1.0 * @since API 2.0.0
*/ */
API_CHUNKS; API_CHUNKS;
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.api.interfaces.block; package com.seibel.distanthorizons.api.interfaces.block;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper; import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper;
/** /**
@@ -30,12 +31,25 @@ import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper;
*/ */
public interface IDhApiBlockStateWrapper extends IDhApiUnsafeWrapper public interface IDhApiBlockStateWrapper extends IDhApiUnsafeWrapper
{ {
/** @since API 1.0.0 */
boolean isAir(); boolean isAir();
/** @since API 1.0.0 */
boolean isSolid(); boolean isSolid();
/** @since API 1.0.0 */
boolean isLiquid(); boolean isLiquid();
// TODO: /**
// boolean hasNoCollision(); * Returns the full serialized form of the given block
// boolean noFaceIsFullFace(); * as defined by DH's serialization methods.
* @since API 3.0.0
*/
String getSerialString();
/**
* Returns the byte value representing the {@link EDhApiBlockMaterial} enum.
* @see EDhApiBlockMaterial
* @since API 3.0.0
*/
byte getMaterialId();
} }
@@ -36,7 +36,6 @@ public interface IDhApiConfig
IDhApiWorldGenerationConfig worldGenerator(); IDhApiWorldGenerationConfig worldGenerator();
IDhApiMultiplayerConfig multiplayer(); IDhApiMultiplayerConfig multiplayer();
IDhApiMultiThreadingConfig multiThreading(); IDhApiMultiThreadingConfig multiThreading();
IDhApiGpuBuffersConfig gpuBuffers();
// note: DON'T add the Auto Updater to this API. We only want the user's to have the ability to control when things are downloaded to their machines. // note: DON'T add the Auto Updater to this API. We only want the user's to have the ability to control when things are downloaded to their machines.
//IDhApiLoggingConfig logging(); // TODO implement //IDhApiLoggingConfig logging(); // TODO implement
IDhApiDebuggingConfig debugging(); IDhApiDebuggingConfig debugging();
@@ -47,7 +47,7 @@ public interface IDhApiConfigValue<T>
* Returns the value of the config if it was set by the API. * Returns the value of the config if it was set by the API.
* Returns null if the config hasn't been set by the API. * Returns null if the config hasn't been set by the API.
* *
* @since API 1.1.0 * @since API 2.0.0
*/ */
T getApiValue(); T getApiValue();
@@ -68,7 +68,7 @@ public interface IDhApiConfigValue<T>
* use the value set in the config menu. * use the value set in the config menu.
* *
* @return true if the value was set, false otherwise. * @return true if the value was set, false otherwise.
* @since API 1.1.0 * @since API 2.0.0
*/ */
boolean clearValue(); boolean clearValue();
@@ -19,30 +19,28 @@
package com.seibel.distanthorizons.api.interfaces.config.client; package com.seibel.distanthorizons.api.interfaces.config.client;
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigGroup; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigGroup;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
/** /**
* Distant Horizons' OpenGL buffer configuration. * Distant Horizons' generic rendering configuration. <br><br>
* *
* @author James Seibel * @author James Seibel
* @version 2023-6-14 * @version 2024-7-11
* @since API 1.0.0 * @since API 3.0.0
*/ */
public interface IDhApiGpuBuffersConfig extends IDhApiConfigGroup public interface IDhApiGenericRenderingConfig extends IDhApiConfigGroup
{ {
/** Defines how geometry data is uploaded to the GPU. */
IDhApiConfigValue<EDhApiGpuUploadMethod> gpuUploadMethod();
/** /**
* Defines how long we should wait after uploading one * If enabled DH will render generic objects into its terrain pass. <br>
* Megabyte of geometry data to the GPU before uploading * This includes: clouds, beacons, and API added objects.
* the next Megabyte of data. <br>
* This can be set to a non-zero number to reduce stuttering caused by
* uploading buffers to the GPU.
*/ */
IDhApiConfigValue<Integer> gpuUploadPerMegabyteInMilliseconds(); IDhApiConfigValue<Boolean> renderingEnabled();
/** If enabled DH will render beacon beams. */
IDhApiConfigValue<Boolean> beaconRenderingEnabled();
/** If enabled DH will render clouds. */
IDhApiConfigValue<Boolean> cloudRenderingEnabled();
} }
@@ -41,6 +41,7 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup
IDhApiFogConfig fog(); IDhApiFogConfig fog();
IDhApiAmbientOcclusionConfig ambientOcclusion(); IDhApiAmbientOcclusionConfig ambientOcclusion();
IDhApiNoiseTextureConfig noiseTexture(); IDhApiNoiseTextureConfig noiseTexture();
IDhApiGenericRenderingConfig genericRendering();
@@ -121,7 +122,7 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup
* Setting this to 0 will reduce/prevent holes in the world due to clipping to close to the camera * Setting this to 0 will reduce/prevent holes in the world due to clipping to close to the camera
* but may cause overdraw issues with transparent or non-full blocks. * but may cause overdraw issues with transparent or non-full blocks.
* *
* @since API 1.1.0 * @since API 2.0.0
*/ */
IDhApiConfigValue<Double> overdrawPreventionRadius(); IDhApiConfigValue<Double> overdrawPreventionRadius();
@@ -158,7 +159,7 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup
/** /**
* Determines how LODs should be shaded. * Determines how LODs should be shaded.
* *
* @since API 1.1.0 * @since API 2.0.0
*/ */
IDhApiConfigValue<EDhApiLodShading> lodShading(); IDhApiConfigValue<EDhApiLodShading> lodShading();
@@ -171,7 +172,7 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup
* start/stop rendering incorrectly based on the camera direction, * start/stop rendering incorrectly based on the camera direction,
* but will also reduce FPS. * but will also reduce FPS.
* *
* @since API 1.1.0 * @since API 2.0.0
* @see IDhApiGraphicsConfig#disableShadowFrustumCulling() * @see IDhApiGraphicsConfig#disableShadowFrustumCulling()
*/ */
IDhApiConfigValue<Boolean> disableFrustumCulling(); IDhApiConfigValue<Boolean> disableFrustumCulling();
@@ -183,7 +184,7 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup
* *
* Disable this if shadows render incorrectly. * Disable this if shadows render incorrectly.
* *
* @since API 1.1.0 * @since API 2.0.0
* @see IDhApiGraphicsConfig#disableFrustumCulling() * @see IDhApiGraphicsConfig#disableFrustumCulling()
*/ */
IDhApiConfigValue<Boolean> disableShadowFrustumCulling(); IDhApiConfigValue<Boolean> disableShadowFrustumCulling();
@@ -0,0 +1,21 @@
package com.seibel.distanthorizons.api.interfaces.data;
/**
* Can be used to drastically speed up repeat read operations in {@link IDhApiTerrainDataRepo}.
*
* @see IDhApiTerrainDataRepo
*
* @author James Seibel
* @version 2024-7-14
* @since API 3.0.0
*/
public interface IDhApiTerrainDataCache
{
/**
* Removes any data that's currently stored in this cache.
* This cane be done to free up memory or invalidate
* the cache so fresh data can be pulled in.
*/
void clear();
}
@@ -29,6 +29,8 @@ import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
/** /**
* Used to interface with Distant Horizons' terrain data. * Used to interface with Distant Horizons' terrain data.
* *
* @see IDhApiTerrainDataCache
*
* @author James Seibel * @author James Seibel
* @version 2023-6-22 * @version 2023-6-22
* @since API 1.0.0 * @since API 1.0.0
@@ -40,29 +42,50 @@ public interface IDhApiTerrainDataRepo
// getters // // getters //
//=========// //=========//
/** Returns the terrain datapoint at the given block position, at/or containing the given Y position. */ /** @see IDhApiTerrainDataRepo#getSingleDataPointAtBlockPos(IDhApiLevelWrapper, int, int, int, IDhApiTerrainDataCache) */
DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ); default DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ) { return this.getSingleDataPointAtBlockPos(levelWrapper, blockPosX, blockPosY, blockPosZ, null); }
/** Returns every datapoint in the column located at the given block X and Z position top to bottom. */ /**
DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ); * Returns the terrain datapoint at the given block position, at/or containing the given Y position.
* @since API 3.0.0
*/
DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ, IDhApiTerrainDataCache dataCache);
/** @see IDhApiTerrainDataRepo#getColumnDataAtBlockPos(IDhApiLevelWrapper, int, int, IDhApiTerrainDataCache) */
default DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ) { return this.getColumnDataAtBlockPos(levelWrapper, blockPosX, blockPosZ, null); }
/**
* Returns every datapoint in the column located at the given block X and Z position top to bottom.
* @since API 3.0.0
*/
DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ, IDhApiTerrainDataCache dataCache);
/** @see IDhApiTerrainDataRepo#getAllTerrainDataAtChunkPos(IDhApiLevelWrapper, int, int, IDhApiTerrainDataCache) */
default DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ) { return this.getAllTerrainDataAtChunkPos(levelWrapper, chunkPosX, chunkPosZ, null); }
/** /**
* Returns every datapoint in the given chunk's X and Z position. <br><br> * Returns every datapoint in the given chunk's X and Z position. <br><br>
* *
* The returned array is ordered: [relativeBlockX][relativeBlockZ][columnIndex] <br> * The returned array is ordered: [relativeBlockX][relativeBlockZ][columnIndex] <br>
* RelativeBlockX/Z are relative to the block position closest to negative infinity in the chunk's position. <br> * RelativeBlockX/Z are relative to the block position closest to negative infinity in the chunk's position. <br>
* The column data is ordered from top to bottom. Note: each column may have a different number of values. <br> * The column data is ordered from top to bottom. Note: each column may have a different number of values. <br>
*
* @since API 3.0.0
*/ */
DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ); DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ, IDhApiTerrainDataCache dataCache);
/** @see IDhApiTerrainDataRepo#getAllTerrainDataAtRegionPos(IDhApiLevelWrapper, int, int, IDhApiTerrainDataCache) */
default DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ) { return this.getAllTerrainDataAtRegionPos(levelWrapper, regionPosX, regionPosZ, null); }
/** /**
* Returns every datapoint in the given region's X and Z position. <br><br> * Returns every datapoint in the given region's X and Z position. <br><br>
* *
* The returned array is ordered: [relativeBlockX][relativeBlockZ][columnIndex] <br> * The returned array is ordered: [relativeBlockX][relativeBlockZ][columnIndex] <br>
* RelativeBlockX/Z are relative to the block position closest to negative infinity in the region's position. <br> * RelativeBlockX/Z are relative to the block position closest to negative infinity in the region's position. <br>
* The column data is ordered from top to bottom. Note: each column may have a different number of values. <br> * The column data is ordered from top to bottom. Note: each column may have a different number of values. <br>
*
* @since API 3.0.0
*/ */
DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ); DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ, IDhApiTerrainDataCache dataCache);
/** @see IDhApiTerrainDataRepo#getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper, byte, int, int, IDhApiTerrainDataCache) */
default DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ) { return this.getAllTerrainDataAtDetailLevelAndPos(levelWrapper, detailLevel, posX, posZ, null); }
/** /**
* Returns every datapoint in the column located at the given detail level and X/Z position. <br> * Returns every datapoint in the column located at the given detail level and X/Z position. <br>
* This can be used to return terrain data for non-standard sizes (IE 2x2 blocks or 2x2 chunks). * This can be used to return terrain data for non-standard sizes (IE 2x2 blocks or 2x2 chunks).
@@ -71,20 +94,42 @@ public interface IDhApiTerrainDataRepo
* Every increase doubles the width of the returned area. <br> * Every increase doubles the width of the returned area. <br>
* Example values: 0 = block, 1 = 2x2 blocks, 2 = 4x4 blocks, ... 4 = chunk (16x16 blocks), ... 9 = region (512x512 blocks) <br> * Example values: 0 = block, 1 = 2x2 blocks, 2 = 4x4 blocks, ... 4 = chunk (16x16 blocks), ... 9 = region (512x512 blocks) <br>
* See {@link EDhApiDetailLevel} for more information. * See {@link EDhApiDetailLevel} for more information.
*
* @since API 3.0.0
*/ */
DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ); DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ, IDhApiTerrainDataCache dataCache);
/** @see IDhApiTerrainDataRepo#raycast(IDhApiLevelWrapper, double, double, double, float, float, float, int, IDhApiTerrainDataCache) */
default DhApiResult<DhApiRaycastResult> raycast(
IDhApiLevelWrapper levelWrapper,
double rayOriginX, double rayOriginY, double rayOriginZ,
float rayDirectionX, float rayDirectionY, float rayDirectionZ,
int maxRayBlockLength)
{
return this.raycast(
levelWrapper,
rayOriginX, rayOriginY, rayOriginZ,
rayDirectionX, rayDirectionY, rayDirectionZ,
maxRayBlockLength,
null);
}
/** /**
* Returns the datapoint and position of the LOD * Returns the datapoint and position of the LOD
* at the end of the given ray. <br><br> * at the end of the given ray. <br><br>
* *
* Will return "success" with a null datapoint if the ray reaches the max length without finding any data. * Will return "success" with a null datapoint if the ray reaches the max length without finding any data.
*
* @since API 3.0.0
*/ */
DhApiResult<DhApiRaycastResult> raycast( DhApiResult<DhApiRaycastResult> raycast(
IDhApiLevelWrapper levelWrapper, IDhApiLevelWrapper levelWrapper,
double rayOriginX, double rayOriginY, double rayOriginZ, double rayOriginX, double rayOriginY, double rayOriginZ,
float rayDirectionX, float rayDirectionY, float rayDirectionZ, float rayDirectionX, float rayDirectionY, float rayDirectionZ,
int maxRayBlockLength); int maxRayBlockLength,
IDhApiTerrainDataCache dataCache);
@@ -99,14 +144,26 @@ public interface IDhApiTerrainDataRepo
* - Only works if the given {@link IDhApiLevelWrapper} points to a loaded level. <br> * - Only works if the given {@link IDhApiLevelWrapper} points to a loaded level. <br>
* - If the player travels to this chunk, or the chunk is updated in some other way; your data will be replaced * - If the player travels to this chunk, or the chunk is updated in some other way; your data will be replaced
* by whatever the current chunk is. <br> * by whatever the current chunk is. <br>
* - This method may not update the LOD data immediately. Any other chunks have * - This method may not update the LOD data immediately. Any other chunks that have
* been queued to update, they will be handled first. * been queued to update will be handled first.
* *
* @param levelWrapper the level wrapper that the chunk should be saved to. * @param levelWrapper the level wrapper that the chunk should be saved to.
* @param chunkObjectArray see {@link IDhApiWorldGenerator#generateChunks} for what objects are expected. * @param chunkObjectArray see {@link IDhApiWorldGenerator#generateChunks} for what objects are expected.
* @throws ClassCastException if chunkObjectArray doesn't contain the right objects. * @throws ClassCastException if chunkObjectArray doesn't contain the right objects.
* The exception will contain the expected object(s). * The exception will contain the expected object(s).
*/ */
public DhApiResult<Void> overwriteChunkDataAsync(IDhApiLevelWrapper levelWrapper, Object[] chunkObjectArray) throws ClassCastException; DhApiResult<Void> overwriteChunkDataAsync(IDhApiLevelWrapper levelWrapper, Object[] chunkObjectArray) throws ClassCastException;
//=========//
// helpers //
//=========//
/**
* @return a {@link IDhApiTerrainDataCache} backed by {@link java.lang.ref.SoftReference}'s.
* @since API 3.0.0
*/
IDhApiTerrainDataCache getSoftCache();
} }
@@ -31,7 +31,7 @@ import java.io.IOException;
* *
* @author James Seibel * @author James Seibel
* @version 2023-12-16 * @version 2023-12-16
* @since API 1.1.0 * @since API 2.0.0
*/ */
public interface IDhApiWrapperFactory public interface IDhApiWrapperFactory
{ {
@@ -50,7 +50,7 @@ public interface IDhApiWrapperFactory
* @throws ClassCastException if any of the given parameters is of the wrong type. * @throws ClassCastException if any of the given parameters is of the wrong type.
* If thrown the error message will contain the list of expected object types in order. * If thrown the error message will contain the list of expected object types in order.
* *
* @since API 1.1.0 * @since API 2.0.0
*/ */
IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) throws ClassCastException; IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) throws ClassCastException;
@@ -67,23 +67,46 @@ public interface IDhApiWrapperFactory
* @throws ClassCastException if any of the given parameters is of the wrong type. * @throws ClassCastException if any of the given parameters is of the wrong type.
* If thrown the error message will contain the list of expected object types in order. * If thrown the error message will contain the list of expected object types in order.
* *
* @since API 1.1.0 * @since API 2.0.0
*/ */
IDhApiBlockStateWrapper getBlockStateWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) throws ClassCastException; IDhApiBlockStateWrapper getBlockStateWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) throws ClassCastException;
/** /**
* Returns the {@link IDhApiBlockStateWrapper} representing air. * Returns the {@link IDhApiBlockStateWrapper} representing air.
* @since API 1.1.0 * @since API 2.0.0
*/ */
IDhApiBlockStateWrapper getAirBlockStateWrapper(); IDhApiBlockStateWrapper getAirBlockStateWrapper();
///** /**
// * Specifically designed to be used with the API. * Constructs a {@link IDhApiBiomeWrapper} for use by other DhApi methods.
// * *
// * @throws ClassCastException with instructions on expected objects if the object couldn't be cast * @param resourceLocationString example: "minecraft:plains"
// */ *
//IChunkWrapper createChunkWrapper(Object[] objectArray) throws ClassCastException; * @param levelWrapper Expects a {@link IDhApiLevelWrapper} returned by one of DH's {@link DhApi.Delayed#worldProxy} methods. <br>
* A custom implementation of {@link IDhApiLevelWrapper} will not be accepted.
*
* @throws IOException if the resourceLocationString wasn't able to be parsed or converted into a valid {@link IDhApiBiomeWrapper}
* @throws ClassCastException if the wrong levelWrapper type was given
*
* @since API 3.0.0
*/
IDhApiBiomeWrapper getBiomeWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException;
/**
* Constructs a {@link IDhApiBlockStateWrapper} for use by other DhApi methods.
* This returns the default blockstate for the given resource location.
*
* @param resourceLocationString examples: "minecraft:bedrock", "minecraft:stone", "minecraft:grass_block"
* @param levelWrapper Expects a {@link IDhApiBlockStateWrapper} returned by one of DH's {@link DhApi.Delayed#worldProxy} methods. <br>
* A custom implementation of {@link IDhApiBlockStateWrapper} will not be accepted.
*
* @throws IOException if the resourceLocationString wasn't able to be parsed or converted into a valid {@link IDhApiBlockStateWrapper}
* @throws ClassCastException if the wrong levelWrapper type was given
*
* @since API 3.0.0
*/
IDhApiBlockStateWrapper getDefaultBlockStateWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException;
} }
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.api.interfaces.override.rendering;
import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel; import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel;
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
/** /**
* Used to determine if a LOD should be rendered or is outside the * Used to determine if a LOD should be rendered or is outside the
@@ -29,7 +29,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
* *
* @author James Seibel * @author James Seibel
* @version 2024-2-6 * @version 2024-2-6
* @since API 1.1.0 * @since API 2.0.0
*/ */
public interface IDhApiCullingFrustum extends IDhApiOverrideable public interface IDhApiCullingFrustum extends IDhApiOverrideable
{ {
@@ -41,7 +41,7 @@ public interface IDhApiCullingFrustum extends IDhApiOverrideable
* @param worldMaxBlockY the highest block position this level allows. * @param worldMaxBlockY the highest block position this level allows.
* @param worldViewProjection the projection matrix used in this render pass. * @param worldViewProjection the projection matrix used in this render pass.
*/ */
void update(int worldMinBlockY, int worldMaxBlockY, Mat4f worldViewProjection); void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection);
/** /**
* returns true if the LOD bounds intersect this frustum * returns true if the LOD bounds intersect this frustum
@@ -24,7 +24,7 @@ import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
/** /**
* @author James Seibel * @author James Seibel
* @version 2024-1-24 * @version 2024-1-24
* @since API 1.1.0 * @since API 2.0.0
*/ */
public interface IDhApiFramebuffer extends IDhApiOverrideable public interface IDhApiFramebuffer extends IDhApiOverrideable
{ {
@@ -0,0 +1,80 @@
/*
* 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.api.interfaces.override.rendering;
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
/**
* @see IDhApiShaderProgram
*
* @author James Seibel
* @version 2024-7-11
* @since API 3.0.0
*/
public interface IDhApiGenericObjectShaderProgram extends IDhApiOverrideable
{
/**
* If this method is called that means this program has the highest priority as defined by {@link IDhApiOverrideable#getPriority()}
* and gets to decide if it wants to be used to render this frame or not. <br><br>
*
* If this method returns true then this program will be used for this frame. <br>
* If this returns false then the default DH {@link IDhApiGenericObjectShaderProgram} will be used instead.
*/
boolean overrideThisFrame();
/** @return the OpenGL ID for this shader program */
int getId();
/** Free any OpenGL objects owned by this program. */
void free();
/** Runs any necessary binding this program needs so rendering can be done. */
void bind(DhApiRenderParam renderEventParam);
/** Runs any necessary unbinding this program needs so rendering can be done by another program. */
void unbind();
/** Binds the given Vertex Buffer Object to this shader program for rendering. */
void bindVertexBuffer(int vbo);
/** sets up the necessary uniforms for rendering */
void fillIndirectUniformData(
DhApiRenderParam renderParameters,
DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup,
DhApiVec3d camPos);
/** sets up the necessary uniforms for rendering */
void fillSharedDirectUniformData(
DhApiRenderParam renderParameters,
DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup,
DhApiVec3d camPos);
void fillDirectUniformData(
DhApiRenderParam renderParameters,
IDhApiRenderableBoxGroup boxGroup, DhApiRenderableBox box,
DhApiVec3d camPos);
}
@@ -21,13 +21,14 @@ package com.seibel.distanthorizons.api.interfaces.override.rendering;
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
/** /**
* @see IDhApiGenericObjectShaderProgram
*
* @author James Seibel * @author James Seibel
* @version 2024-1-24 * @version 2024-1-24
* @since API 1.1.0 * @since API 2.0.0
*/ */
public interface IDhApiShaderProgram extends IDhApiOverrideable public interface IDhApiShaderProgram extends IDhApiOverrideable
{ {
@@ -57,7 +58,7 @@ public interface IDhApiShaderProgram extends IDhApiOverrideable
void fillUniformData(DhApiRenderParam renderParameters); void fillUniformData(DhApiRenderParam renderParameters);
/** sets the vec3 that all DH verticies should be offset by when rendering */ /** sets the vec3 that all DH verticies should be offset by when rendering */
void setModelOffsetPos(Vec3f modelPos); void setModelOffsetPos(DhApiVec3f modelPos);
/** Binds the given Vertex Buffer Object to this shader program for rendering. */ /** Binds the given Vertex Buffer Object to this shader program for rendering. */
void bindVertexBuffer(int vbo); void bindVertexBuffer(int vbo);
@@ -19,10 +19,6 @@
package com.seibel.distanthorizons.api.interfaces.override.rendering; package com.seibel.distanthorizons.api.interfaces.override.rendering;
import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel;
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
/** /**
* The culling frustum used during Distant Horizons' shadow pass * The culling frustum used during Distant Horizons' shadow pass
* if another mod has enabled Distant Horizons' shadow * if another mod has enabled Distant Horizons' shadow
@@ -35,7 +31,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
* *
* @author James Seibel * @author James Seibel
* @version 2024-2-10 * @version 2024-2-10
* @since API 1.1.0 * @since API 2.0.0
*/ */
public interface IDhApiShadowCullingFrustum extends IDhApiCullingFrustum public interface IDhApiShadowCullingFrustum extends IDhApiCullingFrustum
{ {
@@ -22,6 +22,8 @@ package com.seibel.distanthorizons.api.interfaces.override.worldGenerator;
import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel; import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
import com.seibel.distanthorizons.api.objects.data.DhApiChunk;
import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
import java.io.Closeable; import java.io.Closeable;
@@ -77,13 +79,41 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh
}, worldGeneratorThreadPool); }, worldGeneratorThreadPool);
} }
@Override
public final CompletableFuture<Void> generateApiChunks(
int chunkPosMinX,
int chunkPosMinZ,
byte granularity,
byte targetDataDetail,
EDhApiDistantGeneratorMode generatorMode,
ExecutorService worldGeneratorThreadPool,
Consumer<DhApiChunk> resultConsumer
)
{
return CompletableFuture.runAsync(() ->
{
// TODO what does this mean?
int genChunkWidth = BitShiftUtil.powerOfTwo(granularity - 4);
for (int chunkX = chunkPosMinX; chunkX < chunkPosMinX + genChunkWidth; chunkX++)
{
for (int chunkZ = chunkPosMinZ; chunkZ < chunkPosMinZ + genChunkWidth; chunkZ++)
{
DhApiChunk apiChunk = this.generateApiChunk(chunkX, chunkZ, generatorMode);
resultConsumer.accept(apiChunk);
}
}
}, worldGeneratorThreadPool);
}
/** /**
* This method is called to generate terrain over a given area * This method is called to generate terrain over a given area
* from a thread defined by Distant Horizons. <br><br> * from a thread defined by Distant Horizons. <br><br>
* *
* @param chunkPosX the chunk X position in the level (not to be confused with the chunk's BlockPos in the level) * @param chunkPosX the chunk X position in the level (not to be confused with the chunk's BlockPos in the level)
* @param chunkPosZ the chunk Z position in the level (not to be confused with the chunk's BlockPos in the level) * @param chunkPosZ the chunk Z position in the level (not to be confused with the chunk's BlockPos in the level)
* @param generatorMode how far into the world gen pipeline this method run. See {@link EDhApiDistantGeneratorMode} for additional documentation. * @param generatorMode how far into the world gen pipeline this method should run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
* *
* @return See {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator.generateChunks} * @return See {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator.generateChunks}
* for the list of Object's this method should return along with additional documentation. * for the list of Object's this method should return along with additional documentation.
@@ -92,4 +122,21 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh
*/ */
public abstract Object[] generateChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode); public abstract Object[] generateChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode);
/**
* This method is called to generate terrain over a given area
* from a thread defined by Distant Horizons. <br><br>
*
* @param chunkPosX the chunk X position in the level (not to be confused with the chunk's BlockPos in the level)
* @param chunkPosZ the chunk Z position in the level (not to be confused with the chunk's BlockPos in the level)
* @param generatorMode how far into the world gen pipeline this method should run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
*
* @return A {@link DhApiChunk} with the generated {@link DhApiTerrainDataPoint} including air blocks.
* Note: if air blocks aren't included with the proper lighting, lower detail levels will appear as black/unlit.
*
* @see IDhApiWorldGenerator#generateApiChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)
*
* @since API 3.0.0
*/
public abstract DhApiChunk generateApiChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode);
} }
@@ -91,10 +91,28 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
default byte getMaxGenerationGranularity() { return (byte) (EDhApiDetailLevel.CHUNK.detailLevel + 2); } default byte getMaxGenerationGranularity() { return (byte) (EDhApiDetailLevel.CHUNK.detailLevel + 2); }
/** /**
* @return true if the generator is unable to accept new generation requests. * Starting in API 3.0.0 DH now handles future queuing/management internally. <br><br>
*
* Previous description: <br>
* true if the generator is unable to accept new generation requests. <br>
*
* @since API 1.0.0 * @since API 1.0.0
* @deprecated API 3.0.0
*/ */
boolean isBusy(); @Deprecated
default boolean isBusy() { return false; }
/**
* Only used if {@link #getReturnType()} returns {@link EDhApiWorldGeneratorReturnType#API_CHUNKS}. <Br>
* If true DH will run additional validation on the {@link DhApiChunk}'s returned. <Br>
* This should be disabled during release but should be enabled during development to help spot issues with your data format.
*
* @see #getReturnType()
* @see DhApiChunk
* @see EDhApiWorldGeneratorReturnType#API_CHUNKS
* @since API 3.0.0
*/
default boolean runApiChunkValidation() { return true; }
@@ -154,6 +172,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* *
* After the {@link DhApiChunk} has been generated, it should be passed into the * After the {@link DhApiChunk} has been generated, it should be passed into the
* resultConsumer's {@link Consumer#accept(Object)} method. * resultConsumer's {@link Consumer#accept(Object)} method.
* Note: if air blocks aren't included in the with the {@link DhApiChunk} with proper lighting, lower detail levels will appear as black/unlit.
* *
* @implNote the default implementation of this method throws an {@link UnsupportedOperationException}, * @implNote the default implementation of this method throws an {@link UnsupportedOperationException},
* and must be overridden when {@link #getReturnType()} returns {@link EDhApiWorldGeneratorReturnType#API_CHUNKS}. * and must be overridden when {@link #getReturnType()} returns {@link EDhApiWorldGeneratorReturnType#API_CHUNKS}.
@@ -168,7 +187,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* *
* @return a future that should run on the worldGeneratorThreadPool and complete once the given generation task has completed. * @return a future that should run on the worldGeneratorThreadPool and complete once the given generation task has completed.
* *
* @since API 1.1.0 * @since API 2.0.0
*/ */
default CompletableFuture<Void> generateApiChunks( default CompletableFuture<Void> generateApiChunks(
int chunkPosMinX, int chunkPosMinX,
@@ -189,7 +208,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* which means that {@link #generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)} * which means that {@link #generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)}
* will be invoked whenever Distant Horizons wants to generate terrain with this world generator. * will be invoked whenever Distant Horizons wants to generate terrain with this world generator.
* *
* @since API 1.1.0 * @since API 2.0.0
*/ */
default EDhApiWorldGeneratorReturnType getReturnType() { return EDhApiWorldGeneratorReturnType.VANILLA_CHUNKS; } default EDhApiWorldGeneratorReturnType getReturnType() { return EDhApiWorldGeneratorReturnType.VANILLA_CHUNKS; }
@@ -0,0 +1,67 @@
package com.seibel.distanthorizons.api.interfaces.render;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
import java.util.List;
/**
* Handles creating
* {@link IDhApiRenderableBoxGroup} objects,
* which can be added via a {@link IDhApiCustomRenderRegister}.
*
* @see IDhApiCustomRenderRegister
* @see IDhApiRenderableBoxGroup
*
* @author James Seibel
* @version 2024-7-3
* @since API 3.0.0
*/
public interface IDhApiCustomRenderObjectFactory
{
/**
* Creates a {@link IDhApiRenderableBoxGroup} from for the given {@link DhApiRenderableBox}
* where the box is positioned relative to the level's origin.
*
* @param resourceLocation A colon separated Resource Location string, similar to vanilla Minecraft, for example: "DistantHorizons:Clouds"
*
* @see DhApiRenderableBox
* @see IDhApiRenderableBoxGroup#getResourceLocationNamespace()
* @see IDhApiRenderableBoxGroup#getResourceLocationPath()
*
* @throws IllegalArgumentException if <code>resourceLocation</code> is null, isn't separated by a colon, or has multiple colons.
*/
IDhApiRenderableBoxGroup createForSingleBox(String resourceLocation, DhApiRenderableBox cube) throws IllegalArgumentException;
/**
* Creates a {@link IDhApiRenderableBoxGroup} from the given list of {@link DhApiRenderableBox} where each
* one is positioned relative to given <code>originBlockPos</code>, which in turn is relative to the level's origin.
*
* @param resourceLocation A colon separated Resource Location string, similar to vanilla Minecraft, for example: "DistantHorizons:Clouds"
* @param originBlockPos The starting position for this {@link IDhApiRenderableBoxGroup}, can be changed during runtime.
*
*
* @see DhApiRenderableBox
* @see IDhApiRenderableBoxGroup#getResourceLocationNamespace()
* @see IDhApiRenderableBoxGroup#getResourceLocationPath()
*
* @throws IllegalArgumentException if <code>resourceLocation</code> is null, isn't separated by a colon, or has multiple colons.
*/
IDhApiRenderableBoxGroup createRelativePositionedGroup(String resourceLocation, DhApiVec3d originBlockPos, List<DhApiRenderableBox> cubeList);
/**
* Creates a {@link IDhApiRenderableBoxGroup} from the given list of {@link DhApiRenderableBox} where each
* one is positioned relative to the level's origin.
*
* @param resourceLocation A colon separated Resource Location string, similar to vanilla Minecraft, for example: "DistantHorizons:Clouds"
*
* @see DhApiRenderableBox
* @see IDhApiRenderableBoxGroup#getResourceLocationNamespace()
* @see IDhApiRenderableBoxGroup#getResourceLocationPath()
*
* @throws IllegalArgumentException if <code>resourceLocation</code> is null, isn't separated by a colon, or has multiple colons.
*/
IDhApiRenderableBoxGroup createAbsolutePositionedGroup(String resourceLocation, List<DhApiRenderableBox> cubeList);
}
@@ -0,0 +1,30 @@
package com.seibel.distanthorizons.api.interfaces.render;
import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiWorldProxy;
/**
* Handles adding and removing
* {@link IDhApiRenderableBoxGroup} objects,
* from DH's renderer. <br><br>
*
* Can be accessed in
* {@link DhApi.Delayed#worldProxy} -> {@link IDhApiLevelWrapper}.
*
* @see IDhApiCustomRenderObjectFactory
* @see IDhApiRenderableBoxGroup
* @see IDhApiWorldProxy
* @see IDhApiLevelWrapper
*
* @author James Seibel
* @version 2024-7-3
* @since API 3.0.0
*/
public interface IDhApiCustomRenderRegister
{
void add(IDhApiRenderableBoxGroup cubeGroup) throws IllegalArgumentException;
IDhApiRenderableBoxGroup remove(long id);
}
@@ -26,7 +26,7 @@ import com.seibel.distanthorizons.api.objects.DhApiResult;
* Used to interact with Distant Horizons' rendering system. * Used to interact with Distant Horizons' rendering system.
* *
* @author James Seibel * @author James Seibel
* @version 2023-10-13 * @version 2024-7-27
* @since API 1.0.0 * @since API 1.0.0
*/ */
public interface IDhApiRenderProxy public interface IDhApiRenderProxy
@@ -39,10 +39,8 @@ public interface IDhApiRenderProxy
* If this is called on a dedicated server it won't do anything and will return {@link DhApiResult#success} = false <Br><Br> * If this is called on a dedicated server it won't do anything and will return {@link DhApiResult#success} = false <Br><Br>
* *
* Background: <Br> * Background: <Br>
* Distant Horizons has two different file formats: Full data and Render data. <Br> * When rendering Distant Horizons bakes each block's color into the geometry that's rendered. <Br>
* - Full data files store the block, biome, etc. information and is the result of loading or generating new chunks. <Br> * This improves rendering speed and VRAM size, but prevents dynamically changing LOD colors. <Br>
* - Render data files store LOD colors and are created using the Full data and currently loaded resource packs. <Br>
* This is the data cleared by this method.
*/ */
DhApiResult<Boolean> clearRenderDataCache(); DhApiResult<Boolean> clearRenderDataCache();
@@ -0,0 +1,98 @@
package com.seibel.distanthorizons.api.interfaces.render;
import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3i;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
import java.util.List;
import java.util.function.Consumer;
/**
* A list of {@link DhApiRenderableBox}'s that
* can be rendered to DH's terrain pass.
*
* @see DhApiRenderableBox
*
* @author James Seibel
* @version 2024-6-30
* @since API 3.0.0
*/
public interface IDhApiRenderableBoxGroup extends List<DhApiRenderableBox>
{
/**
* A unique numerical ID used by DH during rendering.
* This can also be used to bind/unbind specific {@link IDhApiRenderableBoxGroup}'s from the renderer.
* @return the ID for this specific group
*/
long getId();
/**
* Used to determine which mods have added what to the DH renderer.
* This can be used both by the F3 pie chart so you as a mod developer can profile your code
* or by shader developers who want to render your objects differently. <br><br>
*
* Should be used the same as a vanilla Minecraft ResourceLocation.
* For example if your mod named "Heavy Thunder" adds additional clouds named "Storm Front",
* your Resource Location would be something like "HeavyThunder:StormFront"
* and this method would return "HeavyThunder".
*/
String getResourceLocationNamespace();
/**
* Used to determine what type of object mods have added what to the DH renderer.
* This can be used both by the F3 pie chart so you as a mod developer can profile your code
* or by shader developers who want to render your objects differently. <br><br>
*
* Should be used the same as a vanilla Minecraft ResourceLocation.
* For example if your mod named "Heavy Thunder" adds additional clouds named "Storm Front",
* your Resource Location would be something like "HeavyThunder:StormFront"
* and this method would return "StormFront".
*/
String getResourceLocationPath();
/** Sets whether this group should render or not. */
void setActive(boolean active);
/** @return if active this group will render. */
boolean isActive();
/** Sets whether this group should render with Screen Space Ambient Occlusioning. */
void setSsaoEnabled(boolean ssaoEnabled);
/** @return if active this group will render with Screen Space Ambient Occlusioning. */
boolean isSsaoEnabled();
/** Sets where this group will render in the level. */
void setOriginBlockPos(DhApiVec3d pos);
/** @return the block position in the level that all {@see DhApiRenderableBox} will render relative to. */
DhApiVec3d getOriginBlockPos();
/**
* Called right before this group is rendered. <br>
* This is a good place to change the origin or notify of any box changes.
*/
void setPreRenderFunc(Consumer<DhApiRenderParam> renderEventParam);
void setPostRenderFunc(Consumer<DhApiRenderParam> renderEventParam); // TODO name?
/**
* If a cube's color, position, or other property is changed this method
* must be called for those changes to render. <br><br>
*
* Note: changing the group's position via {@link #setOriginBlockPos} doesn't
* require calling this method.
*/
void triggerBoxChange();
/** Only accepts values between 0 and 15 */
void setSkyLight(int skyLight);
int getSkyLight();
/** Only accepts values between 0 and 15 */
void setBlockLight(int blockLight);
int getBlockLight();
void setShading(DhApiRenderableBoxGroupShading shading);
DhApiRenderableBoxGroupShading getShading();
}
@@ -0,0 +1,18 @@
package com.seibel.distanthorizons.api.interfaces.util;
/**
* Used for objects that need deep clones. <br>
* Replacement for {@link Cloneable}.
*
* @see Cloneable
*
* @author James Seibel
* @version 2024-7-12
* @since API 3.0.0
*/
public interface IDhApiCopyable
{
/** Returns a deep clone of all parameters whenever possible. */
IDhApiCopyable copy();
}
@@ -21,13 +21,14 @@ package com.seibel.distanthorizons.api.interfaces.world;
import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper; import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
/** /**
* Can be either a Server or Client level.<br> * Can be either a Server or Client level.<br>
* A level is equivalent to a dimension in vanilla Minecraft. * A level is equivalent to a dimension in vanilla Minecraft.
* *
* @author James Seibel * @author James Seibel
* @version 2022-7-14 * @version 2024-7-28
* @since API 1.0.0 * @since API 1.0.0
*/ */
public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper
@@ -40,8 +41,19 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper
boolean hasSkyLight(); boolean hasSkyLight();
/** Returns the max block height of the level(?) */ /**
int getHeight(); * Deprecated, use {@link IDhApiLevelWrapper#getMaxHeight} instead. <br>
* Returns the max block height of the level.
*
* @see IDhApiLevelWrapper#getMaxHeight
*/
@Deprecated
default int getHeight() { return this.getMaxHeight(); }
/**
* Returns the max block height of the level
* @since API 3.0.0
*/
int getMaxHeight();
/** /**
* Returns the lowest possible block position for the level. <br> * Returns the lowest possible block position for the level. <br>
@@ -49,4 +61,12 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper
*/ */
default int getMinHeight() { return 0; } default int getMinHeight() { return 0; }
/**
* Will return null if called on the server,
* or if called before the renderer has been set up.
*
* @since API 3.0.0
*/
IDhApiCustomRenderRegister getRenderRegister();
} }
@@ -26,17 +26,20 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
/** /**
* Fired after Distant Horizons finishes rendering a frame. <br> * Fired after Distant Horizons finishes rendering a frame. <br>
* At this point DH will have also finished cleaning up any modifications it * At this point DH will have also finished cleaning up any modifications it
* did to the OpenGL state, so the state should be back to Minecraft's defaults. * did to the OpenGL state, so the state should be back to Minecraft's defaults. <br><br>
*
* Note: as of API v 3.0.0 no {@link DhApiRenderParam} is included in this event
* because the specific parameters may change
* depending on whether deferred rendering is enabled or not.
* *
* @author James Seibel * @author James Seibel
* @version 2024-1-31 * @version 2024-7-14
* @see DhApiRenderParam
* @since API 1.0.0 * @since API 1.0.0
*/ */
public abstract class DhApiAfterRenderEvent implements IDhApiEvent<DhApiRenderParam> public abstract class DhApiAfterRenderEvent implements IDhApiEvent<Void>
{ {
/** Fired after Distant Horizons finishes rendering fake chunks. */ /** Fired after Distant Horizons finishes rendering fake chunks. */
public abstract void afterRender(DhApiEventParam<DhApiRenderParam> event); public abstract void afterRender(DhApiEventParam<Void> event);
//=========================// //=========================//
@@ -44,6 +47,6 @@ public abstract class DhApiAfterRenderEvent implements IDhApiEvent<DhApiRenderPa
//=========================// //=========================//
@Override @Override
public final void fireEvent(DhApiEventParam<DhApiRenderParam> event) { this.afterRender(event); } public final void fireEvent(DhApiEventParam<Void> event) { this.afterRender(event); }
} }
@@ -31,7 +31,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
* *
* @author James Seibel * @author James Seibel
* @version 2024-1-31 * @version 2024-1-31
* @since API 1.1.0 * @since API 2.0.0
*/ */
public abstract class DhApiBeforeApplyShaderRenderEvent implements IDhApiCancelableEvent<DhApiRenderParam> public abstract class DhApiBeforeApplyShaderRenderEvent implements IDhApiCancelableEvent<DhApiRenderParam>
{ {
@@ -20,9 +20,10 @@
package com.seibel.distanthorizons.api.methods.events.abstractEvents; package com.seibel.distanthorizons.api.methods.events.abstractEvents;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
/** /**
* Called before Distant Horizons starts rendering a buffer. <br> * Called before Distant Horizons starts rendering a buffer. <br>
@@ -30,7 +31,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
* *
* @author James Seibel * @author James Seibel
* @version 2023-1-31 * @version 2023-1-31
* @since API 1.1.0 * @since API 2.0.0
* *
* @see DhApiBeforeRenderEvent * @see DhApiBeforeRenderEvent
*/ */
@@ -52,20 +53,29 @@ public abstract class DhApiBeforeBufferRenderEvent implements IDhApiEvent<DhApiB
// parameter object // // parameter object //
//==================// //==================//
public static class EventParam extends DhApiRenderParam public static class EventParam extends DhApiRenderParam implements IDhApiEventParam
{ {
/** /**
* Measured in blocks. * Measured in blocks.
* Should be applied to the model view matrix to move the buffer into its proper place. * Should be applied to the model view matrix to move the buffer into its proper place.
*/ */
public final Vec3f modelPos; public final DhApiVec3f modelPos;
public EventParam(DhApiRenderParam parent, Vec3f modelPos) public EventParam(DhApiRenderParam parent, DhApiVec3f modelPos)
{ {
super(parent); super(parent);
this.modelPos = modelPos; this.modelPos = modelPos;
} }
@Override
public EventParam copy()
{
return new EventParam(
this, this.modelPos.copy()
);
}
} }
} }
@@ -29,7 +29,7 @@ import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy;
* *
* @author James Seibel * @author James Seibel
* @version 2024-1-22 * @version 2024-1-22
* @since API 1.1.0 * @since API 2.0.0
*/ */
public abstract class DhApiBeforeDeferredRenderEvent extends DhApiBeforeRenderEvent public abstract class DhApiBeforeDeferredRenderEvent extends DhApiBeforeRenderEvent
{ {
@@ -0,0 +1,97 @@
/*
* 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.api.methods.events.abstractEvents;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiCancelableEvent;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
/**
* Called before Distant Horizons starts rendering a generic object. <br>
* Canceling this event will prevent the triggering {@link IDhApiRenderableBoxGroup} from rendering this frame.
*
* @author James Seibel
* @version 2024-7-11
* @since API 3.0.0
*/
public abstract class DhApiBeforeGenericObjectRenderEvent implements IDhApiCancelableEvent<DhApiBeforeGenericObjectRenderEvent.EventParam>
{
/** Fired before Distant Horizons renders a generic object. */
public abstract void beforeRender(DhApiCancelableEventParam<EventParam> event);
//=========================//
// internal DH API methods //
//=========================//
@Override
public final void fireEvent(DhApiCancelableEventParam<EventParam> input) { this.beforeRender(input); }
//==================//
// parameter object //
//==================//
public static class EventParam extends DhApiRenderParam implements IDhApiEventParam
{
public final long boxGroupId;
public final String resourceLocationNamespace;
public final String resourceLocationPath;
public EventParam(
DhApiRenderParam renderParam,
IDhApiRenderableBoxGroup boxGroup
)
{
super(renderParam);
this.boxGroupId = boxGroup.getId();
this.resourceLocationNamespace = boxGroup.getResourceLocationNamespace();
this.resourceLocationPath = boxGroup.getResourceLocationPath();
}
public EventParam(
DhApiRenderParam renderParam,
long boxGroupId, String resourceLocationNamespace, String resourceLocationPath
)
{
super(renderParam);
this.boxGroupId = boxGroupId;
this.resourceLocationNamespace = resourceLocationNamespace;
this.resourceLocationPath = resourceLocationPath;
}
@Override
public EventParam copy()
{
return new EventParam(
this,
this.boxGroupId, this.resourceLocationNamespace, this.resourceLocationPath
);
}
}
}
@@ -0,0 +1,47 @@
/*
* 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.api.methods.events.abstractEvents;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
/**
* Called before Distant Horizons starts the cleanup process done after rendering generic objects. <br>
* This is called after all generic objects have finished rendering.
*
* @author James Seibel
* @version 2024-7-13
* @since API 3.0.0
*/
public abstract class DhApiBeforeGenericRenderCleanupEvent implements IDhApiEvent<DhApiRenderParam>
{
/** Fired before Distant Horizons starts the cleanup process once rendering has finished. */
public abstract void beforeCleanup(DhApiEventParam<DhApiRenderParam> event);
//=========================//
// internal DH API methods //
//=========================//
@Override
public final void fireEvent(DhApiEventParam<DhApiRenderParam> event) { this.beforeCleanup(event); }
}
@@ -0,0 +1,50 @@
/*
* 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.api.methods.events.abstractEvents;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
/**
* Called before Distant Horizons has started setting up OpenGL objects for rendering generic objects. <br>
* If you want to modify already bound DH OpenGL objects try using {@link DhApiBeforeGenericObjectRenderEvent}.
*
* @author James Seibel
* @version 2024-7-12
* @since API 3.0.0
*
* @see DhApiBeforeGenericObjectRenderEvent
*/
public abstract class DhApiBeforeGenericRenderSetupEvent implements IDhApiEvent<DhApiRenderParam>
{
/** Fired before Distant Horizons has started setting up OpenGL objects for rendering generic objects. */
public abstract void beforeSetup(DhApiEventParam<DhApiRenderParam> input);
//=========================//
// internal DH API methods //
//=========================//
@Override
public final void fireEvent(DhApiEventParam<DhApiRenderParam> input) { this.beforeSetup(input); }
}
@@ -29,11 +29,11 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
* *
* @author James Seibel * @author James Seibel
* @version 2024-1-31 * @version 2024-1-31
* @since API 1.1.0 * @since API 2.0.0
*/ */
public abstract class DhApiBeforeRenderCleanupEvent implements IDhApiEvent<DhApiRenderParam> public abstract class DhApiBeforeRenderCleanupEvent implements IDhApiEvent<DhApiRenderParam>
{ {
/** Fired before Distant Horizons renders LODs. */ /** Fired before Distant Horizons starts the cleanup process once rendering has finished. */
public abstract void beforeCleanup(DhApiEventParam<DhApiRenderParam> event); public abstract void beforeCleanup(DhApiEventParam<DhApiRenderParam> event);
@@ -31,7 +31,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
* *
* @author James Seibel * @author James Seibel
* @version 2023-1-31 * @version 2023-1-31
* @since API 1.1.0 * @since API 2.0.0
* *
* @see DhApiBeforeRenderEvent * @see DhApiBeforeRenderEvent
*/ */
@@ -29,7 +29,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
* *
* @author James Seibel * @author James Seibel
* @version 2024-1-31 * @version 2024-1-31
* @since API 1.1.0 * @since API 2.0.0
* *
* @see DhApiBeforeRenderPassEvent * @see DhApiBeforeRenderPassEvent
*/ */
@@ -31,7 +31,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
* *
* @author James Seibel * @author James Seibel
* @version 2024-1-31 * @version 2024-1-31
* @since API 1.1.0 * @since API 2.0.0
*/ */
public abstract class DhApiBeforeTextureClearEvent implements IDhApiCancelableEvent<DhApiRenderParam> public abstract class DhApiBeforeTextureClearEvent implements IDhApiCancelableEvent<DhApiRenderParam>
{ {
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.api.methods.events.abstractEvents;
import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataRepo; import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataRepo;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
/** /**
@@ -53,7 +54,7 @@ public abstract class DhApiChunkModifiedEvent implements IDhApiEvent<DhApiChunkM
// parameter object // // parameter object //
//==================// //==================//
public static class EventParam public static class EventParam implements IDhApiEventParam
{ {
/** The saved level. */ /** The saved level. */
public final IDhApiLevelWrapper levelWrapper; public final IDhApiLevelWrapper levelWrapper;
@@ -71,6 +72,15 @@ public abstract class DhApiChunkModifiedEvent implements IDhApiEvent<DhApiChunkM
this.chunkZ = chunkZ; this.chunkZ = chunkZ;
} }
@Override
public EventParam copy()
{
return new EventParam(
this.levelWrapper,
this.chunkX, this.chunkZ
);
}
} }
} }
@@ -20,6 +20,7 @@
package com.seibel.distanthorizons.api.methods.events.abstractEvents; package com.seibel.distanthorizons.api.methods.events.abstractEvents;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
/** /**
@@ -28,7 +29,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
* *
* @author James Seibel * @author James Seibel
* @version 2024-3-2 * @version 2024-3-2
* @since API 1.1.0 * @since API 2.0.0
*/ */
public abstract class DhApiColorDepthTextureCreatedEvent implements IDhApiEvent<DhApiColorDepthTextureCreatedEvent.EventParam> public abstract class DhApiColorDepthTextureCreatedEvent implements IDhApiEvent<DhApiColorDepthTextureCreatedEvent.EventParam>
{ {
@@ -48,7 +49,7 @@ public abstract class DhApiColorDepthTextureCreatedEvent implements IDhApiEvent<
// parameter object // // parameter object //
//==================// //==================//
public static class EventParam public static class EventParam implements IDhApiEventParam
{ {
/** Measured in pixels */ /** Measured in pixels */
public final int previousWidth; public final int previousWidth;
@@ -72,6 +73,16 @@ public abstract class DhApiColorDepthTextureCreatedEvent implements IDhApiEvent<
this.newHeight = newHeight; this.newHeight = newHeight;
} }
@Override
public EventParam copy()
{
return new EventParam(
this.previousWidth, this.previousHeight,
this.newWidth, this.newHeight
);
}
} }
} }
@@ -21,6 +21,7 @@ package com.seibel.distanthorizons.api.methods.events.abstractEvents;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
/** /**
@@ -49,13 +50,16 @@ public abstract class DhApiLevelLoadEvent implements IDhApiEvent<DhApiLevelLoadE
// parameter object // // parameter object //
//==================// //==================//
public static class EventParam public static class EventParam implements IDhApiEventParam
{ {
/** The newly loaded level. */ /** The newly loaded level. */
public final IDhApiLevelWrapper levelWrapper; public final IDhApiLevelWrapper levelWrapper;
public EventParam(IDhApiLevelWrapper newLevelWrapper) { this.levelWrapper = newLevelWrapper; } public EventParam(IDhApiLevelWrapper newLevelWrapper) { this.levelWrapper = newLevelWrapper; }
@Override
public EventParam copy() { return new EventParam(this.levelWrapper); }
} }
} }
@@ -19,9 +19,9 @@
package com.seibel.distanthorizons.api.methods.events.abstractEvents; package com.seibel.distanthorizons.api.methods.events.abstractEvents;
import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
/** /**
@@ -49,13 +49,16 @@ public abstract class DhApiLevelUnloadEvent implements IDhApiEvent<DhApiLevelUnl
// parameter object // // parameter object //
//==================// //==================//
public static class EventParam public static class EventParam implements IDhApiEventParam
{ {
/** The recently unloaded level. */ /** The recently unloaded level. */
public final IDhApiLevelWrapper levelWrapper; public final IDhApiLevelWrapper levelWrapper;
public EventParam(IDhApiLevelWrapper newLevelWrapper) { this.levelWrapper = newLevelWrapper; } public EventParam(IDhApiLevelWrapper newLevelWrapper) { this.levelWrapper = newLevelWrapper; }
@Override
public EventParam copy() { return new EventParam(this.levelWrapper); }
} }
} }
@@ -0,0 +1,13 @@
package com.seibel.distanthorizons.api.methods.events.interfaces;
import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable;
/**
* @author James Seibel
* @version 2024-7-12
* @since API 3.0.0
*/
public interface IDhApiEventParam extends IDhApiCopyable
{
}
@@ -20,7 +20,8 @@
package com.seibel.distanthorizons.api.methods.events.sharedParameterObjects; package com.seibel.distanthorizons.api.methods.events.sharedParameterObjects;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass; import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
/** /**
* Contains information relevant to Distant Horizons and Minecraft rendering. * Contains information relevant to Distant Horizons and Minecraft rendering.
@@ -29,7 +30,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
* @version 2024-1-31 * @version 2024-1-31
* @since API 1.0.0 * @since API 1.0.0
*/ */
public class DhApiRenderParam public class DhApiRenderParam implements IDhApiEventParam
{ {
/** Indicates what render pass DH is currently rendering */ /** Indicates what render pass DH is currently rendering */
public final EDhApiRenderPass renderPass; public final EDhApiRenderPass renderPass;
@@ -49,18 +50,15 @@ public class DhApiRenderParam
public final float farClipPlane; public final float farClipPlane;
/** The projection matrix Minecraft is using to render this frame. */ /** The projection matrix Minecraft is using to render this frame. */
public final Mat4f mcProjectionMatrix; public final DhApiMat4f mcProjectionMatrix;
/** The model view matrix Minecraft is using to render this frame. */ /** The model view matrix Minecraft is using to render this frame. */
public final Mat4f mcModelViewMatrix; public final DhApiMat4f mcModelViewMatrix;
/** The projection matrix Distant Horizons is using to render this frame. */ /** The projection matrix Distant Horizons is using to render this frame. */
public final Mat4f dhProjectionMatrix; public final DhApiMat4f dhProjectionMatrix;
/** The model view matrix Distant Horizons is using to render this frame. */ /** The model view matrix Distant Horizons is using to render this frame. */
public final Mat4f dhModelViewMatrix; public final DhApiMat4f dhModelViewMatrix;
public final int lightmapBindingIndex = 0;
// TODO why is this here? wouldn't it make more sense to have this built into the vertex buffer data?
public final int worldYOffset; public final int worldYOffset;
@@ -69,24 +67,24 @@ public class DhApiRenderParam
// constructors // // constructors //
//==============// //==============//
public DhApiRenderParam(DhApiRenderParam parent) public DhApiRenderParam(DhApiRenderParam parent)
{ {
this( this(
parent.renderPass, parent.renderPass,
parent.partialTicks, parent.partialTicks,
parent.nearClipPlane, parent.farClipPlane, parent.nearClipPlane, parent.farClipPlane,
parent.mcProjectionMatrix, parent.mcModelViewMatrix, parent.mcProjectionMatrix.copy(), parent.mcModelViewMatrix.copy(),
parent.dhProjectionMatrix, parent.dhModelViewMatrix, parent.dhProjectionMatrix.copy(), parent.dhModelViewMatrix.copy(),
parent.worldYOffset parent.worldYOffset
); );
} }
public DhApiRenderParam( public DhApiRenderParam(
EDhApiRenderPass renderPass, EDhApiRenderPass renderPass,
float newPartialTicks, float newPartialTicks,
float nearClipPlane, float farClipPlane, float nearClipPlane, float farClipPlane,
Mat4f newMcProjectionMatrix, Mat4f newMcModelViewMatrix, DhApiMat4f newMcProjectionMatrix, DhApiMat4f newMcModelViewMatrix,
Mat4f newDhProjectionMatrix, Mat4f newDhModelViewMatrix, DhApiMat4f newDhProjectionMatrix, DhApiMat4f newDhModelViewMatrix,
int worldYOffset int worldYOffset
) )
{ {
@@ -107,4 +105,16 @@ public class DhApiRenderParam
} }
//================//
// base overrides //
//================//
@Override
public DhApiRenderParam copy()
{
return new DhApiRenderParam(this);
}
} }
@@ -21,16 +21,18 @@ package com.seibel.distanthorizons.api.objects.data;
import com.seibel.distanthorizons.api.interfaces.factories.IDhApiWrapperFactory; import com.seibel.distanthorizons.api.interfaces.factories.IDhApiWrapperFactory;
import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGenerator; import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGenerator;
import org.apache.logging.log4j.LogManager;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
/** /**
* Contains a list of {@link DhApiTerrainDataPoint} representing the blocks in a Minecraft chunk. * Contains a list of {@link DhApiTerrainDataPoint} representing the blocks in a Minecraft chunk.
* *
* @author Builderb0y, James Seibel * @author Builderb0y, James Seibel
* @version 2023-12-21 * @version 2024-7-21
* @since API 1.1.0 * @since API 2.0.0
* *
* @see IDhApiWrapperFactory * @see IDhApiWrapperFactory
* @see DhApiTerrainDataPoint * @see DhApiTerrainDataPoint
@@ -41,8 +43,8 @@ public class DhApiChunk
public final int chunkPosX; public final int chunkPosX;
public final int chunkPosZ; public final int chunkPosZ;
public final int topYBlockPos;
public final int bottomYBlockPos; public final int bottomYBlockPos;
public final int topYBlockPos;
private final List<List<DhApiTerrainDataPoint>> dataPoints; private final List<List<DhApiTerrainDataPoint>> dataPoints;
@@ -52,12 +54,32 @@ public class DhApiChunk
// constructors // // constructors //
//==============// //==============//
/**
* Deprecated due to the topYBlockPos and bottomYBlockPos variables being put in the wrong order.
* They should have been in bottom -> top order.
*
* @see DhApiChunk#create(int, int, int, int)
*/
@Deprecated
public DhApiChunk(int chunkPosX, int chunkPosZ, int topYBlockPos, int bottomYBlockPos) public DhApiChunk(int chunkPosX, int chunkPosZ, int topYBlockPos, int bottomYBlockPos)
{ this(chunkPosX, chunkPosZ, bottomYBlockPos, topYBlockPos, false); }
/**
* @since API 3.0.0
*/
public static DhApiChunk create(int chunkPosX, int chunkPosZ, int bottomYBlockPos, int topYBlockPos)
{ return new DhApiChunk(chunkPosX, chunkPosZ, bottomYBlockPos, topYBlockPos, false); }
/**
* Only visible to internal DH methods
* @param ignoredParameter is only present to differentiate the two constructors and isn't actually used
*/
private DhApiChunk(int chunkPosX, int chunkPosZ, int bottomYBlockPos, int topYBlockPos, boolean ignoredParameter)
{ {
this.chunkPosX = chunkPosX; this.chunkPosX = chunkPosX;
this.chunkPosZ = chunkPosZ; this.chunkPosZ = chunkPosZ;
this.topYBlockPos = topYBlockPos;
this.bottomYBlockPos = bottomYBlockPos; this.bottomYBlockPos = bottomYBlockPos;
this.topYBlockPos = topYBlockPos;
// populate the array to prevent null pointers // populate the array to prevent null pointers
this.dataPoints = new ArrayList<>(16 * 16); // 256 this.dataPoints = new ArrayList<>(16 * 16); // 256
@@ -94,27 +116,34 @@ public class DhApiChunk
*/ */
public void setDataPoints(int relX, int relZ, List<DhApiTerrainDataPoint> dataPoints) throws IndexOutOfBoundsException, IllegalArgumentException public void setDataPoints(int relX, int relZ, List<DhApiTerrainDataPoint> dataPoints) throws IndexOutOfBoundsException, IllegalArgumentException
{ {
//==================//
// basic validation //
//==================//
// heavier validation is done in the world generator if requested
int internalArrayIndex = (relZ << 4) | relX;
throwIfRelativePosOutOfBounds(relX, relZ); throwIfRelativePosOutOfBounds(relX, relZ);
// validate the incoming datapoints if (dataPoints == null)
if (dataPoints != null)
{ {
for (int i = 0; i < dataPoints.size(); i++) // standard for-loop used instead of an enhanced for-loop to slightly reduce GC overhead due to iterator allocation // we don't allow null columns
{ throw new IllegalArgumentException("Null columns aren't allowed. If you want to remove all data from a column please clear the list or pass in an empty list.");
DhApiTerrainDataPoint dataPoint = dataPoints.get(i);
if (dataPoint == null)
{
throw new IllegalArgumentException("Null DhApiTerrainDataPoints are not allowed. If you want to represent empty terrain, please use AIR.");
} }
if (dataPoint.detailLevel != 0)
{
throw new IllegalArgumentException("DhApiTerrainDataPoints has the wrong detail level ["+dataPoint.detailLevel+"], all data points must be block sized; IE their detail level must be [0].");
}
}
}
this.dataPoints.set((relZ << 4) | relX, dataPoints);
//================//
// set datapoints //
//================//
List<DhApiTerrainDataPoint> column = this.dataPoints.get(internalArrayIndex);
if (column == null)
{
column = new ArrayList<>();
this.dataPoints.set(internalArrayIndex, column);
}
column.addAll(dataPoints);
} }
@@ -20,7 +20,6 @@
package com.seibel.distanthorizons.api.objects.data; package com.seibel.distanthorizons.api.objects.data;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; import com.seibel.distanthorizons.api.objects.math.DhApiVec3i;
import com.seibel.distanthorizons.coreapi.util.math.Vec3i;
/** /**
* Holds a single datapoint of terrain data * Holds a single datapoint of terrain data
@@ -47,7 +46,7 @@ public class DhApiRaycastResult
public DhApiRaycastResult(DhApiTerrainDataPoint dataPoint, Vec3i blockPos) public DhApiRaycastResult(DhApiTerrainDataPoint dataPoint, DhApiVec3i blockPos)
{ {
this.dataPoint = dataPoint; this.dataPoint = dataPoint;
this.pos = blockPos; this.pos = blockPos;
@@ -19,14 +19,17 @@
package com.seibel.distanthorizons.api.objects.data; package com.seibel.distanthorizons.api.objects.data;
import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel;
import com.seibel.distanthorizons.api.interfaces.block.IDhApiBiomeWrapper; import com.seibel.distanthorizons.api.interfaces.block.IDhApiBiomeWrapper;
import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper; import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper;
import java.util.ArrayList;
/** /**
* Holds a single datapoint of terrain data. * Holds a single datapoint of terrain data.
* *
* @author James Seibel * @author James Seibel
* @version 2022-11-13 * @version 2024-7-20
* @since API 1.0.0 * @since API 1.0.0
*/ */
public class DhApiTerrainDataPoint public class DhApiTerrainDataPoint
@@ -37,27 +40,79 @@ public class DhApiTerrainDataPoint
* 2 = 4x4 blocks <br> * 2 = 4x4 blocks <br>
* 4 = chunk (16x16 blocks) <br> * 4 = chunk (16x16 blocks) <br>
* 9 = region (512x512 blocks) <br> * 9 = region (512x512 blocks) <br>
*
* @see EDhApiDetailLevel
*/ */
public final byte detailLevel; public final byte detailLevel;
public final int blockLightLevel; public final int blockLightLevel;
public final int skyLightLevel; public final int skyLightLevel;
public final int topYBlockPos;
public final int bottomYBlockPos; public final int bottomYBlockPos;
public final int topYBlockPos;
public final IDhApiBlockStateWrapper blockStateWrapper; public final IDhApiBlockStateWrapper blockStateWrapper;
public final IDhApiBiomeWrapper biomeWrapper; public final IDhApiBiomeWrapper biomeWrapper;
public DhApiTerrainDataPoint(byte detailLevel, int blockLightLevel, int skyLightLevel, int topYBlockPos, int bottomYBlockPos, IDhApiBlockStateWrapper blockStateWrapper, IDhApiBiomeWrapper biomeWrapper) //==============//
// constructors //
//==============//
/**
* Deprecated due to the topYBlockPos and bottomYBlockPos variables being put in the wrong order.
* They should have been in bottom -> top order.
*
* @see DhApiTerrainDataPoint#create(byte, int, int, int, int, IDhApiBlockStateWrapper, IDhApiBiomeWrapper)
*/
@Deprecated
public DhApiTerrainDataPoint(
byte detailLevel,
int blockLightLevel, int skyLightLevel,
int topYBlockPos, int bottomYBlockPos,
IDhApiBlockStateWrapper blockStateWrapper, IDhApiBiomeWrapper biomeWrapper)
{
this(detailLevel, blockLightLevel, skyLightLevel,
bottomYBlockPos, topYBlockPos,
blockStateWrapper, biomeWrapper,
false);
}
/**
* @since API 3.0.0
*/
public static DhApiTerrainDataPoint create(
byte detailLevel,
int blockLightLevel, int skyLightLevel,
int bottomYBlockPos, int topYBlockPos,
IDhApiBlockStateWrapper blockStateWrapper, IDhApiBiomeWrapper biomeWrapper
)
{
return new DhApiTerrainDataPoint(
detailLevel, blockLightLevel, skyLightLevel,
bottomYBlockPos, topYBlockPos,
blockStateWrapper, biomeWrapper,
false);
}
/**
* Only visible to internal DH methods
* @param ignoredParameter is only present to differentiate the two constructors and isn't actually used
*/
private DhApiTerrainDataPoint(
byte detailLevel,
int blockLightLevel, int skyLightLevel,
int bottomYBlockPos, int topYBlockPos,
IDhApiBlockStateWrapper blockStateWrapper, IDhApiBiomeWrapper biomeWrapper,
boolean ignoredParameter
)
{ {
this.detailLevel = detailLevel; this.detailLevel = detailLevel;
this.blockLightLevel = blockLightLevel; this.blockLightLevel = blockLightLevel;
this.skyLightLevel = skyLightLevel; this.skyLightLevel = skyLightLevel;
this.topYBlockPos = topYBlockPos;
this.bottomYBlockPos = bottomYBlockPos; this.bottomYBlockPos = bottomYBlockPos;
this.topYBlockPos = topYBlockPos;
this.blockStateWrapper = blockStateWrapper; this.blockStateWrapper = blockStateWrapper;
this.biomeWrapper = biomeWrapper; this.biomeWrapper = biomeWrapper;
@@ -17,46 +17,55 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
package com.seibel.distanthorizons.coreapi.util.math; package com.seibel.distanthorizons.api.objects.math;
import org.joml.Matrix4f; import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable;
import org.joml.Matrix4fc;
import java.nio.FloatBuffer;
/** /**
* An (almost) exact copy of Minecraft's 1.16.5 * An (almost) exact copy of Minecraft's 1.16.5
* implementation of a 4x4 float matrix. * implementation of a 4x4 float matrix. <br><br>
*
* <code>
* m00, m10, m20, m30, <br>
* m01, m11, m21, m31, <br>
* m02, m12, m22, m32, <br>
* m03, m13, m23, m33 <br>
* </code>
* *
* @author James Seibel * @author James Seibel
* @version 11-11-2021 * @version 2024-6-30
*/ */
public class Mat4f public class DhApiMat4f implements IDhApiCopyable
{ {
private float m00; public float m00;
private float m01; public float m01;
private float m02; public float m02;
private float m03; public float m03;
private float m10;
private float m11; public float m10;
private float m12; public float m11;
private float m13; public float m12;
private float m20; public float m13;
private float m21;
private float m22; public float m20;
private float m23; public float m21;
private float m30; public float m22;
private float m31; public float m23;
private float m32;
private float m33; public float m30;
public float m31;
public float m32;
public float m33;
public Mat4f()
{
} //==============//
// constructors //
//==============//
public Mat4f(Mat4f sourceMatrix) public DhApiMat4f() { /* all values are 0 */ }
public DhApiMat4f(DhApiMat4f sourceMatrix)
{ {
this.m00 = sourceMatrix.m00; this.m00 = sourceMatrix.m00;
this.m01 = sourceMatrix.m01; this.m01 = sourceMatrix.m01;
@@ -76,163 +85,36 @@ public class Mat4f
this.m33 = sourceMatrix.m33; this.m33 = sourceMatrix.m33;
} }
public Mat4f(Matrix4fc sourceMatrix) { this(convertJomlMatrixToArray(sourceMatrix)); } /** Expects the values of the input array to be in row major order (AKA rows then columns) */
private static float[] convertJomlMatrixToArray(Matrix4fc sourceMatrix) public DhApiMat4f(float[] values)
{ {
FloatBuffer buffer = FloatBuffer.allocate(16); m00 = values[0];
m01 = values[1];
m02 = values[2];
m03 = values[3];
buffer.put(bufferIndex(0, 0), sourceMatrix.m00()); m10 = values[4];
buffer.put(bufferIndex(0, 1), sourceMatrix.m01()); m11 = values[5];
buffer.put(bufferIndex(0, 2), sourceMatrix.m02()); m12 = values[6];
buffer.put(bufferIndex(0, 3), sourceMatrix.m03()); m13 = values[7];
buffer.put(bufferIndex(1, 0), sourceMatrix.m10());
buffer.put(bufferIndex(1, 1), sourceMatrix.m11());
buffer.put(bufferIndex(1, 2), sourceMatrix.m12());
buffer.put(bufferIndex(1, 3), sourceMatrix.m13());
buffer.put(bufferIndex(2, 0), sourceMatrix.m20());
buffer.put(bufferIndex(2, 1), sourceMatrix.m21());
buffer.put(bufferIndex(2, 2), sourceMatrix.m22());
buffer.put(bufferIndex(2, 3), sourceMatrix.m23());
buffer.put(bufferIndex(3, 0), sourceMatrix.m30());
buffer.put(bufferIndex(3, 1), sourceMatrix.m31());
buffer.put(bufferIndex(3, 2), sourceMatrix.m32());
buffer.put(bufferIndex(3, 3), sourceMatrix.m33());
return buffer.array(); m20 = values[8];
} m21 = values[9];
m22 = values[10];
m23 = values[11];
/* Quaternions are not currently needed/implemented m30 = values[12];
public Matrix4float(Quaternion p_i48104_1_) m31 = values[13];
{ m32 = values[14];
float f = p_i48104_1_.i(); m33 = values[15];
float f1 = p_i48104_1_.j();
float f2 = p_i48104_1_.k();
float f3 = p_i48104_1_.r();
float f4 = 2.0F * f * f;
float f5 = 2.0F * f1 * f1;
float f6 = 2.0F * f2 * f2;
this.m00 = 1.0F - f5 - f6;
this.m11 = 1.0F - f6 - f4;
this.m22 = 1.0F - f4 - f5;
this.m33 = 1.0F;
float f7 = f * f1;
float f8 = f1 * f2;
float f9 = f2 * f;
float f10 = f * f3;
float f11 = f1 * f3;
float f12 = f2 * f3;
this.m10 = 2.0F * (f7 + f12);
this.m01 = 2.0F * (f7 - f12);
this.m20 = 2.0F * (f9 - f11);
this.m02 = 2.0F * (f9 + f11);
this.m21 = 2.0F * (f8 + f10);
this.m12 = 2.0F * (f8 - f10);
}
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && this.getClass() == obj.getClass())
{
Mat4f otherMatrix = (Mat4f) obj;
return Float.compare(otherMatrix.m00, this.m00) == 0
&& Float.compare(otherMatrix.m01, this.m01) == 0
&& Float.compare(otherMatrix.m02, this.m02) == 0
&& Float.compare(otherMatrix.m03, this.m03) == 0
&& Float.compare(otherMatrix.m10, this.m10) == 0
&& Float.compare(otherMatrix.m11, this.m11) == 0
&& Float.compare(otherMatrix.m12, this.m12) == 0
&& Float.compare(otherMatrix.m13, this.m13) == 0
&& Float.compare(otherMatrix.m20, this.m20) == 0
&& Float.compare(otherMatrix.m21, this.m21) == 0
&& Float.compare(otherMatrix.m22, this.m22) == 0
&& Float.compare(otherMatrix.m23, this.m23) == 0
&& Float.compare(otherMatrix.m30, this.m30) == 0
&& Float.compare(otherMatrix.m31, this.m31) == 0
&& Float.compare(otherMatrix.m32, this.m32) == 0
&& Float.compare(otherMatrix.m33, this.m33) == 0;
}
else
{
return false;
}
}
@Override
public int hashCode()
{
int i = this.m00 != 0.0F ? Float.floatToIntBits(this.m00) : 0;
i = 31 * i + (this.m01 != 0.0F ? Float.floatToIntBits(this.m01) : 0);
i = 31 * i + (this.m02 != 0.0F ? Float.floatToIntBits(this.m02) : 0);
i = 31 * i + (this.m03 != 0.0F ? Float.floatToIntBits(this.m03) : 0);
i = 31 * i + (this.m10 != 0.0F ? Float.floatToIntBits(this.m10) : 0);
i = 31 * i + (this.m11 != 0.0F ? Float.floatToIntBits(this.m11) : 0);
i = 31 * i + (this.m12 != 0.0F ? Float.floatToIntBits(this.m12) : 0);
i = 31 * i + (this.m13 != 0.0F ? Float.floatToIntBits(this.m13) : 0);
i = 31 * i + (this.m20 != 0.0F ? Float.floatToIntBits(this.m20) : 0);
i = 31 * i + (this.m21 != 0.0F ? Float.floatToIntBits(this.m21) : 0);
i = 31 * i + (this.m22 != 0.0F ? Float.floatToIntBits(this.m22) : 0);
i = 31 * i + (this.m23 != 0.0F ? Float.floatToIntBits(this.m23) : 0);
i = 31 * i + (this.m30 != 0.0F ? Float.floatToIntBits(this.m30) : 0);
i = 31 * i + (this.m31 != 0.0F ? Float.floatToIntBits(this.m31) : 0);
i = 31 * i + (this.m32 != 0.0F ? Float.floatToIntBits(this.m32) : 0);
return 31 * i + (this.m33 != 0.0F ? Float.floatToIntBits(this.m33) : 0);
} }
@Override
public String toString()
{
return "Matrix4f:\n" +
this.m00 + " " + this.m01 + " " + this.m02 + " " + this.m03 + "\n" +
this.m10 + " " + this.m11 + " " + this.m12 + " " + this.m13 + "\n" +
this.m20 + " " + this.m21 + " " + this.m22 + " " + this.m23 + "\n" +
this.m30 + " " + this.m31 + " " + this.m32 + " " + this.m33 + "\n";
}
public void store(FloatBuffer floatBuffer) //=========//
{ // methods //
floatBuffer.put(bufferIndex(0, 0), this.m00); //=========//
floatBuffer.put(bufferIndex(0, 1), this.m01);
floatBuffer.put(bufferIndex(0, 2), this.m02);
floatBuffer.put(bufferIndex(0, 3), this.m03);
floatBuffer.put(bufferIndex(1, 0), this.m10);
floatBuffer.put(bufferIndex(1, 1), this.m11);
floatBuffer.put(bufferIndex(1, 2), this.m12);
floatBuffer.put(bufferIndex(1, 3), this.m13);
floatBuffer.put(bufferIndex(2, 0), this.m20);
floatBuffer.put(bufferIndex(2, 1), this.m21);
floatBuffer.put(bufferIndex(2, 2), this.m22);
floatBuffer.put(bufferIndex(2, 3), this.m23);
floatBuffer.put(bufferIndex(3, 0), this.m30);
floatBuffer.put(bufferIndex(3, 1), this.m31);
floatBuffer.put(bufferIndex(3, 2), this.m32);
floatBuffer.put(bufferIndex(3, 3), this.m33);
}
public Matrix4f createJomlMatrix()
{
return new Matrix4f(
this.m00, this.m10, this.m20, this.m30,
this.m01, this.m11, this.m21, this.m31,
this.m02, this.m12, this.m22, this.m32,
this.m03, this.m13, this.m23, this.m33
);
}
private static int bufferIndex(int xIndex, int zIndex)
{
return (zIndex * 4) + xIndex;
}
public void setIdentity() public void setIdentity()
{ {
@@ -341,7 +223,7 @@ public class Mat4f
} }
} }
public void multiply(Mat4f multMatrix) public void multiply(DhApiMat4f multMatrix)
{ {
float f = this.m00 * multMatrix.m00 + this.m01 * multMatrix.m10 + this.m02 * multMatrix.m20 + this.m03 * multMatrix.m30; float f = this.m00 * multMatrix.m00 + this.m01 * multMatrix.m10 + this.m02 * multMatrix.m20 + this.m03 * multMatrix.m30;
float f1 = this.m00 * multMatrix.m01 + this.m01 * multMatrix.m11 + this.m02 * multMatrix.m21 + this.m03 * multMatrix.m31; float f1 = this.m00 * multMatrix.m01 + this.m01 * multMatrix.m11 + this.m02 * multMatrix.m21 + this.m03 * multMatrix.m31;
@@ -377,13 +259,6 @@ public class Mat4f
this.m33 = f15; this.m33 = f15;
} }
/* Quaternions aren't currently needed/implemented
public void multiply(Quaternion p_226596_1_)
{
this.multiply(new Matrix4f(p_226596_1_));
}
*/
public void multiply(float scalar) public void multiply(float scalar)
{ {
this.m00 *= scalar; this.m00 *= scalar;
@@ -404,81 +279,6 @@ public class Mat4f
this.m33 *= scalar; this.m33 *= scalar;
} }
public static Mat4f perspective(double fov, float widthHeightRatio, float nearClipPlane, float farClipPlane)
{
float f = (float) (1.0D / Math.tan(fov * ((float) Math.PI / 180F) / 2.0D));
Mat4f matrix = new Mat4f();
matrix.m00 = f / widthHeightRatio;
matrix.m11 = f;
matrix.m22 = (farClipPlane + nearClipPlane) / (nearClipPlane - farClipPlane);
matrix.m32 = -1.0F;
matrix.m23 = 2.0F * farClipPlane * nearClipPlane / (nearClipPlane - farClipPlane);
return matrix;
}
/* not currently needed/implemented
* Also the parameter names should be double checked as they may be incorrect
public static Matrix4Float orthographic(float left, float right, float top, float bottom)
{
Matrix4Float matrix4f = new Matrix4Float();
matrix4f.m00 = 2.0F / left;
matrix4f.m11 = 2.0F / right;
float f = bottom - top;
matrix4f.m22 = -2.0F / f;
matrix4f.m33 = 1.0F;
matrix4f.m03 = -1.0F;
matrix4f.m13 = -1.0F;
matrix4f.m23 = -(bottom + top) / f;
return matrix4f;
}
*/
/**
* TODO: what kind of translation is this?
* and how is this different from "multiplyTranslationMatrix"?
* Answer: This is faster and direct (but only if this is pure translation matrix without rotate)
*/
public void translate(Vec3f vec)
{
this.m03 += vec.x;
this.m13 += vec.y;
this.m23 += vec.z;
}
/** originally "translate" from Minecraft's MatrixStack */
public void multiplyTranslationMatrix(double x, double y, double z)
{
multiply(createTranslateMatrix((float) x, (float) y, (float) z));
}
public Mat4f copy()
{
return new Mat4f(this);
}
public static Mat4f createScaleMatrix(float x, float y, float z)
{
Mat4f matrix = new Mat4f();
matrix.m00 = x;
matrix.m11 = y;
matrix.m22 = z;
matrix.m33 = 1.0F;
return matrix;
}
public static Mat4f createTranslateMatrix(float x, float y, float z)
{
Mat4f matrix = new Mat4f();
matrix.m00 = 1.0F;
matrix.m11 = 1.0F;
matrix.m22 = 1.0F;
matrix.m33 = 1.0F;
matrix.m03 = x;
matrix.m13 = y;
matrix.m23 = z;
return matrix;
}
@@ -487,6 +287,8 @@ public class Mat4f
// methods // // methods //
//==================// //==================//
private static int getArrayIndex(int xIndex, int zIndex) { return (zIndex * 4) + xIndex; }
/** Returns the values of this matrix in row major order (AKA rows then columns) */ /** Returns the values of this matrix in row major order (AKA rows then columns) */
public float[] getValuesAsArray() public float[] getValuesAsArray()
{ {
@@ -513,113 +315,77 @@ public class Mat4f
}; };
} }
public Vec3f asNonNormalizedLookForwardVector()
//================//
// base overrides //
//================//
@Override
public boolean equals(Object obj)
{ {
return new Vec3f(this.m02, this.m12, this.m22); if (this == obj)
}
//===============//
// Forge methods //
//===============//
public Mat4f(float[] values)
{ {
m00 = values[0]; return true;
m01 = values[1];
m02 = values[2];
m03 = values[3];
m10 = values[4];
m11 = values[5];
m12 = values[6];
m13 = values[7];
m20 = values[8];
m21 = values[9];
m22 = values[10];
m23 = values[11];
m30 = values[12];
m31 = values[13];
m32 = values[14];
m33 = values[15];
} }
else if (obj != null && this.getClass() == obj.getClass())
public Mat4f(FloatBuffer buffer)
{ {
this(buffer.array()); DhApiMat4f otherMatrix = (DhApiMat4f) obj;
return Float.compare(otherMatrix.m00, this.m00) == 0
&& Float.compare(otherMatrix.m01, this.m01) == 0
&& Float.compare(otherMatrix.m02, this.m02) == 0
&& Float.compare(otherMatrix.m03, this.m03) == 0
&& Float.compare(otherMatrix.m10, this.m10) == 0
&& Float.compare(otherMatrix.m11, this.m11) == 0
&& Float.compare(otherMatrix.m12, this.m12) == 0
&& Float.compare(otherMatrix.m13, this.m13) == 0
&& Float.compare(otherMatrix.m20, this.m20) == 0
&& Float.compare(otherMatrix.m21, this.m21) == 0
&& Float.compare(otherMatrix.m22, this.m22) == 0
&& Float.compare(otherMatrix.m23, this.m23) == 0
&& Float.compare(otherMatrix.m30, this.m30) == 0
&& Float.compare(otherMatrix.m31, this.m31) == 0
&& Float.compare(otherMatrix.m32, this.m32) == 0
&& Float.compare(otherMatrix.m33, this.m33) == 0;
} }
else
public void set(Mat4f mat)
{ {
this.m00 = mat.m00; return false;
this.m01 = mat.m01; }
this.m02 = mat.m02;
this.m03 = mat.m03;
this.m10 = mat.m10;
this.m11 = mat.m11;
this.m12 = mat.m12;
this.m13 = mat.m13;
this.m20 = mat.m20;
this.m21 = mat.m21;
this.m22 = mat.m22;
this.m23 = mat.m23;
this.m30 = mat.m30;
this.m31 = mat.m31;
this.m32 = mat.m32;
this.m33 = mat.m33;
} }
public void add(Mat4f other) @Override
public int hashCode()
{ {
m00 += other.m00; int i = this.m00 != 0.0F ? Float.floatToIntBits(this.m00) : 0;
m01 += other.m01; i = 31 * i + (this.m01 != 0.0F ? Float.floatToIntBits(this.m01) : 0);
m02 += other.m02; i = 31 * i + (this.m02 != 0.0F ? Float.floatToIntBits(this.m02) : 0);
m03 += other.m03; i = 31 * i + (this.m03 != 0.0F ? Float.floatToIntBits(this.m03) : 0);
m10 += other.m10; i = 31 * i + (this.m10 != 0.0F ? Float.floatToIntBits(this.m10) : 0);
m11 += other.m11; i = 31 * i + (this.m11 != 0.0F ? Float.floatToIntBits(this.m11) : 0);
m12 += other.m12; i = 31 * i + (this.m12 != 0.0F ? Float.floatToIntBits(this.m12) : 0);
m13 += other.m13; i = 31 * i + (this.m13 != 0.0F ? Float.floatToIntBits(this.m13) : 0);
m20 += other.m20; i = 31 * i + (this.m20 != 0.0F ? Float.floatToIntBits(this.m20) : 0);
m21 += other.m21; i = 31 * i + (this.m21 != 0.0F ? Float.floatToIntBits(this.m21) : 0);
m22 += other.m22; i = 31 * i + (this.m22 != 0.0F ? Float.floatToIntBits(this.m22) : 0);
m23 += other.m23; i = 31 * i + (this.m23 != 0.0F ? Float.floatToIntBits(this.m23) : 0);
m30 += other.m30; i = 31 * i + (this.m30 != 0.0F ? Float.floatToIntBits(this.m30) : 0);
m31 += other.m31; i = 31 * i + (this.m31 != 0.0F ? Float.floatToIntBits(this.m31) : 0);
m32 += other.m32; i = 31 * i + (this.m32 != 0.0F ? Float.floatToIntBits(this.m32) : 0);
m33 += other.m33; return 31 * i + (this.m33 != 0.0F ? Float.floatToIntBits(this.m33) : 0);
} }
public void multiplyBackward(Mat4f other) @Override
public String toString()
{ {
Mat4f copy = other.copy(); return "Matrix4f:\n" +
copy.multiply(this); this.m00 + " " + this.m01 + " " + this.m02 + " " + this.m03 + "\n" +
this.set(copy); this.m10 + " " + this.m11 + " " + this.m12 + " " + this.m13 + "\n" +
this.m20 + " " + this.m21 + " " + this.m22 + " " + this.m23 + "\n" +
this.m30 + " " + this.m31 + " " + this.m32 + " " + this.m33 + "\n";
} }
public void setTranslation(float x, float y, float z) @Override
{ public DhApiMat4f copy() { return new DhApiMat4f(this); }
this.m00 = 1.0F;
this.m11 = 1.0F;
this.m22 = 1.0F;
this.m33 = 1.0F;
this.m03 = x;
this.m13 = y;
this.m23 = z;
}
/**
* Changes the values that store the clipping planes.
* Formula for calculating matrix values is the same that OpenGL uses when making matrices.
*
* @param nearClip New near clipping plane value.
* @param farClip New far clipping plane value.
*/
public void setClipPlanes(float nearClip, float farClip)
{
//convert to matrix values, formula copied from a textbook / openGL specification.
float matNearClip = -((farClip + nearClip) / (farClip - nearClip));
float matFarClip = -((2 * farClip * nearClip) / (farClip - nearClip));
//set new values for the clip planes.
this.m22 = matNearClip;
this.m23 = matFarClip;
}
} }
@@ -0,0 +1,94 @@
/*
* 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.api.objects.math;
/**
* Often used to store block positions or any other
* position in 3D space.
*
* @author James Seibel
* @version 2024-7-9
* @since API 3.0.0
*/
public class DhApiVec3d
{
public double x;
public double y;
public double z;
/** creates a Vec3 at (0,0,0) */
public DhApiVec3d()
{
this.x = 0;
this.y = 0;
this.z = 0;
}
public DhApiVec3d(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && this.getClass() == obj.getClass())
{
DhApiVec3d Vec3d = (DhApiVec3d) obj;
if (Double.compare(Vec3d.x, this.x) != 0)
{
return false;
}
else if (Double.compare(Vec3d.y, this.y) != 0)
{
return false;
}
else
{
return Double.compare(Vec3d.z, this.z) == 0;
}
}
else
{
return false;
}
}
@Override
public int hashCode()
{
long i = Double.doubleToLongBits(this.x);
i = 31 * i + Double.doubleToLongBits(this.y);
i = 31 * i + Double.doubleToLongBits(this.z);
return Long.hashCode(i);
}
@Override
public String toString() { return "[" + this.x + ", " + this.y + ", " + this.z + "]"; }
}
@@ -0,0 +1,98 @@
/*
* 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.api.objects.math;
import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable;
/**
* Often used to store block positions or any other
* position in 3D space.
*
* @author James Seibel
* @version 2024-6-3
* @since API 2.2.0
*/
public class DhApiVec3f implements IDhApiCopyable
{
public float x;
public float y;
public float z;
/** creates a Vec3 at (0,0,0) */
public DhApiVec3f()
{
this.x = 0;
this.y = 0;
this.z = 0;
}
public DhApiVec3f(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && this.getClass() == obj.getClass())
{
DhApiVec3f Vec3f = (DhApiVec3f) obj;
if (Float.compare(Vec3f.x, this.x) != 0)
{
return false;
}
else if (Float.compare(Vec3f.y, this.y) != 0)
{
return false;
}
else
{
return Float.compare(Vec3f.z, this.z) == 0;
}
}
else
{
return false;
}
}
@Override
public int hashCode()
{
int i = Float.floatToIntBits(this.x);
i = 31 * i + Float.floatToIntBits(this.y);
return 31 * i + Float.floatToIntBits(this.z);
}
@Override
public String toString() { return "[" + this.x + ", " + this.y + ", " + this.z + "]"; }
@Override
public DhApiVec3f copy() { return new DhApiVec3f(this.x, this.y, this.z); }
}
@@ -0,0 +1,52 @@
package com.seibel.distanthorizons.api.objects.render;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
import java.awt.*;
/**
* @see IDhApiRenderableBoxGroup
*
* @author James Seibel
* @version 2024-6-30
* @since API 3.0.0
*/
public class DhApiRenderableBox
{
/** the position closest to (-inf,-inf) */
public DhApiVec3d minPos;
/** the position closest to (+inf,+inf) */
public DhApiVec3d maxPos;
public Color color;
public byte material;
//==============//
// constructors //
//==============//
public DhApiRenderableBox(DhApiVec3d minPos, float width, Color color, EDhApiBlockMaterial material)
{
this(minPos, new DhApiVec3d(
minPos.x + width,
minPos.y + width,
minPos.z + width
), color, material);
}
public DhApiRenderableBox(DhApiVec3d minPos, DhApiVec3d maxPos, Color color, EDhApiBlockMaterial material)
{
this.minPos = minPos;
this.maxPos = maxPos;
this.color = color;
this.material = material.index;
}
}
@@ -0,0 +1,93 @@
package com.seibel.distanthorizons.api.objects.render;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
import java.awt.*;
/**
* @see IDhApiRenderableBoxGroup
*
* Shading values are multiplied against the color for each direction,
* for example: <br>
* A shading value of 1.0 indicates the color is unchanged. <br>
* A shading value of 0.0 changes the color to black. <br>
*
* @author James Seibel
* @version 2024-7-7
* @since API 3.0.0
*/
public class DhApiRenderableBoxGroupShading
{
/** negative X */
public float north = 1.0f;
/** positive X */
public float south = 1.0f;
/** positive X */
public float east = 1.0f;
/** negative X */
public float west = 1.0f;
/** positive Y */
public float top = 1.0f;
/** negative Y */
public float bottom = 1.0f;
//==============//
// constructors //
//==============//
public static DhApiRenderableBoxGroupShading getDefaultShaded()
{
DhApiRenderableBoxGroupShading shading = new DhApiRenderableBoxGroupShading();
shading.setDefaultShaded();
return shading;
}
public static DhApiRenderableBoxGroupShading getUnshaded()
{
DhApiRenderableBoxGroupShading shading = new DhApiRenderableBoxGroupShading();
shading.setUnshaded();
return shading;
}
//=========//
// methods //
//=========//
/**
* Directions will have different brightness similar to Minecraft blocks. <br>
* This is a good default for un-lit objects.
*/
public void setDefaultShaded()
{
this.north = 0.8f;
this.south = 0.8f;
this.east = 0.6f;
this.west = 0.6f;
this.top = 1.0f;
this.bottom = 0.5f;
}
/**
* All directions render with the same brightness. <br>
* This is best used for glowing objects like beacons.
*/
public void setUnshaded()
{
this.north = 1.0f;
this.south = 1.0f;
this.east = 1.0f;
this.west = 1.0f;
this.top = 1.0f;
this.bottom = 1.0f;
}
}
@@ -22,6 +22,7 @@ package com.seibel.distanthorizons.coreapi.DependencyInjection;
import com.seibel.distanthorizons.api.interfaces.events.IDhApiEventInjector; import com.seibel.distanthorizons.api.interfaces.events.IDhApiEventInjector;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiCancelableEvent; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiCancelableEvent;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiOneTimeEvent; import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiOneTimeEvent;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
@@ -140,7 +141,26 @@ public class ApiEventInjector extends DependencyInjector<IDhApiEvent> implements
// fire each event and record if any of them // fire each event and record if any of them
// request to cancel the event. // request to cancel the event.
DhApiEventParam<T> eventParam = createEventParamWrapper(event, eventInput);
// attempt to clone the event input if possible
// this is done to reduce the likely hood that one event listener
// will make change the event parameter for other listeners
T input = eventInput;
if (eventInput instanceof IDhApiEventParam)
{
try
{
//noinspection unchecked
input = (T) ((IDhApiEventParam) eventInput).copy();
}
catch (Exception e)
{
LOGGER.error("Unable to clone event parameter ["+eventInput.getClass().getSimpleName()+"], error: ["+e.getMessage()+"].", e);
}
}
DhApiEventParam<T> eventParam = createEventParamWrapper(event, input);
event.fireEvent(eventParam); event.fireEvent(eventParam);
if (eventParam instanceof DhApiCancelableEventParam) if (eventParam instanceof DhApiCancelableEventParam)
@@ -34,16 +34,16 @@ public final class ModInfo
public static final String NAME = "DistantHorizons"; public static final String NAME = "DistantHorizons";
/** Human-readable version of NAME */ /** Human-readable version of NAME */
public static final String READABLE_NAME = "Distant Horizons"; public static final String READABLE_NAME = "Distant Horizons";
public static final String VERSION = "2.0.4-a-dev"; public static final String VERSION = "2.2.1-a";
/** Returns true if the current build is an unstable developer build, false otherwise. */ /** Returns true if the current build is an unstable developer build, false otherwise. */
public static boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev"); public static boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev");
/** This version should only be updated when breaking changes are introduced to the DH API */ /** This version should only be updated when breaking changes are introduced to the DH API */
public static final int API_MAJOR_VERSION = 1; public static final int API_MAJOR_VERSION = 3;
/** This version should be updated whenever new methods are added to the DH API */ /** This version should be updated whenever new methods are added to the DH API */
public static final int API_MINOR_VERSION = 1; public static final int API_MINOR_VERSION = 0;
/** This version should be updated whenever non-breaking fixes are added to the DH API */ /** This version should be updated whenever non-breaking fixes are added to the DH API */
public static final int API_PATH_VERSION = 0; public static final int API_PATCH_VERSION = 1;
public static final String NETWORKING_RESOURCE_NAMESPACE = "distant_horizons"; public static final String NETWORKING_RESOURCE_NAMESPACE = "distant_horizons";
public static final String MULTIVERSE_PLUGIN_NAMESPACE = "world_control"; public static final String MULTIVERSE_PLUGIN_NAMESPACE = "world_control";
@@ -67,10 +67,11 @@ public interface IConfigEntry<T>
* Checks if the option is valid * Checks if the option is valid
* *
* 0 == valid * 0 == valid
* 2 == invalid
* 1 == number too high * 1 == number too high
* -1 == number too low * -1 == number too low
*/ */
byte isValid(); byte isValid(); // TODO replace with an enum
/** Checks if a value is valid */ /** Checks if a value is valid */
byte isValid(T value); byte isValid(T value);
@@ -24,12 +24,12 @@ import java.util.Arrays;
/** /**
* Miscellaneous string helper functions. * Miscellaneous string helper functions.
*
* @author James Seibel
* @version 2022-7-19
*/ */
public class StringUtil public class StringUtil
{ {
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
/** /**
* Returns the n-th index of the given string. <br> <br> * Returns the n-th index of the given string. <br> <br>
* *
@@ -67,8 +67,6 @@ public class StringUtil
return stringBuilder.toString(); return stringBuilder.toString();
} }
private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
/** /**
* Converts the given byte array into a hex string representation. <br> * Converts the given byte array into a hex string representation. <br>
* source: https://stackoverflow.com/a/9855338 * source: https://stackoverflow.com/a/9855338
@@ -85,4 +83,20 @@ public class StringUtil
return new String(hexChars); return new String(hexChars);
} }
/**
* Returns a shortened version of the given string that is no longer than maxLength. <br>
* If null returns the empty string.
*/
public static String shortenString(String str, int maxLength)
{
if (str == null)
{
return "";
}
else
{
return str.substring(0, Math.min(str.length(), maxLength));
}
}
} }
@@ -1,263 +0,0 @@
/*
* 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.coreapi.util.math;
import com.seibel.distanthorizons.coreapi.util.MathUtil;
/**
* A (almost) exact copy of Minecraft's 1.16.5
* implementation of a 3 element float vector.
*
* @author James Seibel
* @version 11-11-2021
*/
public class Vec3f
{
public static Vec3f XNeg = new Vec3f(-1.0F, 0.0F, 0.0F);
public static Vec3f XPos = new Vec3f(1.0F, 0.0F, 0.0F);
public static Vec3f YNeg = new Vec3f(0.0F, -1.0F, 0.0F);
public static Vec3f YPos = new Vec3f(0.0F, 1.0F, 0.0F);
public static Vec3f ZNeg = new Vec3f(0.0F, 0.0F, -1.0F);
public static Vec3f ZPos = new Vec3f(0.0F, 0.0F, 1.0F);
public float x;
public float y;
public float z;
public Vec3f()
{
}
public Vec3f(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
else if (obj != null && this.getClass() == obj.getClass())
{
Vec3f Vec3f = (Vec3f) obj;
if (Float.compare(Vec3f.x, this.x) != 0)
{
return false;
}
else if (Float.compare(Vec3f.y, this.y) != 0)
{
return false;
}
else
{
return Float.compare(Vec3f.z, this.z) == 0;
}
}
else
{
return false;
}
}
@Override
public int hashCode()
{
int i = Float.floatToIntBits(this.x);
i = 31 * i + Float.floatToIntBits(this.y);
return 31 * i + Float.floatToIntBits(this.z);
}
public void mul(float scalar)
{
this.x *= scalar;
this.y *= scalar;
this.z *= scalar;
}
public void mul(float x, float y, float z)
{
this.x *= x;
this.y *= y;
this.z *= z;
}
public void clamp(float min, float max)
{
this.x = MathUtil.clamp(min, this.x, max);
this.y = MathUtil.clamp(min, this.y, max);
this.z = MathUtil.clamp(min, this.z, max);
}
public void set(float x, float y, float z)
{
this.x = x;
this.y = y;
this.z = z;
}
public void add(float x, float y, float z)
{
this.x += x;
this.y += y;
this.z += z;
}
public void add(Vec3f vector)
{
this.x += vector.x;
this.y += vector.y;
this.z += vector.z;
}
public void subtract(Vec3f vector)
{
this.x -= vector.x;
this.y -= vector.y;
this.z -= vector.z;
}
public float dotProduct(Vec3f vector)
{
return this.x * vector.x + this.y * vector.y + this.z * vector.z;
}
/** Returns true if normalization had to be done */
public boolean normalize()
{
float squaredSum = this.x * this.x + this.y * this.y + this.z * this.z;
if (squaredSum < 1.0E-5D)
{
return false;
}
else
{
float f1 = MathUtil.fastInvSqrt(squaredSum);
this.x *= f1;
this.y *= f1;
this.z *= f1;
return true;
}
}
public void crossProduct(Vec3f vector)
{
float f = this.x;
float f1 = this.y;
float f2 = this.z;
float f3 = vector.x;
float f4 = vector.y;
float f5 = vector.z;
this.x = f1 * f5 - f2 * f4;
this.y = f2 * f3 - f * f5;
this.z = f * f4 - f1 * f3;
}
/* Matrix3f is not currently needed/implemented
public void transform(Matrix3f p_229188_1_)
{
float f = this.x;
float f1 = this.y;
float f2 = this.z;
this.x = p_229188_1_.m00 * f + p_229188_1_.m01 * f1 + p_229188_1_.m02 * f2;
this.y = p_229188_1_.m10 * f + p_229188_1_.m11 * f1 + p_229188_1_.m12 * f2;
this.z = p_229188_1_.m20 * f + p_229188_1_.m21 * f1 + p_229188_1_.m22 * f2;
}
*/
/* Quaternions are not currently needed/implemented
public void transform(Quaternion p_214905_1_)
{
Quaternion quaternion = new Quaternion(p_214905_1_);
quaternion.mul(new Quaternion(this.x(), this.y(), this.z(), 0.0F));
Quaternion quaternion1 = new Quaternion(p_214905_1_);
quaternion1.conj();
quaternion.mul(quaternion1);
this.set(quaternion.i(), quaternion.j(), quaternion.k());
}
*/
/* not currently needed
* percent may actually be partial ticks (which is available when rendering)
public void linearInterp(Vec3f resultingVector, float percent)
{
float f = 1.0F - percent;
this.x = this.x * f + resultingVector.x * percent;
this.y = this.y * f + resultingVector.y * percent;
this.z = this.z * f + resultingVector.z * percent;
}
*/
/* Quaternions are not currently needed/implemented
public Quaternion rotation(float p_229193_1_)
{
return new Quaternion(this, p_229193_1_, false);
}
@OnlyIn(Dist.CLIENT)
public Quaternion rotationDegrees(float p_229187_1_)
{
return new Quaternion(this, p_229187_1_, true);
}
*/
public Vec3f copy()
{
return new Vec3f(this.x, this.y, this.z);
}
/* not currently needed/implemented
public void map(Float2FloatFunction p_229191_1_)
{
this.x = p_229191_1_.get(this.x);
this.y = p_229191_1_.get(this.y);
this.z = p_229191_1_.get(this.z);
}
*/
@Override
public String toString()
{
return "[" + this.x + ", " + this.y + ", " + this.z + "]";
}
// Forge start
public Vec3f(float[] values)
{
set(values);
}
public void set(float[] values)
{
this.x = values[0];
this.y = values[1];
this.z = values[2];
}
}
+2 -2
View File
@@ -1,6 +1,6 @@
plugins { plugins {
id "java" id "java"
id "com.github.johnrengelman.shadow" version '7.1.2' apply false // Set this to true if you're using the standalone Core project id "com.github.johnrengelman.shadow" version '8.1.1' apply false // Set this to true if you're using the standalone Core project
} }
apply plugin: "application" apply plugin: "application"
@@ -57,7 +57,7 @@ artifacts {
} }
shadowJar { shadowJar {
def librariesLocation = "distanthorizons.libraries" def librariesLocation = "DistantHorizons.libraries"
// relocate "it.unimi.dsi.fastutil", "${librariesLocation}.unimi.dsi.fastutil" // relocate "it.unimi.dsi.fastutil", "${librariesLocation}.unimi.dsi.fastutil"
mergeServiceFiles() mergeServiceFiles()
} }
@@ -20,6 +20,7 @@
package com.seibel.distanthorizons.core; package com.seibel.distanthorizons.core;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory;
import com.seibel.distanthorizons.core.sql.DatabaseUpdater; import com.seibel.distanthorizons.core.sql.DatabaseUpdater;
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
@@ -93,6 +94,7 @@ public class Initializer
DhApi.Delayed.terrainRepo = DhApiTerrainDataRepo.INSTANCE; DhApi.Delayed.terrainRepo = DhApiTerrainDataRepo.INSTANCE;
DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE; DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE;
DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE; DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE;
DhApi.Delayed.customRenderObjectFactory = GenericRenderObjectFactory.INSTANCE;
DhApi.Delayed.wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class); DhApi.Delayed.wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
if (DhApi.Delayed.wrapperFactory == null) if (DhApi.Delayed.wrapperFactory == null)
{ {
@@ -42,8 +42,6 @@ public class DhApiConfig implements IDhApiConfig
@Override @Override
public IDhApiMultiThreadingConfig multiThreading() { return DhApiMultiThreadingConfig.INSTANCE; } public IDhApiMultiThreadingConfig multiThreading() { return DhApiMultiThreadingConfig.INSTANCE; }
@Override @Override
public IDhApiGpuBuffersConfig gpuBuffers() { return DhApiGpuBuffersConfig.INSTANCE; }
@Override
public IDhApiDebuggingConfig debugging() { return DhApiDebuggingConfig.INSTANCE; } public IDhApiDebuggingConfig debugging() { return DhApiDebuggingConfig.INSTANCE; }
} }
@@ -20,23 +20,27 @@
package com.seibel.distanthorizons.core.api.external.methods.config.client; package com.seibel.distanthorizons.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGpuBuffersConfig; import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGenericRenderingConfig;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiNoiseTextureConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
public class DhApiGpuBuffersConfig implements IDhApiGpuBuffersConfig public class DhApiGenericRenderingConfig implements IDhApiGenericRenderingConfig
{ {
public static DhApiGpuBuffersConfig INSTANCE = new DhApiGpuBuffersConfig(); public static DhApiGenericRenderingConfig INSTANCE = new DhApiGenericRenderingConfig();
private DhApiGpuBuffersConfig() { } private DhApiGenericRenderingConfig() { }
public IDhApiConfigValue<EDhApiGpuUploadMethod> gpuUploadMethod() @Override
{ return new DhApiConfigValue<>(Config.Client.Advanced.GpuBuffers.gpuUploadMethod); } public IDhApiConfigValue<Boolean> renderingEnabled()
{ return new DhApiConfigValue<Boolean, Boolean>(Config.Client.Advanced.Graphics.GenericRendering.enableRendering); }
public IDhApiConfigValue<Integer> gpuUploadPerMegabyteInMilliseconds() @Override
{ return new DhApiConfigValue<>(Config.Client.Advanced.GpuBuffers.gpuUploadPerMegabyteInMilliseconds); } public IDhApiConfigValue<Boolean> beaconRenderingEnabled()
{ return new DhApiConfigValue<Boolean, Boolean>(Config.Client.Advanced.Graphics.GenericRendering.enableBeaconRendering); }
@Override
public IDhApiConfigValue<Boolean> cloudRenderingEnabled()
{ return new DhApiConfigValue<Boolean, Boolean>(Config.Client.Advanced.Graphics.GenericRendering.enableCloudRendering); }
} }
@@ -22,10 +22,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.enums.config.*; import com.seibel.distanthorizons.api.enums.config.*;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiTransparency; import com.seibel.distanthorizons.api.enums.rendering.EDhApiTransparency;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue; import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiAmbientOcclusionConfig; import com.seibel.distanthorizons.api.interfaces.config.client.*;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiFogConfig;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGraphicsConfig;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiNoiseTextureConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue; import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode; import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode;
import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.config.Config;
@@ -42,9 +39,14 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig
// inner layers // // inner layers //
//==============// //==============//
@Override
public IDhApiFogConfig fog() { return DhApiFogConfig.INSTANCE; } public IDhApiFogConfig fog() { return DhApiFogConfig.INSTANCE; }
@Override
public IDhApiAmbientOcclusionConfig ambientOcclusion() { return DhApiAmbientOcclusionConfig.INSTANCE; } public IDhApiAmbientOcclusionConfig ambientOcclusion() { return DhApiAmbientOcclusionConfig.INSTANCE; }
@Override
public IDhApiNoiseTextureConfig noiseTexture() { return DhApiNoiseTextureConfig.INSTANCE; } public IDhApiNoiseTextureConfig noiseTexture() { return DhApiNoiseTextureConfig.INSTANCE; }
@Override
public IDhApiGenericRenderingConfig genericRendering() { return DhApiGenericRenderingConfig.INSTANCE; }
@@ -0,0 +1,87 @@
package com.seibel.distanthorizons.core.api.external.methods.data;
import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataCache;
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongSet;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import java.lang.ref.SoftReference;
public class DhApiTerrainDataCache implements IDhApiTerrainDataCache
{
private final Object modificationLock = new Object();
private Long2ReferenceOpenHashMap<SoftReference<FullDataSourceV2>> posToFullDataRef = new Long2ReferenceOpenHashMap<>();
private static final Logger LOGGER = LogManager.getLogger(DhApiTerrainDataCache.class.getSimpleName());
//==================//
// internal methods //
//==================//
public void add(long pos, FullDataSourceV2 dataSource)
{
synchronized (this.modificationLock)
{
this.posToFullDataRef.put(pos, new SoftReference<>(dataSource));
}
}
@Nullable
public FullDataSourceV2 get(long pos)
{
synchronized (this.modificationLock)
{
SoftReference<FullDataSourceV2> ref = this.posToFullDataRef.get(pos);
if (ref != null)
{
return ref.get();
}
else
{
return null;
}
}
}
//=============//
// API methods //
//=============//
@Override
public void clear()
{
synchronized (this.modificationLock)
{
LongSet keySet = this.posToFullDataRef.keySet();
for (long pos : keySet)
{
SoftReference<FullDataSourceV2> dataRef = this.posToFullDataRef.remove(pos);
if (dataRef != null)
{
FullDataSourceV2 dataSource = dataRef.get();
if (dataSource != null)
{
try
{
dataSource.close();
}
catch (Exception e)
{
LOGGER.warn("Unable to close data source, error: [" + e.getMessage() + "].", e);
}
}
}
}
}
}
}
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.core.api.external.methods.data; package com.seibel.distanthorizons.core.api.external.methods.data;
import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataCache;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper; import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.objects.DhApiResult; import com.seibel.distanthorizons.api.objects.DhApiResult;
import com.seibel.distanthorizons.api.objects.data.DhApiRaycastResult; import com.seibel.distanthorizons.api.objects.data.DhApiRaycastResult;
@@ -35,6 +36,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.util.FullDataPointUtil; import com.seibel.distanthorizons.core.util.FullDataPointUtil;
import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.RayCastUtil; import com.seibel.distanthorizons.core.util.RayCastUtil;
import com.seibel.distanthorizons.core.util.math.Vec3f;
import com.seibel.distanthorizons.core.world.AbstractDhWorld; import com.seibel.distanthorizons.core.world.AbstractDhWorld;
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory; import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
@@ -43,12 +45,12 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRen
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil; import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
import com.seibel.distanthorizons.coreapi.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3d;
import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import com.seibel.distanthorizons.core.util.math.Vec3i;
import com.seibel.distanthorizons.coreapi.util.math.Vec3i;
import it.unimi.dsi.fastutil.longs.LongArrayList; import it.unimi.dsi.fastutil.longs.LongArrayList;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
@@ -56,9 +58,6 @@ import java.util.concurrent.ExecutionException;
/** /**
* Allows interfacing with the terrain data Distant Horizons has stored. * Allows interfacing with the terrain data Distant Horizons has stored.
*
* @author James Seibel
* @version 2022-11-19
*/ */
public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
{ {
@@ -68,12 +67,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
// debugging values // debugging values
private static volatile boolean debugThreadRunning = false; private static volatile boolean debugThreadRunning = false;
private static String currentDebugBiomeName = ""; private static DhApiTerrainDataCache debugDataCache = new DhApiTerrainDataCache();
private static int currentDebugBlockColorInt = -1;
private static DhApiVec3i currentDebugVec3i = new Vec3i(); private static DhApiVec3i currentDebugVec3i = new Vec3i();
//=============//
// constructor //
//=============//
private DhApiTerrainDataRepo() private DhApiTerrainDataRepo()
{ {
@@ -86,41 +88,32 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
//================// //================//
@Override @Override
public DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ) public DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ, @Nullable IDhApiTerrainDataCache dataCache)
{ { return getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY, dataCache); }
return getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY);
}
@Override @Override
public DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ) public DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ, @Nullable IDhApiTerrainDataCache dataCache)
{ { return getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null, dataCache); }
return getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null);
}
@Override @Override
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ) public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ, @Nullable IDhApiTerrainDataCache dataCache)
{ { return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPosX, chunkPosZ), dataCache); }
return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPosX, chunkPosZ));
}
@Override @Override
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ) public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ, @Nullable IDhApiTerrainDataCache dataCache)
{ { return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ), dataCache); }
return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ));
}
@Override @Override
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ) public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ, @Nullable IDhApiTerrainDataCache dataCache)
{ { return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(detailLevel, posX, posZ), dataCache); }
return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(detailLevel, posX, posZ));
}
// private getters // // private getters //
/** Returns a single API terrain datapoint that contains the given Y block position */ /** Returns a single API terrain datapoint that contains the given Y block position */
private static DhApiResult<DhApiTerrainDataPoint> getTerrainDataAtBlockYPos(IDhApiLevelWrapper levelWrapper, DhLodPos requestedColumnPos, Integer blockYPos) private static DhApiResult<DhApiTerrainDataPoint> getTerrainDataAtBlockYPos(IDhApiLevelWrapper levelWrapper, DhLodPos requestedColumnPos, Integer blockYPos, @Nullable IDhApiTerrainDataCache dataCache)
{ {
DhApiResult<DhApiTerrainDataPoint[]> result = getTerrainDataColumnArray(levelWrapper, requestedColumnPos, blockYPos); DhApiResult<DhApiTerrainDataPoint[]> result = getTerrainDataColumnArray(levelWrapper, requestedColumnPos, blockYPos, dataCache);
if (result.success && result.payload.length > 0) if (result.success && result.payload.length > 0)
{ {
return DhApiResult.createSuccess(result.message, result.payload[0]); return DhApiResult.createSuccess(result.message, result.payload[0]);
@@ -140,7 +133,9 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
* *
* will stop and return the in progress data if any errors are encountered. * will stop and return the in progress data if any errors are encountered.
*/ */
private static DhApiResult<DhApiTerrainDataPoint[][][]> getTerrainDataOverAreaForPositionDetailLevel(IDhApiLevelWrapper levelWrapper, DhLodPos requestedAreaPos) private static DhApiResult<DhApiTerrainDataPoint[][][]> getTerrainDataOverAreaForPositionDetailLevel(
IDhApiLevelWrapper levelWrapper, DhLodPos requestedAreaPos,
@Nullable IDhApiTerrainDataCache dataCache)
{ {
DhLodPos startingBlockPos = requestedAreaPos.getCornerLodPos(LodUtil.BLOCK_DETAIL_LEVEL); DhLodPos startingBlockPos = requestedAreaPos.getCornerLodPos(LodUtil.BLOCK_DETAIL_LEVEL);
int widthOfAreaInBlocks = BitShiftUtil.powerOfTwo(requestedAreaPos.detailLevel); int widthOfAreaInBlocks = BitShiftUtil.powerOfTwo(requestedAreaPos.detailLevel);
@@ -154,7 +149,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
for (int z = 0; z < widthOfAreaInBlocks; z++) for (int z = 0; z < widthOfAreaInBlocks; z++)
{ {
DhLodPos blockColumnPos = new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, startingBlockPos.x + x, startingBlockPos.z + z); DhLodPos blockColumnPos = new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, startingBlockPos.x + x, startingBlockPos.z + z);
DhApiResult<DhApiTerrainDataPoint[]> result = getTerrainDataColumnArray(levelWrapper, blockColumnPos, null); DhApiResult<DhApiTerrainDataPoint[]> result = getTerrainDataColumnArray(levelWrapper, blockColumnPos, null, dataCache);
if (result.success) if (result.success)
{ {
returnArray[x][z] = result.payload; returnArray[x][z] = result.payload;
@@ -177,8 +172,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
* If the ApiResult is successful there will be an array of data. <br> * If the ApiResult is successful there will be an array of data. <br>
* The returned array will be empty if no data could be retrieved. * The returned array will be empty if no data could be retrieved.
*/ */
private static DhApiResult<DhApiTerrainDataPoint[]> getTerrainDataColumnArray(IDhApiLevelWrapper levelWrapper, DhLodPos requestedColumnPos, Integer nullableBlockYPos) private static DhApiResult<DhApiTerrainDataPoint[]> getTerrainDataColumnArray(
IDhApiLevelWrapper levelWrapper,
DhLodPos requestedColumnPos, Integer nullableBlockYPos,
@Nullable IDhApiTerrainDataCache apiDataCache)
{ {
//============//
// validation //
//============//
AbstractDhWorld currentWorld = SharedApi.getAbstractDhWorld(); AbstractDhWorld currentWorld = SharedApi.getAbstractDhWorld();
if (currentWorld == null) if (currentWorld == null)
{ {
@@ -194,6 +196,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
ILevelWrapper coreLevelWrapper = (ILevelWrapper) levelWrapper; ILevelWrapper coreLevelWrapper = (ILevelWrapper) levelWrapper;
if (!(apiDataCache instanceof DhApiTerrainDataCache))
{
// custom level wrappers aren't supported,
// the API user must get a level wrapper from our code somewhere
return DhApiResult.createFail("Unsupported [" + IDhApiTerrainDataCache.class.getSimpleName() + "] implementation, only the core class [" + DhApiTerrainDataCache.class.getSimpleName() + "] is a valid parameter.");
}
DhApiTerrainDataCache dataCache = (DhApiTerrainDataCache) apiDataCache;
IDhLevel level = currentWorld.getLevel(coreLevelWrapper); IDhLevel level = currentWorld.getLevel(coreLevelWrapper);
if (level == null) if (level == null)
{ {
@@ -209,17 +220,38 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
DhLodPos relativePos = requestedColumnPos.getDhSectionRelativePositionForDetailLevel(); DhLodPos relativePos = requestedColumnPos.getDhSectionRelativePositionForDetailLevel();
//=====================//
// get the data source //
//=====================//
try try
{
FullDataSourceV2 dataSource = null;
// try using the cached data if possible
if (dataCache != null)
{
dataSource = dataCache.get(sectionPos);
}
if (dataSource == null)
{ {
// attempt to get/generate the data source for this section // attempt to get/generate the data source for this section
FullDataSourceV2 dataSource = level.getFullDataProvider().getAsync(sectionPos).get(); dataSource = level.getFullDataProvider().getAsync(sectionPos).get();
if (dataSource == null) if (dataSource == null)
{ {
return DhApiResult.createFail("Unable to find/generate any data at the " + DhSectionPos.class.getSimpleName() + " [" + DhSectionPos.toString(sectionPos) + "]."); return DhApiResult.createFail("Unable to find/generate any data at the " + DhSectionPos.class.getSimpleName() + " [" + DhSectionPos.toString(sectionPos) + "].");
} }
else dataCache.add(sectionPos, dataSource);
{ }
// attempt to get the LOD data from the data source
//===============================//
// get LOD data from data source //
//===============================//
FullDataPointIdMap mapping = dataSource.mapping; FullDataPointIdMap mapping = dataSource.mapping;
LongArrayList dataColumn = dataSource.get(relativePos.x, relativePos.z); LongArrayList dataColumn = dataSource.get(relativePos.x, relativePos.z);
if (dataColumn != null) if (dataColumn != null)
@@ -271,8 +303,13 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
// the requested data wasn't present in this column (and/or the column wasn't able to be accessed/generated) // the requested data wasn't present in this column (and/or the column wasn't able to be accessed/generated)
return DhApiResult.createSuccess(new DhApiTerrainDataPoint[0]); return DhApiResult.createSuccess(new DhApiTerrainDataPoint[0]);
} }
}
catch (InterruptedException | ExecutionException e) catch (InterruptedException | ExecutionException e)
{
// shouldn't normally happen, but just in case
LOGGER.error("getTerrainDataColumnArray operation canceled. Error: [" + e.getMessage() + "]", e);
return DhApiResult.createFail("Operation cancled before it could complete: [" + e.getMessage() + "].");
}
catch (Exception e)
{ {
// shouldn't normally happen, but just in case // shouldn't normally happen, but just in case
LOGGER.error("Unexpected exception in getTerrainDataColumnArray. Error: [" + e.getMessage() + "]", e); LOGGER.error("Unexpected exception in getTerrainDataColumnArray. Error: [" + e.getMessage() + "]", e);
@@ -289,9 +326,10 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
int height = FullDataPointUtil.getHeight(dataPoint); int height = FullDataPointUtil.getHeight(dataPoint);
int topY = bottomY + height; int topY = bottomY + height;
return new DhApiTerrainDataPoint(detailLevel, return DhApiTerrainDataPoint.create(
detailLevel,
FullDataPointUtil.getBlockLight(dataPoint), FullDataPointUtil.getSkyLight(dataPoint), FullDataPointUtil.getBlockLight(dataPoint), FullDataPointUtil.getSkyLight(dataPoint),
topY, bottomY, bottomY, topY,
blockState, biomeWrapper); blockState, biomeWrapper);
} }
@@ -306,9 +344,11 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
IDhApiLevelWrapper levelWrapper, IDhApiLevelWrapper levelWrapper,
double rayOriginX, double rayOriginY, double rayOriginZ, double rayOriginX, double rayOriginY, double rayOriginZ,
float rayDirectionX, float rayDirectionY, float rayDirectionZ, float rayDirectionX, float rayDirectionY, float rayDirectionZ,
int maxRayBlockLength) int maxRayBlockLength,
@Nullable
IDhApiTerrainDataCache dataCache)
{ {
return this.raycastLodData(levelWrapper, new Vec3d(rayOriginX, rayOriginY, rayOriginZ), new Vec3f(rayDirectionX, rayDirectionY, rayDirectionZ), maxRayBlockLength); return this.raycastLodData(levelWrapper, new Vec3d(rayOriginX, rayOriginY, rayOriginZ), new Vec3f(rayDirectionX, rayDirectionY, rayDirectionZ), maxRayBlockLength, dataCache);
} }
/** /**
@@ -317,12 +357,17 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
* Works by walking through the world and attempting to get the LOD <br> * Works by walking through the world and attempting to get the LOD <br>
* data present at each step. * data present at each step.
*/ */
private DhApiResult<DhApiRaycastResult> raycastLodData(IDhApiLevelWrapper levelWrapper, Vec3d rayOrigin, Vec3f rayDirection, int maxRayBlockLength) private DhApiResult<DhApiRaycastResult> raycastLodData(
IDhApiLevelWrapper levelWrapper,
Vec3d rayOrigin, Vec3f rayDirection,
int maxRayBlockLength,
@Nullable
IDhApiTerrainDataCache dataCache)
{ {
rayDirection.normalize(); rayDirection.normalize();
int minBlockHeight = levelWrapper.getMinHeight(); int minBlockHeight = levelWrapper.getMinHeight();
int maxBlockHeight = levelWrapper.getHeight(); int maxBlockHeight = levelWrapper.getMaxHeight();
@@ -346,7 +391,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
for (Vec3i columnPos : columnPositions) for (Vec3i columnPos : columnPositions)
{ {
// check each column // check each column
DhApiResult<DhApiTerrainDataPoint[]> result = this.getColumnDataAtBlockPos(levelWrapper, columnPos.x, columnPos.z); DhApiResult<DhApiTerrainDataPoint[]> result = this.getColumnDataAtBlockPos(levelWrapper, columnPos.x, columnPos.z, dataCache);
if (!result.success) if (!result.success)
{ {
// if there was an error, stop and return it // if there was an error, stop and return it
@@ -414,7 +459,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
*/ */
private static ArrayList<Vec3i> getIntersectingColumnsAtPosition(Vec3i rayEndingPos, Vec3f rayDirection) private static ArrayList<Vec3i> getIntersectingColumnsAtPosition(Vec3i rayEndingPos, Vec3f rayDirection)
{ {
ArrayList<Vec3i> returnList = new ArrayList<Vec3i>(9); ArrayList<Vec3i> returnList = new ArrayList<>(9);
for (int x = -1; x <= 1; x++) for (int x = -1; x <= 1; x++)
{ {
@@ -469,6 +514,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
//=============//
// API helpers //
//=============//
@Override
public IDhApiTerrainDataCache getSoftCache() { return new DhApiTerrainDataCache(); }
//===============// //===============//
// debug methods // // debug methods //
//===============// //===============//
@@ -485,15 +539,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
Thread thread = new Thread(() -> { Thread thread = new Thread(() -> {
try try
{ {
DhApiResult<DhApiTerrainDataPoint> single = getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY); DhApiResult<DhApiTerrainDataPoint> single = getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY, debugDataCache);
DhApiResult<DhApiTerrainDataPoint[]> column = getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null); DhApiResult<DhApiTerrainDataPoint[]> column = getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null, debugDataCache);
DhLodPos chunkPos = new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ).convertToDetailLevel(LodUtil.CHUNK_DETAIL_LEVEL); DhLodPos chunkPos = new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ).convertToDetailLevel(LodUtil.CHUNK_DETAIL_LEVEL);
DhApiResult<DhApiTerrainDataPoint[][][]> area = getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, chunkPos); DhApiResult<DhApiTerrainDataPoint[][][]> area = getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, chunkPos, debugDataCache);
IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
DhApiResult<DhApiRaycastResult> rayCast = INSTANCE.raycastLodData(levelWrapper, MC_RENDER.getCameraExactPosition(), MC_RENDER.getLookAtVector(), 1000); DhApiResult<DhApiRaycastResult> rayCast = INSTANCE.raycastLodData(levelWrapper, MC_RENDER.getCameraExactPosition(), MC_RENDER.getLookAtVector(), 1000, debugDataCache);
if (rayCast.payload != null && !rayCast.payload.pos.equals(currentDebugVec3i)) if (rayCast.payload != null && !rayCast.payload.pos.equals(currentDebugVec3i))
{ {
currentDebugVec3i = rayCast.payload.pos; currentDebugVec3i = rayCast.payload.pos;
@@ -23,6 +23,7 @@ import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass; import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*; import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager; import com.seibel.distanthorizons.core.level.IKeyedClientLevelManager;
import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.render.DhApiRenderProxy; import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
@@ -38,7 +39,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger; import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger; import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
import com.seibel.distanthorizons.core.logging.SpamReducedLogger; import com.seibel.distanthorizons.core.logging.SpamReducedLogger;
import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import com.seibel.distanthorizons.core.util.math.Mat4f;
import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.render.glObject.GLProxy;
import com.seibel.distanthorizons.core.render.renderer.TestRenderer; import com.seibel.distanthorizons.core.render.renderer.TestRenderer;
import com.seibel.distanthorizons.core.util.RenderUtil; import com.seibel.distanthorizons.core.util.RenderUtil;
@@ -53,6 +54,7 @@ import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import java.io.File;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Queue; import java.util.Queue;
@@ -71,7 +73,7 @@ public class ClientApi
public static boolean prefLoggerEnabled = false; public static boolean prefLoggerEnabled = false;
public static final ClientApi INSTANCE = new ClientApi(); public static final ClientApi INSTANCE = new ClientApi();
public static TestRenderer testRenderer = new TestRenderer(); public static final TestRenderer TEST_RENDERER = new TestRenderer();
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
@@ -80,6 +82,7 @@ public class ClientApi
public static final long SPAM_LOGGER_FLUSH_NS = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS); public static final long SPAM_LOGGER_FLUSH_NS = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
private boolean configOverrideReminderPrinted = false; private boolean configOverrideReminderPrinted = false;
private boolean lowMemoryWarningPrinted = false;
private final Queue<String> chatMessageQueueForNextFrame = new LinkedBlockingQueue<>(); private final Queue<String> chatMessageQueueForNextFrame = new LinkedBlockingQueue<>();
@@ -124,9 +127,28 @@ public class ClientApi
public synchronized void onClientOnlyConnected() public synchronized void onClientOnlyConnected()
{ {
// only continue if the client is connected to a different server // only continue if the client is connected to a different server
if (MC.clientConnectedToDedicatedServer()) boolean connectedToServer = MC.clientConnectedToDedicatedServer();
boolean connectedToReplay = MC.connectedToReplay();
if (connectedToServer || connectedToReplay)
{
if (connectedToServer)
{ {
LOGGER.info("Client on ClientOnly mode connecting."); LOGGER.info("Client on ClientOnly mode connecting.");
}
else
{
LOGGER.info("Replay on ClientServer mode connecting.");
if (Config.Client.Advanced.Logging.showReplayWarningOnStartup.get())
{
MC.sendChatMessage("\u00A76" + "Distant Horizons: Replay detected." + "\u00A7r"); // gold color
MC.sendChatMessage("DH may behave strangely or have missing functionality.");
MC.sendChatMessage("In order to use pre-generated LODs, put your DH database(s) in:");
MC.sendChatMessage("\u00A77"+".Minecraft" + File.separator + ClientOnlySaveStructure.SERVER_DATA_FOLDER_NAME + File.separator + ClientOnlySaveStructure.REPLAY_SERVER_FOLDER_NAME + File.separator + "DIMENSION_NAME"+"\u00A7r"); // light gray color
MC.sendChatMessage("This can be disabled in DH's config under Advanced -> Logging.");
MC.sendChatMessage("");
}
}
// firing after clientLevelLoadEvent // firing after clientLevelLoadEvent
// TODO if level has prepped to load it should fire level load event // TODO if level has prepped to load it should fire level load event
@@ -475,29 +497,7 @@ public class ClientApi
{ {
// logging // // logging //
// dev build this.sendQueuedChatMessages();
if (ModInfo.IS_DEV_BUILD && !this.configOverrideReminderPrinted && MC.playerExists())
{
this.configOverrideReminderPrinted = true;
// remind the user that this is a development build
MC.sendChatMessage("Distant Horizons nightly/unstable build, version: [" + ModInfo.VERSION+"].");
MC.sendChatMessage("Issues may occur with this version.");
MC.sendChatMessage("Here be dragons!");
MC.sendChatMessage("");
}
// generic messages
while (!this.chatMessageQueueForNextFrame.isEmpty())
{
String message = this.chatMessageQueueForNextFrame.poll();
if (message == null)
{
// done to prevent potential null pointers
message = "";
}
MC.sendChatMessage(message);
}
IProfilerWrapper profiler = MC.getProfiler(); IProfilerWrapper profiler = MC.getProfiler();
profiler.pop(); // get out of "terrain" profiler.pop(); // get out of "terrain"
@@ -552,8 +552,17 @@ public class ClientApi
} }
IDhClientLevel level = dhClientWorld.getOrLoadClientLevel(levelWrapper); IDhClientLevel level = dhClientWorld.getOrLoadClientLevel(levelWrapper);
if (this.rendererDisabledBecauseOfExceptions) if (this.rendererDisabledBecauseOfExceptions)
{ {
// re-enable rendering if the user toggles DH rendering
if (!Config.Client.quickEnableRendering.get())
{
LOGGER.info("DH Renderer re-enabled after exception. Some rendering issues may occur. Please reboot Minecraft if you see any rendering issues.");
this.rendererDisabledBecauseOfExceptions = false;
Config.Client.quickEnableRendering.set(true);
}
return; return;
} }
@@ -573,13 +582,13 @@ public class ClientApi
if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering()) if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering())
{ {
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, renderEventParam); ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null);
} }
} }
else if (Config.Client.Advanced.Debugging.rendererMode.get() == EDhApiRendererMode.DEBUG) else if (Config.Client.Advanced.Debugging.rendererMode.get() == EDhApiRendererMode.DEBUG)
{ {
profiler.push("Render Debug"); profiler.push("Render Debug");
ClientApi.testRenderer.render(); ClientApi.TEST_RENDERER.render();
profiler.pop(); profiler.pop();
} }
} }
@@ -594,7 +603,7 @@ public class ClientApi
if (DhApi.Delayed.renderProxy.getDeferTransparentRendering()) if (DhApi.Delayed.renderProxy.getDeferTransparentRendering())
{ {
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, renderEventParam); ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null);
} }
} }
} }
@@ -604,11 +613,23 @@ public class ClientApi
LOGGER.error("Unexpected Renderer error in render pass [" + renderPass + "]. Error: " + e.getMessage(), e); LOGGER.error("Unexpected Renderer error in render pass [" + renderPass + "]. Error: " + e.getMessage(), e);
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons renderer has encountered an exception!"); MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons renderer has encountered an exception!");
MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues."); MC.sendChatMessage("\u00A74Renderer disabled to try preventing GL state corruption.");
MC.sendChatMessage("\u00A74Exception detail: " + e); MC.sendChatMessage("\u00A74Toggle DH rendering via the config UI to re-activate DH rendering.");
MC.sendChatMessage("\u00A74Error: " + e);
} }
finally finally
{ {
try
{
// these tasks always need to be called, regardless of whether the renderer is enabled or not to prevent memory leaks
GLProxy.getInstance().runRenderThreadTasks();
}
catch (Exception e)
{
LOGGER.error("Unexpected issue running render thread tasks.", e);
}
profiler.pop(); // end LOD profiler.pop(); // end LOD
profiler.push("terrain"); // go back into "terrain" profiler.push("terrain"); // go back into "terrain"
} }
@@ -648,6 +669,57 @@ public class ClientApi
} }
} }
private void sendQueuedChatMessages()
{
// dev build
if (ModInfo.IS_DEV_BUILD && !this.configOverrideReminderPrinted && MC.playerExists())
{
this.configOverrideReminderPrinted = true;
// remind the user that this is a development build
String message =
// green text
"\u00A72" + "Distant Horizons: nightly/unstable build, version: [" + ModInfo.VERSION+"]." + "\u00A7r\n" +
"Issues may occur with this version.\n" +
"Here be dragons!\n";
MC.sendChatMessage(message);
}
// memory
if (!this.lowMemoryWarningPrinted && Config.Client.Advanced.Logging.showLowMemoryWarningOnStartup.get())
{
this.lowMemoryWarningPrinted = true;
// 4 GB
long minimumRecommendedMemoryInBytes = 4L * 1_000_000_000L;
// Java returned 17,171,480,576 for 16 GB so it might be slightly off what you'd expect
long maxMemoryInBytes = Runtime.getRuntime().maxMemory();
if (maxMemoryInBytes < minimumRecommendedMemoryInBytes)
{
String message =
// orange text
"\u00A76" + "Distant Horizons: Low memory detected." + "\u00A7r \n" +
"Stuttering or low FPS may occur. \n" +
"Please increase Minecraft's available memory to 4 gigabytes. \n" +
"This warning can be disabled in DH's config under Advanced -> Logging. \n";
MC.sendChatMessage(message);
}
}
// generic messages
while (!this.chatMessageQueueForNextFrame.isEmpty())
{
String message = this.chatMessageQueueForNextFrame.poll();
if (message == null)
{
// done to prevent potential null pointers
message = "";
}
MC.sendChatMessage(message);
}
}
/** /**
* Queues the given message to appear in chat the next valid frame. * Queues the given message to appear in chat the next valid frame.
* Useful for queueing up messages that may be triggered before the user has loaded into the world. * Useful for queueing up messages that may be triggered before the user has loaded into the world.
@@ -141,7 +141,7 @@ public class ServerApi
//=======================// //=======================//
public void serverChunkLoadEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false); } public void serverChunkLoadEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false); }
public void serverChunkSaveEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false); } public void serverChunkSaveEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, true); }
@@ -26,9 +26,10 @@ import com.seibel.distanthorizons.core.generation.DhLightingEngine;
import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.level.IDhLevel;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.logging.f3.F3Screen; import com.seibel.distanthorizons.core.logging.f3.F3Screen;
import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.TimerUtil; import com.seibel.distanthorizons.core.util.TimerUtil;
import com.seibel.distanthorizons.core.util.objects.Pair; import com.seibel.distanthorizons.core.util.objects.Pair;
@@ -41,13 +42,8 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import java.util.ArrayList; import java.util.*;
import java.util.Set; import java.util.concurrent.*;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
/** Contains code and variables used by both {@link ClientApi} and {@link ServerApi} */ /** Contains code and variables used by both {@link ClientApi} and {@link ServerApi} */
public class SharedApi public class SharedApi
@@ -59,32 +55,23 @@ public class SharedApi
private static final Set<DhChunkPos> UPDATING_CHUNK_POS_SET = ConcurrentHashMap.newKeySet(); private static final Set<DhChunkPos> UPDATING_CHUNK_POS_SET = ConcurrentHashMap.newKeySet();
/** how many chunks can be queued for updating per thread, used to prevent updates from infinitely pilling up if the user flys around extremely fast */ /** how many chunks can be queued for updating per thread, used to prevent updates from infinitely pilling up if the user flys around extremely fast */
private static final int MAX_UPDATING_CHUNK_COUNT_PER_THREAD = 500; private static final int MAX_UPDATING_CHUNK_COUNT_PER_THREAD = 500;
private static final int MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE = 5_000; private static final int MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE = 30_000;
private static final Timer CHUNK_UPDATE_TIMER = TimerUtil.CreateTimer("ChunkUpdateTimer"); private static final Timer CHUNK_UPDATE_TIMER = TimerUtil.CreateTimer("ChunkUpdateTimer");
private static AbstractDhWorld currentWorld; private static AbstractDhWorld currentWorld;
private static int lastWorldGenTickDelta = 0; private static int lastWorldGenTickDelta = 0;
private static long lastOverloadedLogMessageMsTime = 0; private static long lastOverloadedLogMessageMsTime = 0;
public F3Screen.DynamicMessage f3Message;
//=============// //=============//
// constructor // // constructor //
//=============// //=============//
private SharedApi() private SharedApi() { }
{
this.f3Message = new F3Screen.DynamicMessage(() ->
{
int maxUpdateCount = MAX_UPDATING_CHUNK_COUNT_PER_THREAD * Config.Client.Advanced.MultiThreading.numberOfLodBuilderThreads.get();
return LodUtil.formatLog("Queued chunk updates: " + UPDATING_CHUNK_POS_SET.size() + " / " + maxUpdateCount);
});
}
public static void init() { Initializer.init(); } public static void init() { Initializer.init(); }
@@ -110,6 +97,8 @@ public class SharedApi
ThreadPoolUtil.shutdownThreadPools(); ThreadPoolUtil.shutdownThreadPools();
DebugRenderer.clearRenderables(); DebugRenderer.clearRenderables();
MC_RENDER.clearTargetFrameBuffer(); MC_RENDER.clearTargetFrameBuffer();
// shouldn't be necessary, but if we missed closing one of the connections this should make sure they're all closed
AbstractDhRepo.closeAllConnections();
// needs to be closed on world shutdown to clear out un-processed chunks // needs to be closed on world shutdown to clear out un-processed chunks
UPDATING_CHUNK_POS_SET.clear(); UPDATING_CHUNK_POS_SET.clear();
@@ -146,25 +135,16 @@ public class SharedApi
* Used to prevent getting a full chunk from MC if it isn't necessary. <br> * Used to prevent getting a full chunk from MC if it isn't necessary. <br>
* This is important since asking MC for a chunk is slow and may block the render thread. * This is important since asking MC for a chunk is slow and may block the render thread.
*/ */
public static boolean isChunkAtBlockPosAlreadyUpdating(int blockPosX, int blockPosZ) { return UPDATING_CHUNK_POS_SET.contains(new DhChunkPos(new DhBlockPos2D(blockPosX, blockPosZ))); } public static boolean isChunkAtBlockPosAlreadyUpdating(int blockPosX, int blockPosZ)
{ return UPDATING_CHUNK_POS_SET.contains(new DhChunkPos(new DhBlockPos2D(blockPosX, blockPosZ))); }
public static boolean isChunkAtChunkPosAlreadyUpdating(int chunkPosX, int chunkPosZ)
{ return UPDATING_CHUNK_POS_SET.contains(new DhChunkPos(chunkPosX, chunkPosZ)); }
/** handles both block place and break events */ /** handles both block place and break events */
public void chunkBlockChangedEvent(IChunkWrapper chunk, ILevelWrapper level) { this.applyChunkUpdate(chunk, level, true); } public void chunkBlockChangedEvent(IChunkWrapper chunk, ILevelWrapper level) { this.applyChunkUpdate(chunk, level, true); }
public void chunkLoadEvent(IChunkWrapper chunk, ILevelWrapper level) { this.applyChunkUpdate(chunk, level, false); } public void chunkLoadEvent(IChunkWrapper chunk, ILevelWrapper level) { this.applyChunkUpdate(chunk, level, false); }
public void chunkUnloadEvent(IChunkWrapper chunk, ILevelWrapper level)
{
// temporarily disabled since this was originally incorrectly designated as "chunkSaveEvent"
// but didn't actually fire on chunk save
// and generally this is unnecessary and drastically reduces LOD building performance
// when traveling around the world
if (false)
{
this.applyChunkUpdate(chunk, level, false);
}
}
public void applyChunkUpdate(IChunkWrapper chunkWrapper, ILevelWrapper level, boolean updateNeighborChunks) public void applyChunkUpdate(IChunkWrapper chunkWrapper, ILevelWrapper level, boolean updateNeighborChunks)
{ {
@@ -223,7 +203,13 @@ public class SharedApi
if (msBetweenLastLog >= MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE) if (msBetweenLastLog >= MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE)
{ {
lastOverloadedLogMessageMsTime = System.currentTimeMillis(); lastOverloadedLogMessageMsTime = System.currentTimeMillis();
LOGGER.warn("Too many chunks queued for updating, max queue count ["+maxQueueCount+"] (["+MAX_UPDATING_CHUNK_COUNT_PER_THREAD+"] per thread). Some LODs may not be updated or may be missing. Please move through the world slower, decrease your vanilla render distance, or increase the CPU load config.");
String message = "Distant Horizons overloaded, too many chunks queued for updating. " +
"\nThis may result in holes in your LODs. " +
"\nPlease move through the world slower, decrease your vanilla render distance, slow down your world pre-generator, or increase the Distant Horizons' CPU load config. " +
"\nMax queue count ["+maxQueueCount+"] (["+MAX_UPDATING_CHUNK_COUNT_PER_THREAD+"] per thread).";
ClientApi.INSTANCE.showChatMessageNextFrame(message);
LOGGER.warn(message);
} }
return; return;
@@ -268,7 +254,7 @@ public class SharedApi
else else
{ {
// neighboring chunk // neighboring chunk
DhChunkPos neighbourPos = new DhChunkPos(chunkWrapper.getChunkPos().x + xOffset, chunkWrapper.getChunkPos().z + zOffset); DhChunkPos neighbourPos = new DhChunkPos(chunkWrapper.getChunkPos().getX() + xOffset, chunkWrapper.getChunkPos().getZ() + zOffset);
IChunkWrapper neighbourChunk = dhLevel.getLevelWrapper().tryGetChunk(neighbourPos); IChunkWrapper neighbourChunk = dhLevel.getLevelWrapper().tryGetChunk(neighbourPos);
if (neighbourChunk != null) if (neighbourChunk != null)
{ {
@@ -285,42 +271,47 @@ public class SharedApi
} }
} }
} }
private static void bakeChunkLightingAndSendToLevelAsync(IChunkWrapper chunkWrapper, @Nullable ArrayList<IChunkWrapper> neighbourChunkList, IDhLevel dhLevel) /** returning a {@link CompletableFuture} isn't necessary, but allows Intellij to properly show the full stack trace when debugging. */
@SuppressWarnings("UnusedReturnValue")
private static CompletableFuture<Void> bakeChunkLightingAndSendToLevelAsync(IChunkWrapper chunkWrapper, @Nullable ArrayList<IChunkWrapper> neighbourChunkList, IDhLevel dhLevel)
{ {
// lighting the chunk needs to be done on a separate thread to prevent lagging any of the event threads // lighting the chunk needs to be done on a separate thread to prevent lagging any of the event threads
ThreadPoolExecutor executor = ThreadPoolUtil.getLightPopulatorExecutor(); ThreadPoolExecutor executor = ThreadPoolUtil.getChunkToLodBuilderExecutor();
if (executor == null) if (executor == null)
{ {
return; return CompletableFuture.completedFuture(null);
} }
try try
{ {
executor.execute(() -> return CompletableFuture.runAsync(() ->
{ {
//LOGGER.trace(chunkWrapper.getChunkPos() + " " + executor.getActiveCount() + " / " + executor.getQueue().size() + " - " + executor.getCompletedTaskCount()); //LOGGER.trace(chunkWrapper.getChunkPos() + " " + executor.getActiveCount() + " / " + executor.getQueue().size() + " - " + executor.getCompletedTaskCount());
try try
{ {
// Save or populate the chunk wrapper's lighting boolean checkChunkHash = !Config.Client.Advanced.LodBuilding.disableUnchangedChunkCheck.get();
// this is done so we don't have to worry about MC unloading the lighting data for this chunk
boolean onlyUseDhLighting = Config.Client.Advanced.LodBuilding.onlyUseDhLightingEngine.get(); // check if this chunk has been converted into an LOD already
if (!onlyUseDhLighting && chunkWrapper.isLightCorrect()) int oldChunkHash = dhLevel.getChunkHash(chunkWrapper.getChunkPos()); // shouldn't happen on the render thread since it may take a few moments to run
int newChunkHash = chunkWrapper.getBlockBiomeHashCode();
if (checkChunkHash)
{ {
try if (oldChunkHash == newChunkHash)
{ {
// If MC's lighting engine isn't thread safe this may cause the server thread to lag // if the chunk hashes are the same then we don't need to bother with lighting the chunk
chunkWrapper.bakeDhLightingUsingMcLightingEngine(); // or creating/updating the LODs
} //LOGGER.info("skipping: "+chunkWrapper.getChunkPos()+" "+newChunkHash);
catch (IllegalStateException e) return;
{
LOGGER.warn("Chunk light baking error: " + e.getMessage(), e);
}
} }
else else
{ {
// generate the chunk's lighting, using neighboring chunks if present //LOGGER.info("g: "+chunkWrapper.getChunkPos()+" "+newChunkHash);
}
}
// having a list of the nearby chunks is needed for lighting and beacon generation
ArrayList<IChunkWrapper> nearbyChunkList; ArrayList<IChunkWrapper> nearbyChunkList;
if (neighbourChunkList != null) if (neighbourChunkList != null)
{ {
@@ -332,10 +323,45 @@ public class SharedApi
nearbyChunkList.add(chunkWrapper); nearbyChunkList.add(chunkWrapper);
} }
DhLightingEngine.INSTANCE.lightChunk(chunkWrapper, nearbyChunkList, dhLevel.hasSkyLight() ? 15 : 0);
// chunk light baking is disabled since profiling revealed it used
// roughly the same amount of time as generating the lighting ourselves and
// was much more likely to have issues with corrupt (all black or all bright) chunks
boolean tryUsingMcLightingEngine = false;
if (tryUsingMcLightingEngine)
{
// Save or populate the chunk wrapper's lighting
// this is done so we don't have to worry about MC unloading the lighting data for this chunk
boolean chunkLightPopulated = false;
boolean onlyUseDhLighting = Config.Client.Advanced.LodBuilding.onlyUseDhLightingEngine.get();
if (!onlyUseDhLighting && chunkWrapper.isLightCorrect())
{
// If MC's lighting engine isn't thread safe this may cause the server thread to lag
chunkLightPopulated = chunkWrapper.bakeDhLightingUsingMcLightingEngine(dhLevel.getLevelWrapper());
if (!chunkLightPopulated)
{
// clear any existing data to prevent partial or corrupt lighting
// when re-generating it
chunkWrapper.clearDhBlockLighting();
chunkWrapper.clearDhSkyLighting();
}
} }
dhLevel.updateChunkAsync(chunkWrapper); // something went wrong during the baking process so we have to generate the lighting ourselves
if (!chunkLightPopulated)
{
DhLightingEngine.INSTANCE.lightChunk(chunkWrapper, nearbyChunkList, dhLevel.hasSkyLight() ? LodUtil.MAX_MC_LIGHT : LodUtil.MIN_MC_LIGHT);
}
}
else
{
DhLightingEngine.INSTANCE.lightChunk(chunkWrapper, nearbyChunkList, dhLevel.hasSkyLight() ? LodUtil.MAX_MC_LIGHT : LodUtil.MIN_MC_LIGHT);
}
dhLevel.updateBeaconBeamsForChunk(chunkWrapper, nearbyChunkList);
dhLevel.updateChunkAsync(chunkWrapper, newChunkHash);
} }
catch (Exception e) catch (Exception e)
{ {
@@ -360,9 +386,27 @@ public class SharedApi
UPDATING_CHUNK_POS_SET.remove(chunkWrapper.getChunkPos()); UPDATING_CHUNK_POS_SET.remove(chunkWrapper.getChunkPos());
} }
} }
}); }, executor);
} }
catch (RejectedExecutionException ignore) { /* the executor was shut down, it should be back up shortly and able to accept new jobs */ } catch (RejectedExecutionException ignore)
{
// the executor was shut down, it should be back up shortly and able to accept new jobs
return CompletableFuture.completedFuture(null);
}
}
//=========//
// F3 Menu //
//=========//
public String getDebugMenuString()
{
int maxUpdateCount = MAX_UPDATING_CHUNK_COUNT_PER_THREAD * Config.Client.Advanced.MultiThreading.numberOfLodBuilderThreads.get();
String updatingCountStr = F3Screen.NUMBER_FORMAT.format(UPDATING_CHUNK_POS_SET.size());
String maxUpdateCountStr = F3Screen.NUMBER_FORMAT.format(maxUpdateCount);
return "Queued chunk updates: "+updatingCountStr+" / "+maxUpdateCountStr;
} }
@@ -20,17 +20,20 @@
package com.seibel.distanthorizons.core.config; package com.seibel.distanthorizons.core.config;
import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.enums.config.*; import com.seibel.distanthorizons.api.enums.config.*;
import com.seibel.distanthorizons.api.enums.config.quickOptions.*; import com.seibel.distanthorizons.api.enums.config.quickOptions.*;
import com.seibel.distanthorizons.api.enums.rendering.*; import com.seibel.distanthorizons.api.enums.rendering.*;
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode; import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
import com.seibel.distanthorizons.core.config.eventHandlers.*; import com.seibel.distanthorizons.core.config.eventHandlers.*;
import com.seibel.distanthorizons.core.config.eventHandlers.presets.*; import com.seibel.distanthorizons.core.config.eventHandlers.presets.*;
import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener;
import com.seibel.distanthorizons.core.config.types.*; import com.seibel.distanthorizons.core.config.types.*;
import com.seibel.distanthorizons.core.config.types.enums.*; import com.seibel.distanthorizons.core.config.types.enums.*;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.ModInfo;
import com.seibel.distanthorizons.coreapi.util.StringUtil; import com.seibel.distanthorizons.coreapi.util.StringUtil;
@@ -51,7 +54,6 @@ import java.util.List;
* Otherwise, you will have issues where only some of the config entries will exist when your listener is created. * Otherwise, you will have issues where only some of the config entries will exist when your listener is created.
* *
* @author coolGi * @author coolGi
* @version 2023-7-16
*/ */
public class Config public class Config
@@ -104,8 +106,11 @@ public class Config
public static ConfigLinkedEntry quickEnableWorldGenerator = new ConfigLinkedEntry(Advanced.WorldGenerator.enableDistantGeneration); public static ConfigLinkedEntry quickEnableWorldGenerator = new ConfigLinkedEntry(Advanced.WorldGenerator.enableDistantGeneration);
public static ConfigLinkedEntry quickLodCloudRendering = new ConfigLinkedEntry(Advanced.Graphics.GenericRendering.enableCloudRendering);
public static ConfigEntry<Boolean> optionsButton = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> optionsButton = new ConfigEntry.Builder<Boolean>()
.set(true) .set(true)
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
.comment("" + .comment("" +
"Should Distant Horizon's config button appear in the options screen next to fov slider?") "Should Distant Horizon's config button appear in the options screen next to fov slider?")
.build(); .build();
@@ -122,7 +127,6 @@ public class Config
public static ConfigCategory multiplayer = new ConfigCategory.Builder().set(Multiplayer.class).build(); public static ConfigCategory multiplayer = new ConfigCategory.Builder().set(Multiplayer.class).build();
public static ConfigCategory lodBuilding = new ConfigCategory.Builder().set(LodBuilding.class).build(); public static ConfigCategory lodBuilding = new ConfigCategory.Builder().set(LodBuilding.class).build();
public static ConfigCategory multiThreading = new ConfigCategory.Builder().set(MultiThreading.class).build(); public static ConfigCategory multiThreading = new ConfigCategory.Builder().set(MultiThreading.class).build();
public static ConfigCategory buffers = new ConfigCategory.Builder().set(GpuBuffers.class).build();
public static ConfigCategory autoUpdater = new ConfigCategory.Builder().set(AutoUpdater.class).build(); public static ConfigCategory autoUpdater = new ConfigCategory.Builder().set(AutoUpdater.class).build();
public static ConfigCategory logging = new ConfigCategory.Builder().set(Logging.class).build(); public static ConfigCategory logging = new ConfigCategory.Builder().set(Logging.class).build();
@@ -135,6 +139,7 @@ public class Config
public static ConfigCategory fog = new ConfigCategory.Builder().set(Fog.class).build(); public static ConfigCategory fog = new ConfigCategory.Builder().set(Fog.class).build();
public static ConfigCategory ssao = new ConfigCategory.Builder().set(Ssao.class).build(); public static ConfigCategory ssao = new ConfigCategory.Builder().set(Ssao.class).build();
public static ConfigCategory noiseTextureSettings = new ConfigCategory.Builder().set(NoiseTextureSettings.class).build(); public static ConfigCategory noiseTextureSettings = new ConfigCategory.Builder().set(NoiseTextureSettings.class).build();
public static ConfigCategory genericRendering = new ConfigCategory.Builder().set(GenericRendering.class).build();
public static ConfigCategory advancedGraphics = new ConfigCategory.Builder().set(AdvancedGraphics.class).build(); public static ConfigCategory advancedGraphics = new ConfigCategory.Builder().set(AdvancedGraphics.class).build();
@@ -174,6 +179,7 @@ public class Config
+ "Lowest Quality: " + EDhApiVerticalQuality.HEIGHT_MAP + "\n" + "Lowest Quality: " + EDhApiVerticalQuality.HEIGHT_MAP + "\n"
+ "Highest Quality: " + EDhApiVerticalQuality.EXTREME) + "Highest Quality: " + EDhApiVerticalQuality.EXTREME)
.setPerformance(EConfigEntryPerformance.VERY_HIGH) .setPerformance(EConfigEntryPerformance.VERY_HIGH)
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<EDhApiHorizontalQuality> horizontalQuality = new ConfigEntry.Builder<EDhApiHorizontalQuality>() public static ConfigEntry<EDhApiHorizontalQuality> horizontalQuality = new ConfigEntry.Builder<EDhApiHorizontalQuality>()
@@ -195,6 +201,7 @@ public class Config
+ EDhApiTransparency.DISABLED + ": LODs will be opaque. \n" + EDhApiTransparency.DISABLED + ": LODs will be opaque. \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.MEDIUM) .setPerformance(EConfigEntryPerformance.MEDIUM)
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<EDhApiBlocksToAvoid> blocksToIgnore = new ConfigEntry.Builder<EDhApiBlocksToAvoid>() public static ConfigEntry<EDhApiBlocksToAvoid> blocksToIgnore = new ConfigEntry.Builder<EDhApiBlocksToAvoid>()
@@ -206,6 +213,7 @@ public class Config
+ EDhApiBlocksToAvoid.NON_COLLIDING + ": Only represent solid blocks in the LODs (tall grass, torches, etc. won't count for a LOD's height) \n" + EDhApiBlocksToAvoid.NON_COLLIDING + ": Only represent solid blocks in the LODs (tall grass, torches, etc. won't count for a LOD's height) \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.NONE) .setPerformance(EConfigEntryPerformance.NONE)
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<Boolean> tintWithAvoidedBlocks = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> tintWithAvoidedBlocks = new ConfigEntry.Builder<Boolean>()
@@ -217,6 +225,7 @@ public class Config
+ "False: skipped blocks will not change color of surface below them. " + "False: skipped blocks will not change color of surface below them. "
+ "") + "")
.setPerformance(EConfigEntryPerformance.NONE) .setPerformance(EConfigEntryPerformance.NONE)
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
// TODO fixme // TODO fixme
@@ -279,7 +288,7 @@ public class Config
private static final Double FOG_RANGE_MAX = Math.sqrt(2.0); private static final Double FOG_RANGE_MAX = Math.sqrt(2.0);
public static ConfigEntry<Double> farFogStart = new ConfigEntry.Builder<Double>() public static ConfigEntry<Double> farFogStart = new ConfigEntry.Builder<Double>()
.setMinDefaultMax(FOG_RANGE_MIN, 0.0, FOG_RANGE_MAX) .setMinDefaultMax(FOG_RANGE_MIN, 0.4, FOG_RANGE_MAX)
.comment("" .comment(""
+ "At what distance should the far fog start? \n" + "At what distance should the far fog start? \n"
+ "\n" + "\n"
@@ -510,7 +519,8 @@ public class Config
public static ConfigEntry<Integer> noiseSteps = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> noiseSteps = new ConfigEntry.Builder<Integer>()
.setMinDefaultMax(1, 4, null) .setMinDefaultMax(1, 4, null)
.comment("" .comment(""
+ "How many steps of noise should be applied to LODs?") + "How many steps of noise should be applied to LODs?"
+ "")
.build(); .build();
public static ConfigEntry<Double> noiseIntensity = new ConfigEntry.Builder<Double>() // TODO: Make this a float (the ClassicConfigGUI doesn't support floats) public static ConfigEntry<Double> noiseIntensity = new ConfigEntry.Builder<Double>() // TODO: Make this a float (the ClassicConfigGUI doesn't support floats)
@@ -523,7 +533,34 @@ public class Config
.setMinDefaultMax(0, 1024, null) .setMinDefaultMax(0, 1024, null)
.comment("" .comment(""
+ "Defines how far should the noise texture render before it fades away. (in blocks) \n" + "Defines how far should the noise texture render before it fades away. (in blocks) \n"
+ "Set to 0 to disable noise from fading away") + "Set to 0 to disable noise from fading away \n"
+ "")
.build();
}
public static class GenericRendering
{
public static ConfigEntry<Boolean> enableRendering = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "If true non terrain objects will be rendered in DH's terrain. \n"
+ "This includes beacon beams and clouds. \n"
+ "")
.build();
public static ConfigEntry<Boolean> enableBeaconRendering = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "If true LOD beacon beams will be rendered. \n"
+ "")
.build();
public static ConfigEntry<Boolean> enableCloudRendering = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "If true LOD clouds will be rendered. \n"
+ "")
.build(); .build();
} }
@@ -554,6 +591,7 @@ public class Config
+ "0 = black \n" + "0 = black \n"
+ "1 = normal \n" + "1 = normal \n"
+ "2 = near white") + "2 = near white")
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<Double> saturationMultiplier = new ConfigEntry.Builder<Double>() // TODO: Make this a float (the ClassicConfigGUI doesnt support floats) public static ConfigEntry<Double> saturationMultiplier = new ConfigEntry.Builder<Double>() // TODO: Make this a float (the ClassicConfigGUI doesnt support floats)
@@ -564,6 +602,7 @@ public class Config
+ "0 = black and white \n" + "0 = black and white \n"
+ "1 = normal \n" + "1 = normal \n"
+ "2 = very saturated") + "2 = very saturated")
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<Boolean> enableCaveCulling = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> enableCaveCulling = new ConfigEntry.Builder<Boolean>()
@@ -578,12 +617,15 @@ public class Config
+ "Additional Info: Currently this cull all faces \n" + "Additional Info: Currently this cull all faces \n"
+ " with skylight value of 0 in dimensions that \n" + " with skylight value of 0 in dimensions that \n"
+ " does not have a ceiling.") + " does not have a ceiling.")
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<Integer> caveCullingHeight = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> caveCullingHeight = new ConfigEntry.Builder<Integer>()
.setMinDefaultMax(-4096, 40, 4096) .setMinDefaultMax(-4096, 60, 4096)
.comment("" .comment(""
+ "At what Y value should cave culling start?") + "At what Y value should cave culling start? \n"
+ "Lower this value if you get walls for areas with 0 light.")
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<Integer> earthCurveRatio = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> earthCurveRatio = new ConfigEntry.Builder<Integer>()
@@ -621,6 +663,7 @@ public class Config
+ EDhApiLodShading.DISABLED + ": All LOD sides will be rendered with the same brightness. \n" + EDhApiLodShading.DISABLED + ": All LOD sides will be rendered with the same brightness. \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.NONE) .setPerformance(EConfigEntryPerformance.NONE)
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<Boolean> disableFrustumCulling = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> disableFrustumCulling = new ConfigEntry.Builder<Boolean>()
@@ -655,6 +698,18 @@ public class Config
+ EDhApiGrassSideRendering.AS_DIRT + ": sides render entirely as dirt. \n" + EDhApiGrassSideRendering.AS_DIRT + ": sides render entirely as dirt. \n"
+ "") + "")
.setPerformance(EConfigEntryPerformance.NONE) .setPerformance(EConfigEntryPerformance.NONE)
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry<Boolean> disableBeaconDistanceCulling = new ConfigEntry.Builder<Boolean>()
.set(false)
.comment(""
+ "If true all beacons near the camera won't be drawn to prevent vanilla overdraw. \n"
+ "If false all beacons will be rendered. \n"
+ "\n"
+ "Generally this should be left as false. It's main purpose is for debugging\n"
+ "beacon updating/rendering.\n"
+ "")
.build(); .build();
} }
@@ -715,7 +770,7 @@ public class Config
.build(); .build();
public static ConfigEntry<Integer> worldGenerationTimeoutLengthInSeconds = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> worldGenerationTimeoutLengthInSeconds = new ConfigEntry.Builder<Integer>()
.setMinDefaultMax(5, 60, 60 * 10/*10 minutes*/ ) .setMinDefaultMax(5, 60 * 3, 60 * 10/*10 minutes*/ )
.comment("" .comment(""
+ "How long should a world generator thread run for before timing out? \n" + "How long should a world generator thread run for before timing out? \n"
+ "Note: If you are experiencing timeout errors it is better to lower your CPU usage first \n" + "Note: If you are experiencing timeout errors it is better to lower your CPU usage first \n"
@@ -738,8 +793,23 @@ public class Config
+ "") + "")
.build(); .build();
public static ConfigEntry<Boolean> disableUnchangedChunkCheck = new ConfigEntry.Builder<Boolean>()
.set(false)
.comment(""
+ "Normally DH will attempt to skip creating LODs for chunks it's already seen\n"
+ "and that haven't changed.\n"
+ "\n"
+ "However sometimes that logic incorrecly prevents LODs from being updated.\n"
+ "Disabling this check may fix issues where LODs aren't updated after\n"
+ "blocks have been changed.\n"
+ "")
.build();
/** Currently we always use the DH lighting engine because there's a high likelyhood of MC returning incorrect lighting otherwise */
@Deprecated
public static ConfigEntry<Boolean> onlyUseDhLightingEngine = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> onlyUseDhLightingEngine = new ConfigEntry.Builder<Boolean>()
.set(false) .set(false)
.setAppearance(EConfigEntryAppearance.ONLY_IN_API)
.comment("" .comment(""
+ "If false LODs will be lit by Minecraft's lighting engine when possible \n" + "If false LODs will be lit by Minecraft's lighting engine when possible \n"
+ "and fall back to the DH lighting engine only when necessary. \n" + "and fall back to the DH lighting engine only when necessary. \n"
@@ -751,6 +821,20 @@ public class Config
+ "") + "")
.build(); .build();
public static ConfigEntry<Boolean> pullLightingForPregeneratedChunks = new ConfigEntry.Builder<Boolean>()
.set(false)
.comment(""
+ "If true LOD generation for pre-existing chunks will attempt to pull the lighting data \n"
+ "saved in Minecraft's Region files. \n"
+ "If false DH will pull in chunks without lighting and re-light them. \n"
+ " \n"
+ "Setting this to true will result in faster LOD generation \n"
+ "for already generated worlds, but is broken by most lighting mods. \n"
+ " \n"
+ "Set this to false if LODs are black. \n"
+ "")
.build();
public static ConfigEntry<EDhApiDataCompressionMode> dataCompression = new ConfigEntry.Builder<EDhApiDataCompressionMode>() public static ConfigEntry<EDhApiDataCompressionMode> dataCompression = new ConfigEntry.Builder<EDhApiDataCompressionMode>()
.set(EDhApiDataCompressionMode.LZMA2) .set(EDhApiDataCompressionMode.LZMA2)
.comment("" .comment(""
@@ -799,13 +883,47 @@ public class Config
+ "") + "")
.build(); .build();
public static ConfigEntry<Boolean> showMigrationChatWarning = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<String> ignoredRenderBlockCsv = new ConfigEntry.Builder<String>()
.set(true) .set("minecraft:barrier,minecraft:structure_void,minecraft:light,minecraft:tripwire")
.comment("" .comment(""
+ "Determines if a message should be displayed in the chat when LOD migration starts. \n" + "A comma separated list of block resource locations that won't be rendered by DH. \n"
+ "Note: air is always included in this list. \n"
+ "") + "")
.build(); .build();
public static ConfigEntry<String> ignoredRenderCaveBlockCsv = new ConfigEntry.Builder<String>()
.set("minecraft:glow_lichen,minecraft:rail,minecraft:water,minecraft:lava,minecraft:bubble_column")
.comment(""
+ "A comma separated list of block resource locations that shouldn't be rendered \n"
+ "if they are in a 0 sky light underground area. \n"
+ "Note: air is always included in this list. \n"
+ "")
.build();
static
{
ignoredRenderBlockCsv.addListener(new ConfigChangeListener<String>(Config.Client.Advanced.LodBuilding.ignoredRenderBlockCsv,
(blockCsv) ->
{
IWrapperFactory wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
if (wrapperFactory != null)
{
wrapperFactory.resetRendererIgnoredBlocksSet();
DhApi.Delayed.renderProxy.clearRenderDataCache();
}
}));
ignoredRenderCaveBlockCsv.addListener(new ConfigChangeListener<String>(Config.Client.Advanced.LodBuilding.ignoredRenderCaveBlockCsv,
(blockCsv) ->
{
IWrapperFactory wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
if (wrapperFactory != null)
{
wrapperFactory.resetRendererIgnoredCaveBlocks();
DhApi.Delayed.renderProxy.clearRenderDataCache();
}
}));
}
} }
public static class Multiplayer public static class Multiplayer
@@ -979,63 +1097,6 @@ public class Config
} }
public static class GpuBuffers
{
public static ConfigEntry<EDhApiGpuUploadMethod> gpuUploadMethod = new ConfigEntry.Builder<EDhApiGpuUploadMethod>()
.set(EDhApiGpuUploadMethod.AUTO)
.comment(""
+ "What method should be used to upload geometry to the GPU? \n"
+ "\n"
+ EDhApiGpuUploadMethod.AUTO + ": Picks the best option based on the GPU you have. \n"
+ "\n"
+ EDhApiGpuUploadMethod.BUFFER_STORAGE + ": Default if OpenGL 4.5 is supported. \n"
+ " Fast rendering, no stuttering. \n"
+ "\n"
+ EDhApiGpuUploadMethod.SUB_DATA + ": Backup option for NVIDIA. \n"
+ " Fast rendering but may stutter when uploading. \n"
+ "\n"
+ EDhApiGpuUploadMethod.BUFFER_MAPPING + ": Slow rendering but won't stutter when uploading. \n"
+ " Generally the best option for integrated GPUs. \n"
+ " Default option for AMD/Intel if OpenGL 4.5 isn't supported. \n"
+ " May end up storing buffers in System memory. \n"
+ " Fast rendering if in GPU memory, slow if in system memory, \n"
+ " but won't stutter when uploading. \n"
+ "\n"
+ EDhApiGpuUploadMethod.DATA + ": Fast rendering but will stutter when uploading. \n"
+ " Backup option for AMD/Intel. \n"
+ " Fast rendering but may stutter when uploading. \n"
+ "\n"
+ "If you don't see any difference when changing these settings, \n"
+ "or the world looks corrupted: restart your game."
+ "")
.build();
public static ConfigEntry<Integer> gpuUploadPerMegabyteInMilliseconds = new ConfigEntry.Builder<Integer>()
.setMinDefaultMax(0, 0, 50)
.comment(""
+ "How long should a buffer wait per Megabyte of data uploaded? \n"
+ "Helpful resource for frame times: https://fpstoms.com \n"
+ "\n"
+ "Longer times may reduce stuttering but will make LODs \n"
+ "transition and load slower. Change this to [0] for no timeout. \n"
+ "\n"
+ "NOTE:\n"
+ "Before changing this config, try changing the \"GPU Upload method\" first. \n"
+ "")
.build();
public static ConfigEntry<Boolean> gpuUploadAsync = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "If true geometry data will be uploaded on a DH controlled thread, reducing FPS stuttering. \n"
+ "If false uploading will be done on Minecraft's main rendering thread. \n"
+ "\n"
+ "Setting this to false may reduce crashes or corrupted geometry on systems with an AMD GPU when Sodium is installed.\n"
+ "")
.build();
}
public static class AutoUpdater public static class AutoUpdater
{ {
public static ConfigEntry<Boolean> enableAutoUpdater = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> enableAutoUpdater = new ConfigEntry.Builder<Boolean>()
@@ -1053,11 +1114,12 @@ public class Config
.build(); .build();
public static ConfigEntry<EDhApiUpdateBranch> updateBranch = new ConfigEntry.Builder<EDhApiUpdateBranch>() public static ConfigEntry<EDhApiUpdateBranch> updateBranch = new ConfigEntry.Builder<EDhApiUpdateBranch>()
.set( .set(EDhApiUpdateBranch.AUTO)
ModInfo.IS_DEV_BUILD? EDhApiUpdateBranch.NIGHTLY: EDhApiUpdateBranch.STABLE // If it's already a nightly build, then download the nightly build ofc
)
.comment("" .comment(""
+ " If DH should use the nightly (provided by Gitlab), or stable (provided by Modrinth) build") + "If DH should use the nightly (provided by Gitlab), or stable (provided by Modrinth) build. \n"
+ "If ["+EDhApiUpdateBranch.AUTO+"] is selected DH will update to new stable releases if the current jar is a stable jar \n"
+ "and will update to new nightly builds if the current jar is a nightly jar (IE the version number ends in '-dev')."
+ "")
.build(); .build();
} }
@@ -1066,68 +1128,90 @@ public class Config
// TODO add change all option // TODO add change all option
// TODO default to error chat and info file // TODO default to error chat and info file
public static ConfigEntry<EDhApiLoggerMode> logWorldGenEvent = new ConfigEntry.Builder<EDhApiLoggerMode>() public static ConfigEntry<EDhApiLoggerMode> logWorldGenEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE)
.comment("" .comment(""
+ "If enabled, the mod will log information about the world generation process. \n" + "If enabled, the mod will log information about the world generation process. \n"
+ "This can be useful for debugging.") + "This can be useful for debugging.")
.build(); .build();
public static ConfigEntry<EDhApiLoggerMode> logWorldGenPerformance = new ConfigEntry.Builder<EDhApiLoggerMode>() public static ConfigEntry<EDhApiLoggerMode> logWorldGenPerformance = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_FILE) .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE)
.comment("" .comment(""
+ "If enabled, the mod will log performance about the world generation process. \n" + "If enabled, the mod will log performance about the world generation process. \n"
+ "This can be useful for debugging.") + "This can be useful for debugging.")
.build(); .build();
public static ConfigEntry<EDhApiLoggerMode> logWorldGenLoadEvent = new ConfigEntry.Builder<EDhApiLoggerMode>() public static ConfigEntry<EDhApiLoggerMode> logWorldGenLoadEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_FILE) .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE)
.comment("" .comment(""
+ "If enabled, the mod will log information about the world generation process. \n" + "If enabled, the mod will log information about the world generation process. \n"
+ "This can be useful for debugging.") + "This can be useful for debugging.")
.build(); .build();
public static ConfigEntry<EDhApiLoggerMode> logLodBuilderEvent = new ConfigEntry.Builder<EDhApiLoggerMode>() public static ConfigEntry<EDhApiLoggerMode> logLodBuilderEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE)
.comment("" .comment(""
+ "If enabled, the mod will log information about the LOD generation process. \n" + "If enabled, the mod will log information about the LOD generation process. \n"
+ "This can be useful for debugging.") + "This can be useful for debugging.")
.build(); .build();
public static ConfigEntry<EDhApiLoggerMode> logRendererBufferEvent = new ConfigEntry.Builder<EDhApiLoggerMode>() public static ConfigEntry<EDhApiLoggerMode> logRendererBufferEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE)
.comment("" .comment(""
+ "If enabled, the mod will log information about the renderer buffer process. \n" + "If enabled, the mod will log information about the renderer buffer process. \n"
+ "This can be useful for debugging.") + "This can be useful for debugging.")
.build(); .build();
public static ConfigEntry<EDhApiLoggerMode> logRendererGLEvent = new ConfigEntry.Builder<EDhApiLoggerMode>() public static ConfigEntry<EDhApiLoggerMode> logRendererGLEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE)
.comment("" .comment(""
+ "If enabled, the mod will log information about the renderer OpenGL process. \n" + "If enabled, the mod will log information about the renderer OpenGL process. \n"
+ "This can be useful for debugging.") + "This can be useful for debugging.")
.build(); .build();
public static ConfigEntry<EDhApiLoggerMode> logFileReadWriteEvent = new ConfigEntry.Builder<EDhApiLoggerMode>() public static ConfigEntry<EDhApiLoggerMode> logFileReadWriteEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE)
.comment("" .comment(""
+ "If enabled, the mod will log information about file read/write operations. \n" + "If enabled, the mod will log information about file read/write operations. \n"
+ "This can be useful for debugging.") + "This can be useful for debugging.")
.build(); .build();
public static ConfigEntry<EDhApiLoggerMode> logFileSubDimEvent = new ConfigEntry.Builder<EDhApiLoggerMode>() public static ConfigEntry<EDhApiLoggerMode> logFileSubDimEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE)
.comment("" .comment(""
+ "If enabled, the mod will log information about file sub-dimension operations. \n" + "If enabled, the mod will log information about file sub-dimension operations. \n"
+ "This can be useful for debugging.") + "This can be useful for debugging.")
.build(); .build();
public static ConfigEntry<EDhApiLoggerMode> logNetworkEvent = new ConfigEntry.Builder<EDhApiLoggerMode>() public static ConfigEntry<EDhApiLoggerMode> logNetworkEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE) .set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE)
.comment("" .comment(""
+ "If enabled, the mod will log information about network operations. \n" + "If enabled, the mod will log information about network operations. \n"
+ "This can be useful for debugging.") + "This can be useful for debugging.")
.build(); .build();
public static ConfigEntry<Boolean> showLowMemoryWarningOnStartup = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "If enabled, a chat message will be displayed if Java doesn't have enough \n"
+ "memory allocated to run DH well.")
.build();
public static ConfigEntry<Boolean> showReplayWarningOnStartup = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "If enabled, a chat message will be displayed when a replay is started \n"
+ "giving some basic information about how DH will function.")
.build();
public static ConfigEntry<Boolean> showModCompatibilityWarningsOnStartup = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "If enabled, a chat message will be displayed when a potentially problematic \n"
+ "mod is installed alongside DH.")
.build();
} }
public static class Debugging public static class Debugging
@@ -1195,6 +1279,15 @@ public class Config
+ "") + "")
.build(); .build();
public static ConfigEntry<Boolean> logBufferGarbageCollection = new ConfigEntry.Builder<Boolean>()
.set(false)
.comment(""
+ "If true OpenGL Buffer garbage collection will be logged \n"
+ "this also includes the number of live buffers. \n"
+ "")
.build();
// Note: This will reset on game restart, and should have a warning on the tooltip // Note: This will reset on game restart, and should have a warning on the tooltip
public static ConfigEntry<Boolean> allowUnsafeValues = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> allowUnsafeValues = new ConfigEntry.Builder<Boolean>()
.set(false) .set(false)
@@ -1205,22 +1298,38 @@ public class Config
public static ConfigEntry<Boolean> columnBuilderDebugEnable = new ConfigEntry.Builder<Boolean>() public static ConfigEntry<Boolean> columnBuilderDebugEnable = new ConfigEntry.Builder<Boolean>()
.set(false) .set(false)
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.addListener(DebugColumnConfigEventHandler.INSTANCE) .addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<Integer> columnBuilderDebugDetailLevel = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> columnBuilderDebugDetailLevel = new ConfigEntry.Builder<Integer>()
.set((int) DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) .set((int) DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL)
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.addListener(DebugColumnConfigEventHandler.INSTANCE) .addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<Integer> columnBuilderDebugXPos = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> columnBuilderDebugXPos = new ConfigEntry.Builder<Integer>()
.set(0) .set(0)
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.addListener(DebugColumnConfigEventHandler.INSTANCE) .addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
public static ConfigEntry<Integer> columnBuilderDebugZPos = new ConfigEntry.Builder<Integer>() public static ConfigEntry<Integer> columnBuilderDebugZPos = new ConfigEntry.Builder<Integer>()
.set(0) .set(0)
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.addListener(DebugColumnConfigEventHandler.INSTANCE) .addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry<Integer> columnBuilderDebugXRow = new ConfigEntry.Builder<Integer>()
.set(-1)
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry<Integer> columnBuilderDebugZRow = new ConfigEntry.Builder<Integer>()
.set(-1)
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build();
public static ConfigEntry<Integer> columnBuilderDebugColumnIndex = new ConfigEntry.Builder<Integer>()
.set(-1)
.setAppearance(EConfigEntryAppearance.ONLY_IN_GUI)
.addListener(ReloadLodsConfigEventHandler.INSTANCE)
.build(); .build();
@@ -23,9 +23,9 @@ import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy;
import com.seibel.distanthorizons.core.config.listeners.IConfigListener; import com.seibel.distanthorizons.core.config.listeners.IConfigListener;
public class DebugColumnConfigEventHandler implements IConfigListener public class ReloadLodsConfigEventHandler implements IConfigListener
{ {
public static DebugColumnConfigEventHandler INSTANCE = new DebugColumnConfigEventHandler(); public static ReloadLodsConfigEventHandler INSTANCE = new ReloadLodsConfigEventHandler();
@Override @Override
public void onConfigValueSet() public void onConfigValueSet()
@@ -168,7 +168,7 @@ public abstract class AbstractPresetConfigEventHandler<TPresetEnum extends Enum<
if (newPreset != currentPreset) if (newPreset != currentPreset)
{ {
this.getPresetConfigEntry().set(this.getCustomPresetEnum()); this.getPresetConfigEntry().set(newPreset);
} }
} }
@@ -37,28 +37,27 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
public static final ThreadPresetConfigEventHandler INSTANCE = new ThreadPresetConfigEventHandler(); public static final ThreadPresetConfigEventHandler INSTANCE = new ThreadPresetConfigEventHandler();
private static final Logger LOGGER = LogManager.getLogger(); private static final Logger LOGGER = LogManager.getLogger();
private static final boolean LOW_THREAD_COUNT_CPU = (Runtime.getRuntime().availableProcessors() <= 4);
public static int getWorldGenDefaultThreadCount() { return getThreadCountByPercent(0.15); } public static int getWorldGenDefaultThreadCount() { return getThreadCountByPercent(0.1); }
private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Integer> worldGenThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads, private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Integer> worldGenThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfWorldGenerationThreads,
new HashMap<EDhApiThreadPreset, Integer>() new HashMap<EDhApiThreadPreset, Integer>()
{{ {{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 1); this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 1);
this.put(EDhApiThreadPreset.LOW_IMPACT, getWorldGenDefaultThreadCount()); this.put(EDhApiThreadPreset.LOW_IMPACT, getWorldGenDefaultThreadCount());
this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.25)); this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.15));
this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.5)); this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.25));
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(0.5));
}}); }});
public static double getWorldGenDefaultRunTimeRatio() { return LOW_THREAD_COUNT_CPU ? 0.5 : 0.75; } public static double getWorldGenDefaultRunTimeRatio() { return 0.5; }
private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Double> worldGenRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForWorldGenerationThreads, private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Double> worldGenRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForWorldGenerationThreads,
new HashMap<EDhApiThreadPreset, Double>() new HashMap<EDhApiThreadPreset, Double>()
{{ {{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, LOW_THREAD_COUNT_CPU ? 0.1 : 0.25); this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 0.1);
this.put(EDhApiThreadPreset.LOW_IMPACT, getWorldGenDefaultRunTimeRatio()); this.put(EDhApiThreadPreset.LOW_IMPACT, getWorldGenDefaultRunTimeRatio());
this.put(EDhApiThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.5 : 0.75); this.put(EDhApiThreadPreset.BALANCED, 0.75);
this.put(EDhApiThreadPreset.AGGRESSIVE, LOW_THREAD_COUNT_CPU ? 0.75 : 1.0); this.put(EDhApiThreadPreset.AGGRESSIVE, 1.0);
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0);
}}); }});
@@ -71,13 +70,13 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
this.put(EDhApiThreadPreset.LOW_IMPACT, getFileHandlerDefaultThreadCount()); this.put(EDhApiThreadPreset.LOW_IMPACT, getFileHandlerDefaultThreadCount());
this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.2)); this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.2));
this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.2)); this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.2));
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(0.5));
}}); }});
public static double getFileHandlerDefaultRunTimeRatio() { return 0.75; } public static double getFileHandlerDefaultRunTimeRatio() { return 0.5; }
private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Double> fileHandlerRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForFileHandlerThreads, private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Double> fileHandlerRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForFileHandlerThreads,
new HashMap<EDhApiThreadPreset, Double>() new HashMap<EDhApiThreadPreset, Double>()
{{ {{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 0.50); this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 0.25);
this.put(EDhApiThreadPreset.LOW_IMPACT, getFileHandlerDefaultRunTimeRatio()); this.put(EDhApiThreadPreset.LOW_IMPACT, getFileHandlerDefaultRunTimeRatio());
this.put(EDhApiThreadPreset.BALANCED, 1.0); this.put(EDhApiThreadPreset.BALANCED, 1.0);
this.put(EDhApiThreadPreset.AGGRESSIVE, 1.0); this.put(EDhApiThreadPreset.AGGRESSIVE, 1.0);
@@ -85,24 +84,24 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
}}); }});
public static int getUpdatePropagatorDefaultThreadCount() { return getThreadCountByPercent(0.25); } public static int getUpdatePropagatorDefaultThreadCount() { return getThreadCountByPercent(0.10); }
private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Integer> UpdatePropagatorThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfUpdatePropagatorThreads, private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Integer> UpdatePropagatorThreadCount = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.numberOfUpdatePropagatorThreads,
new HashMap<EDhApiThreadPreset, Integer>() new HashMap<EDhApiThreadPreset, Integer>()
{{ {{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 1); this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 1);
this.put(EDhApiThreadPreset.LOW_IMPACT, getUpdatePropagatorDefaultThreadCount()); this.put(EDhApiThreadPreset.LOW_IMPACT, getUpdatePropagatorDefaultThreadCount());
this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.5)); this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.25));
this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.75)); this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.50));
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(0.75));
}}); }});
public static double getUpdatePropagatorDefaultRunTimeRatio() { return 0.5; } public static double getUpdatePropagatorDefaultRunTimeRatio() { return 0.25; }
private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Double> UpdatePropagatorRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForUpdatePropagatorThreads, private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Double> UpdatePropagatorRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForUpdatePropagatorThreads,
new HashMap<EDhApiThreadPreset, Double>() new HashMap<EDhApiThreadPreset, Double>()
{{ {{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 0.25); this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 0.1);
this.put(EDhApiThreadPreset.LOW_IMPACT, getUpdatePropagatorDefaultRunTimeRatio()); this.put(EDhApiThreadPreset.LOW_IMPACT, getUpdatePropagatorDefaultRunTimeRatio());
this.put(EDhApiThreadPreset.BALANCED, 0.75); this.put(EDhApiThreadPreset.BALANCED, 0.50);
this.put(EDhApiThreadPreset.AGGRESSIVE, 1.0); this.put(EDhApiThreadPreset.AGGRESSIVE, 0.75);
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0);
}}); }});
@@ -115,16 +114,16 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
this.put(EDhApiThreadPreset.LOW_IMPACT, getLodBuilderDefaultThreadCount()); this.put(EDhApiThreadPreset.LOW_IMPACT, getLodBuilderDefaultThreadCount());
this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.2)); this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.2));
this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.4)); this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.4));
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0)); this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(0.6));
}}); }});
public static double getLodBuilderDefaultRunTimeRatio() { return LOW_THREAD_COUNT_CPU ? 0.25 : 0.5; } public static double getLodBuilderDefaultRunTimeRatio() { return 0.25; }
private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Double> lodBuilderRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForLodBuilderThreads, private final ConfigEntryWithPresetOptions<EDhApiThreadPreset, Double> lodBuilderRunTime = new ConfigEntryWithPresetOptions<>(Config.Client.Advanced.MultiThreading.runTimeRatioForLodBuilderThreads,
new HashMap<EDhApiThreadPreset, Double>() new HashMap<EDhApiThreadPreset, Double>()
{{ {{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 0.1); this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 0.1);
this.put(EDhApiThreadPreset.LOW_IMPACT, getLodBuilderDefaultRunTimeRatio()); this.put(EDhApiThreadPreset.LOW_IMPACT, getLodBuilderDefaultRunTimeRatio());
this.put(EDhApiThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.5 : 0.75); this.put(EDhApiThreadPreset.BALANCED, 0.5);
this.put(EDhApiThreadPreset.AGGRESSIVE, 1.0); this.put(EDhApiThreadPreset.AGGRESSIVE, 0.75);
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0); this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0);
}}); }});
@@ -265,7 +265,11 @@ public class ConfigFileHandling
) )
return; return;
nightConfig.setComment(entry.getNameWCategory(), " " + entry.getComment().replaceAll("\n", "\n ") + "\n "); String comment = entry.getComment().replaceAll("\n", "\n ").trim();
// the new line makes it easier to read and separate configs
// the space makes sure the first word of a comment isn't directly in line with the "#"
comment = "\n " + comment;
nightConfig.setComment(entry.getNameWCategory(), comment);
} }
@@ -82,8 +82,7 @@ public class OpenGLConfigScreen extends AbstractScreen
private void createBuffer() private void createBuffer()
{ {
GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer()); sharedContextBuffer = createTextingBuffer();
GLProxy.ensureAllGLJobCompleted();
sameContextBuffer = createTextingBuffer(); sameContextBuffer = createTextingBuffer();
} }
@@ -256,21 +256,39 @@ public class ConfigEntry<T> extends AbstractConfigType<T, ConfigEntry<T>> implem
public byte isValid(T value, T min, T max) public byte isValid(T value, T min, T max)
{ {
if (this.configBase.disableMinMax) if (this.configBase.disableMinMax)
{
return 0; return 0;
}
if (value == null || this.value == null || value.getClass() != this.value.getClass()) // If the 2 variables aren't the same type then it will be invalid else if (min == null && max == null)
{
// no validation is needed for this field
return 0;
}
else if (value == null || this.value == null
|| value.getClass() != this.value.getClass())
{
// If the 2 variables aren't the same type then it will be invalid
return 2; return 2;
if (Number.class.isAssignableFrom(value.getClass())) }
{ // Only check min max if it is a number else if (Number.class.isAssignableFrom(value.getClass()))
{
// Only check min max if it is a number
if (max != null && NumberUtil.greaterThan((Number) value, (Number) max)) if (max != null && NumberUtil.greaterThan((Number) value, (Number) max))
{
return 1; return 1;
}
if (min != null && NumberUtil.lessThan((Number) value, (Number) min)) if (min != null && NumberUtil.lessThan((Number) value, (Number) min))
{
return -1; return -1;
}
return 0; return 0;
} }
else
{
return 0; return 0;
} }
}
/** This should normally not be called since set() automatically calls this */ /** This should normally not be called since set() automatically calls this */
public void save() { configBase.configFileINSTANCE.saveEntry(this); } public void save() { configBase.configFileINSTANCE.saveEntry(this); }

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