Compare commits

...

174 Commits

Author SHA1 Message Date
James Seibel 1e6eb4c096 Add complete multidraw 2024-07-17 17:39:52 -05:00
James Seibel 618707533b add multidraw 2024-07-17 17:09:56 -05:00
James Seibel 2d7e2e2444 Merge render VBOs 2024-07-17 15:15:43 -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 894a2dbe7d Fix incorrect DhSectionPos method var order 2024-05-16 22:14:34 -05:00
James Seibel 172e7560fd Replace DhSectionPos with long primitives to reduce GC 2024-05-16 22:07:57 -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 cd5ff8ce35 Start adding new DhSectionPos and unit tests 2024-05-15 18:48:25 -05:00
James Seibel 6e717a383d Remove unused OldSectionPos methods and add serialize methods to V1 repo 2024-05-15 18:47:51 -05:00
James Seibel bef873b875 Add comments to EDhDirection 2024-05-15 18:47:09 -05:00
James Seibel 331d75a3bc Rename DhSectionPos -> OldDhSectionPos before rewrite 2024-05-15 07:50:52 -04:00
James Seibel cec6438602 Replace QuadTree iterator linked list with ArrayDeque
Thanks JustALittleWolf!
2024-05-15 07:36:32 -04:00
James Seibel f5e0c112e3 Revert max world gen tasks 2 -> 20
I was hoping it would fix LODs not appearing, although it appears there was a different problem which has since been fixed.
2024-05-11 16:23:20 -05:00
James Seibel 899c4aca91 Add Quad Tree Render Status debug wireframe 2024-05-11 16:21:53 -05:00
James Seibel a4ac483e5b Potentially fix LODs not loading in 2024-05-11 16:19:10 -05:00
James Seibel 723f67ea0c Attempt to prevent thread starvation due to world gen
Hopefully this should help prevent issues on low end machines not loading in LODs
2024-05-10 22:27:22 -05:00
James Seibel 4575701bd4 disable sql timeout 2024-05-09 23:21:35 -05:00
James Seibel 7cfcfb0695 Handle missing/corrupted block/biome ID's in the full data 2024-05-09 19:45:54 -05:00
James Seibel f33bfa1d69 Fix monoliths due to duplicate IDs
This would specifically happen if moving from one MC version that has more blockstate attributes to one with fewer. If that was done then the both blockstates would act like they were the same, screwing up the ID map.
2024-05-09 19:44:33 -05:00
James Seibel a3c1f1563d minor FullDataToRenderDataTransformer reformat 2024-05-09 19:35:43 -05:00
James Seibel 361d197c5e Add DataCorruptedException(message, exception) constructor 2024-05-09 19:04:07 -05:00
James Seibel 04379691bc Potential fix for NaN multiverse similarity 2024-05-09 07:34:47 -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
James Seibel e1ca398b8f Fix updating chunk count not clearing on world close 2024-05-04 15:35:29 -05:00
James Seibel f34e67e6bb Fix F3 levels not closing with multiverse 2024-05-04 15:12:26 -05:00
James Seibel aad095ca1a Fix #670 Remove outdated world gen options from tooltip 2024-05-04 09:48:35 -05:00
James Seibel 950c951c2d minor ConfigBasedLogger cleanup 2024-05-02 17:31:53 -05:00
cola98765 37eaa2656a Update file FullDataToRenderDataTransformer.java 2024-05-01 10:31:43 +00:00
James Seibel 945853d014 Improve nightly build warning message 2024-04-30 21:53:00 -05:00
James Seibel 6bb38ad500 Improve migration queue messages 2024-04-30 21:52:13 -05:00
James Seibel 980086c533 Fix debug wireframes rendering on top of LODs 2024-04-30 21:23:54 -05:00
James Seibel c8f1154831 Remove ZStd compression option
Any ZStd data will be automatically deleted and re-generated
2024-04-30 21:17:26 -05:00
James Seibel 9196480e50 Remove references to FastUtil 8.5.13 2024-04-30 20:28:34 -05:00
James Seibel f0506d28e5 Fix incorrect refernce to fastutil in LzmaArrayCache 2024-04-30 20:26:34 -05:00
James Seibel 8ecd5dd9cb Fix optifine 1.16 support 2024-04-30 18:57:07 -05:00
James Seibel c83140a2d0 add IClientLevelWrapper.getPlainsBiomeWrapper() 2024-04-28 17:31:08 -05:00
James Seibel 3b600ce800 Add corrupt data read handling 2024-04-28 15:52:08 -05:00
James Seibel 7f874b4dc5 Revert a613540b 2024-04-27 12:56:08 -05:00
James Seibel 23e857a20d Fix some lib shading issues 2024-04-27 11:35:08 -05:00
James Seibel 2298ef0e0d up the version number 2.0.3 -> 2.0.4 2024-04-26 07:33:42 -05:00
James Seibel 7470455e50 Fix issues with compressors not appearing at runtime 2024-04-26 07:33:14 -05:00
James Seibel 614884c29e Merge Data_source_rewrite into main 2024-04-26 07:21:48 -05:00
coolGi cb0c294df6 Removed test code being included in main repo code 2024-03-24 12:26:10 +10:30
cola98765 7714569251 Merge branch 'blending_change' into 'main'
Update LodRenderer.java

See merge request jeseibel/distant-horizons-core!53
2024-03-17 23:47:26 +00:00
cola98765 8b9e48d4d3 Update LodRenderer.java 2024-03-17 23:47:25 +00:00
244 changed files with 10040 additions and 4254 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
plugins {
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.override.IDhApiOverrideable;
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.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
import com.seibel.distanthorizons.api.methods.override.DhApiWorldGeneratorOverrideRegister;
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.
* @since API 1.1.0
* @since API 2.0.0
*/
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;
}
@@ -198,7 +206,7 @@ public class DhApi
/**
* 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); }
@@ -23,7 +23,7 @@ package com.seibel.distanthorizons.api.enums.config;
* NONE, <br>
* NON_COLLIDING, <br>
*
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiBlocksToAvoid
@@ -22,14 +22,13 @@ package com.seibel.distanthorizons.api.enums.config;
/**
* UNCOMPRESSED <br>
* LZ4 <br>
* ZSTD <br>
* XZ <br><br>
*
* Note: speed and compression ratios are examples
* and should only be used for estimated comparisons.
*
* @version 2024-3-16
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiDataCompressionMode
{
@@ -56,14 +55,15 @@ public enum EDhApiDataCompressionMode
*/
LZ4(1),
/**
/*
* Decent speed and good compression. <br><br>
*
* Read Speed: 11.78 MS / DTO <br>
* Write Speed: 16.76 MS / DTO <br>
* Compression ratio: 0.2199 <br>
*/
Z_STD(2),
//@Deprecated
//Z_STD(2),
/**
* Extremely slow, but very good compression. <br><br>
@@ -82,7 +82,8 @@ public enum EDhApiDataCompressionMode
EDhApiDataCompressionMode(int value) { this.value = (byte) value; }
public static EDhApiDataCompressionMode getFromValue(byte value)
/** @throws IllegalArgumentException if the value doesn't map to a value */
public static EDhApiDataCompressionMode getFromValue(byte value) throws IllegalArgumentException
{
EDhApiDataCompressionMode[] enumList = EDhApiDataCompressionMode.values();
for (int i = 0; i < enumList.length; i++)
@@ -20,7 +20,7 @@
package com.seibel.distanthorizons.api.enums.config;
/**
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiGLErrorHandlingMode
@@ -20,7 +20,7 @@
package com.seibel.distanthorizons.api.enums.config;
/**
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiGlProfileMode
@@ -29,7 +29,7 @@ package com.seibel.distanthorizons.api.enums.config;
* @author Leetom
* @author James Seibel
* @version 2024-4-6
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiGpuUploadMethod
{
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums.config;
* FADE_TO_DIRT <br>
* AS_DIRT <br>
*
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-7
*/
public enum EDhApiGrassSideRendering
@@ -26,7 +26,7 @@ package com.seibel.distanthorizons.api.enums.config;
* HIGH <br>
* UNLIMITED <br>
*
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiHorizontalQuality
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums.config;
* ENABLED <br>
* DISABLED <br>
*
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiLodShading
@@ -22,7 +22,7 @@ package com.seibel.distanthorizons.api.enums.config;
import org.apache.logging.log4j.Level;
/**
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiLoggerMode
@@ -33,7 +33,7 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil;
*
* @author James Seibel
* @author Leonardo Amato
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiMaxHorizontalResolution
@@ -30,7 +30,7 @@ package com.seibel.distanthorizons.api.enums.config;
* Determines how the multiplayer folders should be named.
*
* @author James Seibel
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiServerFolderNameMode
@@ -1,14 +1,41 @@
package com.seibel.distanthorizons.api.enums.config;
import com.seibel.distanthorizons.coreapi.ModInfo;
/**
* AUTO, <br>
* STABLE, <br>
* NIGHTLY, <br><br>
*
* @since API 1.1.0
* @version 2024-4-6
* @since API 2.1.0
* @version 2024-6-8
*/
public enum EDhApiUpdateBranch
{
AUTO,
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.
*
* @author James Seibel
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
@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
* @version 2024-4-6
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiVerticalQuality
{
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums.config;
* VISUALLY_EQUAL <br><br>
*
* @version 2024-3-27
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiWorldCompressionMode
{
@@ -30,7 +30,7 @@ import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui
* HIGH, <br>
* EXTREME, <br>
*
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiQualityPreset
@@ -29,7 +29,7 @@ import com.seibel.distanthorizons.api.enums.config.DisallowSelectingViaConfigGui
* BALANCED, <br>
* AGGRESSIVE, <br>
*
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiThreadPreset
@@ -0,0 +1,67 @@
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 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 James Seibel
* @version 2024-4-6
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiDebugRendering
{
@@ -25,7 +25,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
*
* @author James Seibel
* @version 2024-4-6
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiFogColorMode
{
@@ -25,7 +25,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* FOG_DISABLED <br>
*
* @author James Seibel
* @since API 1.1.0
* @since API 2.0.0
* @version 2022-6-2
*/
public enum EDhApiFogDrawMode
@@ -26,7 +26,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
*
* @author Leetom
* @version 2022-6-30
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiFogFalloff
{
@@ -33,7 +33,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
*
* @author Leetom
* @version 2024-4-6
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiHeightFogMixMode
{
@@ -29,7 +29,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
*
* @author Leetom
* @version 2024-4-6
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiHeightFogMode
{
@@ -7,7 +7,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
*
* @author James Seibel
* @version 2024-1-30
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiRenderPass
{
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* Debug <br>
* Disabled <br>
*
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiRendererMode
@@ -24,7 +24,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* FAKE, <br>
* COMPLETE, <br>
*
* @since API 1.1.0
* @since API 2.0.0
* @version 2024-4-6
*/
public enum EDhApiTransparency
@@ -31,7 +31,7 @@ import java.util.function.Consumer;
*
* @author Builderb0y, James Seibel
* @version 2023-12-21
* @since API 1.1.0
* @since API 2.0.0
*/
public enum EDhApiWorldGeneratorReturnType
{
@@ -40,7 +40,7 @@ public enum EDhApiWorldGeneratorReturnType
* {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)}
* will be used when generating terrain.
*
* @since API 1.1.0
* @since API 2.0.0
*/
VANILLA_CHUNKS,
@@ -49,7 +49,7 @@ public enum EDhApiWorldGeneratorReturnType
* {@link IDhApiWorldGenerator#generateApiChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)}
* will be used when generating terrain.
*
* @since API 1.1.0
* @since API 2.0.0
*/
API_CHUNKS;
@@ -30,12 +30,21 @@ import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper;
*/
public interface IDhApiBlockStateWrapper extends IDhApiUnsafeWrapper
{
/** @since API 1.0.0 */
boolean isAir();
/** @since API 1.0.0 */
boolean isSolid();
/** @since API 1.0.0 */
boolean isLiquid();
// TODO:
// boolean hasNoCollision();
// boolean noFaceIsFullFace();
/**
* Returns the full serialized form of the given block
* as defined by DH's serialization methods.
* @since API 3.0.0
*/
String getSerialString();
/** @since API 3.0.0 */
byte getMaterialId();
}
@@ -47,7 +47,7 @@ public interface IDhApiConfigValue<T>
* 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.
*
* @since API 1.1.0
* @since API 2.0.0
*/
T getApiValue();
@@ -68,7 +68,7 @@ public interface IDhApiConfigValue<T>
* use the value set in the config menu.
*
* @return true if the value was set, false otherwise.
* @since API 1.1.0
* @since API 2.0.0
*/
boolean clearValue();
@@ -0,0 +1,46 @@
/*
* 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.config.client;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigGroup;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
/**
* Distant Horizons' generic rendering configuration. <br><br>
*
* @author James Seibel
* @version 2024-7-11
* @since API 3.0.0
*/
public interface IDhApiGenericRenderingConfig extends IDhApiConfigGroup
{
/**
* If enabled DH will render generic objects into its terrain pass. <br>
* This includes: clouds, beacons, and API added objects.
*/
IDhApiConfigValue<Boolean> renderingEnabled();
/** If enabled DH will render beacon beams. */
IDhApiConfigValue<Boolean> beaconRenderingEnabled();
/** If enabled DH will render clouds. */
IDhApiConfigValue<Boolean> cloudRenderingEnabled();
}
@@ -36,13 +36,4 @@ public interface IDhApiGpuBuffersConfig extends IDhApiConfigGroup
/** Defines how geometry data is uploaded to the GPU. */
IDhApiConfigValue<EDhApiGpuUploadMethod> gpuUploadMethod();
/**
* Defines how long we should wait after uploading one
* Megabyte of geometry data to the GPU before uploading
* 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();
}
@@ -41,6 +41,7 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup
IDhApiFogConfig fog();
IDhApiAmbientOcclusionConfig ambientOcclusion();
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
* but may cause overdraw issues with transparent or non-full blocks.
*
* @since API 1.1.0
* @since API 2.0.0
*/
IDhApiConfigValue<Double> overdrawPreventionRadius();
@@ -158,7 +159,7 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup
/**
* Determines how LODs should be shaded.
*
* @since API 1.1.0
* @since API 2.0.0
*/
IDhApiConfigValue<EDhApiLodShading> lodShading();
@@ -171,7 +172,7 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup
* start/stop rendering incorrectly based on the camera direction,
* but will also reduce FPS.
*
* @since API 1.1.0
* @since API 2.0.0
* @see IDhApiGraphicsConfig#disableShadowFrustumCulling()
*/
IDhApiConfigValue<Boolean> disableFrustumCulling();
@@ -183,7 +184,7 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup
*
* Disable this if shadows render incorrectly.
*
* @since API 1.1.0
* @since API 2.0.0
* @see IDhApiGraphicsConfig#disableFrustumCulling()
*/
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.
*
* @see IDhApiTerrainDataCache
*
* @author James Seibel
* @version 2023-6-22
* @since API 1.0.0
@@ -40,29 +42,50 @@ public interface IDhApiTerrainDataRepo
// getters //
//=========//
/** Returns the terrain datapoint at the given block position, at/or containing the given Y position. */
DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ);
/** 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);
/** @see IDhApiTerrainDataRepo#getSingleDataPointAtBlockPos(IDhApiLevelWrapper, int, int, int, IDhApiTerrainDataCache) */
default DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ) { return this.getSingleDataPointAtBlockPos(levelWrapper, blockPosX, blockPosY, blockPosZ, null); }
/**
* 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>
*
* 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>
* 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>
*
* 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>
* 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>
* 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>
* 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.
*
* @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
* 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.
*
* @since API 3.0.0
*/
DhApiResult<DhApiRaycastResult> raycast(
IDhApiLevelWrapper levelWrapper,
double rayOriginX, double rayOriginY, double rayOriginZ,
float rayDirectionX, float rayDirectionY, float rayDirectionZ,
int maxRayBlockLength);
int maxRayBlockLength,
IDhApiTerrainDataCache dataCache);
@@ -98,15 +143,27 @@ public interface IDhApiTerrainDataRepo
* Notes: <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
* by whatever the current chunk is. <br>
* - This method may not update the LOD data immediately. Any other chunks have
* been queued to update, they will be handled first.
* by whatever the current chunk is. <br>
* - This method may not update the LOD data immediately. Any other chunks that have
* been queued to update will be handled first.
*
* @param levelWrapper the level wrapper that the chunk should be saved to.
* @param chunkObjectArray see {@link IDhApiWorldGenerator#generateChunks} for what objects are expected.
* @throws ClassCastException if chunkObjectArray doesn't contain the right objects.
* 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
* @version 2023-12-16
* @since API 1.1.0
* @since API 2.0.0
*/
public interface IDhApiWrapperFactory
{
@@ -50,7 +50,7 @@ public interface IDhApiWrapperFactory
* @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.
*
* @since API 1.1.0
* @since API 2.0.0
*/
IDhApiBiomeWrapper getBiomeWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) throws ClassCastException;
@@ -67,13 +67,13 @@ public interface IDhApiWrapperFactory
* @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.
*
* @since API 1.1.0
* @since API 2.0.0
*/
IDhApiBlockStateWrapper getBlockStateWrapper(Object[] objectArray, IDhApiLevelWrapper levelWrapper) throws ClassCastException;
/**
* Returns the {@link IDhApiBlockStateWrapper} representing air.
* @since API 1.1.0
* @since API 2.0.0
*/
IDhApiBlockStateWrapper getAirBlockStateWrapper();
@@ -21,7 +21,7 @@ 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;
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
/**
* 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
* @version 2024-2-6
* @since API 1.1.0
* @since API 2.0.0
*/
public interface IDhApiCullingFrustum extends IDhApiOverrideable
{
@@ -41,7 +41,7 @@ public interface IDhApiCullingFrustum extends IDhApiOverrideable
* @param worldMaxBlockY the highest block position this level allows.
* @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
@@ -24,7 +24,7 @@ import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
/**
* @author James Seibel
* @version 2024-1-24
* @since API 1.1.0
* @since API 2.0.0
*/
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.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
/**
* @see IDhApiGenericObjectShaderProgram
*
* @author James Seibel
* @version 2024-1-24
* @since API 1.1.0
* @since API 2.0.0
*/
public interface IDhApiShaderProgram extends IDhApiOverrideable
{
@@ -57,7 +58,7 @@ public interface IDhApiShaderProgram extends IDhApiOverrideable
void fillUniformData(DhApiRenderParam renderParameters);
/** 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. */
void bindVertexBuffer(int vbo);
@@ -19,10 +19,6 @@
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
* if another mod has enabled Distant Horizons' shadow
@@ -35,7 +31,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
*
* @author James Seibel
* @version 2024-2-10
* @since API 1.1.0
* @since API 2.0.0
*/
public interface IDhApiShadowCullingFrustum extends IDhApiCullingFrustum
{
@@ -168,7 +168,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.
*
* @since API 1.1.0
* @since API 2.0.0
*/
default CompletableFuture<Void> generateApiChunks(
int chunkPosMinX,
@@ -189,7 +189,7 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
* 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.
*
* @since API 1.1.0
* @since API 2.0.0
*/
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);
}
@@ -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,6 +21,7 @@ package com.seibel.distanthorizons.api.interfaces.world;
import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper;
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>
@@ -41,7 +42,7 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper
boolean hasSkyLight();
/** Returns the max block height of the level(?) */
int getHeight();
int getMaxHeight();
/**
* Returns the lowest possible block position for the level. <br>
@@ -49,4 +50,10 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper
*/
default int getMinHeight() { return 0; }
/**
* Will return null if called on the server,
* or if called before the renderer has been set up.
*/
IDhApiCustomRenderRegister getRenderRegister();
}
@@ -26,17 +26,20 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
/**
* Fired after Distant Horizons finishes rendering a frame. <br>
* 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
* @version 2024-1-31
* @see DhApiRenderParam
* @version 2024-7-14
* @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. */
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
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
* @version 2024-1-31
* @since API 1.1.0
* @since API 2.0.0
*/
public abstract class DhApiBeforeApplyShaderRenderEvent implements IDhApiCancelableEvent<DhApiRenderParam>
{
@@ -20,9 +20,10 @@
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.IDhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
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>
@@ -30,7 +31,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
*
* @author James Seibel
* @version 2023-1-31
* @since API 1.1.0
* @since API 2.0.0
*
* @see DhApiBeforeRenderEvent
*/
@@ -52,20 +53,29 @@ public abstract class DhApiBeforeBufferRenderEvent implements IDhApiEvent<DhApiB
// parameter object //
//==================//
public static class EventParam extends DhApiRenderParam
public static class EventParam extends DhApiRenderParam implements IDhApiEventParam
{
/**
* Measured in blocks.
* 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);
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
* @version 2024-1-22
* @since API 1.1.0
* @since API 2.0.0
*/
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
* @version 2024-1-31
* @since API 1.1.0
* @since API 2.0.0
*/
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);
@@ -31,7 +31,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
*
* @author James Seibel
* @version 2023-1-31
* @since API 1.1.0
* @since API 2.0.0
*
* @see DhApiBeforeRenderEvent
*/
@@ -29,7 +29,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
*
* @author James Seibel
* @version 2024-1-31
* @since API 1.1.0
* @since API 2.0.0
*
* @see DhApiBeforeRenderPassEvent
*/
@@ -31,7 +31,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
*
* @author James Seibel
* @version 2024-1-31
* @since API 1.1.0
* @since API 2.0.0
*/
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.world.IDhApiLevelWrapper;
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;
/**
@@ -53,7 +54,7 @@ public abstract class DhApiChunkModifiedEvent implements IDhApiEvent<DhApiChunkM
// parameter object //
//==================//
public static class EventParam
public static class EventParam implements IDhApiEventParam
{
/** The saved level. */
public final IDhApiLevelWrapper levelWrapper;
@@ -71,6 +72,15 @@ public abstract class DhApiChunkModifiedEvent implements IDhApiEvent<DhApiChunkM
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;
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;
/**
@@ -28,7 +29,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
*
* @author James Seibel
* @version 2024-3-2
* @since API 1.1.0
* @since API 2.0.0
*/
public abstract class DhApiColorDepthTextureCreatedEvent implements IDhApiEvent<DhApiColorDepthTextureCreatedEvent.EventParam>
{
@@ -48,7 +49,7 @@ public abstract class DhApiColorDepthTextureCreatedEvent implements IDhApiEvent<
// parameter object //
//==================//
public static class EventParam
public static class EventParam implements IDhApiEventParam
{
/** Measured in pixels */
public final int previousWidth;
@@ -72,6 +73,16 @@ public abstract class DhApiColorDepthTextureCreatedEvent implements IDhApiEvent<
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.methods.events.interfaces.IDhApiEvent;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
/**
@@ -49,13 +50,16 @@ public abstract class DhApiLevelLoadEvent implements IDhApiEvent<DhApiLevelLoadE
// parameter object //
//==================//
public static class EventParam
public static class EventParam implements IDhApiEventParam
{
/** The newly loaded level. */
public final IDhApiLevelWrapper levelWrapper;
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;
import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
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;
/**
@@ -49,13 +49,16 @@ public abstract class DhApiLevelUnloadEvent implements IDhApiEvent<DhApiLevelUnl
// parameter object //
//==================//
public static class EventParam
public static class EventParam implements IDhApiEventParam
{
/** The recently unloaded level. */
public final IDhApiLevelWrapper levelWrapper;
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;
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.
@@ -29,7 +30,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
* @version 2024-1-31
* @since API 1.0.0
*/
public class DhApiRenderParam
public class DhApiRenderParam implements IDhApiEventParam
{
/** Indicates what render pass DH is currently rendering */
public final EDhApiRenderPass renderPass;
@@ -49,18 +50,15 @@ public class DhApiRenderParam
public final float farClipPlane;
/** 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. */
public final Mat4f mcModelViewMatrix;
public final DhApiMat4f mcModelViewMatrix;
/** 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. */
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;
@@ -69,24 +67,24 @@ public class DhApiRenderParam
// constructors //
//==============//
public DhApiRenderParam(DhApiRenderParam parent)
{
this(
parent.renderPass,
parent.partialTicks,
parent.nearClipPlane, parent.farClipPlane,
parent.mcProjectionMatrix, parent.mcModelViewMatrix,
parent.dhProjectionMatrix, parent.dhModelViewMatrix,
parent.worldYOffset
);
parent.renderPass,
parent.partialTicks,
parent.nearClipPlane, parent.farClipPlane,
parent.mcProjectionMatrix.copy(), parent.mcModelViewMatrix.copy(),
parent.dhProjectionMatrix.copy(), parent.dhModelViewMatrix.copy(),
parent.worldYOffset
);
}
public DhApiRenderParam(
EDhApiRenderPass renderPass,
float newPartialTicks,
float nearClipPlane, float farClipPlane,
Mat4f newMcProjectionMatrix, Mat4f newMcModelViewMatrix,
Mat4f newDhProjectionMatrix, Mat4f newDhModelViewMatrix,
DhApiMat4f newMcProjectionMatrix, DhApiMat4f newMcModelViewMatrix,
DhApiMat4f newDhProjectionMatrix, DhApiMat4f newDhModelViewMatrix,
int worldYOffset
)
{
@@ -107,4 +105,16 @@ public class DhApiRenderParam
}
//================//
// base overrides //
//================//
@Override
public DhApiRenderParam copy()
{
return new DhApiRenderParam(this);
}
}
@@ -30,7 +30,7 @@ import java.util.List;
*
* @author Builderb0y, James Seibel
* @version 2023-12-21
* @since API 1.1.0
* @since API 2.0.0
*
* @see IDhApiWrapperFactory
* @see DhApiTerrainDataPoint
@@ -20,7 +20,6 @@
package com.seibel.distanthorizons.api.objects.data;
import com.seibel.distanthorizons.api.objects.math.DhApiVec3i;
import com.seibel.distanthorizons.coreapi.util.math.Vec3i;
/**
* 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.pos = blockPos;
@@ -17,46 +17,55 @@
* 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 org.joml.Matrix4fc;
import java.nio.FloatBuffer;
import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable;
/**
* 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
* @version 11-11-2021
* @version 2024-6-30
*/
public class Mat4f
public class DhApiMat4f implements IDhApiCopyable
{
private float m00;
private float m01;
private float m02;
private float m03;
private float m10;
private float m11;
private float m12;
private float m13;
private float m20;
private float m21;
private float m22;
private float m23;
private float m30;
private float m31;
private float m32;
private float m33;
public float m00;
public float m01;
public float m02;
public float m03;
public float m10;
public float m11;
public float m12;
public float m13;
public float m20;
public float m21;
public float m22;
public float m23;
public float m30;
public float m31;
public float m32;
public float m33;
public Mat4f()
{
}
public Mat4f(Mat4f sourceMatrix)
//==============//
// constructors //
//==============//
public DhApiMat4f() { /* all values are 0 */ }
public DhApiMat4f(DhApiMat4f sourceMatrix)
{
this.m00 = sourceMatrix.m00;
this.m01 = sourceMatrix.m01;
@@ -76,163 +85,36 @@ public class Mat4f
this.m33 = sourceMatrix.m33;
}
public Mat4f(Matrix4fc sourceMatrix) { this(convertJomlMatrixToArray(sourceMatrix)); }
private static float[] convertJomlMatrixToArray(Matrix4fc sourceMatrix)
/** Expects the values of the input array to be in row major order (AKA rows then columns) */
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());
buffer.put(bufferIndex(0, 1), sourceMatrix.m01());
buffer.put(bufferIndex(0, 2), sourceMatrix.m02());
buffer.put(bufferIndex(0, 3), sourceMatrix.m03());
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());
m10 = values[4];
m11 = values[5];
m12 = values[6];
m13 = values[7];
return buffer.array();
}
/* Quaternions are not currently needed/implemented
public Matrix4float(Quaternion p_i48104_1_)
{
float f = p_i48104_1_.i();
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);
m20 = values[8];
m21 = values[9];
m22 = values[10];
m23 = values[11];
m30 = values[12];
m31 = values[13];
m32 = values[14];
m33 = values[15];
}
@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)
{
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;
}
//=========//
// methods //
//=========//
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 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;
}
/* 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)
{
this.m00 *= scalar;
@@ -404,81 +279,6 @@ public class Mat4f
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 //
//==================//
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) */
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)
{
return true;
}
else if (obj != null && this.getClass() == obj.getClass())
{
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
{
return false;
}
}
//===============//
// Forge methods //
//===============//
public Mat4f(float[] values)
@Override
public int hashCode()
{
m00 = values[0];
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];
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);
}
public Mat4f(FloatBuffer buffer)
@Override
public String toString()
{
this(buffer.array());
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 set(Mat4f mat)
{
this.m00 = mat.m00;
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)
{
m00 += other.m00;
m01 += other.m01;
m02 += other.m02;
m03 += other.m03;
m10 += other.m10;
m11 += other.m11;
m12 += other.m12;
m13 += other.m13;
m20 += other.m20;
m21 += other.m21;
m22 += other.m22;
m23 += other.m23;
m30 += other.m30;
m31 += other.m31;
m32 += other.m32;
m33 += other.m33;
}
public void multiplyBackward(Mat4f other)
{
Mat4f copy = other.copy();
copy.multiply(this);
this.set(copy);
}
public void setTranslation(float x, float y, float z)
{
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;
}
@Override
public DhApiMat4f copy() { return new DhApiMat4f(this); }
}
@@ -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.methods.events.interfaces.IDhApiCancelableEvent;
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.sharedParameterObjects.DhApiCancelableEventParam;
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
// 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);
if (eventParam instanceof DhApiCancelableEventParam)
@@ -34,14 +34,14 @@ public final class ModInfo
public static final String NAME = "DistantHorizons";
/** Human-readable version of NAME */
public static final String READABLE_NAME = "Distant Horizons";
public static final String VERSION = "2.0.3-a-dev";
public static final String VERSION = "2.1.3-a-dev";
/** Returns true if the current build is an unstable developer build, false otherwise. */
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 */
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 */
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 */
public static final int API_PATH_VERSION = 0;
@@ -19,7 +19,8 @@
package com.seibel.distanthorizons.coreapi.util;
import java.util.ArrayList;
import java.text.CharacterIterator;
import java.text.StringCharacterIterator;
import java.util.Arrays;
/**
@@ -85,4 +86,25 @@ public class StringUtil
return new String(hexChars);
}
/**
* Source:
* https://stackoverflow.com/questions/3758606/how-can-i-convert-byte-size-into-a-human-readable-format-in-java#3758880
*/
public static String convertByteCountToHumanReadableSI(long bytes)
{
if (-1000 < bytes && bytes < 1000)
{
return bytes + " B";
}
CharacterIterator ci = new StringCharacterIterator("kMGTPE");
while (bytes <= -999_950 || bytes >= 999_950)
{
bytes /= 1000;
ci.next();
}
return String.format("%.1f %cB", bytes / 1000.0, ci.current());
}
}
@@ -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];
}
}
+6 -65
View File
@@ -1,6 +1,6 @@
plugins {
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"
@@ -39,36 +39,9 @@ dependencies { // All of these dependencies are in Vanilla Minecraft, but we nee
runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
runtimeOnly "org.lwjgl:lwjgl-tinyfd::$lwjglNatives"
// fast util
shade("it.unimi.dsi:fastutil:${rootProject.fastutil_version}")
// Compression
shade("org.lz4:lz4-java:${rootProject.lz4_version}") // LZ4
shade("com.github.luben:zstd-jni:${rootProject.zstd_version}") // Zstd
shade("org.tukaani:xz:${rootProject.xz_version}") // LZMA
// Sqlite Database
shade("org.xerial:sqlite-jdbc:${rootProject.sqlite_jdbc_version}")
// Netty
shade("io.netty:netty-all:${rootProject.netty_version}")
// NightConfig (includes Toml & Json)
// needed in both common and core
shade("com.electronwill.night-config:toml:${rootProject.nightconfig_version}")
shade("com.electronwill.night-config:json:${rootProject.nightconfig_version}")
// needed for the standalone jar
shade("org.apache.logging.log4j:log4j-core:2.23.1")
shade("org.apache.logging.log4j:log4j-api:2.23.1")
// SVG (not needed atm)
//shade("com.formdev:svgSalamander:${rootProject.svgSalamander_version}")
// FIXME for some reason this line doesn't actually shade in the library
// shade "it.unimi.dsi:fastutil:${rootProject.fastutil_version}" // Add our own fastutil version
// Some other dependencies
@@ -80,43 +53,11 @@ dependencies { // All of these dependencies are in Vanilla Minecraft, but we nee
}
artifacts {
shade shadowJar
shadowedArtifact shadowJar // Setup the configuration shadowedArtifact to be the shadowJar
}
shadowJar {
configurations = [project.configurations.shade]
def librariesLocation = "distanthorizons.libraries"
relocate "it.unimi.dsi.fastutil", "${librariesLocation}.unimi.dsi.fastutil"
// LWJGL
// Only ever shadow the dependencies we use otherwise some stuff would break when running on an external client
relocate "org.lwjgl.system.jawt", "${librariesLocation}.lwjgl.system.jawt"
// Compression
relocate "net.jpountz", "${librariesLocation}.jpountz"
relocate "com.github.luben", "${librariesLocation}.github.luben"
relocate "org.tukaani", "${librariesLocation}.tukaani"
// Sqlite Database
//At the moment, there is a bug in this library which doesnt allow it to be relocated
// relocate "org.sqlite", "${librariesLocation}.sqlite"
// JOML
if (project.hasProperty("embed_joml") && embed_joml == "true")
relocate "org.joml", "${librariesLocation}.joml"
// NightConfig (includes Toml & Json)
relocate "com.electronwill.nightconfig", "${librariesLocation}.electronwill.nightconfig"
// Netty
relocate "io.netty", "${librariesLocation}.netty"
relocate "org.apache.logging", "${librariesLocation}.apache.logging"
def librariesLocation = "DistantHorizons.libraries"
// relocate "it.unimi.dsi.fastutil", "${librariesLocation}.unimi.dsi.fastutil"
mergeServiceFiles()
}
}
@@ -20,6 +20,7 @@
package com.seibel.distanthorizons.core;
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.wrapperInterfaces.IWrapperFactory;
import com.seibel.distanthorizons.coreapi.ModInfo;
@@ -28,10 +29,10 @@ import com.seibel.distanthorizons.core.api.external.methods.config.DhApiConfig;
import com.seibel.distanthorizons.core.api.external.methods.data.DhApiTerrainDataRepo;
import com.seibel.distanthorizons.api.DhApi;
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
import io.netty.buffer.ByteBuf;
import net.jpountz.lz4.LZ4FrameOutputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.tukaani.xz.XZOutputStream;
import java.awt.*;
@@ -47,13 +48,17 @@ public class Initializer
{
// if any library isn't present in the jar its class
// will throw an error (not an exception)
Class<?> compressor = LZ4FrameOutputStream.class;
Class<?> networking = ByteBuf.class;
Class<?> toml = com.electronwill.nightconfig.core.Config.class;
Class<?> fastCompressor = LZ4FrameOutputStream.class;
Class<?> smallCompressor = XZOutputStream.class;
//Class<?> networking = ByteBuf.class;
Class<?> config = com.electronwill.nightconfig.core.Config.class;
Class<?> oldFastUtil = it.unimi.dsi.fastutil.longs.LongArrayList.class; // available in 8.2.1
//Class<?> newFastUtil = it.unimi.dsi.fastutil.ints.IntUnaryOperator.class; // available in 8.5.13
}
catch (Throwable e)
{
LOGGER.fatal("Critical programmer error: One or more libraries aren't present. Error: [" + e.getMessage() + "].");
// throwing here should crash the game, notifying the developer that something is wrong
throw e;
}
@@ -89,6 +94,7 @@ public class Initializer
DhApi.Delayed.terrainRepo = DhApiTerrainDataRepo.INSTANCE;
DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE;
DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE;
DhApi.Delayed.customRenderObjectFactory = GenericRenderObjectFactory.INSTANCE;
DhApi.Delayed.wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
if (DhApi.Delayed.wrapperFactory == null)
{
@@ -0,0 +1,46 @@
/*
* 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.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
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.core.config.Config;
public class DhApiGenericRenderingConfig implements IDhApiGenericRenderingConfig
{
public static DhApiGenericRenderingConfig INSTANCE = new DhApiGenericRenderingConfig();
private DhApiGenericRenderingConfig() { }
@Override
public IDhApiConfigValue<Boolean> renderingEnabled()
{ return new DhApiConfigValue<Boolean, Boolean>(Config.Client.Advanced.Graphics.GenericRendering.enableRendering); }
@Override
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); }
}
@@ -36,7 +36,4 @@ public class DhApiGpuBuffersConfig implements IDhApiGpuBuffersConfig
public IDhApiConfigValue<EDhApiGpuUploadMethod> gpuUploadMethod()
{ return new DhApiConfigValue<>(Config.Client.Advanced.GpuBuffers.gpuUploadMethod); }
public IDhApiConfigValue<Integer> gpuUploadPerMegabyteInMilliseconds()
{ return new DhApiConfigValue<>(Config.Client.Advanced.GpuBuffers.gpuUploadPerMegabyteInMilliseconds); }
}
@@ -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.rendering.EDhApiTransparency;
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.IDhApiFogConfig;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGraphicsConfig;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiNoiseTextureConfig;
import com.seibel.distanthorizons.api.interfaces.config.client.*;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode;
import com.seibel.distanthorizons.core.config.Config;
@@ -42,9 +39,14 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig
// inner layers //
//==============//
@Override
public IDhApiFogConfig fog() { return DhApiFogConfig.INSTANCE; }
@Override
public IDhApiAmbientOcclusionConfig ambientOcclusion() { return DhApiAmbientOcclusionConfig.INSTANCE; }
@Override
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;
import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataCache;
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
import com.seibel.distanthorizons.api.objects.DhApiResult;
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.LodUtil;
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.wrapperInterfaces.IWrapperFactory;
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.ILevelWrapper;
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
import com.seibel.distanthorizons.coreapi.util.math.Vec3i;
import com.seibel.distanthorizons.core.util.math.Vec3d;
import com.seibel.distanthorizons.core.util.math.Vec3i;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.concurrent.ExecutionException;
@@ -56,9 +58,6 @@ import java.util.concurrent.ExecutionException;
/**
* Allows interfacing with the terrain data Distant Horizons has stored.
*
* @author James Seibel
* @version 2022-11-19
*/
public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
{
@@ -68,12 +67,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
// debugging values
private static volatile boolean debugThreadRunning = false;
private static String currentDebugBiomeName = "";
private static int currentDebugBlockColorInt = -1;
private static DhApiTerrainDataCache debugDataCache = new DhApiTerrainDataCache();
private static DhApiVec3i currentDebugVec3i = new Vec3i();
//=============//
// constructor //
//=============//
private DhApiTerrainDataRepo()
{
@@ -86,41 +88,32 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
//================//
@Override
public DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ)
{
return getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY);
}
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); }
@Override
public DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ)
{
return getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null);
}
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); }
@Override
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ)
{
return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPosX, 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); }
@Override
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ)
{
return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.REGION_DETAIL_LEVEL, regionPosX, 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); }
@Override
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ)
{
return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(detailLevel, posX, 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); }
// private getters //
/** 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)
{
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.
*/
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);
int widthOfAreaInBlocks = BitShiftUtil.powerOfTwo(requestedAreaPos.detailLevel);
@@ -154,7 +149,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
for (int z = 0; z < widthOfAreaInBlocks; 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)
{
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>
* 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();
if (currentWorld == null)
{
@@ -194,6 +196,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
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);
if (level == null)
{
@@ -205,74 +216,100 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
byte sectionDetailLevel = (byte) (requestedDetailLevel + DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL);
// get the positions for this request
DhSectionPos sectionPos = requestedColumnPos.getSectionPosWithSectionDetailLevel(sectionDetailLevel);
long sectionPos = requestedColumnPos.getSectionPosWithSectionDetailLevel(sectionDetailLevel);
DhLodPos relativePos = requestedColumnPos.getDhSectionRelativePositionForDetailLevel();
//=====================//
// get the data source //
//=====================//
try
{
// attempt to get/generate the data source for this section
FullDataSourceV2 dataSource = level.getFullDataProvider().getAsync(sectionPos).get();
FullDataSourceV2 dataSource = null;
// try using the cached data if possible
if (dataCache != null)
{
dataSource = dataCache.get(sectionPos);
}
if (dataSource == null)
{
return DhApiResult.createFail("Unable to find/generate any data at the " + DhSectionPos.class.getSimpleName() + " [" + sectionPos + "].");
}
else
{
// attempt to get the LOD data from the data source
FullDataPointIdMap mapping = dataSource.mapping;
LongArrayList dataColumn = dataSource.get(relativePos.x, relativePos.z);
if (dataColumn != null)
// attempt to get/generate the data source for this section
dataSource = level.getFullDataProvider().getAsync(sectionPos).get();
if (dataSource == null)
{
int dataColumnIndexCount = dataColumn.size();
DhApiTerrainDataPoint[] returnArray = new DhApiTerrainDataPoint[dataColumnIndexCount];
long dataPoint;
return DhApiResult.createFail("Unable to find/generate any data at the " + DhSectionPos.class.getSimpleName() + " [" + DhSectionPos.toString(sectionPos) + "].");
}
dataCache.add(sectionPos, dataSource);
}
//===============================//
// get LOD data from data source //
//===============================//
FullDataPointIdMap mapping = dataSource.mapping;
LongArrayList dataColumn = dataSource.get(relativePos.x, relativePos.z);
if (dataColumn != null)
{
int dataColumnIndexCount = dataColumn.size();
DhApiTerrainDataPoint[] returnArray = new DhApiTerrainDataPoint[dataColumnIndexCount];
long dataPoint;
boolean getSpecificYCoordinate = nullableBlockYPos != null;
int levelMinimumHeight = levelWrapper.getMinHeight();
// search for a datapoint that contains the block y position
for (int i = 0; i < dataColumnIndexCount; i++)
{
dataPoint = dataColumn.getLong(i);
boolean getSpecificYCoordinate = nullableBlockYPos != null;
int levelMinimumHeight = levelWrapper.getMinHeight();
// search for a datapoint that contains the block y position
for (int i = 0; i < dataColumnIndexCount; i++)
if (!getSpecificYCoordinate)
{
dataPoint = dataColumn.getLong(i);
if (!getSpecificYCoordinate)
// if we aren't look for a specific datapoint, add each datapoint to the return array
returnArray[i] = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint);
}
else
{
// we are looking for a specific datapoint,
// don't look at null ones
if (dataPoint != 0)
{
// if we aren't look for a specific datapoint, add each datapoint to the return array
returnArray[i] = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint);
}
else
{
// we are looking for a specific datapoint,
// don't look at null ones
if (dataPoint != 0)
int requestedY = nullableBlockYPos;
int bottomY = FullDataPointUtil.getBottomY(dataPoint) + levelMinimumHeight;
int height = FullDataPointUtil.getHeight(dataPoint);
int topY = bottomY + height;
// does this datapoint contain the requested Y position?
if (bottomY <= requestedY && requestedY < topY) // blockPositions start from the bottom of the block, thus "<=" for bottomY, just "<" for topY
{
int requestedY = nullableBlockYPos;
int bottomY = FullDataPointUtil.getBottomY(dataPoint) + levelMinimumHeight;
int height = FullDataPointUtil.getHeight(dataPoint);
int topY = bottomY + height;
// does this datapoint contain the requested Y position?
if (bottomY <= requestedY && requestedY < topY) // blockPositions start from the bottom of the block, thus "<=" for bottomY, just "<" for topY
{
// this datapoint contains the requested block position, return it
DhApiTerrainDataPoint apiTerrainData = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint);
return DhApiResult.createSuccess(new DhApiTerrainDataPoint[]{apiTerrainData});
}
// this datapoint contains the requested block position, return it
DhApiTerrainDataPoint apiTerrainData = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint);
return DhApiResult.createSuccess(new DhApiTerrainDataPoint[]{apiTerrainData});
}
}
}
// return all collected data
return DhApiResult.createSuccess(returnArray);
}
// 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 all collected data
return DhApiResult.createSuccess(returnArray);
}
// 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]);
}
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
LOGGER.error("Unexpected exception in getTerrainDataColumnArray. Error: [" + e.getMessage() + "]", e);
@@ -306,9 +343,11 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
IDhApiLevelWrapper levelWrapper,
double rayOriginX, double rayOriginY, double rayOriginZ,
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 +356,17 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
* Works by walking through the world and attempting to get the LOD <br>
* 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();
int minBlockHeight = levelWrapper.getMinHeight();
int maxBlockHeight = levelWrapper.getHeight();
int maxBlockHeight = levelWrapper.getMaxHeight();
@@ -346,7 +390,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
for (Vec3i columnPos : columnPositions)
{
// 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 there was an error, stop and return it
@@ -414,7 +458,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
*/
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++)
{
@@ -469,6 +513,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
//=============//
// API helpers //
//=============//
@Override
public IDhApiTerrainDataCache getSoftCache() { return new DhApiTerrainDataCache(); }
//===============//
// debug methods //
//===============//
@@ -485,15 +538,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
Thread thread = new Thread(() -> {
try
{
DhApiResult<DhApiTerrainDataPoint> single = getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY);
DhApiResult<DhApiTerrainDataPoint[]> column = getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null);
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, debugDataCache);
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);
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))
{
currentDebugVec3i = rayCast.payload.pos;
@@ -38,7 +38,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
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.renderer.TestRenderer;
import com.seibel.distanthorizons.core.util.RenderUtil;
@@ -55,6 +55,8 @@ import org.lwjgl.glfw.GLFW;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
/**
@@ -69,7 +71,7 @@ public class ClientApi
public static boolean prefLoggerEnabled = false;
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 IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
@@ -78,9 +80,9 @@ public class ClientApi
public static final long SPAM_LOGGER_FLUSH_NS = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
private boolean configOverrideReminderPrinted = false;
private boolean lowMemoryWarningPrinted = false;
private boolean migrationMessageShown = false;
private boolean showMigrationMessageNextFrame = false;
private final Queue<String> chatMessageQueueForNextFrame = new LinkedBlockingQueue<>();
public boolean rendererDisabledBecauseOfExceptions = false;
@@ -474,30 +476,7 @@ public class ClientApi
{
// logging //
// dev build
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 experimental build version [" + ModInfo.VERSION+"].");
MC.sendChatMessage("You are running an unsupported version of Distant Horizons!");
MC.sendChatMessage("Here be dragons!");
MC.sendChatMessage("");
}
// data migration
if (this.showMigrationMessageNextFrame
&& !this.migrationMessageShown
&& Config.Client.Advanced.LodBuilding.showMigrationChatWarning.get())
{
this.showMigrationMessageNextFrame = false;
this.migrationMessageShown = true;
MC.sendChatMessage("Old Distant Horizons data is being migrated.");
MC.sendChatMessage("During migration LODs may load slowly and DH world gen is disabled.");
MC.sendChatMessage("");
}
this.sendChatMessagesNow();
IProfilerWrapper profiler = MC.getProfiler();
profiler.pop(); // get out of "terrain"
@@ -573,13 +552,13 @@ public class ClientApi
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)
{
profiler.push("Render Debug");
ClientApi.testRenderer.render();
ClientApi.TEST_RENDERER.render();
profiler.pop();
}
}
@@ -594,7 +573,7 @@ public class ClientApi
if (DhApi.Delayed.renderProxy.getDeferTransparentRendering())
{
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, renderEventParam);
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null);
}
}
}
@@ -605,10 +584,22 @@ public class ClientApi
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons renderer has encountered an exception!");
MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues.");
MC.sendChatMessage("\u00A74Please restart your game to re-enable Distant Horizons' LOD rendering.");
MC.sendChatMessage("\u00A74Exception detail: " + e);
}
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.push("terrain"); // go back into "terrain"
}
@@ -648,7 +639,57 @@ public class ClientApi
}
}
// TODO there's probably a better way of handling chat messages
public void showMigrationMessageOnNextFrame() { this.showMigrationMessageNextFrame = true; }
private void sendChatMessagesNow()
{
// dev build
if (ModInfo.IS_DEV_BUILD && !this.configOverrideReminderPrinted && MC.playerExists())
{
this.configOverrideReminderPrinted = true;
// remind the user that this is a development build
MC.sendChatMessage("\u00A72" + "Distant Horizons: nightly/unstable build, version: [" + ModInfo.VERSION+"]." + "\u00A7r");
MC.sendChatMessage("Issues may occur with this version.");
MC.sendChatMessage("Here be dragons!");
MC.sendChatMessage("");
}
// 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)
{
MC.sendChatMessage("\u00A76" + "Distant Horizons: Low memory detected." + "\u00A7r");
MC.sendChatMessage("Stuttering or low FPS may occur.");
MC.sendChatMessage("Please increase Minecraft's available memory to 4 gigabytes.");
MC.sendChatMessage("This warning can be disabled in DH's config under Advanced -> Logging.");
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);
}
}
/**
* 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.
*/
public void showChatMessageNextFrame(String chatMessage) { this.chatMessageQueueForNextFrame.add(chatMessage); }
}
@@ -141,7 +141,7 @@ public class ServerApi
//=======================//
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); }
@@ -29,7 +29,8 @@ import com.seibel.distanthorizons.core.logging.f3.F3Screen;
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
import com.seibel.distanthorizons.core.pos.DhChunkPos;
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
import com.seibel.distanthorizons.core.util.TimerUtil;
import com.seibel.distanthorizons.core.util.objects.Pair;
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
@@ -41,10 +42,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import org.apache.logging.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
@@ -59,7 +57,7 @@ public class SharedApi
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 */
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");
@@ -68,23 +66,13 @@ public class SharedApi
private static int lastWorldGenTickDelta = 0;
private static long lastOverloadedLogMessageMsTime = 0;
public F3Screen.DynamicMessage f3Message;
//=============//
// constructor //
//=============//
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);
});
}
private SharedApi() { }
public static void init() { Initializer.init(); }
@@ -110,6 +98,10 @@ public class SharedApi
ThreadPoolUtil.shutdownThreadPools();
DebugRenderer.clearRenderables();
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
UPDATING_CHUNK_POS_SET.clear();
// recommend that the garbage collector cleans up any objects from the old world and thread pools
System.gc();
@@ -144,7 +136,8 @@ public class SharedApi
* 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.
*/
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))); }
/** handles both block place and break events */
@@ -221,7 +214,13 @@ public class SharedApi
if (msBetweenLastLog >= MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE)
{
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;
@@ -300,6 +299,35 @@ public class SharedApi
try
{
// check if this chunk has been converted into an LOD already
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 (oldChunkHash == newChunkHash)
{
// if the chunk hashes are the same then we don't need to bother with lighting the chunk
// or creating/updating the LODs
//LOGGER.info("skipping: "+chunkWrapper.getChunkPos()+" "+newChunkHash);
return;
}
else
{
//LOGGER.info("g: "+chunkWrapper.getChunkPos()+" "+newChunkHash);
}
// having a list of the nearby chunks is needed for lighting and beacon generation
ArrayList<IChunkWrapper> nearbyChunkList;
if (neighbourChunkList != null)
{
nearbyChunkList = neighbourChunkList;
}
else
{
nearbyChunkList = new ArrayList<>(1);
nearbyChunkList.add(chunkWrapper);
}
// 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 onlyUseDhLighting = Config.Client.Advanced.LodBuilding.onlyUseDhLightingEngine.get();
@@ -318,22 +346,18 @@ public class SharedApi
else
{
// generate the chunk's lighting, using neighboring chunks if present
ArrayList<IChunkWrapper> nearbyChunkList;
if (neighbourChunkList != null)
{
nearbyChunkList = neighbourChunkList;
}
else
{
nearbyChunkList = new ArrayList<>(1);
nearbyChunkList.add(chunkWrapper);
}
DhLightingEngine.INSTANCE.lightChunk(chunkWrapper, nearbyChunkList, dhLevel.hasSkyLight() ? 15 : 0);
}
// get this chunk's active beacons
List<BeaconBeamDTO> beaconBeamList = chunkWrapper.getAllActiveBeacons(nearbyChunkList);
dhLevel.setBeaconBeamsForChunk(chunkWrapper.getChunkPos(), beaconBeamList);
dhLevel.updateChunkAsync(chunkWrapper);
dhLevel.setChunkHash(chunkWrapper.getChunkPos(), newChunkHash);
}
catch (Exception e)
{
@@ -364,4 +388,18 @@ public class SharedApi
}
//=========//
// 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;
}
}
@@ -106,6 +106,7 @@ public class Config
public static ConfigEntry<Boolean> optionsButton = new ConfigEntry.Builder<Boolean>()
.set(true)
.setAppearance(EConfigEntryAppearance.ONLY_IN_FILE)
.comment("" +
"Should Distant Horizon's config button appear in the options screen next to fov slider?")
.build();
@@ -135,6 +136,7 @@ public class Config
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 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();
@@ -279,7 +281,7 @@ public class Config
private static final Double FOG_RANGE_MAX = Math.sqrt(2.0);
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(""
+ "At what distance should the far fog start? \n"
+ "\n"
@@ -510,7 +512,8 @@ public class Config
public static ConfigEntry<Integer> noiseSteps = new ConfigEntry.Builder<Integer>()
.setMinDefaultMax(1, 4, null)
.comment(""
+ "How many steps of noise should be applied to LODs?")
+ "How many steps of noise should be applied to LODs?"
+ "")
.build();
public static ConfigEntry<Double> noiseIntensity = new ConfigEntry.Builder<Double>() // TODO: Make this a float (the ClassicConfigGUI doesn't support floats)
@@ -523,7 +526,34 @@ public class Config
.setMinDefaultMax(0, 1024, null)
.comment(""
+ "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();
}
@@ -715,7 +745,7 @@ public class Config
.build();
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(""
+ "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"
@@ -751,6 +781,20 @@ public class Config
+ "")
.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>()
.set(EDhApiDataCompressionMode.LZMA2)
.comment(""
@@ -771,12 +815,6 @@ public class Config
+ "Estimated average DTO read speed: 1.85 ms\n"
+ "Estimated average DTO write speed: 9.46 ms\n"
+ "\n"
+ EDhApiDataCompressionMode.Z_STD + " \n"
+ "A good middle ground between speed and compression.\n"
+ "Expected Compression Ratio: 0.21\n"
+ "Estimated average DTO read speed: 11.78 ms\n"
+ "Estimated average DTO write speed: 16.77 ms\n"
+ "\n"
+ EDhApiDataCompressionMode.LZMA2 + " \n"
+ "Slow but very good compression.\n"
+ "Expected Compression Ratio: 0.14\n"
@@ -805,12 +843,12 @@ public class Config
+ "")
.build();
public static ConfigEntry<Boolean> showMigrationChatWarning = new ConfigEntry.Builder<Boolean>()
.set(true)
.comment(""
+ "Determines if a message should be displayed in the chat when LOD migration starts. \n"
+ "")
.build();
//public static ConfigEntry<Boolean> showMigrationChatWarning = new ConfigEntry.Builder<Boolean>()
// .set(true)
// .comment(""
// + "Determines if a message should be displayed in the chat when LOD migration starts. \n"
// + "")
// .build();
}
@@ -1016,30 +1054,6 @@ public class Config
+ "")
.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
@@ -1059,11 +1073,12 @@ public class Config
.build();
public static ConfigEntry<EDhApiUpdateBranch> updateBranch = new ConfigEntry.Builder<EDhApiUpdateBranch>()
.set(
ModInfo.IS_DEV_BUILD? EDhApiUpdateBranch.NIGHTLY: EDhApiUpdateBranch.STABLE // If it's already a nightly build, then download the nightly build ofc
)
.set(EDhApiUpdateBranch.AUTO)
.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();
}
@@ -1072,68 +1087,76 @@ public class Config
// TODO add change all option
// TODO default to error chat and info file
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)
.comment(""
+ "If enabled, the mod will log information about the world generation process. \n"
+ "This can be useful for debugging.")
.build();
public static ConfigEntry<EDhApiLoggerMode> logWorldGenPerformance = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_FILE)
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
.comment(""
+ "If enabled, the mod will log performance about the world generation process. \n"
+ "This can be useful for debugging.")
.build();
public static ConfigEntry<EDhApiLoggerMode> logWorldGenLoadEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_FILE)
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
.comment(""
+ "If enabled, the mod will log information about the world generation process. \n"
+ "This can be useful for debugging.")
.build();
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)
.comment(""
+ "If enabled, the mod will log information about the LOD generation process. \n"
+ "This can be useful for debugging.")
.build();
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)
.comment(""
+ "If enabled, the mod will log information about the renderer buffer process. \n"
+ "This can be useful for debugging.")
.build();
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)
.comment(""
+ "If enabled, the mod will log information about the renderer OpenGL process. \n"
+ "This can be useful for debugging.")
.build();
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)
.comment(""
+ "If enabled, the mod will log information about file read/write operations. \n"
+ "This can be useful for debugging.")
.build();
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)
.comment(""
+ "If enabled, the mod will log information about file sub-dimension operations. \n"
+ "This can be useful for debugging.")
.build();
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)
.comment(""
+ "If enabled, the mod will log information about network operations. \n"
+ "This can be useful for debugging.")
.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 class Debugging
@@ -1201,6 +1224,15 @@ public class Config
+ "")
.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
public static ConfigEntry<Boolean> allowUnsafeValues = new ConfigEntry.Builder<Boolean>()
.set(false)
@@ -1258,6 +1290,11 @@ public class Config
.comment("Render LOD section status?")
.build();
public static ConfigEntry<Boolean> showQuadTreeRenderStatus = new ConfigEntry.Builder<Boolean>()
.set(false)
.comment("Render Quad Tree Rendering status?")
.build();
public static ConfigEntry<Boolean> showFullDataUpdateStatus = new ConfigEntry.Builder<Boolean>()
.set(false)
.comment("Render full data update/lock status?")
@@ -37,28 +37,27 @@ public class ThreadPresetConfigEventHandler extends AbstractPresetConfigEventHan
public static final ThreadPresetConfigEventHandler INSTANCE = new ThreadPresetConfigEventHandler();
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,
new HashMap<EDhApiThreadPreset, Integer>()
{{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 1);
this.put(EDhApiThreadPreset.LOW_IMPACT, getWorldGenDefaultThreadCount());
this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.25));
this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.5));
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0));
this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.15));
this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.25));
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,
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.BALANCED, LOW_THREAD_COUNT_CPU ? 0.5 : 0.75);
this.put(EDhApiThreadPreset.AGGRESSIVE, LOW_THREAD_COUNT_CPU ? 0.75 : 1.0);
this.put(EDhApiThreadPreset.BALANCED, 0.75);
this.put(EDhApiThreadPreset.AGGRESSIVE, 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.BALANCED, 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,
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.BALANCED, 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,
new HashMap<EDhApiThreadPreset, Integer>()
{{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 1);
this.put(EDhApiThreadPreset.LOW_IMPACT, getUpdatePropagatorDefaultThreadCount());
this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.5));
this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.75));
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, getThreadCountByPercent(1.0));
this.put(EDhApiThreadPreset.BALANCED, getThreadCountByPercent(0.25));
this.put(EDhApiThreadPreset.AGGRESSIVE, getThreadCountByPercent(0.50));
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,
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.BALANCED, 0.75);
this.put(EDhApiThreadPreset.AGGRESSIVE, 1.0);
this.put(EDhApiThreadPreset.BALANCED, 0.50);
this.put(EDhApiThreadPreset.AGGRESSIVE, 0.75);
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.BALANCED, getThreadCountByPercent(0.2));
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,
new HashMap<EDhApiThreadPreset, Double>()
{{
this.put(EDhApiThreadPreset.MINIMAL_IMPACT, 0.1);
this.put(EDhApiThreadPreset.LOW_IMPACT, getLodBuilderDefaultRunTimeRatio());
this.put(EDhApiThreadPreset.BALANCED, LOW_THREAD_COUNT_CPU ? 0.5 : 0.75);
this.put(EDhApiThreadPreset.AGGRESSIVE, 1.0);
this.put(EDhApiThreadPreset.BALANCED, 0.5);
this.put(EDhApiThreadPreset.AGGRESSIVE, 0.75);
this.put(EDhApiThreadPreset.I_PAID_FOR_THE_WHOLE_CPU, 1.0);
}});
@@ -265,7 +265,11 @@ public class ConfigFileHandling
)
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()
{
GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer());
GLProxy.ensureAllGLJobCompleted();
sharedContextBuffer = createTextingBuffer();
sameContextBuffer = createTextingBuffer();
}
@@ -27,6 +27,7 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance
*
* @author coolGi
*/
@Deprecated // FIXME doesn't work with localization
public class ConfigLinkedEntry extends AbstractConfigType<AbstractConfigType<?, ?>, ConfigLinkedEntry>
{
public ConfigLinkedEntry(AbstractConfigType<?, ?> value)
@@ -21,6 +21,8 @@ package com.seibel.distanthorizons.core.dataObjects.fullData;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.objects.DataCorruptedException;
import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataInputStream;
import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataOutputStream;
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
@@ -65,7 +67,7 @@ public class FullDataPointIdMap
private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
/** should only be used for debugging */
private DhSectionPos pos;
private long pos;
/** The index should be the same as the Entry's ID */
private final ArrayList<Entry> entryList = new ArrayList<>();
@@ -77,7 +79,7 @@ public class FullDataPointIdMap
// constructor //
//=============//
public FullDataPointIdMap(DhSectionPos pos) { this.pos = pos; }
public FullDataPointIdMap(long pos) { this.pos = pos; }
@@ -117,9 +119,11 @@ public class FullDataPointIdMap
/** @return -1 if the list is empty */
public int getMaxValidId() { return this.entryList.size() - 1; }
public int size() { return this.entryList.size(); }
public boolean isEmpty() { return this.entryList.isEmpty(); }
public DhSectionPos getPos() { return this.pos; }
public long getPos() { return this.pos; }
@@ -168,9 +172,67 @@ public class FullDataPointIdMap
}
}
/** allows for adding duplicate {@link Entry} */
private void add(Entry biomeBlockStateEntry, boolean useWriteLocks)
{
try
{
if (useWriteLocks)
{
this.readWriteLock.writeLock().lock();
}
int id = this.entryList.size();
this.entryList.add(biomeBlockStateEntry);
this.idMap.put(biomeBlockStateEntry, id);
}
finally
{
if (useWriteLocks)
{
this.readWriteLock.writeLock().unlock();
}
}
}
/**
* Adds each entry from the given map to this map.
* Adds every {@link Entry} from inputMap into this map. <br>
* Allows duplicate entries. <br><br>
*
* Allowing duplicate entries should be done if a datasource is just being read in and
* a merge step isn't being done afterwards. If duplicates are removed it may cause
* the ID's to get out of sync since everything will be shifted down after the removed
* ID(s).
*/
public void addAll(FullDataPointIdMap inputMap)
{
try
{
//LOGGER.trace("adding {" + this.pos + ", " + this.entryList.size() + "} and {" + inputMap.pos + ", " + inputMap.entryList.size() + "}");
inputMap.readWriteLock.readLock().lock();
this.readWriteLock.writeLock().lock();
ArrayList<Entry> entriesToMerge = inputMap.entryList;
for (int i = 0; i < entriesToMerge.size(); i++)
{
Entry entity = entriesToMerge.get(i);
this.add(entity, false);
}
}
finally
{
this.readWriteLock.writeLock().unlock();
inputMap.readWriteLock.readLock().unlock();
//LOGGER.trace("finished merging {" + this.pos + ", " + this.entryList.size() + "} and {" + inputMap.pos + ", " + inputMap.entryList.size() + "}");
}
}
/**
* Adds each entry from the given map to this map. <br><br>
*
* Note: when using this function be careful about re-mapping the
* same data source multiple times.
@@ -208,7 +270,7 @@ public class FullDataPointIdMap
}
/** Should only be used if this map is going to be reused, otherwise bad things will happen. */
public void clear(DhSectionPos pos)
public void clear(long pos)
{
this.pos = pos;
this.entryList.clear();
@@ -259,9 +321,14 @@ public class FullDataPointIdMap
}
/** Creates a new IdBiomeBlockStateMap from the given UTF formatted stream */
public static FullDataPointIdMap deserialize(DhDataInputStream inputStream, DhSectionPos pos, ILevelWrapper levelWrapper) throws IOException, InterruptedException
public static FullDataPointIdMap deserialize(DhDataInputStream inputStream, long pos, ILevelWrapper levelWrapper) throws IOException, InterruptedException, DataCorruptedException
{
int entityCount = inputStream.readInt();
if (entityCount < 0)
{
throw new DataCorruptedException("FullDataPointIdMap deserialize entry count should have a number greater than or equal to 0, returned value ["+entityCount+"].");
}
// only used when debugging
HashMap<String, FullDataPointIdMap.Entry> dataPointEntryBySerialization = new HashMap<>();
@@ -269,6 +336,13 @@ public class FullDataPointIdMap
FullDataPointIdMap newMap = new FullDataPointIdMap(pos);
for (int i = 0; i < entityCount; i++)
{
// necessary to prevent issues with deserializing objects after the level has been closed
if (Thread.interrupted())
{
throw new InterruptedException(FullDataPointIdMap.class.getSimpleName() + " task interrupted.");
}
String entryString = inputStream.readUTF();
Entry newEntry = Entry.deserialize(entryString, levelWrapper);
newMap.entryList.add(newEntry);
@@ -287,7 +361,11 @@ public class FullDataPointIdMap
}
}
//LOGGER.trace("deserialized " + pos + " " + newMap.entryList.size() + "-" + entityCount);
if (newMap.size() != entityCount)
{
// if the mappings are out of sync then the LODs will render incorrectly due to IDs being wrong
LodUtil.assertNotReach("ID maps failed to deserialize for pos: ["+ DhSectionPos.toString(pos)+"], incorrect entity count. Expected count ["+entityCount+"], actual count ["+newMap.size()+"]");
}
return newMap;
}
@@ -457,22 +535,16 @@ public class FullDataPointIdMap
public String serialize() { return this.biome.getSerialString() + BLOCK_STATE_SEPARATOR_STRING + this.blockState.getSerialString(); }
public static Entry deserialize(String str, ILevelWrapper levelWrapper) throws IOException, InterruptedException
public static Entry deserialize(String str, ILevelWrapper levelWrapper) throws IOException, DataCorruptedException
{
String[] stringArray = str.split(BLOCK_STATE_SEPARATOR_STRING);
if (stringArray.length != 2)
{
throw new IOException("Failed to deserialize BiomeBlockStateEntry");
throw new DataCorruptedException("Failed to deserialize BiomeBlockStateEntry");
}
// necessary to prevent issues with deserializing objects after the level has been closed
if (Thread.interrupted())
{
throw new InterruptedException(FullDataPointIdMap.class.getSimpleName() + " task interrupted.");
}
IBiomeWrapper biome = WRAPPER_FACTORY.deserializeBiomeWrapper(stringArray[0], levelWrapper);
IBlockStateWrapper blockState = WRAPPER_FACTORY.deserializeBlockStateWrapper(stringArray[1], levelWrapper);
IBiomeWrapper biome = WRAPPER_FACTORY.deserializeBiomeWrapperOrGetDefault(stringArray[0], levelWrapper);
IBlockStateWrapper blockState = WRAPPER_FACTORY.deserializeBlockStateWrapperOrGetDefault(stringArray[1], levelWrapper);
return Entry.getEntry(biome, blockState);
}
@@ -27,6 +27,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV1DTO;
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.objects.DataCorruptedException;
import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataInputStream;
import com.seibel.distanthorizons.core.util.objects.dataStreams.DhDataOutputStream;
import com.seibel.distanthorizons.core.dataObjects.fullData.FullDataPointIdMap;
@@ -74,7 +75,7 @@ public class FullDataSourceV1 implements IDataSource<IDhLevel>
/** A flattened 2D array (for the X and Z directions) containing an array for the Y direction. */
private final long[][] dataArrays;
private DhSectionPos sectionPos;
private long pos;
private boolean isEmpty = true;
@@ -84,12 +85,12 @@ public class FullDataSourceV1 implements IDataSource<IDhLevel>
// constructors //
//==============//
public static FullDataSourceV1 createEmpty(DhSectionPos pos) { return new FullDataSourceV1(pos); }
private FullDataSourceV1(DhSectionPos sectionPos)
public static FullDataSourceV1 createEmpty(long pos) { return new FullDataSourceV1(pos); }
private FullDataSourceV1(long pos)
{
this.dataArrays = new long[WIDTH * WIDTH][0];
this.mapping = new FullDataPointIdMap(sectionPos);
this.sectionPos = sectionPos;
this.mapping = new FullDataPointIdMap(pos);
this.pos = pos;
}
@@ -110,19 +111,21 @@ public class FullDataSourceV1 implements IDataSource<IDhLevel>
//=====================//
@Override
public DhSectionPos getKey() { return this.sectionPos; }
public Long getKey() { return this.pos; }
@Override
public String getKeyDisplayString() { return DhSectionPos.toString(this.pos); }
@Override
public DhSectionPos getPos() { return this.sectionPos; }
public Long getPos() { return this.pos; }
public void resizeDataStructuresForRepopulation(DhSectionPos pos)
public void resizeDataStructuresForRepopulation(long pos)
{
// no data structures need to be changed, only the source's position
this.sectionPos = pos;
this.pos = pos;
}
@Override
public byte getDataDetailLevel() { return (byte) (this.sectionPos.getDetailLevel() - SECTION_SIZE_OFFSET); }
public byte getDataDetailLevel() { return (byte) (DhSectionPos.getDetailLevel(this.pos) - SECTION_SIZE_OFFSET); }
public boolean isEmpty() { return this.isEmpty; }
@@ -152,7 +155,7 @@ public class FullDataSourceV1 implements IDataSource<IDhLevel>
* Clears and then overwrites any data in this object with the data from the given file and stream.
* This is expected to be used with an existing {@link FullDataSourceV1} and can be used in place of a constructor to reuse an existing {@link FullDataSourceV1} object.
*/
public void repopulateFromStream(FullDataSourceV1DTO dto, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException
public void repopulateFromStream(FullDataSourceV1DTO dto, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException, DataCorruptedException
{
// clear/overwrite the old data
this.resizeDataStructuresForRepopulation(dto.pos);
@@ -166,7 +169,7 @@ public class FullDataSourceV1 implements IDataSource<IDhLevel>
* Overwrites any data in this object with the data from the given file and stream.
* This is expected to be used with an empty {@link FullDataSourceV1} and functions similar to a constructor.
*/
public void populateFromStream(FullDataSourceV1DTO dto, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException
public void populateFromStream(FullDataSourceV1DTO dto, DhDataInputStream inputStream, IDhLevel level) throws IOException, InterruptedException, DataCorruptedException
{
FullDataSourceSummaryData summaryData = this.readSourceSummaryInfo(dto, inputStream, level);
this.setSourceSummaryData(summaryData);
@@ -361,7 +364,7 @@ public class FullDataSourceV1 implements IDataSource<IDhLevel>
outputStream.writeInt(DATA_GUARD_BYTE);
this.mapping.serialize(outputStream);
}
public FullDataPointIdMap readIdMappings(DhDataInputStream inputStream, ILevelWrapper levelWrapper) throws IOException, InterruptedException
public FullDataPointIdMap readIdMappings(DhDataInputStream inputStream, ILevelWrapper levelWrapper) throws IOException, InterruptedException, DataCorruptedException
{
int guardByte = inputStream.readInt();
if (guardByte != DATA_GUARD_BYTE)
@@ -369,7 +372,7 @@ public class FullDataSourceV1 implements IDataSource<IDhLevel>
throw new IOException("Invalid data content end guard for ID mapping");
}
return FullDataPointIdMap.deserialize(inputStream, this.sectionPos, levelWrapper);
return FullDataPointIdMap.deserialize(inputStream, this.pos, levelWrapper);
}
public void setIdMapping(FullDataPointIdMap mappings) { this.mapping.mergeAndReturnRemappedEntityIds(mappings); }
@@ -32,6 +32,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos;
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.RenderDataPointUtil;
import com.seibel.distanthorizons.core.util.objects.DataCorruptedException;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.coreapi.ModInfo;
import it.unimi.dsi.fastutil.longs.LongArrayList;
@@ -70,9 +71,11 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
private int cachedHashCode = 0;
private DhSectionPos pos;
private long pos;
@Override
public DhSectionPos getKey() { return this.pos; }
public Long getKey() { return this.pos; }
@Override
public String getKeyDisplayString() { return DhSectionPos.toString(this.pos); }
public final FullDataPointIdMap mapping;
@@ -111,8 +114,8 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
// constructors //
//==============//
public static FullDataSourceV2 createEmpty(DhSectionPos pos) { return new FullDataSourceV2(pos); }
private FullDataSourceV2(DhSectionPos pos)
public static FullDataSourceV2 createEmpty(long pos) { return new FullDataSourceV2(pos); }
private FullDataSourceV2(long pos)
{
this.pos = pos;
this.dataPoints = new LongArrayList[WIDTH * WIDTH];
@@ -125,8 +128,8 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
this.columnWorldCompressionMode = new byte[WIDTH * WIDTH];
}
public static FullDataSourceV2 createWithData(DhSectionPos pos, FullDataPointIdMap mapping, LongArrayList[] data, byte[] columnGenerationStep, byte[] columnWorldCompressionMode) { return new FullDataSourceV2(pos, mapping, data, columnGenerationStep, columnWorldCompressionMode); }
private FullDataSourceV2(DhSectionPos pos, FullDataPointIdMap mapping, LongArrayList[] data, byte[] columnGenerationSteps, byte[] columnWorldCompressionMode)
public static FullDataSourceV2 createWithData(long pos, FullDataPointIdMap mapping, LongArrayList[] data, byte[] columnGenerationStep, byte[] columnWorldCompressionMode) { return new FullDataSourceV2(pos, mapping, data, columnGenerationStep, columnWorldCompressionMode); }
private FullDataSourceV2(long pos, FullDataPointIdMap mapping, LongArrayList[] data, byte[] columnGenerationSteps, byte[] columnWorldCompressionMode)
{
LodUtil.assertTrue(data.length == WIDTH * WIDTH);
@@ -229,8 +232,8 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
}
byte thisDetailLevel = this.pos.getDetailLevel();
byte inputDetailLevel = inputDataSource.pos.getDetailLevel();
byte thisDetailLevel = DhSectionPos.getDetailLevel(this.pos);
byte inputDetailLevel = DhSectionPos.getDetailLevel(inputDataSource.pos);
// determine the mapping changes necessary for the input to map onto this datasource
@@ -255,7 +258,7 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
}
// determine if this data source should be applied to its parent
this.applyToParent = (dataChanged && this.pos.getDetailLevel() < AbstractDataSourceHandler.TOP_SECTION_DETAIL_LEVEL);
this.applyToParent = (dataChanged && DhSectionPos.getDetailLevel(this.pos) < AbstractDataSourceHandler.TOP_SECTION_DETAIL_LEVEL);
if (dataChanged)
{
@@ -268,9 +271,9 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
public boolean updateFromSameDetailLevel(FullDataSourceV2 inputDataSource, int[] remappedIds)
{
// both data sources should have the same detail level
if (inputDataSource.pos.getDetailLevel() != this.pos.getDetailLevel())
if (DhSectionPos.getDetailLevel(inputDataSource.pos) != DhSectionPos.getDetailLevel(this.pos))
{
throw new IllegalArgumentException("Both data sources must have the same detail level. Expected ["+this.pos.getDetailLevel()+"], received ["+inputDataSource.pos.getDetailLevel()+"].");
throw new IllegalArgumentException("Both data sources must have the same detail level. Expected ["+ DhSectionPos.getDetailLevel(this.pos)+"], received ["+ DhSectionPos.getDetailLevel(inputDataSource.pos)+"].");
}
// copy over everything from the input data source into this one
@@ -350,9 +353,9 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
}
public boolean updateFromOneBelowDetailLevel(FullDataSourceV2 inputDataSource, int[] remappedIds)
{
if (inputDataSource.pos.getDetailLevel() + 1 != this.pos.getDetailLevel())
if (DhSectionPos.getDetailLevel(inputDataSource.pos) + 1 != DhSectionPos.getDetailLevel(this.pos))
{
throw new IllegalArgumentException("Input data source must be exactly 1 detail level below this data source. Expected [" + (this.pos.getDetailLevel() - 1) + "], received [" + inputDataSource.pos.getDetailLevel() + "].");
throw new IllegalArgumentException("Input data source must be exactly 1 detail level below this data source. Expected [" + (DhSectionPos.getDetailLevel(this.pos) - 1) + "], received [" + DhSectionPos.getDetailLevel(inputDataSource.pos) + "].");
}
// input is one detail level lower (higher detail)
@@ -361,10 +364,10 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
// determine where in the input data source should be written to
// since the input is one detail level below it will be one of this position's 4 children
int minChildXPos = this.pos.getChildByIndex(0).getX();
int recipientOffsetX = (inputDataSource.pos.getX() == minChildXPos) ? 0 : (WIDTH / 2);
int minChildZPos = this.pos.getChildByIndex(0).getZ();
int recipientOffsetZ = (inputDataSource.pos.getZ() == minChildZPos) ? 0 : (WIDTH / 2);
int minChildXPos = DhSectionPos.getX(DhSectionPos.getChildByIndex(this.pos, 0));
int recipientOffsetX = (DhSectionPos.getX(inputDataSource.pos) == minChildXPos) ? 0 : (WIDTH / 2);
int minChildZPos = DhSectionPos.getZ(DhSectionPos.getChildByIndex(this.pos, 0));
int recipientOffsetZ = (DhSectionPos.getZ(inputDataSource.pos) == minChildZPos) ? 0 : (WIDTH / 2);
@@ -616,7 +619,16 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
{
if (height != 0)
{
newColumnList.add(FullDataPointUtil.encode(lastId, height, minY, lastBlockLight, lastSkyLight));
try
{
long datapoint = FullDataPointUtil.encode(lastId, height, minY, lastBlockLight, lastSkyLight);
newColumnList.add(datapoint);
}
catch (DataCorruptedException e)
{
// shouldn't happen, (especially if validation is disabled) but just in case
LOGGER.warn("Skipping corrupt datapoint for pos "+inputDataSource.pos+" at relative position ["+x+","+z+"] with data: ID["+lastId+"], Height["+height+"], minY["+minY+"], lastBlockLight["+lastBlockLight+"], lastSkyLight["+lastSkyLight+"].");
}
}
lastId = id;
@@ -630,7 +642,15 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
// add the last slice if present
if (height != 0)
{
newColumnList.add(FullDataPointUtil.encode(lastId, height, minY, lastBlockLight, lastSkyLight));
try
{
newColumnList.add(FullDataPointUtil.encode(lastId, height, minY, lastBlockLight, lastSkyLight));
}
catch (DataCorruptedException e)
{
// shouldn't happen, (especially if validation is disabled) but just in case
LOGGER.warn("Skipping corrupt datapoint for pos "+inputDataSource.pos+" at relative position ["+x+","+z+"] with data: ID["+lastId+"], Height["+height+"], minY["+minY+"], lastBlockLight["+lastBlockLight+"], lastSkyLight["+lastSkyLight+"].");
}
}
@@ -765,7 +785,7 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
*
* @see FullDataSourceV2#dataPoints
*/
public static void throwIfDataColumnInWrongOrder(DhSectionPos pos, LongArrayList dataArray) throws IllegalStateException
public static void throwIfDataColumnInWrongOrder(long pos, LongArrayList dataArray) throws IllegalStateException
{
long firstDataPoint = dataArray.getLong(0);
int firstBottomY = FullDataPointUtil.getBottomY(firstDataPoint);
@@ -775,7 +795,7 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
if (firstBottomY < lastBottomY)
{
throw new IllegalStateException("Incorrect data point order at pos: "+pos+", first datapoint bottom Y ["+firstBottomY+"], last datapoint bottom Y ["+lastBottomY+"].");
throw new IllegalStateException("Incorrect data point order at pos: ["+ DhSectionPos.toString(pos)+"], first datapoint bottom Y ["+firstBottomY+"], last datapoint bottom Y ["+lastBottomY+"].");
}
}
@@ -811,7 +831,7 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
// pooling //
//=========//
private static void prepPooledDataSource(DhSectionPos pos, boolean clearData, FullDataSourceV2 dataSource)
private static void prepPooledDataSource(long pos, boolean clearData, FullDataSourceV2 dataSource)
{
dataSource.pos = pos;
@@ -839,10 +859,10 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
//=====================//
@Override
public DhSectionPos getPos() { return this.pos; }
public Long getPos() { return this.pos; }
@Override
public byte getDataDetailLevel() { return (byte) (this.pos.getDetailLevel() - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); }
public byte getDataDetailLevel() { return (byte) (DhSectionPos.getDetailLevel(this.pos) - DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); }
public EDhApiWorldGenerationStep getWorldGenStepAtRelativePos(int relX, int relZ)
{
@@ -881,7 +901,7 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
//================//
@Override
public String toString() { return this.pos.toString(); }
public String toString() { return DhSectionPos.toString(this.pos); }
@Override
public int hashCode()
@@ -894,7 +914,7 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
}
private void generateHashCode()
{
int result = this.pos.hashCode();
int result = DhSectionPos.hashCode(this.pos);
result = 31 * result + Arrays.deepHashCode(this.dataPoints);
result = 17 * result + Arrays.hashCode(this.columnGenerationSteps);
result = 43 * result + Arrays.hashCode(this.columnWorldCompressionMode);
@@ -911,7 +931,7 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
}
FullDataSourceV2 other = (FullDataSourceV2) obj;
if (!other.pos.equals(this.pos))
if (other.pos != this.pos)
{
return false;
}
@@ -59,7 +59,7 @@ public class ColumnRenderSource implements IDataSource<IDhClientLevel>
/** will be zero if an empty data source was created */
public int verticalDataCount;
public DhSectionPos pos;
public long pos;
public int yOffset;
public LongArrayList renderDataContainer;
@@ -77,11 +77,11 @@ public class ColumnRenderSource implements IDataSource<IDhClientLevel>
//==============//
/**
* This is separate from {@link DataSourcePool#getPooledSource(DhSectionPos, boolean)}
* This is separate from {@link DataSourcePool#getPooledSource(long, boolean)}
* because we need to pass in a couple extra values,
* specifically maxVerticalSize and yOffset.
*/
public static ColumnRenderSource getPooledRenderSource(DhSectionPos pos, int maxVerticalSize, int yOffset, boolean clearData)
public static ColumnRenderSource getPooledRenderSource(long pos, int maxVerticalSize, int yOffset, boolean clearData)
{
ColumnRenderSource renderSource = DATA_SOURCE_POOL.getPooledSource(pos);
@@ -109,14 +109,14 @@ public class ColumnRenderSource implements IDataSource<IDhClientLevel>
}
private static ColumnRenderSource createEmptyRenderSource(DhSectionPos sectionPos) { return new ColumnRenderSource(sectionPos, 0, 0); }
private static ColumnRenderSource createEmptyRenderSource(long sectionPos) { return new ColumnRenderSource(sectionPos, 0, 0); }
/**
* Creates an empty ColumnRenderSource.
*
* @param pos the relative position of the container
* @param maxVerticalSize the maximum vertical size of the container
*/
private ColumnRenderSource(DhSectionPos pos, int maxVerticalSize, int yOffset)
private ColumnRenderSource(long pos, int maxVerticalSize, int yOffset)
{
this.verticalDataCount = maxVerticalSize;
this.renderDataContainer = new LongArrayList(new long[SECTION_SIZE * SECTION_SIZE * this.verticalDataCount]);
@@ -155,7 +155,7 @@ public class ColumnRenderSource implements IDataSource<IDhClientLevel>
final String errorMessagePrefix = "Unable to complete update for RenderSource pos: [" + this.pos + "] and pos: [" + inputFullDataSource.getPos() + "]. Error:";
boolean dataChanged = false;
if (inputFullDataSource.getPos().getDetailLevel() == this.pos.getDetailLevel())
if (DhSectionPos.getDetailLevel(inputFullDataSource.getPos()) == DhSectionPos.getDetailLevel(this.pos))
{
try
{
@@ -167,8 +167,8 @@ public class ColumnRenderSource implements IDataSource<IDhClientLevel>
DhBlockPos2D centerBlockPos = inputFullDataSource.getPos().getCenterBlockPos();
int halfBlockWidth = inputFullDataSource.getPos().getBlockWidth() / 2;
DhBlockPos2D centerBlockPos = DhSectionPos.getCenterBlockPos(inputFullDataSource.getPos());
int halfBlockWidth = DhSectionPos.getBlockWidth(inputFullDataSource.getPos()) / 2;
DhBlockPos2D minBlockPos = new DhBlockPos2D(centerBlockPos.x - halfBlockWidth, centerBlockPos.z - halfBlockWidth);
for (int x = 0; x < FullDataSourceV2.WIDTH; x++)
@@ -215,11 +215,13 @@ public class ColumnRenderSource implements IDataSource<IDhClientLevel>
// data helper methods //
//=====================//
public DhSectionPos getPos() { return this.pos; }
public Long getPos() { return this.pos; }
@Override
public DhSectionPos getKey() { return this.pos; }
public Long getKey() { return this.pos; }
@Override
public String getKeyDisplayString() { return DhSectionPos.toString(this.pos); }
public byte getDataDetailLevel() { return (byte) (this.pos.getDetailLevel() - SECTION_SIZE_OFFSET); }
public byte getDataDetailLevel() { return (byte) (DhSectionPos.getDetailLevel(this.pos) - SECTION_SIZE_OFFSET); }
public boolean isEmpty() { return this.isEmpty; }
public void markNotEmpty() { this.isEmpty = false; }
@@ -19,6 +19,7 @@
package com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.enums.EDhDirection;
import com.seibel.distanthorizons.core.util.ColorUtil;
@@ -475,10 +476,10 @@ public class ColumnBox
throw new RuntimeException("Loop error");
if (previousAdjDepth > adjYMax)
{
if (irisBlockMaterialId == IBlockStateWrapper.IrisBlockMaterial.GRASS)
if (irisBlockMaterialId == EDhApiBlockMaterial.GRASS.index)
{
// this LOD is underneath another, grass will never show here
irisBlockMaterialId = IBlockStateWrapper.IrisBlockMaterial.DIRT;
irisBlockMaterialId = EDhApiBlockMaterial.DIRT.index;
}
builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (previousAdjDepth - adjYMax), color, irisBlockMaterialId,
@@ -20,16 +20,11 @@
package com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding;
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
import com.seibel.distanthorizons.core.enums.EGLProxyContext;
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.pos.DhBlockPos;
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.util.objects.StatsMap;
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
import com.seibel.distanthorizons.core.util.*;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
@@ -51,19 +46,21 @@ public class ColumnRenderBuffer implements AutoCloseable
private static final long MAX_BUFFER_UPLOAD_TIMEOUT_NANOSECONDS = 1_000_000;
public static final int QUADS_BYTE_SIZE = LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 4; // TODO what does the 4 represent
public static final int MAX_QUADS_PER_BUFFER = (1024 * 1024 * 1) / QUADS_BYTE_SIZE; // TODO what do these multiples represent?
/** number of bytes a single quad takes */
public static final int QUADS_BYTE_SIZE = LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 4;
/** how big a single VBO can be in bytes */
public static final int MAX_VBO_BYTE_SIZE = 1024 * 1024; // 1 MB
public static final int MAX_QUADS_PER_BUFFER = MAX_VBO_BYTE_SIZE / QUADS_BYTE_SIZE;
public static final int FULL_SIZED_BUFFER = MAX_QUADS_PER_BUFFER * QUADS_BYTE_SIZE;
public final DhBlockPos pos;
public boolean buffersUploaded = false;
private GLVertexBuffer[] vbos;
private GLVertexBuffer[] vbosTransparent;
public SharedVbo.BufferSlice[] opaqueBufferSlices;
public SharedVbo.BufferSlice[] transparentBufferSlices;
@@ -74,14 +71,12 @@ public class ColumnRenderBuffer implements AutoCloseable
public ColumnRenderBuffer(DhBlockPos pos)
{
this.pos = pos;
this.vbos = new GLVertexBuffer[0];
this.vbosTransparent = new GLVertexBuffer[0];
this.opaqueBufferSlices = new SharedVbo.BufferSlice[0];
this.transparentBufferSlices = new SharedVbo.BufferSlice[0];
}
//==================//
// buffer uploading //
//==================//
@@ -92,249 +87,166 @@ public class ColumnRenderBuffer implements AutoCloseable
LodUtil.assertTrue(Thread.currentThread().getName().startsWith(ThreadUtil.THREAD_NAME_PREFIX), "Buffer uploading needs to be done on a DH thread to prevent locking up any MC threads.");
// the async is relative to MC's render thread
boolean uploadAsync = Config.Client.Advanced.GpuBuffers.gpuUploadAsync.get();
if (uploadAsync)
// upload on MC's render thread
CompletableFuture<Void> uploadFuture = new CompletableFuture<>();
minecraftClient.executeOnRenderThread(() ->
{
// upload here on a DH thread
GLProxy glProxy = GLProxy.getInstance();
EGLProxyContext oldContext = glProxy.getGlContext();
glProxy.setGlContext(EGLProxyContext.LOD_BUILDER);
try
{
this.uploadBuffersUsingUploadMethod(builder, gpuUploadMethod);
uploadFuture.complete(null);
}
finally
catch (InterruptedException e)
{
glProxy.setGlContext(oldContext);
throw new CompletionException(e);
}
}
else
});
try
{
// upload on MC's render thread
CompletableFuture<Void> uploadFuture = new CompletableFuture<>();
minecraftClient.executeOnRenderThread(() ->
{
try
{
this.uploadBuffersUsingUploadMethod(builder, gpuUploadMethod);
uploadFuture.complete(null);
}
catch (InterruptedException e)
{
throw new CompletionException(e);
}
});
try
{
// wait for the upload to finish
uploadFuture.get(1000, TimeUnit.MILLISECONDS);
}
catch (ExecutionException e)
{
LOGGER.warn("Error uploading builder ["+builder+"] synchronously. Error: "+e.getMessage(), e);
}
catch (TimeoutException e)
{
// timeouts can be ignored because it generally means the
// MC Render thread executor was closed
//LOGGER.warn("Error uploading builder ["+builder+"] synchronously. Error: "+e.getMessage(), e);
}
// wait for the upload to finish
uploadFuture.get(5_000, TimeUnit.MILLISECONDS);
}
catch (ExecutionException e)
{
LOGGER.warn("Error uploading builder ["+builder+"] synchronously. Error: "+e.getMessage(), e);
}
catch (TimeoutException e)
{
// timeouts can be ignored because it generally means the
// MC Render thread executor was closed
//LOGGER.warn("Error uploading builder ["+builder+"] synchronously. Error: "+e.getMessage(), e);
}
}
private void uploadBuffersUsingUploadMethod(LodQuadBuilder builder, EDhApiGpuUploadMethod gpuUploadMethod) throws InterruptedException
{
if (gpuUploadMethod.useEarlyMapping)
{
this.uploadBuffersMapped(builder, gpuUploadMethod);
}
else
{
this.uploadBuffersDirect(builder, gpuUploadMethod);
}
//if (gpuUploadMethod.useEarlyMapping)
//{
// this.uploadBuffersMapped(builder, gpuUploadMethod);
//}
//else
//{
this.uploadBuffersDirect(builder);
//}
this.buffersUploaded = true;
}
private void uploadBuffersMapped(LodQuadBuilder builder, EDhApiGpuUploadMethod method)
//private void uploadBuffersMapped(LodQuadBuilder builder, EDhApiGpuUploadMethod method)
//{
// // opaque vbos //
//
// this.vbos = ColumnRenderBufferBuilder.resizeBuffer(this.vbos, builder.getCurrentNeededOpaqueVertexBufferCount());
// for (int i = 0; i < this.vbos.length; i++)
// {
// if (this.vbos[i] == null)
// {
// this.vbos[i] = new GLVertexBuffer(method.useBufferStorage);
// }
// }
// LodQuadBuilder.BufferFiller func = builder.makeOpaqueBufferFiller(method);
// for (GLVertexBuffer vbo : this.vbos)
// {
// func.fill(vbo);
// }
//
//
// // transparent vbos //
//
// this.vbosTransparent = ColumnRenderBufferBuilder.resizeBuffer(this.vbosTransparent, builder.getCurrentNeededTransparentVertexBufferCount());
// for (int i = 0; i < this.vbosTransparent.length; i++)
// {
// if (this.vbosTransparent[i] == null)
// {
// this.vbosTransparent[i] = new GLVertexBuffer(method.useBufferStorage);
// }
// }
// LodQuadBuilder.BufferFiller transparentFillerFunc = builder.makeTransparentBufferFiller(method);
// for (GLVertexBuffer vbo : this.vbosTransparent)
// {
// transparentFillerFunc.fill(vbo);
// }
//}
private void uploadBuffersDirect(LodQuadBuilder builder)
{
// opaque vbos //
this.vbos = ColumnRenderBufferBuilder.resizeBuffer(this.vbos, builder.getCurrentNeededOpaqueVertexBufferCount());
for (int i = 0; i < this.vbos.length; i++)
int opaqueSliceCount = builder.getCurrentNeededOpaqueVertexBufferCount();
if (this.opaqueBufferSlices.length != opaqueSliceCount)
{
if (this.vbos[i] == null)
{
this.vbos[i] = new GLVertexBuffer(method.useBufferStorage);
}
}
LodQuadBuilder.BufferFiller func = builder.makeOpaqueBufferFiller(method);
for (GLVertexBuffer vbo : this.vbos)
{
func.fill(vbo);
SharedVbo.OPAQUE.deallocate(this.opaqueBufferSlices);
this.opaqueBufferSlices = new SharedVbo.BufferSlice[opaqueSliceCount];
}
uploadBuffersDirect(SharedVbo.OPAQUE, this.opaqueBufferSlices, builder.makeOpaqueVertexBuffers());
// transparent vbos //
this.vbosTransparent = ColumnRenderBufferBuilder.resizeBuffer(this.vbosTransparent, builder.getCurrentNeededTransparentVertexBufferCount());
for (int i = 0; i < this.vbosTransparent.length; i++)
int transparentSliceCount = builder.getCurrentNeededTransparentVertexBufferCount();
if (this.transparentBufferSlices.length != transparentSliceCount)
{
if (this.vbosTransparent[i] == null)
{
this.vbosTransparent[i] = new GLVertexBuffer(method.useBufferStorage);
}
}
LodQuadBuilder.BufferFiller transparentFillerFunc = builder.makeTransparentBufferFiller(method);
for (GLVertexBuffer vbo : this.vbosTransparent)
{
transparentFillerFunc.fill(vbo);
SharedVbo.TRANSPARENT.deallocate(this.transparentBufferSlices);
this.transparentBufferSlices = new SharedVbo.BufferSlice[transparentSliceCount];
}
uploadBuffersDirect(SharedVbo.TRANSPARENT, this.transparentBufferSlices, builder.makeTransparentVertexBuffers());
}
private void uploadBuffersDirect(LodQuadBuilder builder, EDhApiGpuUploadMethod method) throws InterruptedException
private static void uploadBuffersDirect(SharedVbo handler, SharedVbo.BufferSlice[] bufferSlices, Iterator<ByteBuffer> iter)
{
this.vbos = ColumnRenderBufferBuilder.resizeBuffer(this.vbos, builder.getCurrentNeededOpaqueVertexBufferCount());
uploadBuffersDirect(this.vbos, builder.makeOpaqueVertexBuffers(), method);
this.vbosTransparent = ColumnRenderBufferBuilder.resizeBuffer(this.vbosTransparent, builder.getCurrentNeededTransparentVertexBufferCount());
uploadBuffersDirect(this.vbosTransparent, builder.makeTransparentVertexBuffers(), method);
}
private static void uploadBuffersDirect(GLVertexBuffer[] vbos, Iterator<ByteBuffer> iter, EDhApiGpuUploadMethod method) throws InterruptedException
{
long remainingMS = 0;
long MBPerMS = Config.Client.Advanced.GpuBuffers.gpuUploadPerMegabyteInMilliseconds.get();
int vboIndex = 0;
int i = 0;
while (iter.hasNext())
{
if (vboIndex >= vbos.length)
if (i >= bufferSlices.length)
{
throw new RuntimeException("Too many vertex buffers!!");
}
// get or create the VBO
if (vbos[vboIndex] == null)
// get or create the buffer
if (bufferSlices[i] == null)
{
vbos[vboIndex] = new GLVertexBuffer(method.useBufferStorage);
bufferSlices[i] = handler.allocateSlice();
}
GLVertexBuffer vbo = vbos[vboIndex];
SharedVbo.BufferSlice slice = bufferSlices[i];
ByteBuffer bb = iter.next();
int size = bb.limit() - bb.position();
ByteBuffer buffer = iter.next();
try
{
vbo.bind();
vbo.uploadBuffer(bb, size / LodUtil.LOD_VERTEX_FORMAT.getByteSize(), method, FULL_SIZED_BUFFER);
handler.updateBuffer(slice, buffer);
}
catch (Exception e)
{
vbos[vboIndex] = null;
vbo.close();
LOGGER.error("Failed to upload buffer: ", e);
bufferSlices[i] = null;
handler.deallocate(slice);
LOGGER.error("Failed to upload buffer. Error: ["+e.getMessage()+"].", e);
}
if (MBPerMS > 0)
{
// upload buffers over an extended period of time
// to hopefully prevent stuttering.
remainingMS += size * MBPerMS;
if (remainingMS >= TimeUnit.NANOSECONDS.convert(1000 / 60, TimeUnit.MILLISECONDS))
{
if (remainingMS > MAX_BUFFER_UPLOAD_TIMEOUT_NANOSECONDS)
{
remainingMS = MAX_BUFFER_UPLOAD_TIMEOUT_NANOSECONDS;
}
Thread.sleep(remainingMS / 1000000, (int) (remainingMS % 1000000));
remainingMS = 0;
}
}
vboIndex++;
i++;
}
if (vboIndex < vbos.length)
if (i < bufferSlices.length)
{
throw new RuntimeException("Too few vertex buffers!!");
throw new RuntimeException("Too few buffer chunks!");
}
}
//========//
// render //
//========//
/** @return true if something was rendered, false otherwise */
public boolean renderOpaque(LodRenderer renderContext, DhApiRenderParam renderEventParam)
{
boolean hasRendered = false;
renderContext.setModelViewMatrixOffset(this.pos, renderEventParam);
for (GLVertexBuffer vbo : this.vbos)
{
if (vbo == null)
{
continue;
}
if (vbo.getVertexCount() == 0)
{
continue;
}
hasRendered = true;
renderContext.drawVbo(vbo);
//LodRenderer.tickLogger.info("Vertex buffer: {}", vbo);
}
return hasRendered;
}
/** @return true if something was rendered, false otherwise */
public boolean renderTransparent(LodRenderer renderContext, DhApiRenderParam renderEventParam)
{
boolean hasRendered = false;
try
{
// can throw an IllegalStateException if the GL program was freed before it should've been
renderContext.setModelViewMatrixOffset(this.pos, renderEventParam);
for (GLVertexBuffer vbo : this.vbosTransparent)
{
if (vbo == null)
{
continue;
}
if (vbo.getVertexCount() == 0)
{
continue;
}
hasRendered = true;
renderContext.drawVbo(vbo);
//LodRenderer.tickLogger.info("Vertex buffer: {}", vbo);
}
}
catch (IllegalStateException e)
{
LOGGER.error("renderContext program doesn't exist for pos: "+this.pos, e);
}
return hasRendered;
}
//public void renderOpaque(LodRenderer renderContext, DhApiRenderParam renderEventParam)
//{
// renderContext.setModelViewMatrixOffset(this.pos, renderEventParam);
// renderContext.drawSharedVbo(SharedVbo.OPAQUE, this.opaqueBufferSlices);
//}
//
//public void renderTransparent(LodRenderer renderContext, DhApiRenderParam renderEventParam)
//{
// renderContext.setModelViewMatrixOffset(this.pos, renderEventParam);
// renderContext.drawSharedVbo(SharedVbo.TRANSPARENT, this.transparentBufferSlices);
//}
@@ -342,41 +254,26 @@ public class ColumnRenderBuffer implements AutoCloseable
// misc methods //
//==============//
// TODO
/** can be used when debugging */
public boolean hasNonEmptyBuffers()
public boolean hasNonNullVbos() { return false; } //this.vbos != null || this.vbosTransparent != null; }
/** can be used when debugging */
public int bufferSliceCount()
{
for (GLVertexBuffer vertexBuffer : this.vbos)
int count = 0;
if (this.opaqueBufferSlices != null)
{
if (vertexBuffer != null && vertexBuffer.getSize() != 0)
{
return true;
}
count += this.opaqueBufferSlices.length;
}
if (this.transparentBufferSlices != null)
{
count += this.transparentBufferSlices.length;
}
return false;
}
public void debugDumpStats(StatsMap statsMap)
{
statsMap.incStat("RenderBuffers");
statsMap.incStat("SimpleRenderBuffers");
for (GLVertexBuffer vertexBuffer : vbos)
{
if (vertexBuffer != null)
{
statsMap.incStat("VBOs");
if (vertexBuffer.getSize() == FULL_SIZED_BUFFER)
{
statsMap.incStat("FullsizedVBOs");
}
if (vertexBuffer.getSize() == 0)
{
GLProxy.GL_LOGGER.warn("VBO with size 0");
}
statsMap.incBytesStat("TotalUsage", vertexBuffer.getSize());
}
}
return count;
}
/**
@@ -390,24 +287,8 @@ public class ColumnRenderBuffer implements AutoCloseable
{
this.buffersUploaded = false;
GLProxy.getInstance().queueRunningOnRenderThread(() ->
{
for (GLVertexBuffer buffer : this.vbos)
{
if (buffer != null)
{
buffer.destroy(false);
}
}
for (GLVertexBuffer buffer : this.vbosTransparent)
{
if (buffer != null)
{
buffer.destroy(false);
}
}
});
SharedVbo.OPAQUE.deallocate(this.opaqueBufferSlices);
SharedVbo.TRANSPARENT.deallocate(this.transparentBufferSlices);
}
}
@@ -54,11 +54,6 @@ public class ColumnRenderBufferBuilder
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
public static final int MAX_NUMBER_OF_CONCURRENT_CALLS_PER_THREAD = 3;
public static int maxNumberOfConcurrentCalls = MAX_NUMBER_OF_CONCURRENT_CALLS_PER_THREAD;
//==============//
// vbo building //
@@ -98,7 +93,7 @@ public class ColumnRenderBufferBuilder
&& !clientLevel.getLevelWrapper().getDimensionType().isTheEnd()
// FIXME temporary fix
// Cave culling is currently broken for any detail level above 0
&& renderSource.pos.getDetailLevel() == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL
&& DhSectionPos.getDetailLevel(renderSource.pos) == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL
);
int skyLightCullingBelow = Config.Client.Advanced.Graphics.AdvancedGraphics.caveCullingHeight.get();
@@ -131,7 +126,7 @@ public class ColumnRenderBufferBuilder
{
try
{
ColumnRenderBuffer buffer = new ColumnRenderBuffer(new DhBlockPos(renderSource.pos.getMinCornerLodPos().getCornerBlockPos(), clientLevel.getMinY()));
ColumnRenderBuffer buffer = new ColumnRenderBuffer(new DhBlockPos(DhSectionPos.getMinCornerBlockX(renderSource.pos), clientLevel.getMinY(), DhSectionPos.getMinCornerBlockZ(renderSource.pos)));
try
{
buffer.uploadBuffer(quadBuilder, GLProxy.getInstance().getGpuUploadMethod());
@@ -174,9 +169,9 @@ public class ColumnRenderBufferBuilder
boolean enableColumnBufferLimit = Config.Client.Advanced.Debugging.columnBuilderDebugEnable.get();
if (enableColumnBufferLimit)
{
if (renderSource.pos.getDetailLevel() == Config.Client.Advanced.Debugging.columnBuilderDebugDetailLevel.get()
&& renderSource.pos.getX() == Config.Client.Advanced.Debugging.columnBuilderDebugXPos.get()
&& renderSource.pos.getZ() == Config.Client.Advanced.Debugging.columnBuilderDebugZPos.get())
if (DhSectionPos.getDetailLevel(renderSource.pos) == Config.Client.Advanced.Debugging.columnBuilderDebugDetailLevel.get()
&& DhSectionPos.getX(renderSource.pos) == Config.Client.Advanced.Debugging.columnBuilderDebugXPos.get()
&& DhSectionPos.getZ(renderSource.pos) == Config.Client.Advanced.Debugging.columnBuilderDebugZPos.get())
{
int test = 0;
}
@@ -338,32 +333,4 @@ public class ColumnRenderBufferBuilder
quadBuilder.finalizeData();
}
//=================//
// vbo interaction //
//=================//
public static GLVertexBuffer[] resizeBuffer(GLVertexBuffer[] vbos, int newSize)
{
if (vbos.length == newSize)
{
return vbos;
}
GLVertexBuffer[] newVbos = new GLVertexBuffer[newSize];
System.arraycopy(vbos, 0, newVbos, 0, Math.min(vbos.length, newSize));
if (newSize < vbos.length)
{
for (int i = newSize; i < vbos.length; i++)
{
if (vbos[i] != null)
{
vbos[i].close();
}
}
}
return newVbos;
}
}

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