Compare commits
2759 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3f16d67746 | |||
| 3a34dc8626 | |||
| c1766fb439 | |||
| cfd47adfda | |||
| 9b9e6b9179 | |||
| 49d1587a71 | |||
| b0f5e55744 | |||
| d9191534d5 | |||
| ff459621e6 | |||
| 64fb45d74d | |||
| 1590abb489 | |||
| a3c9b0654a | |||
| a9388321d9 | |||
| 877c824e58 | |||
| 80f30dfd74 | |||
| 9a087025fe | |||
| 21dc0f13c9 | |||
| 7794958804 | |||
| c245ed6598 | |||
| 6270b03005 | |||
| 2674b945bb | |||
| 0647bdbab3 | |||
| 528a12ac83 | |||
| 4ac9de05df | |||
| a0f1b72089 | |||
| 85c07b11c6 | |||
| 215e1d46d0 | |||
| 5f228f0567 | |||
| f597958e1e | |||
| 95921358f8 | |||
| a22d494797 | |||
| 666e917b8f | |||
| a26a97e7fb | |||
| cdbb9de933 | |||
| feccf12580 | |||
| d371d93c9d | |||
| 5f3e8d76b2 | |||
| a7bd72e35b | |||
| 0a5326d2b1 | |||
| dad2014c46 | |||
| 70dd0bda72 | |||
| 8213901229 | |||
| 668ba491e8 | |||
| d85589c41a | |||
| 7f5316108d | |||
| 9c1abbac2b | |||
| 1bb957a866 | |||
| 6ccba17baf | |||
| e4c5d8adab | |||
| 823f204424 | |||
| 505e9a77fd | |||
| 4c580fe4ff | |||
| efc1865f87 | |||
| ae08ad56c4 | |||
| 633544e0b0 | |||
| 2432028aa0 | |||
| eb6aa13815 | |||
| 55155103ec | |||
| 667dd85aef | |||
| 9bd946a41c | |||
| 241baef7af | |||
| b5890a4783 | |||
| e3b67ef500 | |||
| 5905fe3df2 | |||
| 9d35a70437 | |||
| f121860563 | |||
| 9715db3ac6 | |||
| 03a29fbacb | |||
| e91888934b | |||
| 030f814398 | |||
| 90ef8fd64d | |||
| 0ffefaa8c1 | |||
| 99703d65df | |||
| bd2f5a7836 | |||
| a44556f86a | |||
| 4597b7f647 | |||
| 0de80cfaa7 | |||
| 034aaddca3 | |||
| a1d493f25d | |||
| 4b5a4dda79 | |||
| ce528f3fd5 | |||
| e4c769e95e | |||
| f13095875f | |||
| 3d1af8f944 | |||
| d73867efd6 | |||
| 045733deb5 | |||
| b552bf2566 | |||
| 33d37b3937 | |||
| 15a044d059 | |||
| 9e5be3ad21 | |||
| ba977a29f0 | |||
| c6c94ef906 | |||
| 7fed4b1ddb | |||
| dfee36f416 | |||
| cf6945b44c | |||
| a01a9ac356 | |||
| 89619696cb | |||
| 88f945bf22 | |||
| 3555133d7f | |||
| 294013eff0 | |||
| 6748ec25ff | |||
| 485c3dedb3 | |||
| 4ceecdfb09 | |||
| 23d3e44002 | |||
| 3a5d6e7370 | |||
| 71237caa81 | |||
| 7e19f9e6eb | |||
| f7b5b9a2f5 | |||
| 77016de6e6 | |||
| e530d0ffda | |||
| b04a308090 | |||
| 385d6919fb | |||
| 458cc9b505 | |||
| afdccfe087 | |||
| 4d7674348b | |||
| a2c96ba7ff | |||
| 5c5de3c744 | |||
| 18acb5d101 | |||
| c86c32b39e | |||
| 3c680b5daf | |||
| 84d1298e18 | |||
| 354b6567d4 | |||
| 3498faed59 | |||
| f8eb1e8a97 | |||
| 19057218d6 | |||
| f745e9c51a | |||
| da922a8c69 | |||
| 3f2d8ea6ae | |||
| 550f36e9fa | |||
| ba0835bf4a | |||
| 766a41ce56 | |||
| 3b5728692d | |||
| 05d573c847 | |||
| 9360e45a39 | |||
| 71aaff32a2 | |||
| 2fbeb43894 | |||
| ae6fa83c50 | |||
| f4171ffca1 | |||
| dedcc875d2 | |||
| 224a5449ed | |||
| b0d325fd14 | |||
| 36ad3f4e43 | |||
| b5eff6aa80 | |||
| f1e93ad547 | |||
| e59c22fb69 | |||
| 183882f9ce | |||
| 5b825f9dbb | |||
| 933d5c957c | |||
| 1bfa93eea3 | |||
| 2866aefb90 | |||
| c5bfdbc430 | |||
| 0ae83929b7 | |||
| 1a600e7c53 | |||
| dc92a341d4 | |||
| 31a534f945 | |||
| 2c3345a596 | |||
| d14349383b | |||
| db378d64b0 | |||
| 7963303a48 | |||
| 42d2cc6915 | |||
| 45128fff6b | |||
| 854885db64 | |||
| 963e62c595 | |||
| d2e41792a7 | |||
| fedd4b5cce | |||
| 804412698e | |||
| 09fa469a7d | |||
| 163ee63f9e | |||
| e143fb91a3 | |||
| 5897fc816c | |||
| da1dc04e98 | |||
| 7a05c8cdde | |||
| b219370469 | |||
| 2f7ab04984 | |||
| caf7f64f11 | |||
| 7834213a60 | |||
| 000c6053ed | |||
| 879b117959 | |||
| 272012ed22 | |||
| 3d9b988410 | |||
| 8b850f14d3 | |||
| 76f69b238a | |||
| 0b6e1135ce | |||
| 17b0d2e763 | |||
| a1a92ffd14 | |||
| 52cf6ac9df | |||
| 02a309cd34 | |||
| 0ec9e60396 | |||
| 597b659026 | |||
| 67c6061c7a | |||
| 0843a6f355 | |||
| d8d8d6f9a0 | |||
| c42ce57022 | |||
| db34b455aa | |||
| 59c82f0499 | |||
| f78e771c8b | |||
| 1be141348c | |||
| d9b5195bee | |||
| 4d0472749d | |||
| b8ebc54dee | |||
| 413ee3cdf4 | |||
| dee58dafc9 | |||
| 7b326d63e8 | |||
| 74f80ca2f5 | |||
| 6246f66300 | |||
| 037231c0ac | |||
| b416746ba2 | |||
| 5f7181f6f1 | |||
| 6b23e0de7e | |||
| fe6c4f7507 | |||
| e83d490b0e | |||
| 09bc303583 | |||
| 3fb09fa811 | |||
| 4984d00d36 | |||
| 87222f3b39 | |||
| c58a8d8e69 | |||
| f1deb7e592 | |||
| 00abfb735a | |||
| d2e831885d | |||
| d7358ed7a3 | |||
| bffffbb333 | |||
| 2e7185da5d | |||
| 32775ac3e5 | |||
| d360402bc3 | |||
| cb59d76f09 | |||
| 7512a41ef7 | |||
| 7d083bdad2 | |||
| 9972363846 | |||
| 4f171234c4 | |||
| 6c56d09b18 | |||
| 2716059840 | |||
| a60887e9a7 | |||
| 1b6c5a451a | |||
| 4e91911e58 | |||
| bfae194919 | |||
| e562b2fdca | |||
| 47fa6d7d8b | |||
| 053d1333ca | |||
| 961c4190ad | |||
| 2f2ac0859c | |||
| b59781b064 | |||
| 39cc5bb8aa | |||
| abdbc73865 | |||
| 596f9f834a | |||
| 8f2aaf4ef4 | |||
| 2320740a4a | |||
| 4f0dc07995 | |||
| 336a9a94c8 | |||
| 1158496d9d | |||
| 84479ed48c | |||
| 0c71ca96c6 | |||
| 43dff26063 | |||
| 3cba883ba2 | |||
| 2d2e7524ae | |||
| e8ff7abaea | |||
| 008ad52bbc | |||
| d0b44a1ffc | |||
| 4ffe430686 | |||
| 19ca97c6c1 | |||
| 3334394bfd | |||
| 180e7cd814 | |||
| 84cf4505f2 | |||
| 1d74eea3ef | |||
| 6ee2e6be25 | |||
| b5c47d67cb | |||
| ead59d0817 | |||
| 1c9229c8f1 | |||
| 968a14c6a5 | |||
| 5608db9c56 | |||
| 81b6a25805 | |||
| 276d90b3e6 | |||
| 851c7439d5 | |||
| c902357a8f | |||
| 63170078f5 | |||
| d0dd1f125b | |||
| 32950d793e | |||
| 54e9bad907 | |||
| bb4ac770bd | |||
| 16afada6e9 | |||
| 7d0785a5fa | |||
| 6a67df462b | |||
| 0c45c76ff8 | |||
| bcb442e38d | |||
| 977ae471ea | |||
| b1701ab0d0 | |||
| c048d5cb56 | |||
| 2702f742d6 | |||
| 7add025c8a | |||
| 9dc220feb2 | |||
| 79955252c9 | |||
| bf13cc48a3 | |||
| cf454c80d7 | |||
| e6404cd882 | |||
| 52e64dc403 | |||
| 7c858afc5d | |||
| a44a5d7465 | |||
| f2d373b779 | |||
| 5138af0b78 | |||
| 37e99cd0a5 | |||
| 6cb8cd2bd9 | |||
| c5ae7da96c | |||
| 59b886c5e3 | |||
| 01e78f249f | |||
| e1c3da59db | |||
| cdfb46b041 | |||
| f944fe4409 | |||
| c2e45f3d65 | |||
| a9c4f3ea46 | |||
| 204d48517b | |||
| 759ec3676c | |||
| 8d2b5fa3ce | |||
| 2851b2c2db | |||
| e5ea86bf8f | |||
| 533c6a7f93 | |||
| ff41e070fd | |||
| b3f607e132 | |||
| 9ecbb9cc9f | |||
| 7888de8200 | |||
| d2327ae836 | |||
| ea92a8f922 | |||
| 47e97630b4 | |||
| c518345bcd | |||
| c250a7408e | |||
| 30da01f580 | |||
| 2c71c2bf76 | |||
| 13a4505d7d | |||
| 7f0eeb9f15 | |||
| d7eabcf3a6 | |||
| 7047d0afdf | |||
| f318b52280 | |||
| f50613e20c | |||
| af3a993042 | |||
| ace1aab42e | |||
| 350d72b6ec | |||
| 986a6cdc19 | |||
| 2aa8d9f489 | |||
| 5652a9328c | |||
| b7253b6549 | |||
| e026cf104c | |||
| ab4a9cbb55 | |||
| a709ab6071 | |||
| 3c11a2dc33 | |||
| ce2aa6602a | |||
| 738aff8ec6 | |||
| 91da0bf252 | |||
| af8dea9d9f | |||
| 384933d351 | |||
| a5344d50c2 | |||
| 2b4c5b91a4 | |||
| 3090544b85 | |||
| 75e1bbbe17 | |||
| 31b604b5c8 | |||
| 70ba93abec | |||
| f628a7f21e | |||
| 254f51ea5e | |||
| d44152dc46 | |||
| 0ef979ee6c | |||
| f67fb1758d | |||
| cf643372b6 | |||
| dc1a117f6b | |||
| 2545c7e76d | |||
| 506ba05b34 | |||
| 70be3f9364 | |||
| 8d9b5f66fa | |||
| 3a01151137 | |||
| 197051747a | |||
| 45efeb96fa | |||
| e05dff3fb9 | |||
| aec28854a3 | |||
| 106d97e0a1 | |||
| 63acd94fd4 | |||
| 34412305d0 | |||
| 6a418de153 | |||
| 41c6b2936b | |||
| 97130d1535 | |||
| d61dcfaab6 | |||
| 3c3f1ef41b | |||
| ed1d6396fd | |||
| 518ec18362 | |||
| 5715cd9266 | |||
| 56953efabc | |||
| 351802de4c | |||
| f60e74c838 | |||
| 2007a6af24 | |||
| 4bc199fe14 | |||
| bcd9a0da2c | |||
| 50c97e3ca3 | |||
| 7539cb94d4 | |||
| 3a20329096 | |||
| 702002c540 | |||
| 7f790e2c9c | |||
| b3f8b03fdf | |||
| 3597d69fa4 | |||
| ab10265150 | |||
| 671ee84136 | |||
| c489cebae3 | |||
| e55eeda1ac | |||
| 0086f40053 | |||
| 71bb151e61 | |||
| a71ceac15d | |||
| ada36c34c7 | |||
| 3cfb4386d9 | |||
| 352d0f4759 | |||
| d158a89592 | |||
| 9cc826f8a9 | |||
| 22a4c6bc79 | |||
| 20b9f4f1cb | |||
| 5c0c1c5e20 | |||
| 69645994c9 | |||
| fdcbb0594d | |||
| e5711b4ddb | |||
| cb1a617b92 | |||
| 4187eaf112 | |||
| 084de2b3f1 | |||
| 7b0a9d4843 | |||
| c42f800db5 | |||
| 300ef3745f | |||
| 5a9fdb3314 | |||
| 8708ca3048 | |||
| 9cfdbdc0ca | |||
| 48f82b0966 | |||
| 75f7ef0085 | |||
| 270776a782 | |||
| 21fff72521 | |||
| a860a9740d | |||
| a2105699fa | |||
| ea4838c791 | |||
| 9168543945 | |||
| 460996d8cd | |||
| c3948abc40 | |||
| 8ed902f6f2 | |||
| 15dda30050 | |||
| 26428ff905 | |||
| 4419ab4b8c | |||
| 5d50994beb | |||
| ce9f843048 | |||
| 8c934b4982 | |||
| 9ae41865f3 | |||
| ade7a8d8dc | |||
| 461dad9fe8 | |||
| b832e77ac2 | |||
| 66c41e49db | |||
| 0f968255e0 | |||
| ed50161cfd | |||
| 7e18acdb8f | |||
| 5c05fdd9fa | |||
| afca4d837f | |||
| 6db3795fa5 | |||
| 21fe38da8e | |||
| 340c0bc586 | |||
| 77c7ebc0d0 | |||
| f55cb4b320 | |||
| 9d3c88f0b2 | |||
| e397a3e47a | |||
| 4ff315de91 | |||
| 2fb1c43d7c | |||
| 58b5fac20b | |||
| ec238d29c6 | |||
| dac36c9e34 | |||
| caca05c0f0 | |||
| 5ce7eae7c0 | |||
| 2c38401637 | |||
| 489fe753f5 | |||
| 2293afc2d3 | |||
| b48adeb3e3 | |||
| 438186cb70 | |||
| c86ff4acae | |||
| e27e1bc2d7 | |||
| 336bf2ea26 | |||
| e72c08b0bc | |||
| 4ced316304 | |||
| c84ee721e3 | |||
| c46c056980 | |||
| d486878876 | |||
| b0b0b38bf8 | |||
| 9e43896864 | |||
| d09ddf57d3 | |||
| 486edac1d8 | |||
| 3b3731a137 | |||
| 563ec70154 | |||
| 175f5ed6d6 | |||
| 1e63607233 | |||
| 4dd8be23fa | |||
| 7fac5b4c6e | |||
| f2ec1ecf3f | |||
| 2674e6b2e9 | |||
| bcbe3f0fb7 | |||
| f85108ed11 | |||
| 2bc5169ce5 | |||
| 1edd809708 | |||
| 475111b38b | |||
| b44a967e56 | |||
| acea685e75 | |||
| 20f15a6b39 | |||
| debf52418c | |||
| cf71491381 | |||
| 0a4a8466cf | |||
| 31fac60d34 | |||
| c335020c2f | |||
| 4db4f2fbc6 | |||
| f9f4a208e7 | |||
| b5fa5936b3 | |||
| 6ceabe7895 | |||
| ec3d8afbfc | |||
| e9a0c6d097 | |||
| 0238568370 | |||
| 74be00e025 | |||
| c10af6dd04 | |||
| 85ee5ac833 | |||
| 21877d67a5 | |||
| ae33a79d6e | |||
| 9204b357d8 | |||
| 78b1b74036 | |||
| 864c5b5f86 | |||
| b271c8e119 | |||
| 79bdae5b8b | |||
| d5dc9f6b79 | |||
| a50f13caa0 | |||
| 75b3649a97 | |||
| 69adb54b91 | |||
| 458c1ae7e0 | |||
| a647551d26 | |||
| 3a45bdd2a2 | |||
| 4806cd2445 | |||
| af7f90f128 | |||
| f72ad60f58 | |||
| 6015afbf4c | |||
| 0369ae63f3 | |||
| 278d5063fb | |||
| a64e72034e | |||
| fcdb56660c | |||
| 0c26261cd5 | |||
| b50525fff9 | |||
| 92e403823b | |||
| e02f56f4ef | |||
| aa4681e044 | |||
| 1c9130c3f1 | |||
| c3597cd843 | |||
| d4a52ac5a3 | |||
| 1b9d14e7b4 | |||
| 0ea27b676e | |||
| cd73608b07 | |||
| 03fc22f611 | |||
| cc251e46b0 | |||
| 7aa0bfefec | |||
| 9bdad5e4f1 | |||
| baebb7323d | |||
| 8a3175f345 | |||
| dc58efb301 | |||
| c9ac4b2ada | |||
| 6e1ec476ed | |||
| d1aa5a524b | |||
| 5c661a3a76 | |||
| d29e9085a1 | |||
| d392de3c0d | |||
| 7209193f8f | |||
| ed4f644a3f | |||
| 34038684a7 | |||
| 6fe6694c82 | |||
| 8e52f1aca5 | |||
| 5ce3dda2d5 | |||
| f4f81f4d7f | |||
| 7c37a5c370 | |||
| b495ac4799 | |||
| 2ddeaf50eb | |||
| 3721ebea6e | |||
| 98f8a87362 | |||
| 10a743ddef | |||
| 95c896f964 | |||
| 040bc16874 | |||
| 35d3fdb473 | |||
| 549f7510f7 | |||
| fab64d8477 | |||
| 4a6a35f617 | |||
| 2b519a826f | |||
| 445c01b5ae | |||
| 0f08bd540e | |||
| 77088465f9 | |||
| affe014433 | |||
| 4c06bf6dbd | |||
| dcab616385 | |||
| 89b7d08e9b | |||
| 724e318221 | |||
| a40d62d46a | |||
| 2f6b4c079b | |||
| 951e3c0271 | |||
| 84825c2d09 | |||
| ec627e2eba | |||
| 06bc9a349f | |||
| ff6c4e227b | |||
| a4d46ffe94 | |||
| bd5c140782 | |||
| 229c3f7c91 | |||
| 693369bc08 | |||
| d109fe6c43 | |||
| 3c9d3707cf | |||
| 6e53564835 | |||
| 2480fe0d86 | |||
| 691c9d3f45 | |||
| 3faf25636d | |||
| ab3bfbefb4 | |||
| 890e802de4 | |||
| c13bc0cd6e | |||
| 7143b7de08 | |||
| d136d782f5 | |||
| 29a160316c | |||
| 1f6f64d322 | |||
| 37c0af529d | |||
| 1341ea3f3d | |||
| c0bb120669 | |||
| f8887e403f | |||
| 949ee423c8 | |||
| b19ed3f30c | |||
| 2d085e1074 | |||
| 6ba0490cf7 | |||
| b6a0878241 | |||
| 50f5371084 | |||
| df74b8d243 | |||
| fce2868c62 | |||
| a36cd0763b | |||
| 0fba015f54 | |||
| f251c90472 | |||
| 492a051a3b | |||
| 0aa4743c1b | |||
| 85f16944b2 | |||
| dddb0be2ac | |||
| 4a3effa2f5 | |||
| a0a9151bfd | |||
| aa3d15f38f | |||
| adcb2a3a05 | |||
| 78f2cb24cc | |||
| 67945509ed | |||
| c653e526a5 | |||
| 49b50c4c88 | |||
| 7449f46c5e | |||
| 069fc39aad | |||
| 4979ccf3e2 | |||
| dd7f9c20b6 | |||
| e96f9de1f0 | |||
| c902e1957f | |||
| d40afb7a2a | |||
| 01474d72e3 | |||
| 7c5af1836b | |||
| a9bf6ae7e4 | |||
| aef3162246 | |||
| 97ce869076 | |||
| 91b3c83ffd | |||
| 1522df19cb | |||
| 3845564128 | |||
| 23ef7cf27a | |||
| bec28a5694 | |||
| 8f20f103ad | |||
| 246e77cc56 | |||
| 87fa29c77a | |||
| 5010256ce6 | |||
| a66ad19343 | |||
| 913a458a1a | |||
| 093d3a801e | |||
| 61ccf7bf60 | |||
| f948072253 | |||
| b748f27a1c | |||
| 4dd4bb9ef0 | |||
| 5051bde3b0 | |||
| 42cf639acc | |||
| 9e6953a596 | |||
| 7f4f8a40eb | |||
| 89ca535a6f | |||
| 145182502e | |||
| d61dfc9e03 | |||
| 611d7d87ae | |||
| 2f6a2d99ab | |||
| d88ca0c98d | |||
| 0f64df7be0 | |||
| 23a1f0b025 | |||
| 4a72e02550 | |||
| 521bcdcc0f | |||
| 4eb20d5ce8 | |||
| 3ad68aaf42 | |||
| 2a9a03771e | |||
| 8f7823a4d2 | |||
| cc4b965966 | |||
| a6418de927 | |||
| 5303415d05 | |||
| 836515934f | |||
| 228dc46d6b | |||
| a91f9670dc | |||
| 81313252f2 | |||
| f65d411978 | |||
| 8c8a5ffeaf | |||
| 68793fbe8d | |||
| d8401a8f49 | |||
| 07ff00f7c9 | |||
| fadaff1113 | |||
| ff6bf7b4c9 | |||
| 082b1224a8 | |||
| bc475373fc | |||
| 498e958eca | |||
| 82e0cfe0b4 | |||
| 31d89e3349 | |||
| a3775c1f88 | |||
| e070bf4244 | |||
| 8287192cd0 | |||
| d40f4dfe19 | |||
| 595cdf011a | |||
| 96f2f8c3b2 | |||
| c883ded7c4 | |||
| 834269da67 | |||
| a9bebf03d5 | |||
| 939f6304bf | |||
| 6e9f466570 | |||
| a0b5cc7a5c | |||
| 82708d998d | |||
| 613e444490 | |||
| f493e201d4 | |||
| 2a8013b1d6 | |||
| 54fed62507 | |||
| e51bec9ce4 | |||
| e47a83b706 | |||
| 8029c7b00c | |||
| 2b38dc2575 | |||
| 46cafb4cbe | |||
| ff96533c93 | |||
| 89e73f6383 | |||
| 069ebfe24e | |||
| 8b374c4734 | |||
| 1febade083 | |||
| deedd85914 | |||
| 218c27adae | |||
| fde48b6f1a | |||
| f2a36e73d0 | |||
| c5429ad139 | |||
| 7bc2ee296c | |||
| 4e26e4ab31 | |||
| a91685b590 | |||
| 06f73c9b0a | |||
| 062dc29fd4 | |||
| 4096a24306 | |||
| 2563de3ba3 | |||
| 4a99b42fa8 | |||
| f12f119ce2 | |||
| 775adfaad5 | |||
| 2a9c319935 | |||
| fda44c41a8 | |||
| 8247f5f215 | |||
| 7eba6848bb | |||
| 6e84cac0d2 | |||
| 2bf96ea781 | |||
| d5de4a8171 | |||
| 3cd7c7f1a3 | |||
| 1741ebf8b2 | |||
| 55776f8beb | |||
| a469770e5d | |||
| 851dabc18b | |||
| dccdbaeb73 | |||
| f4126f5378 | |||
| 97af075c7d | |||
| 1dfdd422db | |||
| 072082c56a | |||
| 43caa2a55c | |||
| b8bad9b6bf | |||
| 8afdd6ed2b | |||
| 34968a6945 | |||
| 851a79a77e | |||
| 1ca1db705f | |||
| 8f57c2cce2 | |||
| 942e3093cb | |||
| f3e65010f1 | |||
| b3cfb35fac | |||
| b60d778303 | |||
| 9ec28aa661 | |||
| 98400a9d3c | |||
| ae8658ae77 | |||
| e928fe3ecd | |||
| 963dc4a404 | |||
| 04f42999df | |||
| 730d014f13 | |||
| 1f81c50ce1 | |||
| f60c550879 | |||
| 0d556b5d95 | |||
| 70d897f09c | |||
| 9accb6d584 | |||
| 843dc580c8 | |||
| 77aa4773ef | |||
| fc3c944e3d | |||
| 7d6aecc4c7 | |||
| 528beb8384 | |||
| 5f1180a5dd | |||
| a9f1e8587c | |||
| 7a076f5509 | |||
| 3349e51655 | |||
| 77a366065d | |||
| c2d6ecaae6 | |||
| c9bc830058 | |||
| 6125031d9d | |||
| c041cde574 | |||
| bd946af229 | |||
| 559626456a | |||
| c6843c1d95 | |||
| 0d32fab434 | |||
| 94571de00f | |||
| d062eff8b4 | |||
| b1e46faf6f | |||
| 04ed5b2e03 | |||
| 15d9ff503f | |||
| 64942d77e4 | |||
| f287dbd4d3 | |||
| c387f57d9c | |||
| 2dacb91b79 | |||
| d809568cc3 | |||
| beee44df14 | |||
| f651fc4b50 | |||
| 596e4eae0e | |||
| 6e70073ae4 | |||
| 1beef2b4ad | |||
| a0e4ed8371 | |||
| f40adfd9c6 | |||
| 7fb5e95809 | |||
| 03d5cb9289 | |||
| 3b4b4d6b7e | |||
| b9a97a0fda | |||
| 0dae6942cb | |||
| 8bb6aeb526 | |||
| 32ec420248 | |||
| 1925537da0 | |||
| 3bb4c21fa2 | |||
| 5b61a98196 | |||
| 7c6eba983a | |||
| 0023ab09ed | |||
| c289f5d717 | |||
| 6df3ad722c | |||
| 56f6abd858 | |||
| c326e0ba81 | |||
| 60b28fcf2e | |||
| a9ffd3bd3b | |||
| bc72e925df | |||
| 108df99633 | |||
| ba245ea266 | |||
| ec721ce172 | |||
| 3ad2a95c10 | |||
| e22e241d06 | |||
| cd70d55b4d | |||
| b6c98d3bde | |||
| 5fe605540d | |||
| c232b64f24 | |||
| f94b6dbaa5 | |||
| 928bc5df6c | |||
| a5865b3545 | |||
| 8f15ab7ccd | |||
| 131e4124f3 | |||
| ae6333c7b5 | |||
| d38c622d9b | |||
| fe625e5b55 | |||
| 38a6ad552b | |||
| 222a008514 | |||
| 56684bdf4c | |||
| eb4525c68d | |||
| 66eb2ed0f9 | |||
| 9866842e01 | |||
| e9487b0481 | |||
| 82c5aa907b | |||
| 47b145cb90 | |||
| ff46b925b2 | |||
| 8ca7ff5ae0 | |||
| 70550a21a0 | |||
| 50f911f63c | |||
| 4b0dca5823 | |||
| 0e777f04bc | |||
| b12f27cc18 | |||
| 1a66f457af | |||
| b4dca6a1b4 | |||
| 7759a2f9ea | |||
| fe9bccb91f | |||
| fc6fd310f6 | |||
| 8be161b381 | |||
| 8eba8cb40b | |||
| 44326344e6 | |||
| 17b7ee9045 | |||
| 6a47a2150f | |||
| 13728a7540 | |||
| c51e941413 | |||
| 2a05c32a2f | |||
| 353a507914 | |||
| f3b73d54f8 | |||
| 92ed9b8070 | |||
| 9c3c37bc3e | |||
| 79fb7c654a | |||
| 520b4e0930 | |||
| 45a07206c9 | |||
| ad0b78936a | |||
| 2babae40de | |||
| 17713a9f93 | |||
| 48120a4a38 | |||
| 69ffd795c9 | |||
| 1df5dd5458 | |||
| b77acaa3b2 | |||
| d8024ab488 | |||
| 064d8b3506 | |||
| 9ca6a2116b | |||
| 449c87982c | |||
| 7edfc40b9d | |||
| 9acda97f54 | |||
| 14edd63029 | |||
| f3a1235dd3 | |||
| de93bfee2f | |||
| 6eb80ace00 | |||
| 3ac8d6a8b1 | |||
| 269c8dc4e3 | |||
| c8173005a7 | |||
| ed846ea564 | |||
| f6a8f5c6b5 | |||
| 3c60a7d842 | |||
| 3c97feeaf8 | |||
| b2ac91f7db | |||
| 1ebad39fc1 | |||
| 38a2edff06 | |||
| b2cf38798e | |||
| ed83e41f19 | |||
| 6d52cdba0a | |||
| 05449c9e86 | |||
| 33ef1297ba | |||
| 3b13786990 | |||
| 222d06898e | |||
| 4438adad24 | |||
| 986e474657 | |||
| e8288a0df9 | |||
| 74cab8f4ad | |||
| 5e35572de8 | |||
| 7e0e02bafc | |||
| a301532443 | |||
| 940448f219 | |||
| 8510deb6aa | |||
| 0d0ba5d3bf | |||
| 036371dd76 | |||
| 5aae584ffe | |||
| 201c619915 | |||
| 7cd6a3bb79 | |||
| ca36d4797d | |||
| b5fe3bcbf9 | |||
| e43f9e76f6 | |||
| b8901c3edd | |||
| d28938f8af | |||
| 9f108220f5 | |||
| ffe53a7196 | |||
| 9e12849107 | |||
| 0a8c093682 | |||
| 60056e1654 | |||
| 11a752a99d | |||
| 68097f61eb | |||
| 8b514b07dc | |||
| 8e6010bbe5 | |||
| 95eb07ca79 | |||
| e6e03e78ea | |||
| d2c572414c | |||
| d2e0d5b32b | |||
| d4ba227a44 | |||
| caba007899 | |||
| d5cfe9b8e9 | |||
| f1707236fa | |||
| c55cbdb69a | |||
| 00b69dcc68 | |||
| cd74e33c54 | |||
| 3f14e5dfa5 | |||
| 8c9e6ea79a | |||
| c71de31f57 | |||
| ac869bf06e | |||
| 3175bc0439 | |||
| 23ac6ec957 | |||
| f080a59b41 | |||
| 603200ed8b | |||
| b0774052a0 | |||
| 7e163ce626 | |||
| d19654cf15 | |||
| 838d8be08b | |||
| 2de82b1223 | |||
| 650012fb08 | |||
| a1ef3466ad | |||
| 97421feb33 | |||
| 0c90af6515 | |||
| 9cebd0298c | |||
| 9afcddca4f | |||
| 02fb7eedba | |||
| 4aa9bec15c | |||
| a6eeaa5b3e | |||
| c462325ce6 | |||
| d208b0ab19 | |||
| ab4ef429db | |||
| 86473e022e | |||
| fd89f569d0 | |||
| eefc765823 | |||
| ebccb2516b | |||
| 8c62a40da9 | |||
| d56af5c38f | |||
| 39b1ec61ba | |||
| cb613cf7df | |||
| 28e33b4c36 | |||
| 855e6b8180 | |||
| d62161f529 | |||
| 71d48411f1 | |||
| 731842e09c | |||
| 61169f87c0 | |||
| 9fb3b196d2 | |||
| 867b875cf9 | |||
| 3875c8c4ce | |||
| 89b959d3f5 | |||
| d62e50d6f4 | |||
| 16836a2b49 | |||
| f5651f26a5 | |||
| 82ff59c857 | |||
| 8af61041f0 | |||
| 2a9136b56f | |||
| 64da6c811d | |||
| e6b93e0d92 | |||
| f874219a64 | |||
| b4822740f4 | |||
| af205a50b4 | |||
| 2f6eaf79bd | |||
| 625f1e700f | |||
| 897d5b0b11 | |||
| 95641e2f4e | |||
| cd856b86c7 | |||
| c00aa6d627 | |||
| 398a3fb0bc | |||
| e0fa638ad9 | |||
| 4e42cbd4ce | |||
| b6c6be77cd | |||
| 0964293a72 | |||
| c8b6141ce0 | |||
| 948540369f | |||
| 363df0ad6f | |||
| a37e105434 | |||
| aeea0c00c3 | |||
| 137352674e | |||
| 4734552954 | |||
| 879c2f1ec4 | |||
| 7dc9d2a352 | |||
| cabc470ebd | |||
| 0bf1f493aa | |||
| 705bd14ee4 | |||
| 155955e49b | |||
| c76a793b18 | |||
| 50cc8501a0 | |||
| 209279e3e4 | |||
| 41239572a5 | |||
| 106ab47c3d | |||
| a84f9b60e5 | |||
| 4481e8634a | |||
| 3e432682fb | |||
| 05569c03a4 | |||
| 2d567b84be | |||
| e2a378250f | |||
| e2083a1836 | |||
| 334946ab59 | |||
| 8c9bb98125 | |||
| 726f0f3d3c | |||
| 50e5898692 | |||
| de05a5f674 | |||
| 31b57fae50 | |||
| 2f686057f3 | |||
| 132251341f | |||
| 2bac5f933a | |||
| 2e565aa83a | |||
| 4e9d0f4861 | |||
| 7216b193e8 | |||
| c33a5bf814 | |||
| 97756a5196 | |||
| 377f7d23e3 | |||
| 7005202384 | |||
| 99e8f57bac | |||
| afddf4168e | |||
| fbffdc0c9f | |||
| e6d3647490 | |||
| 13363ff363 | |||
| 7f98e4b1eb | |||
| 408460b0ae | |||
| b69ef5835d | |||
| 0428fa0912 | |||
| 9f3124fa56 | |||
| fbbdab73c6 | |||
| ee9441c521 | |||
| a9e0fd5d9b | |||
| 98464889ca | |||
| eed5fd60c6 | |||
| ac43cd5496 | |||
| 1f16a7c808 | |||
| 39e4c70754 | |||
| 82eb27af4c | |||
| 3aaab94b39 | |||
| 07a0779ca4 | |||
| 2adba02a38 | |||
| 9dd76db3fc | |||
| 97dacf2429 | |||
| 1c189e162a | |||
| f7a0fff869 | |||
| 2f985d0926 | |||
| 2a3c544fba | |||
| 09d133b994 | |||
| 26a4223ecf | |||
| e2943fdcaf | |||
| f1053251b4 | |||
| be1dcaf43c | |||
| a899d988fc | |||
| 06b5b2c514 | |||
| 864a19b79f | |||
| 8974323406 | |||
| 46c9e0103a | |||
| 02203466ed | |||
| 87b22ea1cc | |||
| d26327a930 | |||
| 469d2bdcb7 | |||
| 5516603a0c | |||
| b737adc3da | |||
| f3a8afeee3 | |||
| a4501f86e9 | |||
| 095fff96ff | |||
| a23211d061 | |||
| b57ea41686 | |||
| 62fb5ffb73 | |||
| 99c713967b | |||
| 9f3de07bd8 | |||
| cd74117de3 | |||
| e7d7033548 | |||
| 34db7c9dac | |||
| 272841aae9 | |||
| 389b09a5cd | |||
| 84bd876c71 | |||
| 7e45051ffd | |||
| 5570f3a313 | |||
| f4e71f7012 | |||
| 601d4e6e3a | |||
| a12092c1a1 | |||
| 94ad118c5d | |||
| 48e2978438 | |||
| 96b4c1a9e8 | |||
| cc4a69c10c | |||
| 7293677ddb | |||
| 0f2ff20375 | |||
| 7706240acb | |||
| 4cf48fd997 | |||
| 2708c1ee11 | |||
| ebb0f6ebad | |||
| 2c263a2549 | |||
| 955524c632 | |||
| 564e0d3263 | |||
| c533b2e8ea | |||
| 6073d8122a | |||
| 71ca26bba9 | |||
| 75a51be28c | |||
| a66e4ba157 | |||
| f2b9e428d3 | |||
| 5b2497b9d4 | |||
| e78424def4 | |||
| e2c94de6e6 | |||
| daa3caf684 | |||
| 5991aa42d9 | |||
| ff6a5aae69 | |||
| 80d9b4540b | |||
| 4998991ebe | |||
| 14343569fe | |||
| be6cc5ff4e | |||
| 0ad3391bea | |||
| 582d998e2e | |||
| c00ee26075 | |||
| 4c9f70a52f | |||
| 29481bc123 | |||
| e274c9e004 | |||
| 73988f0308 | |||
| c4a9e7a2a7 | |||
| af6dca6e5e | |||
| a49720a221 | |||
| 12a66e70c9 | |||
| 00d8aa356b | |||
| d40d94a565 | |||
| c1f798793e | |||
| 8fe4ad454c | |||
| 17022f2df2 | |||
| 7fa4bc35f6 | |||
| 85df9c5ef4 | |||
| 45d4f390a9 | |||
| e7b60b7562 | |||
| 2615177907 | |||
| a83d7e2a26 | |||
| 8a2182e238 | |||
| d45455092c | |||
| da18469fd4 | |||
| 6b5bae9bee | |||
| e29a7786e4 | |||
| 55a837ca5e | |||
| 94cba6cf67 | |||
| 294685df00 | |||
| 2642b7a9a4 | |||
| 45594e4e47 | |||
| 54cd1a2e48 | |||
| a20fb982ec | |||
| 184d61e637 | |||
| 06ea56767f | |||
| 1f6e137759 | |||
| c7cf7885ae | |||
| 8e98444887 | |||
| 9bfe2e8233 | |||
| 21f4adc769 | |||
| 3b10ca5809 | |||
| 6cc8284747 | |||
| 6254f7156f | |||
| 0fa03701a4 | |||
| 49125cae47 | |||
| 3298857d0c | |||
| d939cbeb96 | |||
| 54d254be73 | |||
| d433fdea62 | |||
| ffa1c54ff3 | |||
| 019ac6dec3 | |||
| 08d3da47f4 | |||
| 348ac2b734 | |||
| fe014b4985 | |||
| b7f6f3b900 | |||
| 3c76ed71d8 | |||
| 5de1998913 | |||
| 05c0f030cb | |||
| bd85329589 | |||
| da0f4ae326 | |||
| b37e568372 | |||
| b1c6a5c1d4 | |||
| 8222126e8f | |||
| b5b888c69f | |||
| 85f6b8320b | |||
| 6c4740e8aa | |||
| ffda83c25d | |||
| 18859d22a8 | |||
| befa3b375e | |||
| a96c08cad4 | |||
| d7f789c402 | |||
| ed28bcd0ba | |||
| 982ae0c0a0 | |||
| d17897f276 | |||
| c0ccef7e82 | |||
| 55e5c64c68 | |||
| da72f783ed | |||
| 8a9bfa3d33 | |||
| 82937d840a | |||
| c1bd358502 | |||
| a8a22fd9fe | |||
| adb70857fe | |||
| a680596b3e | |||
| b2986ec782 | |||
| f40f7afab3 | |||
| 59555d1ca8 | |||
| 6e2eb7d1ac | |||
| 69483067b4 | |||
| c815591565 | |||
| f82b7ec608 | |||
| 23a107682c | |||
| 26da69c875 | |||
| 8f2df2396d | |||
| dbc9cbb418 | |||
| 09c788e495 | |||
| 9af71ac0ea | |||
| 2db20f8f24 | |||
| 2c9827c227 | |||
| 825b1ab4db | |||
| c61faac06c | |||
| 6b442f03c1 | |||
| 10ab638643 | |||
| d349d0c453 | |||
| e5c948ce9c | |||
| c51255f379 | |||
| 5bbeceee56 | |||
| ee78920a88 | |||
| 138972cf18 | |||
| 1bda767cd7 | |||
| cf1402edb9 | |||
| 778144a553 | |||
| fcca51a8d9 | |||
| 3cc663ee95 | |||
| 52f15a86fd | |||
| 734bb4afb8 | |||
| 9cd48fb5d7 | |||
| cd5c3d9f13 | |||
| 73ba1c8b56 | |||
| 8199b4408a | |||
| c00e3d7393 | |||
| 5d60251da0 | |||
| 855d707b3e | |||
| 592a1c3601 | |||
| da280db0f8 | |||
| 0ee6673e68 | |||
| 8bedb3dbaa | |||
| ea0e24b430 | |||
| cd35461df6 | |||
| 40580e81c2 | |||
| 1a279b90be | |||
| e34203fe3d | |||
| 870c0f68d3 | |||
| 004059dd9f | |||
| 4290cdf8c6 | |||
| 4d038fc5e6 | |||
| 0146d62c2a | |||
| 4e6255dc2b | |||
| 4d73c3ecb8 | |||
| d0dc3ec9bc | |||
| ee922236a0 | |||
| bf088ab29c | |||
| 40102521a1 | |||
| eb491144f3 | |||
| a14748ac75 | |||
| 0c5f38a00b | |||
| feb6dd41b7 | |||
| a093524939 | |||
| 5cc7bebbe5 | |||
| 32a256619f | |||
| f93e648f69 | |||
| 41f022df99 | |||
| c84aac7e45 | |||
| 4e4fbbe48c | |||
| 7265e2b631 | |||
| 0a11f310cf | |||
| a6143780fa | |||
| 761f802ced | |||
| 2e7cc9f4b6 | |||
| 4e6e727799 | |||
| 2da444d03c | |||
| f4f234a159 | |||
| e87823aa29 | |||
| 56167a137e | |||
| 91ac4309df | |||
| 8a5bca3136 | |||
| ec8d1b5538 | |||
| 0ebe8db268 | |||
| 3bba08723f | |||
| 6a6a87a3f7 | |||
| 0ccdcfbb6d | |||
| aa084c885d | |||
| e3a8a7782e | |||
| c578ae0fa4 | |||
| f17bc1eccd | |||
| 08c31e5999 | |||
| dd341c9a22 | |||
| 733fb8e871 | |||
| 4764f0969a | |||
| 41f8c8cfa4 | |||
| 42bcc28d3e | |||
| b878faac96 | |||
| 32c1cc29f8 | |||
| 838d82589b | |||
| b62af66f4b | |||
| 794f524ae3 | |||
| a38551b3d0 | |||
| 03c4926b09 | |||
| 982bf951e1 | |||
| a887e35285 | |||
| 172f2b088d | |||
| 6d7b557c36 | |||
| 9959ebc196 | |||
| d868b8fc72 | |||
| 297c8a1a1e | |||
| e809429a8c | |||
| 200ad05f4c | |||
| 9b4276c29b | |||
| 038073d34d | |||
| 8d32ab9bdb | |||
| 9390b8bc4d | |||
| 0d165860fb | |||
| 4135fa6211 | |||
| 1d89467022 | |||
| e21ac626b3 | |||
| aa73a30ac4 | |||
| 9a8f14c7d3 | |||
| d7618d73c3 | |||
| 5aca47b357 | |||
| 666ab1319b | |||
| 50663edc76 | |||
| 1fbc37f8e7 | |||
| 5f437f8a4e | |||
| 6130c65c48 | |||
| 1e19dfd6e8 | |||
| f866243d5c | |||
| af04c6d995 | |||
| 46bf8d0188 | |||
| fc62c78136 | |||
| 93c2bf530f | |||
| 51b543a23e | |||
| dab5373231 | |||
| 17f274a7b4 | |||
| 841e5ba492 | |||
| 50339c94e7 | |||
| d2ad35ad05 | |||
| 0d65578e6a | |||
| 526df4f184 | |||
| aa6cbd1b7d | |||
| 92f0703723 | |||
| 064241333b | |||
| 39b77c783b | |||
| 0c8717a0da | |||
| 7f89a1a2cc | |||
| 5f16f81d58 | |||
| 10bbcc79d3 | |||
| ffc9771b17 | |||
| 091b115aad | |||
| c3bdc22e28 | |||
| 28d4cc86a9 | |||
| bb6e29f254 | |||
| ea0d4ba7d8 | |||
| 0504882afd | |||
| 0156f03e91 | |||
| d2acaba5c7 | |||
| 60e4128316 | |||
| dc8aa7624b | |||
| 941aeedee0 | |||
| 4d8ce3b5ea | |||
| 6044d24a48 | |||
| d597634ac6 | |||
| cf8b0329bb | |||
| 24520824e9 | |||
| 0d7b0f9fe4 | |||
| 61460f9ac0 | |||
| 14d64d535a | |||
| b00c252f17 | |||
| 0fe017df74 | |||
| 4ae7083dcf | |||
| 7d5357dec8 | |||
| 2bb2f5a233 | |||
| fee1c98a34 | |||
| e787d7d317 | |||
| ed52efa72b | |||
| 963d22b2f5 | |||
| 8714be1dc7 | |||
| 04ddd83519 | |||
| 5b81ca2716 | |||
| 6f8c7e8249 | |||
| fabad7158e | |||
| bae7e44dd8 | |||
| 926c7924df | |||
| 704a2ff217 | |||
| 871c6031b8 | |||
| afb0a57920 | |||
| 1787d2c6d9 | |||
| 1a07fb83b6 | |||
| 4d2ee292bb | |||
| 0fdde61fe5 | |||
| ae8a4912a6 | |||
| ffd8ea8751 | |||
| 4cd10a82fd | |||
| 4955d22649 | |||
| 425b761f8e | |||
| ab3bfd457f | |||
| 0faa64112a | |||
| 46519b096c | |||
| cb7d980e15 | |||
| 6c1562ac33 | |||
| 5e17e4ea8c | |||
| b8e7b14fbb | |||
| 5d8eb185bc | |||
| 7325cedba6 | |||
| e5043d6d9b | |||
| 13e53a18e3 | |||
| dd60c7620f | |||
| 83c01cabfb | |||
| a95171dbbe | |||
| 10d542ed14 | |||
| 7e1c55a0c5 | |||
| 4e25d318ec | |||
| c4228f4e63 | |||
| 1411091f60 | |||
| 6a2278949e | |||
| 374b859882 | |||
| a98bdb94b8 | |||
| de390f5d70 | |||
| 9d4968351b | |||
| e99fbb76bf | |||
| fd175d2f36 | |||
| 0db862e42b | |||
| 58f5d64f91 | |||
| bb54a94acd | |||
| e34a7eef06 | |||
| 3d177369ab | |||
| 946aff24af | |||
| 424429bff1 | |||
| 55df8daa35 | |||
| 734edeaba9 | |||
| 48452e6fe7 | |||
| 314c88a452 | |||
| 3a782a1c4b | |||
| 924b2b7e8e | |||
| 34565992ea | |||
| dbc84cc0f3 | |||
| 15de27eafd | |||
| 8a882d7bf4 | |||
| 04ee9d58bc | |||
| ee867e972f | |||
| a227547daa | |||
| ef1699f2e9 | |||
| 108f692c82 | |||
| a3026fbb61 | |||
| 33c2ca839e | |||
| 4ac4daeac1 | |||
| 49f90aa5c9 | |||
| 6788ac41c5 | |||
| 8e25deb33d | |||
| 3d31d20a46 | |||
| 7b902a4be1 | |||
| fbd48b3cfa | |||
| 9475040627 | |||
| a673a3be4b | |||
| 2d444ab0bf | |||
| 95e29f36ef | |||
| ad97f322b2 | |||
| f19281e832 | |||
| 3c91e53228 | |||
| 3f35909641 | |||
| 384ba30a61 | |||
| 33b5c225a4 | |||
| 1a3560feef | |||
| ae2e45b52f | |||
| 1bb2ef29f5 | |||
| 59ad956ba1 | |||
| 4af6ec7428 | |||
| 32b59ee8a4 | |||
| 0d5a8dee73 | |||
| 91863034e8 | |||
| f705fee90f | |||
| d10a9e08d7 | |||
| 070d7e23d5 | |||
| 1b200259c5 | |||
| e21149466e | |||
| f6528be87f | |||
| e8c2271db8 | |||
| 9f5c63d9e2 | |||
| 539048bfac | |||
| e155e68289 | |||
| 083fab7323 | |||
| 5450a7efe4 | |||
| f6860ed4af | |||
| 15ed0c2392 | |||
| 22f290c8a3 | |||
| 6d39fb23d6 | |||
| 0a523b99c7 | |||
| c537ab2082 | |||
| 63005035d7 | |||
| c8d03a625a | |||
| d11d26dc9f | |||
| 1932cf9e76 | |||
| 97e6797fea | |||
| c4105c3014 | |||
| 826b4a6305 | |||
| 0cb0874c54 | |||
| b831dd84e4 | |||
| 6775bf8a3d | |||
| 61402afd93 | |||
| c5cff674fe | |||
| 679b5c082a | |||
| e00faa8e3c | |||
| e5265f3dbb | |||
| 71e3e10280 | |||
| 9443f6d1e5 | |||
| 415c553308 | |||
| 4b783df11e | |||
| 6d7135ef29 | |||
| c0f8b6729b | |||
| a5a01b8a76 | |||
| ecd44d9d31 | |||
| fb4f0b0440 | |||
| c0bd3dda19 | |||
| d4c94ea5e4 | |||
| 1a48d161d9 | |||
| adbb9cbc40 | |||
| 40db006d62 | |||
| ed64e83807 | |||
| 644b5462f1 | |||
| 33aded7345 | |||
| d04314a9ee | |||
| fadc2e7ab4 | |||
| 8fc6d4a1de | |||
| 87c3f5549c | |||
| 1e9120c6d9 | |||
| 53a6b9fcd0 | |||
| 682fb11e9e | |||
| 17f515ef06 | |||
| 3f6bc262cd | |||
| 5f025808ab | |||
| b93c5815c7 | |||
| 1482bfcd07 | |||
| 71634f509a | |||
| 608e2d5723 | |||
| f39d2d92f7 | |||
| 264a9b66fa | |||
| bee9cce881 | |||
| ec63a025fd | |||
| 69c5f49c72 | |||
| 64d2363050 | |||
| 796f450091 | |||
| aa0f274b87 | |||
| c3103810db | |||
| 7fb021010c | |||
| b5267a0658 | |||
| 1775a58938 | |||
| 76f7371057 | |||
| 727d7ee346 | |||
| 40618bc35a | |||
| 2463d8c024 | |||
| 90c53d8116 | |||
| eb4e3bc793 | |||
| 172d43a11b | |||
| 75419ed5ae | |||
| 94978fe10a | |||
| 71493e79d5 | |||
| 48fc9d13ad | |||
| 867152fdf2 | |||
| 7d13cb4905 | |||
| 115c531be2 | |||
| fee8dc9b13 | |||
| 0bbaa15579 | |||
| aeb7cf6ff1 | |||
| 0be45abc28 | |||
| a6bff2abb0 | |||
| f4d6e63c47 | |||
| 2edabc7168 | |||
| 46e5bf24ca | |||
| ba014fc581 | |||
| 225dad9d84 | |||
| ca2914d3a9 | |||
| 85203847d5 | |||
| db2cdbaecd | |||
| 3a80c6f59e | |||
| 0137a6bfd0 | |||
| 8b4c647fd2 | |||
| d4ba61e341 | |||
| 634df3ba06 | |||
| 88766f30e4 | |||
| 14a15754fb | |||
| c919fe9ab0 | |||
| 13bf04ef2d | |||
| e42919c37f | |||
| 5a3bd0c9dd | |||
| e1907245e2 | |||
| e476b56ac1 | |||
| 776ec93d09 | |||
| fc0aafb070 | |||
| 54fa033e07 | |||
| cbd0521a0c | |||
| e958790f76 | |||
| 06bb4a9cb3 | |||
| b38a8d5e62 | |||
| 84028f78b8 | |||
| 515c45b4c8 | |||
| 0cac09aec1 | |||
| 695809d573 | |||
| e12f33a938 | |||
| 8e69174d5a | |||
| 3ea6bee3cf | |||
| c1fda715d0 | |||
| e4a7056d48 | |||
| 2107d3cbbd | |||
| ef6fc07cd3 | |||
| 56172c69a4 | |||
| a92aa1eca8 | |||
| f2931e8204 | |||
| 5d47a5f391 | |||
| 299fbe7336 | |||
| b30c8ea413 | |||
| 64dea2d730 | |||
| 9edba26910 | |||
| cf6b3d9a89 | |||
| 47f297809b | |||
| 12b4521df6 | |||
| 48291e261e | |||
| 7c9fd5be9c | |||
| 8d822d7f3c | |||
| f42a76c8fd | |||
| 8765f9effa | |||
| 276b839668 | |||
| 507b045eb9 | |||
| 1de8cfb001 | |||
| 1ab8483df5 | |||
| 969edef3b2 | |||
| 20be303dd0 | |||
| fc43f866a1 | |||
| eca04899de | |||
| 7b7fb8db44 | |||
| 313b660334 | |||
| 5b84b26b67 | |||
| 6dc567e079 | |||
| 13b26d5902 | |||
| 3d7b21c444 | |||
| fc5879beab | |||
| 251c9d1134 | |||
| 0a1bf750ba | |||
| a236264d14 | |||
| ba45a7c2f5 | |||
| 95b1ecff0d | |||
| 8ad5565148 | |||
| 5cda6a6f2c | |||
| 6f35d0710e | |||
| 0c87a2a9ea | |||
| 3ddc315826 | |||
| b888103c80 | |||
| 09e689dc2f | |||
| 0f61affac8 | |||
| 57e44cc4a7 | |||
| 876c4f2510 | |||
| 6c4364f009 | |||
| d96fc3c73b | |||
| e3da644b1c | |||
| 34bb512f03 | |||
| fae58503a8 | |||
| 0ea69d0ca4 | |||
| 3144e9d957 | |||
| 30fac5e5ce | |||
| 37cbeebaa5 | |||
| 3aa6cc3383 | |||
| 56dd3c352e | |||
| 83fa1a0281 | |||
| 5b4049e0ca | |||
| 888651ef52 | |||
| a122b2c143 | |||
| a41afa0dbf | |||
| d9b969e7a7 | |||
| 9297ac4c35 | |||
| 7ee42a9529 | |||
| 640559239c | |||
| 263574bf38 | |||
| 60cbbb0393 | |||
| 91f9f17989 | |||
| a96e345fbe | |||
| 9ffc54f0b1 | |||
| bf3428b53c | |||
| c78f6eb66d | |||
| 73f4bc3108 | |||
| 73a42284f1 | |||
| 90accf01db | |||
| 1cb60f6a6d | |||
| bfcc4b001d | |||
| 2f7852f103 | |||
| 944b3c05ab | |||
| 531a308b39 | |||
| 27cd001680 | |||
| e5ee46335d | |||
| ef72cdc0e6 | |||
| 246bd54b55 | |||
| e1147f3f60 | |||
| 3bc0104268 | |||
| 50e9a51f56 | |||
| 87fec5276d | |||
| 2b734bb8d4 | |||
| 2d93a23da9 | |||
| 1ac1b7ee2d | |||
| 81adca92c0 | |||
| d509694ba9 | |||
| 7f658bd310 | |||
| d7728cce45 | |||
| 4d649d8a33 | |||
| c3d0cc2da8 | |||
| 0b67d64ff4 | |||
| 386dc38150 | |||
| ba6b08b818 | |||
| 2cfef3a84d | |||
| 8b20e1ee6d | |||
| b254fde3ae | |||
| 876989346b | |||
| 7278bc1548 | |||
| 1728c3e898 | |||
| 80393529f1 | |||
| b9d635ac69 | |||
| cca668979f | |||
| 0e017cf512 | |||
| b1e75431ae | |||
| e12d7766d6 | |||
| e43ee68508 | |||
| 9a9aac64af | |||
| 5193a3313d | |||
| 2ff1b80650 | |||
| 7e0e51103b | |||
| 2977486866 | |||
| bb9df60004 | |||
| a1b42f61fb | |||
| b394c01f47 | |||
| c047996592 | |||
| cc2340d1b9 | |||
| 01b233e968 | |||
| c53cf3f870 | |||
| 4f0da248e3 | |||
| 44688afeb9 | |||
| 4301ed9917 | |||
| 0b26f8ce3c | |||
| 815aed53fc | |||
| 9cde0edfa3 | |||
| 70b3ba0040 | |||
| 32c89b1af9 | |||
| 21144a7ce4 | |||
| 0935a6e94b | |||
| f28f09dd40 | |||
| f564755d66 | |||
| 2af274171c | |||
| de726b7669 | |||
| 22d134e786 | |||
| 642b040f65 | |||
| 0cc883b6c3 | |||
| 902362f54f | |||
| f9c946e3ce | |||
| 9020d5bbe6 | |||
| fe973d27b9 | |||
| e9c1f41f50 | |||
| 630e3bf16f | |||
| 27df83f8e7 | |||
| 4ad9bb0d71 | |||
| 4fcd4cb2f7 | |||
| 15beb792d1 | |||
| 401daf907c | |||
| a3f6f51a7a | |||
| e4cd89131e | |||
| 32d8553b9b | |||
| 092fc45a36 | |||
| 9f58cf305f | |||
| c1370e74a2 | |||
| 3b3ec1eee2 | |||
| 803d26c7c7 | |||
| 9244f29daa | |||
| 0a9e789cdc | |||
| a761ef4b6b | |||
| 3f4df4289c | |||
| 879c70a7a0 | |||
| b0c1f69023 | |||
| 889474fb42 | |||
| 4ad6c854c8 | |||
| 521549a349 | |||
| ee06d81434 | |||
| 3f6ee90b4e | |||
| a017586c0e | |||
| 027b867afd | |||
| 67b61b55a3 | |||
| b2efeb77e1 | |||
| 2929009e63 | |||
| 4604751f80 | |||
| 6906597165 | |||
| 8235a911ab | |||
| 8af8039a00 | |||
| b399121f20 | |||
| bf519301f5 | |||
| 9f0378f969 | |||
| ea9cb7fcac | |||
| 7ba1f77a19 | |||
| 739947e008 | |||
| cfb0dd4096 | |||
| 92ff5beebc | |||
| 8bb1251dc9 | |||
| a52a122f9f | |||
| c90efed0fe | |||
| b41119232e | |||
| 9fefaf6eca | |||
| b5f3be4fcc | |||
| f6c05303ea | |||
| 18b0b8c6f4 | |||
| 9c73443aa2 | |||
| 8fd5c6e3a4 | |||
| fb57fbbe8d | |||
| 98d2b0db3f | |||
| c895dff2c8 | |||
| 5cd6111e92 | |||
| a57a34ab58 | |||
| 49baaaab85 | |||
| f8a0ce84de | |||
| 7408187507 | |||
| f2c2c5dd92 | |||
| dbefea35c2 | |||
| f887f38e17 | |||
| 080a99d6db | |||
| 7fee50883a | |||
| 9bc97780a4 | |||
| 7b3f63a2f2 | |||
| 60be8302f4 | |||
| c2ec60c6e5 | |||
| fef7369338 | |||
| 036754c54a | |||
| 8e0ccd781b | |||
| 1ee02211b9 | |||
| a2ac2e00da | |||
| a33ecec9d3 | |||
| b0937fd9d0 | |||
| d1283db786 | |||
| dc556efe0b | |||
| 0ff59e49a1 | |||
| febf5c31cc | |||
| 1665999111 | |||
| 14dd26349a | |||
| 54e356d98c | |||
| 959dd4e718 | |||
| a61b2cb2fc | |||
| 6ac5b7f9a3 | |||
| 3f26a70169 | |||
| 084bf635cb | |||
| f1a7e69c63 | |||
| 93cfc64493 | |||
| eeaa836c45 | |||
| 30d3d8c52e | |||
| eaa61098fa | |||
| 2ee087f29d | |||
| d8861f6100 | |||
| 8802ce0a32 | |||
| 7405839718 | |||
| 2d77efd8ea | |||
| 9c73926cd2 | |||
| 0c7b1e06fd | |||
| 113bd75154 | |||
| 3d268adeea | |||
| 3ac2392edb | |||
| 008f5cf915 | |||
| 77cc7fe669 | |||
| b6d352fbce | |||
| fc8426a2ee | |||
| cd78ffc069 | |||
| 5230a4abf9 | |||
| c37304d114 | |||
| 0144619ed4 | |||
| b7cc51bb3e | |||
| 96c844c6e8 | |||
| 09930b1754 | |||
| 8cf51d0f77 | |||
| d3667b0e3a | |||
| 3ae7f3a299 | |||
| 800d64c923 | |||
| fd2a1ca036 | |||
| d8e631f52b | |||
| f41e182f86 | |||
| 4876ee5d7c | |||
| 58d5f16845 | |||
| b26b072332 | |||
| ab62c62079 | |||
| dacf573548 | |||
| 11baa7956d | |||
| 88bab7736b | |||
| cf5dcb63d1 | |||
| fe92203201 | |||
| e9c2a6e0e4 | |||
| 21f665c941 | |||
| c9c96ff2e8 | |||
| 1e8964a162 | |||
| e5cbcf2614 | |||
| 995f30b7e2 | |||
| 64e0f9b48f | |||
| db7001dd6f | |||
| d70de5dac6 | |||
| 0a45192030 | |||
| bdda96854e | |||
| 638e7c19a3 | |||
| cedb63a505 | |||
| 84941639ff | |||
| cb8e4231a5 | |||
| 447759304a | |||
| 0b8f57a952 | |||
| 5808179abb | |||
| 87f3a718b4 | |||
| 6c79c6b1ff | |||
| 889daecc86 | |||
| 10de377081 | |||
| 310b237b7d | |||
| e71727c6f9 | |||
| 213d7a30b4 | |||
| bc1a0123b2 | |||
| b3c4c790dc | |||
| d96c96fc6e | |||
| 79513b6c52 | |||
| 6fca33e496 | |||
| 0184396b6a | |||
| 47963fba43 | |||
| cd95405c6a | |||
| 3936b63580 | |||
| c1c4a91bbf | |||
| 51b93a7e3f | |||
| bde11b5950 | |||
| 3aab0469ab | |||
| dd2c9d1e56 | |||
| 4dbae72eae | |||
| 2aac43485a | |||
| 6aa94d1ec5 | |||
| a9b1ca888a | |||
| 6477408858 | |||
| 1b66672166 | |||
| 207d5cb949 | |||
| 3b90855781 | |||
| 61c4b50528 | |||
| 38085c3e7d | |||
| a16099bc98 | |||
| 0342b4b5a9 | |||
| 9be222f25f | |||
| 5e242561bd | |||
| 014b49246d | |||
| d57192f76a | |||
| a52c286241 | |||
| 16bcf30092 | |||
| b2ba94f6e5 | |||
| 7d8ab781cb | |||
| 52f52b1c1b | |||
| 9a5ebce51e | |||
| 960488bef4 | |||
| 318d514b41 | |||
| 01f767486d | |||
| eba2036718 | |||
| f9a7aa3c62 | |||
| 064c69d66c | |||
| 1ef2084e3b | |||
| 0396c5e384 | |||
| a02fb42490 | |||
| b82d9d6d9a | |||
| e2855e8984 | |||
| 2bbf081f99 | |||
| f4784840fd | |||
| 3464341c04 | |||
| ff16a97ce8 | |||
| 56c666ead8 | |||
| 12ef1f30f1 | |||
| 5d7abd5f70 | |||
| 047dc0d4f5 | |||
| a1f9fdc715 | |||
| 4554052471 | |||
| 17762a9e49 | |||
| bdfc053596 | |||
| 68e93ac19a | |||
| bdd01eef2b | |||
| fc68645ba3 | |||
| 4c2d1458de | |||
| 5f51cb11fe | |||
| 661aa37d71 | |||
| 7756bd4fa1 | |||
| 19daa14f94 | |||
| afbb0e05aa | |||
| 1de329ed9b | |||
| 5915bb1f70 | |||
| 38c368d9fe | |||
| 637a8cfe65 | |||
| ef47e1d85d | |||
| 97f19915bd | |||
| a487653444 | |||
| b649b1c279 | |||
| 1a0f1244fa | |||
| 67612e1e92 | |||
| 650c4b30a5 | |||
| 3be9848da3 | |||
| d339a86b92 | |||
| 64d6e2ea55 | |||
| 77a5906ee5 | |||
| ff0547f2b9 | |||
| b9aa2e1cca | |||
| 7624764ee0 | |||
| 08d15f7728 | |||
| ebd6aa0d74 | |||
| 1b84d8bf0b | |||
| 2b1b54a646 | |||
| a65dc83721 | |||
| 78c6fea352 | |||
| 03da6d87b5 | |||
| e0e6ac402e | |||
| 288459c88b | |||
| fe41d03437 | |||
| 940933eff4 | |||
| e45b479ae3 | |||
| d3ec5a9ac2 | |||
| 7d20354ba5 | |||
| 12548099f1 | |||
| 643c66a12f | |||
| da719b4a7e | |||
| 2a3ae34294 | |||
| 27f7440165 | |||
| 73ff60a0f6 | |||
| a80843ce77 | |||
| 4a9dc216e7 | |||
| 72c9de354e | |||
| ae269b3a74 | |||
| f3bc22cdc8 | |||
| 92cc8bf6f6 | |||
| 05b6e74482 | |||
| 90fb950fc3 | |||
| 005f1ed8a0 | |||
| bb4497dd80 | |||
| 8956bc4980 | |||
| 0a91473402 | |||
| 4df12e7316 | |||
| 3ff4e0f9a6 | |||
| 6c5b1501e9 | |||
| c1fddd1b82 | |||
| 256e3a1dbb | |||
| 2fbc69cb34 | |||
| d3a06b8597 | |||
| 9d9370f2f5 | |||
| aa6ae3084e | |||
| 9bd66aa54b | |||
| c33c0a4acb | |||
| fc9ce8243a | |||
| ddf8950cc0 | |||
| f2832a0fd6 | |||
| 4660c4d5bf | |||
| 1b60c66eec | |||
| ac939a5e95 | |||
| ea0a98c9f0 | |||
| baa11f481e | |||
| 1cbb124ba0 | |||
| 883685de83 | |||
| 91864443d5 | |||
| b48d6bfd4b | |||
| a1ede75450 | |||
| db73aaeabb | |||
| 284690338c | |||
| 550a1a44ef | |||
| 5203c03257 | |||
| 1a9f56c03e | |||
| 3cf0c724f4 | |||
| 3e96b01981 | |||
| 59658441ff | |||
| a4e20114a7 | |||
| aa1315dd57 | |||
| 271149baa4 | |||
| 680f6dc317 | |||
| 0e6282e90e | |||
| e9f66dc091 | |||
| 88f6acb618 | |||
| 6f36cd3305 | |||
| b476da8ba4 | |||
| 873187e210 | |||
| 5ec21065cc | |||
| dbdbb14bac | |||
| 2cbc98a26a | |||
| 5739eb9a85 | |||
| f6887ee7d5 | |||
| 12698c5d39 | |||
| 8244932247 | |||
| 39ef896138 | |||
| 258a2a8ee7 | |||
| 0b570ba15d | |||
| 7d4e6e59d9 | |||
| 9c543e2ec8 | |||
| d9ef9282ad | |||
| 5c1058ca76 | |||
| c30cb1c04d | |||
| 5caf11789f | |||
| ef02856b45 | |||
| 077e25d7a8 | |||
| ef84fe97d5 | |||
| fc3653e577 | |||
| d708867c74 | |||
| e6273fa6a4 | |||
| d517279ca2 | |||
| 71284c3e98 | |||
| 85c7dbaf99 | |||
| 7cc21a2b8e | |||
| 2c8d8e2b2e | |||
| d366da4947 | |||
| 02490440ec | |||
| 019ec0e55d | |||
| c8ef38da3c | |||
| b449072a69 | |||
| 35fde21098 | |||
| 10bad0bc84 | |||
| 27492ba093 | |||
| ed6576df4b | |||
| 1c89f9e88a | |||
| 9cdd7fc687 | |||
| 3a5485ea56 | |||
| 955d1df400 | |||
| d39000fa56 | |||
| 231e98efb8 | |||
| 87299de2ab | |||
| 33c9b48bc9 | |||
| 416208c33a | |||
| 7bba8d2862 | |||
| 8b22349d0f | |||
| cd156630a8 | |||
| 769d5739b8 | |||
| 6d29f58ebd | |||
| 2d8027cd28 | |||
| be9547612d | |||
| 67f8ff841d | |||
| 51a7ccc8d0 | |||
| 3fdaa42206 | |||
| 70c783194f | |||
| aec1d2bbe8 | |||
| cabcbef34b | |||
| d952e5400b | |||
| eba908c153 | |||
| 65feda4e04 | |||
| 81e636b1c6 | |||
| 4c4861b2e3 | |||
| 28972421ad | |||
| 3619acbd54 | |||
| c539f1eeef | |||
| 23cf213200 | |||
| a371c6b364 | |||
| d1e58ccf28 | |||
| 0062a28504 | |||
| 9d00a1eb67 | |||
| 7e75640263 | |||
| 32f1cfa634 | |||
| aed5f54710 | |||
| 267fa4acfa | |||
| a4f731da16 | |||
| 8ee9c42848 | |||
| a43335466c | |||
| 1a0b86d056 | |||
| d96cc5c74b | |||
| 54faa2cbdc | |||
| e7e25cb5b7 | |||
| b4afb2f495 | |||
| 2a5e67a461 | |||
| a71dd0b3b8 | |||
| b2d9c2eec6 | |||
| 518262c515 | |||
| 1de5983260 | |||
| 3c5b1eb423 | |||
| 4d195a6378 | |||
| cdbfad060b | |||
| e9eeba944a | |||
| 3c111cd8d6 | |||
| 68c5362024 | |||
| 40ea294663 | |||
| 1b2afcd02c | |||
| 6c5eb09486 | |||
| 221d011b48 | |||
| ad36204dfb | |||
| 70f8599a0e | |||
| 211ec7f3a6 | |||
| 43a75df119 | |||
| 679c6791c7 | |||
| 033616db7a | |||
| 1a09edd8bb | |||
| 0ff7a5cd11 | |||
| 4e0574af35 | |||
| 027dbf35f8 | |||
| a9dc1e232a | |||
| f50cfab3f7 | |||
| 981d9a095d | |||
| d1670673f2 | |||
| 82fa375afc | |||
| 95d0765ccb | |||
| 8f9524a319 | |||
| a680aa97d2 | |||
| 7ca0092501 | |||
| 4d7321941c | |||
| 8d1c5e4b5b | |||
| 1ebcd49601 | |||
| 9ac7753f04 | |||
| 7ca81fe281 | |||
| 1b5762a133 | |||
| e373969b34 | |||
| f16472c415 | |||
| 72169f271f | |||
| b1149bda39 | |||
| 8f838891cb | |||
| e4518cafeb | |||
| 6022161e0c | |||
| dd8b695cdf | |||
| e896be7324 | |||
| 06298418cb | |||
| fdcbbae3b1 | |||
| a719ec5a3e | |||
| 55bf0c04f4 | |||
| 666293f59d | |||
| 4442fda70a | |||
| cf976cef84 | |||
| e2dcbf48af | |||
| 79ba86d8c2 | |||
| 8de6ca33af | |||
| 89faf6e976 | |||
| bc5861ea95 | |||
| cc3a3c451c | |||
| f0956c0cdb | |||
| dcc143c9f8 | |||
| 56603e8076 | |||
| 06922458f1 | |||
| 17b7a6eb89 | |||
| 52b222de50 | |||
| 35d45057ba | |||
| 6a5ba1a607 | |||
| c01c77e11d | |||
| 27a01d4da3 | |||
| 76f3a3cfcb | |||
| 52005d0b19 | |||
| af6f477f15 | |||
| bf2ffd6dfb | |||
| dd6380d49d | |||
| d59fc82cc7 | |||
| 2f62dd2c49 | |||
| 379f8911b5 | |||
| 1a72c30684 | |||
| 6891bdc34e | |||
| c6a7e52a86 | |||
| 951ef5ed72 | |||
| 20f8e59f2b | |||
| 23b35282a9 | |||
| 27c3c0c404 | |||
| df7728707a | |||
| 6bd7f54a8e | |||
| 954175943d | |||
| a1e8af623d | |||
| af625d912a | |||
| 04d61e81ed | |||
| 78fc6be193 | |||
| 969dfa1dd0 | |||
| 19578f2104 | |||
| de60b15d2b | |||
| 7c5ffe3f10 | |||
| 2daf47f202 | |||
| ec8e54d31b | |||
| d538b5c12b | |||
| 4fe24abc51 | |||
| 4644121fe3 | |||
| f75c9ec06a | |||
| e174939cf5 | |||
| b8ecbdd27d | |||
| 100401e0ac | |||
| a5f2ce79e4 | |||
| 4358360362 | |||
| 889fc7d7fe | |||
| 8fec85d4cb | |||
| de744d1f10 | |||
| 4e50099308 | |||
| e17f201e6b | |||
| 14fb775212 | |||
| 9742a2146a | |||
| 270476f4d2 | |||
| b1205c73d5 | |||
| 760019aac6 | |||
| a89df000d0 | |||
| 3278d3518d | |||
| 0f8bf01d30 | |||
| e4132fe469 | |||
| f593df5d1d | |||
| a42153dc14 | |||
| 7dbb17b339 | |||
| 4e226130df | |||
| abf5ec313a | |||
| 2257ceae53 | |||
| e330a7cd3b | |||
| 9316575534 | |||
| 3046127b03 | |||
| 7a4e784701 | |||
| 96a2b406aa | |||
| e2db3cdc5c | |||
| 99fa754e91 | |||
| be28eaf122 | |||
| cd05d5d811 | |||
| f6f7c1702a | |||
| b593293c05 | |||
| 1f1f44766d | |||
| 6ebd768d97 | |||
| bd75c7454c | |||
| 1c2fab1528 | |||
| 92a096a708 | |||
| e331def140 | |||
| 31c1e40ec1 | |||
| 8ced3f838d | |||
| b37bf72eb2 | |||
| c6485f5e92 | |||
| 4d2132cc08 | |||
| cb3dfd6786 | |||
| 0af836f2f5 | |||
| 509184f5ce | |||
| d788ded283 | |||
| 131e257739 | |||
| 9333c006b7 | |||
| 59ca964231 | |||
| 293942b7de | |||
| fce9a94b96 | |||
| a344389500 | |||
| 000d87ccdd | |||
| f241d849b7 | |||
| a315b1190a | |||
| a35a268670 | |||
| dff898e228 | |||
| 9ab67716bc | |||
| cc554991fe | |||
| 7366b543bd | |||
| 480f3d9563 | |||
| 991e4b8b20 | |||
| 2f6551904a | |||
| dc1ee3faaf | |||
| f96196a421 | |||
| 678eeaa3bf | |||
| 87dbda685b | |||
| 954dc49932 | |||
| 0c031588aa | |||
| 6e419b3120 | |||
| de0ddee3fb | |||
| 59fac2fa11 | |||
| ef0d3b3957 | |||
| f34be62af4 | |||
| 151ee93842 | |||
| c89757aa5d | |||
| 2617fcfab1 | |||
| 0528a2d423 | |||
| aa62921986 | |||
| f39ae98a48 | |||
| e10e51ae26 | |||
| 758e941da9 | |||
| 34777b1672 | |||
| a8156d90d8 | |||
| 45527ada14 | |||
| b6b98b1c00 | |||
| d7b98c9762 | |||
| fc9faeb6e5 | |||
| c965fb41b9 | |||
| 379a09b9c9 | |||
| da0b34b2dc | |||
| 6153b68302 | |||
| 3fc60909d2 | |||
| a20ab505ef | |||
| 8f412d5dc7 | |||
| bb7e993d10 | |||
| 8aeceb717c | |||
| 1b2fc0e364 | |||
| 2bf6b59419 | |||
| 5e6080da78 | |||
| a4a23121c8 | |||
| fa6e36cb44 | |||
| 64eb773ab8 | |||
| 841e831ce0 | |||
| 427b54b1eb | |||
| 00e831c8f3 | |||
| a5d5168b07 | |||
| 521dfb83e4 | |||
| d414a27498 | |||
| 7e8ce1c695 | |||
| 302a894cb3 | |||
| 0c213aa860 | |||
| 142deb47cb | |||
| 4390b1c694 | |||
| c26f196318 | |||
| 4cae95a942 | |||
| d07219758f | |||
| 051b2e31b9 | |||
| 6e0ea18ca3 | |||
| 407d633a6c | |||
| a4ae25886a | |||
| ae02066093 | |||
| fd4f628618 | |||
| b389b144c1 | |||
| 95e929220a | |||
| 3d6d2a62f9 | |||
| 60d8d0be50 | |||
| 18f5c6aa95 | |||
| 13f28a9bd8 | |||
| 640c6b8a9c | |||
| 69202b86cd | |||
| 330bab0616 | |||
| c77d0bab6d | |||
| 7ef14602f5 | |||
| 762ef42a48 | |||
| ba07a4188b | |||
| 4a6387b383 | |||
| b7254c7d12 | |||
| 8873503853 | |||
| 430b23bb45 | |||
| 1c785fded8 | |||
| f2bfc50a31 | |||
| 17ffa3eaba | |||
| a6805eeb9a | |||
| b3d7623276 | |||
| df5e61f4bd | |||
| 8cd841220d | |||
| fd5fd05622 | |||
| 6769702d45 | |||
| 2ce16a0594 | |||
| cd2f2c4ae5 | |||
| 0f4e9792d2 | |||
| cf1be5f3ba | |||
| f2c919725a | |||
| 5e5b218e14 | |||
| 0d18b38434 | |||
| 3838f06723 | |||
| d255e08204 | |||
| c2feac4642 | |||
| 93f2605c6d | |||
| c1c80f1000 | |||
| 7555073c14 | |||
| fa607062fa | |||
| 8bfe624f97 | |||
| 32a5880c17 | |||
| d51d403906 | |||
| 1fb42f3c8e | |||
| 87fdfc5048 | |||
| 5f7de8ff5b | |||
| 3e6a2314bd | |||
| deebd9a8cf | |||
| 3e71f31f8e | |||
| f7d4642a44 | |||
| 59a6cae353 | |||
| ef53a299f9 | |||
| c5def9b663 | |||
| 71860612af | |||
| 354a3c6133 | |||
| bc49bfe2ba | |||
| c0e48a29a5 | |||
| 363f865168 | |||
| d6ceeee2a3 | |||
| f6dc7492f9 | |||
| 4b4b1f0ddc | |||
| e5524edc4a | |||
| 75de1e5fd1 | |||
| 9c1c6d3503 | |||
| ee55f066a9 | |||
| e06889a322 | |||
| 7dd26b110b | |||
| de7dbcb622 | |||
| 9678be05a8 | |||
| db8581da57 | |||
| f7423af5f4 | |||
| 518fcfca97 | |||
| ecdada10c0 | |||
| 7ffdf6f514 | |||
| 2b8aea39d7 | |||
| 502d3424b0 | |||
| 33748510fe | |||
| 9f55203d69 | |||
| 241dd14431 | |||
| bf5fded327 | |||
| 7423b9577d | |||
| 54a3c5750e | |||
| 1bf8317398 | |||
| 5a0d7b0d67 | |||
| 64b0e312f3 | |||
| d22aab08cb | |||
| 0368342336 | |||
| 0ccae5ebbc | |||
| e5a8464647 | |||
| 6acb4d4184 | |||
| 2798368099 | |||
| bcdce2bdf5 | |||
| 43773652aa | |||
| 10072200b5 | |||
| a00647f8e7 | |||
| 96429eec00 | |||
| c49e38a58c | |||
| b2047ce0c0 | |||
| 5b60d515e9 | |||
| cf0205caa4 | |||
| c91ab1deb1 | |||
| 2b5dd236aa | |||
| 0658479921 | |||
| ff8b07ac12 | |||
| fb87ee529a | |||
| 1fabc24e45 | |||
| 9ab2cfcb6a | |||
| e81e31fc24 | |||
| e69b7dec7d | |||
| 534e4a4377 | |||
| 3193773583 | |||
| 4d4906228e | |||
| e4a1d7478a | |||
| cf8eaa57cf | |||
| 2211add5e0 | |||
| e432358e1b | |||
| 3ccce80e1d | |||
| 1952f91540 | |||
| 0e1017111e | |||
| b4be8ab83f | |||
| 3b807dae95 | |||
| 9fdaeed69b | |||
| b7d627f0f5 | |||
| 733bbc0b58 | |||
| 17f6147e13 | |||
| 08c4c8667a | |||
| 526791aae7 | |||
| 8fdd6dcccc | |||
| fb4f5819fd | |||
| 58554f3891 | |||
| 5020084663 | |||
| 5aaab01ac9 | |||
| 024f60de9b | |||
| 1ccc46869d | |||
| 3edcb8d03d | |||
| d7189f0f05 | |||
| f19aa7831e | |||
| 601eeb7fbe | |||
| a8f20a407b | |||
| 872a7d9fa8 | |||
| 310b85ad83 | |||
| b8d94ba7eb | |||
| 4c112aa8ae | |||
| df6da4b48a | |||
| c3e8449979 | |||
| d8707bfe01 | |||
| f07940c11f | |||
| 889c3d32c9 | |||
| 1e502c5933 | |||
| f01e31f475 | |||
| 4285f32b94 | |||
| af5bcafa45 | |||
| 909870b321 | |||
| 2b5dd8b77e | |||
| 4d4e4a9706 | |||
| ac82e90dc2 | |||
| 8063141406 | |||
| 5c17e9599b | |||
| 2e54f2166d | |||
| a0bd2ba4a1 | |||
| 38102ac17f | |||
| 139c5869c9 | |||
| 79206420f9 | |||
| e046b972ca | |||
| ea4949b3a2 | |||
| 05d5f0b943 | |||
| 81df84dc37 | |||
| ff9bab99c7 | |||
| 301ea26a03 | |||
| bd7a03b0ca | |||
| 4e0619a269 | |||
| 8b13afeb23 | |||
| ce44feeb40 | |||
| 821e86b875 | |||
| 015e596eda | |||
| 09e535abf4 | |||
| 855f7f0f9a | |||
| 5fa3e3cb7f | |||
| 0bddc2dcac | |||
| 42a8e0e0f0 | |||
| 7b77e07a7d | |||
| db17d27823 | |||
| 362b800f25 | |||
| 29e26d659d | |||
| afa658cc00 | |||
| cde0d466dd | |||
| 4031b55630 | |||
| 86e07156d1 | |||
| 1e8df274ee | |||
| f0153cc4a6 | |||
| 3044c238fd | |||
| ead58390cd | |||
| 504d22ff37 | |||
| cc42f8667f | |||
| 6135b3ce7f | |||
| 3c8efa17d5 | |||
| dccae0aea0 | |||
| 2728236ced | |||
| 76ce1d6b21 | |||
| 94ddebaec0 | |||
| cec165176b | |||
| 99ad837441 | |||
| f8be132ba2 | |||
| 122f5431a6 | |||
| c2884954a4 | |||
| 3a0453c8c5 | |||
| 9d241ab175 | |||
| ee7eed8d3c | |||
| 1125452a8f | |||
| a3712c8f72 | |||
| e2022fab2d | |||
| bcea1be19b | |||
| 8d799203c5 | |||
| 980ce2f2af | |||
| c6bea3faa3 | |||
| 7707f55b25 | |||
| f087bb7182 | |||
| bf269c9abf | |||
| a8c7405f9d | |||
| 43c9232e7e | |||
| 8351c58d7b | |||
| aa86381b80 | |||
| 563840ca58 | |||
| b5b9b688c3 | |||
| 3731223087 | |||
| 72d770c0f3 | |||
| ee4b83fa99 | |||
| ee6e3a9876 | |||
| 17e375bc61 | |||
| a2c8c90a5e | |||
| b376014df8 | |||
| b9ee54f6ad | |||
| 6c7e1900a3 | |||
| 6f929f40f9 | |||
| b6a8930855 | |||
| 7a91b258de | |||
| 35bef76aeb | |||
| 780d0ad9fb | |||
| c0d5dd6dee | |||
| 3e87e625ba | |||
| 56f9403859 | |||
| 8259c79e9c | |||
| be1e2fe7e6 | |||
| 609ee5c70d | |||
| 207cab9a0f | |||
| c80b025ac1 | |||
| 8610917b86 | |||
| fae4bee871 | |||
| b9608498a2 | |||
| fe59c6b0c9 | |||
| b082b048d6 | |||
| 91712cee2a | |||
| 5adfbb2dee | |||
| ec32d09468 | |||
| 919990820e | |||
| 5cc31efa12 | |||
| 5f48b41693 | |||
| 9530eea287 | |||
| ebbf304c94 | |||
| 7c8ac0c2ff | |||
| eefad5e052 | |||
| 9a1e6e29d4 | |||
| 62ab450d98 | |||
| b4a5da4a74 | |||
| ed82480c89 | |||
| 82449c5edc | |||
| b165726bc9 | |||
| 11910d0f28 | |||
| f66e27b077 | |||
| f84570a6fc | |||
| 835beb607d | |||
| c4e2d3fb0f | |||
| eb3d8d9da5 | |||
| 151d548099 | |||
| c5cdc2760f | |||
| a663bf9f19 | |||
| a0f5af46a2 | |||
| 7ddd48d132 | |||
| 18074f15f5 | |||
| bba0424c6d | |||
| 282f6cfbb8 | |||
| ce10a43cc6 | |||
| 5476af5bb3 | |||
| b97b1b61b7 | |||
| 25d2cfd7b8 | |||
| 1b754387e0 | |||
| bcad40069f | |||
| 5aa9061006 | |||
| 873e8cec57 | |||
| f6f96c3aea | |||
| aeed672295 | |||
| 832fbe6d15 | |||
| 03deddf666 | |||
| d06413d1b4 | |||
| 8afa50d585 | |||
| 9f28f1f812 | |||
| 985388fd90 | |||
| e27e10082a | |||
| 4e510d96fc | |||
| c0ec02f062 | |||
| bd27a96bde | |||
| d6aeaf8e9d | |||
| 2b9bba4aa7 | |||
| 58b0991891 | |||
| 59cbbef327 | |||
| 7047c81a2b | |||
| 6e2ab47359 | |||
| f879332e1d | |||
| 6fcafecc61 | |||
| a5af93aef1 | |||
| 4b84fd2a67 | |||
| 924efc0cbd | |||
| 288457b5bd | |||
| d29fa86de6 | |||
| 97be227e3d | |||
| 909d6a54c3 | |||
| 228b6a80dc | |||
| 6936a5f96f | |||
| 740560a50a | |||
| 47c28f0f37 | |||
| 1c859cd7da | |||
| e4a97dd76d | |||
| 4fd1e5ea06 | |||
| 6039aeabde | |||
| 17a384f074 | |||
| 25e8f5ec6a | |||
| eac8cacd42 | |||
| 81adade05b | |||
| e3808dc986 |
@@ -0,0 +1,19 @@
|
|||||||
|
**/.git
|
||||||
|
**/.gitlab
|
||||||
|
**/.cache
|
||||||
|
|
||||||
|
buildAllJars
|
||||||
|
|
||||||
|
**/_Misc Files
|
||||||
|
*.bat
|
||||||
|
*.md
|
||||||
|
*.sh
|
||||||
|
*.txt
|
||||||
|
|
||||||
|
coreSubProjects/*.md
|
||||||
|
coreSubProjects/*.txt
|
||||||
|
|
||||||
|
**/.gitignore
|
||||||
|
**/.gitattributes
|
||||||
|
**/.gitlab-cy.yml
|
||||||
|
**/.gitmodules
|
||||||
+700
@@ -0,0 +1,700 @@
|
|||||||
|
# DH Main
|
||||||
|
root = true
|
||||||
|
|
||||||
|
# Note: please keep this and the core .editorconfig in sync
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
insert_final_newline = false
|
||||||
|
max_line_length = 1000
|
||||||
|
tab_width = 4
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
ij_continuation_indent_size = 4
|
||||||
|
ij_formatter_off_tag = @formatter:off
|
||||||
|
ij_formatter_on_tag = @formatter:on
|
||||||
|
ij_formatter_tags_enabled = true
|
||||||
|
ij_smart_tabs = false
|
||||||
|
ij_visual_guides = none
|
||||||
|
ij_wrap_on_typing = false
|
||||||
|
|
||||||
|
[*.java]
|
||||||
|
indent_style = tab
|
||||||
|
ij_smart_tabs = true
|
||||||
|
ij_java_align_consecutive_assignments = false
|
||||||
|
ij_java_align_consecutive_variable_declarations = false
|
||||||
|
ij_java_align_group_field_declarations = false
|
||||||
|
ij_java_align_multiline_annotation_parameters = false
|
||||||
|
ij_java_align_multiline_array_initializer_expression = false
|
||||||
|
ij_java_align_multiline_assignment = false
|
||||||
|
ij_java_align_multiline_binary_operation = false
|
||||||
|
ij_java_align_multiline_chained_methods = false
|
||||||
|
ij_java_align_multiline_deconstruction_list_components = false
|
||||||
|
ij_java_align_multiline_extends_list = false
|
||||||
|
ij_java_align_multiline_for = false
|
||||||
|
ij_java_align_multiline_method_parentheses = false
|
||||||
|
ij_java_align_multiline_parameters = false
|
||||||
|
ij_java_align_multiline_parameters_in_calls = false
|
||||||
|
ij_java_align_multiline_parenthesized_expression = false
|
||||||
|
ij_java_align_multiline_records = false
|
||||||
|
ij_java_align_multiline_resources = false
|
||||||
|
ij_java_align_multiline_ternary_operation = false
|
||||||
|
ij_java_align_multiline_text_blocks = false
|
||||||
|
ij_java_align_multiline_throws_list = false
|
||||||
|
ij_java_align_subsequent_simple_methods = false
|
||||||
|
ij_java_align_throws_keyword = false
|
||||||
|
ij_java_align_types_in_multi_catch = false
|
||||||
|
ij_java_annotation_parameter_wrap = off
|
||||||
|
ij_java_array_initializer_new_line_after_left_brace = false
|
||||||
|
ij_java_array_initializer_right_brace_on_new_line = false
|
||||||
|
ij_java_array_initializer_wrap = normal
|
||||||
|
ij_java_assert_statement_colon_on_next_line = false
|
||||||
|
ij_java_assert_statement_wrap = off
|
||||||
|
ij_java_assignment_wrap = off
|
||||||
|
ij_java_binary_operation_sign_on_next_line = false
|
||||||
|
ij_java_binary_operation_wrap = off
|
||||||
|
ij_java_blank_lines_after_anonymous_class_header = 0
|
||||||
|
ij_java_blank_lines_after_class_header = 0
|
||||||
|
ij_java_blank_lines_after_imports = 1
|
||||||
|
ij_java_blank_lines_after_package = 1
|
||||||
|
ij_java_blank_lines_around_class = 1
|
||||||
|
ij_java_blank_lines_around_field = 0
|
||||||
|
ij_java_blank_lines_around_field_in_interface = 0
|
||||||
|
ij_java_blank_lines_around_initializer = 0
|
||||||
|
ij_java_blank_lines_around_method = 0
|
||||||
|
ij_java_blank_lines_around_method_in_interface = 0
|
||||||
|
ij_java_blank_lines_before_class_end = 1
|
||||||
|
ij_java_blank_lines_before_imports = 1
|
||||||
|
ij_java_blank_lines_before_method_body = 0
|
||||||
|
ij_java_blank_lines_before_package = 1
|
||||||
|
ij_java_block_brace_style = next_line
|
||||||
|
ij_java_block_comment_add_space = false
|
||||||
|
ij_java_block_comment_at_first_column = true
|
||||||
|
ij_java_builder_methods = none
|
||||||
|
ij_java_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_java_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_java_call_parameters_wrap = normal
|
||||||
|
ij_java_case_statement_on_separate_line = true
|
||||||
|
ij_java_catch_on_new_line = true
|
||||||
|
ij_java_class_annotation_wrap = off
|
||||||
|
ij_java_class_brace_style = next_line
|
||||||
|
ij_java_class_count_to_use_import_on_demand = 5
|
||||||
|
ij_java_class_names_in_javadoc = 1
|
||||||
|
ij_java_deconstruction_list_wrap = normal
|
||||||
|
ij_java_do_not_indent_top_level_class_members = false
|
||||||
|
ij_java_do_not_wrap_after_single_annotation = false
|
||||||
|
ij_java_do_not_wrap_after_single_annotation_in_parameter = false
|
||||||
|
ij_java_do_while_brace_force = never
|
||||||
|
ij_java_doc_add_blank_line_after_description = true
|
||||||
|
ij_java_doc_add_blank_line_after_param_comments = false
|
||||||
|
ij_java_doc_add_blank_line_after_return = false
|
||||||
|
ij_java_doc_add_p_tag_on_empty_lines = false
|
||||||
|
ij_java_doc_align_exception_comments = false
|
||||||
|
ij_java_doc_align_param_comments = false
|
||||||
|
ij_java_doc_do_not_wrap_if_one_line = true
|
||||||
|
ij_java_doc_enable_formatting = true
|
||||||
|
ij_java_doc_enable_leading_asterisks = true
|
||||||
|
ij_java_doc_indent_on_continuation = false
|
||||||
|
ij_java_doc_keep_empty_lines = true
|
||||||
|
ij_java_doc_keep_empty_parameter_tag = true
|
||||||
|
ij_java_doc_keep_empty_return_tag = false
|
||||||
|
ij_java_doc_keep_empty_throws_tag = true
|
||||||
|
ij_java_doc_keep_invalid_tags = true
|
||||||
|
ij_java_doc_param_description_on_new_line = false
|
||||||
|
ij_java_doc_preserve_line_breaks = false
|
||||||
|
ij_java_doc_use_throws_not_exception_tag = true
|
||||||
|
ij_java_else_on_new_line = true
|
||||||
|
ij_java_enum_constants_wrap = off
|
||||||
|
ij_java_extends_keyword_wrap = normal
|
||||||
|
ij_java_extends_list_wrap = normal
|
||||||
|
ij_java_field_annotation_wrap = off
|
||||||
|
ij_java_finally_on_new_line = true
|
||||||
|
ij_java_for_brace_force = always
|
||||||
|
ij_java_for_statement_new_line_after_left_paren = false
|
||||||
|
ij_java_for_statement_right_paren_on_new_line = false
|
||||||
|
ij_java_for_statement_wrap = off
|
||||||
|
ij_java_generate_final_locals = false
|
||||||
|
ij_java_generate_final_parameters = false
|
||||||
|
ij_java_if_brace_force = never
|
||||||
|
ij_java_imports_layout = *,|,javax.**,java.**,|,$*
|
||||||
|
ij_java_indent_case_from_switch = true
|
||||||
|
ij_java_insert_inner_class_imports = false
|
||||||
|
ij_java_insert_override_annotation = true
|
||||||
|
ij_java_keep_blank_lines_before_right_brace = 10
|
||||||
|
ij_java_keep_blank_lines_between_package_declaration_and_header = 2
|
||||||
|
ij_java_keep_blank_lines_in_code = 10
|
||||||
|
ij_java_keep_blank_lines_in_declarations = 10
|
||||||
|
ij_java_keep_builder_methods_indents = false
|
||||||
|
ij_java_keep_control_statement_in_one_line = true
|
||||||
|
ij_java_keep_first_column_comment = true
|
||||||
|
ij_java_keep_indents_on_empty_lines = true
|
||||||
|
ij_java_keep_line_breaks = true
|
||||||
|
ij_java_keep_multiple_expressions_in_one_line = true
|
||||||
|
ij_java_keep_simple_blocks_in_one_line = false
|
||||||
|
ij_java_keep_simple_classes_in_one_line = true
|
||||||
|
ij_java_keep_simple_lambdas_in_one_line = true
|
||||||
|
ij_java_keep_simple_methods_in_one_line = true
|
||||||
|
ij_java_label_indent_absolute = false
|
||||||
|
ij_java_label_indent_size = 0
|
||||||
|
ij_java_lambda_brace_style = end_of_line
|
||||||
|
ij_java_layout_static_imports_separately = true
|
||||||
|
ij_java_line_comment_add_space = false
|
||||||
|
ij_java_line_comment_add_space_on_reformat = false
|
||||||
|
ij_java_line_comment_at_first_column = false
|
||||||
|
ij_java_method_annotation_wrap = off
|
||||||
|
ij_java_method_brace_style = next_line
|
||||||
|
ij_java_method_call_chain_wrap = normal
|
||||||
|
ij_java_method_parameters_new_line_after_left_paren = true
|
||||||
|
ij_java_method_parameters_right_paren_on_new_line = false
|
||||||
|
ij_java_method_parameters_wrap = normal
|
||||||
|
ij_java_modifier_list_wrap = false
|
||||||
|
ij_java_multi_catch_types_wrap = normal
|
||||||
|
ij_java_names_count_to_use_import_on_demand = 3
|
||||||
|
ij_java_new_line_after_lparen_in_annotation = false
|
||||||
|
ij_java_new_line_after_lparen_in_deconstruction_pattern = true
|
||||||
|
ij_java_new_line_after_lparen_in_record_header = false
|
||||||
|
ij_java_packages_to_use_import_on_demand = java.awt.*,javax.swing.*
|
||||||
|
ij_java_parameter_annotation_wrap = off
|
||||||
|
ij_java_parentheses_expression_new_line_after_left_paren = false
|
||||||
|
ij_java_parentheses_expression_right_paren_on_new_line = false
|
||||||
|
ij_java_place_assignment_sign_on_next_line = false
|
||||||
|
ij_java_prefer_longer_names = true
|
||||||
|
ij_java_prefer_parameters_wrap = false
|
||||||
|
ij_java_record_components_wrap = normal
|
||||||
|
ij_java_repeat_synchronized = true
|
||||||
|
ij_java_replace_instanceof_and_cast = false
|
||||||
|
ij_java_replace_null_check = false
|
||||||
|
ij_java_replace_sum_lambda_with_method_ref = false
|
||||||
|
ij_java_resource_list_new_line_after_left_paren = false
|
||||||
|
ij_java_resource_list_right_paren_on_new_line = false
|
||||||
|
ij_java_resource_list_wrap = on_every_item
|
||||||
|
ij_java_rparen_on_new_line_in_annotation = false
|
||||||
|
ij_java_rparen_on_new_line_in_deconstruction_pattern = true
|
||||||
|
ij_java_rparen_on_new_line_in_record_header = false
|
||||||
|
ij_java_space_after_closing_angle_bracket_in_type_argument = false
|
||||||
|
ij_java_space_after_colon = true
|
||||||
|
ij_java_space_after_comma = true
|
||||||
|
ij_java_space_after_comma_in_type_arguments = true
|
||||||
|
ij_java_space_after_for_semicolon = true
|
||||||
|
ij_java_space_after_quest = true
|
||||||
|
ij_java_space_after_type_cast = true
|
||||||
|
ij_java_space_before_annotation_array_initializer_left_brace = false
|
||||||
|
ij_java_space_before_annotation_parameter_list = false
|
||||||
|
ij_java_space_before_array_initializer_left_brace = false
|
||||||
|
ij_java_space_before_catch_keyword = true
|
||||||
|
ij_java_space_before_catch_left_brace = true
|
||||||
|
ij_java_space_before_catch_parentheses = true
|
||||||
|
ij_java_space_before_class_left_brace = true
|
||||||
|
ij_java_space_before_colon = true
|
||||||
|
ij_java_space_before_colon_in_foreach = true
|
||||||
|
ij_java_space_before_comma = false
|
||||||
|
ij_java_space_before_deconstruction_list = false
|
||||||
|
ij_java_space_before_do_left_brace = true
|
||||||
|
ij_java_space_before_else_keyword = true
|
||||||
|
ij_java_space_before_else_left_brace = true
|
||||||
|
ij_java_space_before_finally_keyword = true
|
||||||
|
ij_java_space_before_finally_left_brace = true
|
||||||
|
ij_java_space_before_for_left_brace = true
|
||||||
|
ij_java_space_before_for_parentheses = true
|
||||||
|
ij_java_space_before_for_semicolon = false
|
||||||
|
ij_java_space_before_if_left_brace = true
|
||||||
|
ij_java_space_before_if_parentheses = true
|
||||||
|
ij_java_space_before_method_call_parentheses = false
|
||||||
|
ij_java_space_before_method_left_brace = true
|
||||||
|
ij_java_space_before_method_parentheses = false
|
||||||
|
ij_java_space_before_opening_angle_bracket_in_type_parameter = false
|
||||||
|
ij_java_space_before_quest = true
|
||||||
|
ij_java_space_before_switch_left_brace = true
|
||||||
|
ij_java_space_before_switch_parentheses = true
|
||||||
|
ij_java_space_before_synchronized_left_brace = false
|
||||||
|
ij_java_space_before_synchronized_parentheses = true
|
||||||
|
ij_java_space_before_try_left_brace = true
|
||||||
|
ij_java_space_before_try_parentheses = true
|
||||||
|
ij_java_space_before_type_parameter_list = false
|
||||||
|
ij_java_space_before_while_keyword = true
|
||||||
|
ij_java_space_before_while_left_brace = true
|
||||||
|
ij_java_space_before_while_parentheses = true
|
||||||
|
ij_java_space_inside_one_line_enum_braces = false
|
||||||
|
ij_java_space_within_empty_array_initializer_braces = true
|
||||||
|
ij_java_space_within_empty_method_call_parentheses = false
|
||||||
|
ij_java_space_within_empty_method_parentheses = false
|
||||||
|
ij_java_spaces_around_additive_operators = true
|
||||||
|
ij_java_spaces_around_annotation_eq = true
|
||||||
|
ij_java_spaces_around_assignment_operators = true
|
||||||
|
ij_java_spaces_around_bitwise_operators = true
|
||||||
|
ij_java_spaces_around_equality_operators = true
|
||||||
|
ij_java_spaces_around_lambda_arrow = true
|
||||||
|
ij_java_spaces_around_logical_operators = true
|
||||||
|
ij_java_spaces_around_method_ref_dbl_colon = false
|
||||||
|
ij_java_spaces_around_multiplicative_operators = true
|
||||||
|
ij_java_spaces_around_relational_operators = true
|
||||||
|
ij_java_spaces_around_shift_operators = true
|
||||||
|
ij_java_spaces_around_type_bounds_in_type_parameters = true
|
||||||
|
ij_java_spaces_around_unary_operator = false
|
||||||
|
ij_java_spaces_within_angle_brackets = false
|
||||||
|
ij_java_spaces_within_annotation_parentheses = false
|
||||||
|
ij_java_spaces_within_array_initializer_braces = false
|
||||||
|
ij_java_spaces_within_braces = true
|
||||||
|
ij_java_spaces_within_brackets = false
|
||||||
|
ij_java_spaces_within_cast_parentheses = false
|
||||||
|
ij_java_spaces_within_catch_parentheses = false
|
||||||
|
ij_java_spaces_within_deconstruction_list = false
|
||||||
|
ij_java_spaces_within_for_parentheses = false
|
||||||
|
ij_java_spaces_within_if_parentheses = false
|
||||||
|
ij_java_spaces_within_method_call_parentheses = false
|
||||||
|
ij_java_spaces_within_method_parentheses = false
|
||||||
|
ij_java_spaces_within_parentheses = false
|
||||||
|
ij_java_spaces_within_record_header = false
|
||||||
|
ij_java_spaces_within_switch_parentheses = false
|
||||||
|
ij_java_spaces_within_synchronized_parentheses = false
|
||||||
|
ij_java_spaces_within_try_parentheses = false
|
||||||
|
ij_java_spaces_within_while_parentheses = false
|
||||||
|
ij_java_special_else_if_treatment = true
|
||||||
|
ij_java_subclass_name_suffix = Impl
|
||||||
|
ij_java_ternary_operation_signs_on_next_line = false
|
||||||
|
ij_java_ternary_operation_wrap = on_every_item
|
||||||
|
ij_java_test_name_suffix = Test
|
||||||
|
ij_java_throws_keyword_wrap = normal
|
||||||
|
ij_java_throws_list_wrap = normal
|
||||||
|
ij_java_use_external_annotations = false
|
||||||
|
ij_java_use_fq_class_names = false
|
||||||
|
ij_java_use_relative_indents = false
|
||||||
|
ij_java_use_single_class_imports = true
|
||||||
|
ij_java_variable_annotation_wrap = off
|
||||||
|
ij_java_visibility = public
|
||||||
|
ij_java_while_brace_force = always
|
||||||
|
ij_java_while_on_new_line = true
|
||||||
|
ij_java_wrap_comments = false
|
||||||
|
ij_java_wrap_first_method_in_call_chain = false
|
||||||
|
ij_java_wrap_long_lines = false
|
||||||
|
|
||||||
|
[*.nbtt]
|
||||||
|
indent_style = tab
|
||||||
|
max_line_length = 150
|
||||||
|
ij_continuation_indent_size = 4
|
||||||
|
ij_nbtt_keep_indents_on_empty_lines = false
|
||||||
|
ij_nbtt_space_after_colon = true
|
||||||
|
ij_nbtt_space_after_comma = true
|
||||||
|
ij_nbtt_space_before_colon = true
|
||||||
|
ij_nbtt_space_before_comma = false
|
||||||
|
ij_nbtt_spaces_within_brackets = false
|
||||||
|
ij_nbtt_spaces_within_parentheses = false
|
||||||
|
|
||||||
|
[*.properties]
|
||||||
|
ij_properties_align_group_field_declarations = false
|
||||||
|
ij_properties_keep_blank_lines = false
|
||||||
|
ij_properties_key_value_delimiter = equals
|
||||||
|
ij_properties_spaces_around_key_value_delimiter = false
|
||||||
|
|
||||||
|
[.editorconfig]
|
||||||
|
ij_editorconfig_align_group_field_declarations = false
|
||||||
|
ij_editorconfig_space_after_colon = false
|
||||||
|
ij_editorconfig_space_after_comma = true
|
||||||
|
ij_editorconfig_space_before_colon = false
|
||||||
|
ij_editorconfig_space_before_comma = false
|
||||||
|
ij_editorconfig_spaces_around_assignment_operators = true
|
||||||
|
|
||||||
|
[{*.ant,*.fxml,*.jhm,*.jnlp,*.jrxml,*.jspx,*.pom,*.rng,*.tagx,*.tld,*.wsdl,*.xml,*.xsd,*.xsl,*.xslt,*.xul}]
|
||||||
|
ij_xml_align_attributes = true
|
||||||
|
ij_xml_align_text = false
|
||||||
|
ij_xml_attribute_wrap = normal
|
||||||
|
ij_xml_block_comment_add_space = false
|
||||||
|
ij_xml_block_comment_at_first_column = true
|
||||||
|
ij_xml_keep_blank_lines = 2
|
||||||
|
ij_xml_keep_indents_on_empty_lines = false
|
||||||
|
ij_xml_keep_line_breaks = true
|
||||||
|
ij_xml_keep_line_breaks_in_text = true
|
||||||
|
ij_xml_keep_whitespaces = false
|
||||||
|
ij_xml_keep_whitespaces_around_cdata = preserve
|
||||||
|
ij_xml_keep_whitespaces_inside_cdata = false
|
||||||
|
ij_xml_line_comment_at_first_column = true
|
||||||
|
ij_xml_space_after_tag_name = false
|
||||||
|
ij_xml_space_around_equals_in_attribute = false
|
||||||
|
ij_xml_space_inside_empty_tag = false
|
||||||
|
ij_xml_text_wrap = normal
|
||||||
|
ij_xml_use_custom_settings = false
|
||||||
|
|
||||||
|
[{*.bash,*.sh,*.zsh}]
|
||||||
|
indent_size = 4
|
||||||
|
tab_width = 4
|
||||||
|
ij_shell_binary_ops_start_line = false
|
||||||
|
ij_shell_keep_column_alignment_padding = false
|
||||||
|
ij_shell_minify_program = false
|
||||||
|
ij_shell_redirect_followed_by_space = false
|
||||||
|
ij_shell_switch_cases_indented = false
|
||||||
|
ij_shell_use_unix_line_separator = true
|
||||||
|
|
||||||
|
[{*.comp,*.frag,*.fsh,*.geom,*.glsl,*.gsh,*.tesc,*.tese,*.vert,*.vsh}]
|
||||||
|
ij_glsl_space_after_colon = true
|
||||||
|
ij_glsl_space_after_comma = true
|
||||||
|
ij_glsl_space_after_for_semicolon = true
|
||||||
|
ij_glsl_space_after_quest = true
|
||||||
|
ij_glsl_space_before_colon = false
|
||||||
|
ij_glsl_space_before_comma = false
|
||||||
|
ij_glsl_space_before_for_semicolon = false
|
||||||
|
ij_glsl_space_before_quest = true
|
||||||
|
ij_glsl_spaces_around_additive_operators = true
|
||||||
|
ij_glsl_spaces_around_assignment_operators = true
|
||||||
|
ij_glsl_spaces_around_bitwise_operators = true
|
||||||
|
ij_glsl_spaces_around_equality_operators = true
|
||||||
|
ij_glsl_spaces_around_logical_operators = true
|
||||||
|
ij_glsl_spaces_around_multiplicative_operators = true
|
||||||
|
ij_glsl_spaces_around_relational_operators = true
|
||||||
|
ij_glsl_spaces_around_shift_operators = true
|
||||||
|
ij_glsl_spaces_within_brackets = false
|
||||||
|
ij_glsl_spaces_within_parentheses = false
|
||||||
|
|
||||||
|
[{*.gant,*.groovy,*.gy}]
|
||||||
|
ij_groovy_align_group_field_declarations = false
|
||||||
|
ij_groovy_align_multiline_array_initializer_expression = false
|
||||||
|
ij_groovy_align_multiline_assignment = false
|
||||||
|
ij_groovy_align_multiline_binary_operation = false
|
||||||
|
ij_groovy_align_multiline_chained_methods = false
|
||||||
|
ij_groovy_align_multiline_extends_list = false
|
||||||
|
ij_groovy_align_multiline_for = true
|
||||||
|
ij_groovy_align_multiline_list_or_map = true
|
||||||
|
ij_groovy_align_multiline_method_parentheses = false
|
||||||
|
ij_groovy_align_multiline_parameters = true
|
||||||
|
ij_groovy_align_multiline_parameters_in_calls = false
|
||||||
|
ij_groovy_align_multiline_resources = true
|
||||||
|
ij_groovy_align_multiline_ternary_operation = false
|
||||||
|
ij_groovy_align_multiline_throws_list = false
|
||||||
|
ij_groovy_align_named_args_in_map = true
|
||||||
|
ij_groovy_align_throws_keyword = false
|
||||||
|
ij_groovy_array_initializer_new_line_after_left_brace = false
|
||||||
|
ij_groovy_array_initializer_right_brace_on_new_line = false
|
||||||
|
ij_groovy_array_initializer_wrap = off
|
||||||
|
ij_groovy_assert_statement_wrap = off
|
||||||
|
ij_groovy_assignment_wrap = off
|
||||||
|
ij_groovy_binary_operation_wrap = off
|
||||||
|
ij_groovy_blank_lines_after_class_header = 0
|
||||||
|
ij_groovy_blank_lines_after_imports = 1
|
||||||
|
ij_groovy_blank_lines_after_package = 1
|
||||||
|
ij_groovy_blank_lines_around_class = 1
|
||||||
|
ij_groovy_blank_lines_around_field = 0
|
||||||
|
ij_groovy_blank_lines_around_field_in_interface = 0
|
||||||
|
ij_groovy_blank_lines_around_method = 1
|
||||||
|
ij_groovy_blank_lines_around_method_in_interface = 1
|
||||||
|
ij_groovy_blank_lines_before_imports = 1
|
||||||
|
ij_groovy_blank_lines_before_method_body = 0
|
||||||
|
ij_groovy_blank_lines_before_package = 0
|
||||||
|
ij_groovy_block_brace_style = end_of_line
|
||||||
|
ij_groovy_block_comment_add_space = false
|
||||||
|
ij_groovy_block_comment_at_first_column = true
|
||||||
|
ij_groovy_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_groovy_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_groovy_call_parameters_wrap = off
|
||||||
|
ij_groovy_catch_on_new_line = false
|
||||||
|
ij_groovy_class_annotation_wrap = split_into_lines
|
||||||
|
ij_groovy_class_brace_style = end_of_line
|
||||||
|
ij_groovy_class_count_to_use_import_on_demand = 5
|
||||||
|
ij_groovy_do_while_brace_force = never
|
||||||
|
ij_groovy_else_on_new_line = false
|
||||||
|
ij_groovy_enable_groovydoc_formatting = true
|
||||||
|
ij_groovy_enum_constants_wrap = off
|
||||||
|
ij_groovy_extends_keyword_wrap = off
|
||||||
|
ij_groovy_extends_list_wrap = off
|
||||||
|
ij_groovy_field_annotation_wrap = split_into_lines
|
||||||
|
ij_groovy_finally_on_new_line = false
|
||||||
|
ij_groovy_for_brace_force = never
|
||||||
|
ij_groovy_for_statement_new_line_after_left_paren = false
|
||||||
|
ij_groovy_for_statement_right_paren_on_new_line = false
|
||||||
|
ij_groovy_for_statement_wrap = off
|
||||||
|
ij_groovy_ginq_general_clause_wrap_policy = 2
|
||||||
|
ij_groovy_ginq_having_wrap_policy = 1
|
||||||
|
ij_groovy_ginq_indent_having_clause = true
|
||||||
|
ij_groovy_ginq_indent_on_clause = true
|
||||||
|
ij_groovy_ginq_on_wrap_policy = 1
|
||||||
|
ij_groovy_ginq_space_after_keyword = true
|
||||||
|
ij_groovy_if_brace_force = never
|
||||||
|
ij_groovy_import_annotation_wrap = 2
|
||||||
|
ij_groovy_imports_layout = *,|,javax.**,java.**,|,$*
|
||||||
|
ij_groovy_indent_case_from_switch = true
|
||||||
|
ij_groovy_indent_label_blocks = true
|
||||||
|
ij_groovy_insert_inner_class_imports = false
|
||||||
|
ij_groovy_keep_blank_lines_before_right_brace = 2
|
||||||
|
ij_groovy_keep_blank_lines_in_code = 2
|
||||||
|
ij_groovy_keep_blank_lines_in_declarations = 2
|
||||||
|
ij_groovy_keep_control_statement_in_one_line = true
|
||||||
|
ij_groovy_keep_first_column_comment = true
|
||||||
|
ij_groovy_keep_indents_on_empty_lines = false
|
||||||
|
ij_groovy_keep_line_breaks = true
|
||||||
|
ij_groovy_keep_multiple_expressions_in_one_line = false
|
||||||
|
ij_groovy_keep_simple_blocks_in_one_line = false
|
||||||
|
ij_groovy_keep_simple_classes_in_one_line = true
|
||||||
|
ij_groovy_keep_simple_lambdas_in_one_line = true
|
||||||
|
ij_groovy_keep_simple_methods_in_one_line = true
|
||||||
|
ij_groovy_label_indent_absolute = false
|
||||||
|
ij_groovy_label_indent_size = 0
|
||||||
|
ij_groovy_lambda_brace_style = end_of_line
|
||||||
|
ij_groovy_layout_static_imports_separately = true
|
||||||
|
ij_groovy_line_comment_add_space = false
|
||||||
|
ij_groovy_line_comment_add_space_on_reformat = false
|
||||||
|
ij_groovy_line_comment_at_first_column = true
|
||||||
|
ij_groovy_method_annotation_wrap = split_into_lines
|
||||||
|
ij_groovy_method_brace_style = end_of_line
|
||||||
|
ij_groovy_method_call_chain_wrap = off
|
||||||
|
ij_groovy_method_parameters_new_line_after_left_paren = false
|
||||||
|
ij_groovy_method_parameters_right_paren_on_new_line = false
|
||||||
|
ij_groovy_method_parameters_wrap = off
|
||||||
|
ij_groovy_modifier_list_wrap = false
|
||||||
|
ij_groovy_names_count_to_use_import_on_demand = 3
|
||||||
|
ij_groovy_packages_to_use_import_on_demand = java.awt.*,javax.swing.*
|
||||||
|
ij_groovy_parameter_annotation_wrap = off
|
||||||
|
ij_groovy_parentheses_expression_new_line_after_left_paren = false
|
||||||
|
ij_groovy_parentheses_expression_right_paren_on_new_line = false
|
||||||
|
ij_groovy_prefer_parameters_wrap = false
|
||||||
|
ij_groovy_resource_list_new_line_after_left_paren = false
|
||||||
|
ij_groovy_resource_list_right_paren_on_new_line = false
|
||||||
|
ij_groovy_resource_list_wrap = off
|
||||||
|
ij_groovy_space_after_assert_separator = true
|
||||||
|
ij_groovy_space_after_colon = true
|
||||||
|
ij_groovy_space_after_comma = true
|
||||||
|
ij_groovy_space_after_comma_in_type_arguments = true
|
||||||
|
ij_groovy_space_after_for_semicolon = true
|
||||||
|
ij_groovy_space_after_quest = true
|
||||||
|
ij_groovy_space_after_type_cast = true
|
||||||
|
ij_groovy_space_before_annotation_parameter_list = false
|
||||||
|
ij_groovy_space_before_array_initializer_left_brace = false
|
||||||
|
ij_groovy_space_before_assert_separator = false
|
||||||
|
ij_groovy_space_before_catch_keyword = true
|
||||||
|
ij_groovy_space_before_catch_left_brace = true
|
||||||
|
ij_groovy_space_before_catch_parentheses = true
|
||||||
|
ij_groovy_space_before_class_left_brace = true
|
||||||
|
ij_groovy_space_before_closure_left_brace = true
|
||||||
|
ij_groovy_space_before_colon = true
|
||||||
|
ij_groovy_space_before_comma = false
|
||||||
|
ij_groovy_space_before_do_left_brace = true
|
||||||
|
ij_groovy_space_before_else_keyword = true
|
||||||
|
ij_groovy_space_before_else_left_brace = true
|
||||||
|
ij_groovy_space_before_finally_keyword = true
|
||||||
|
ij_groovy_space_before_finally_left_brace = true
|
||||||
|
ij_groovy_space_before_for_left_brace = true
|
||||||
|
ij_groovy_space_before_for_parentheses = true
|
||||||
|
ij_groovy_space_before_for_semicolon = false
|
||||||
|
ij_groovy_space_before_if_left_brace = true
|
||||||
|
ij_groovy_space_before_if_parentheses = true
|
||||||
|
ij_groovy_space_before_method_call_parentheses = false
|
||||||
|
ij_groovy_space_before_method_left_brace = true
|
||||||
|
ij_groovy_space_before_method_parentheses = false
|
||||||
|
ij_groovy_space_before_quest = true
|
||||||
|
ij_groovy_space_before_record_parentheses = false
|
||||||
|
ij_groovy_space_before_switch_left_brace = true
|
||||||
|
ij_groovy_space_before_switch_parentheses = true
|
||||||
|
ij_groovy_space_before_synchronized_left_brace = true
|
||||||
|
ij_groovy_space_before_synchronized_parentheses = true
|
||||||
|
ij_groovy_space_before_try_left_brace = true
|
||||||
|
ij_groovy_space_before_try_parentheses = true
|
||||||
|
ij_groovy_space_before_while_keyword = true
|
||||||
|
ij_groovy_space_before_while_left_brace = true
|
||||||
|
ij_groovy_space_before_while_parentheses = true
|
||||||
|
ij_groovy_space_in_named_argument = true
|
||||||
|
ij_groovy_space_in_named_argument_before_colon = false
|
||||||
|
ij_groovy_space_within_empty_array_initializer_braces = false
|
||||||
|
ij_groovy_space_within_empty_method_call_parentheses = false
|
||||||
|
ij_groovy_spaces_around_additive_operators = true
|
||||||
|
ij_groovy_spaces_around_assignment_operators = true
|
||||||
|
ij_groovy_spaces_around_bitwise_operators = true
|
||||||
|
ij_groovy_spaces_around_equality_operators = true
|
||||||
|
ij_groovy_spaces_around_lambda_arrow = true
|
||||||
|
ij_groovy_spaces_around_logical_operators = true
|
||||||
|
ij_groovy_spaces_around_multiplicative_operators = true
|
||||||
|
ij_groovy_spaces_around_regex_operators = true
|
||||||
|
ij_groovy_spaces_around_relational_operators = true
|
||||||
|
ij_groovy_spaces_around_shift_operators = true
|
||||||
|
ij_groovy_spaces_within_annotation_parentheses = false
|
||||||
|
ij_groovy_spaces_within_array_initializer_braces = false
|
||||||
|
ij_groovy_spaces_within_braces = true
|
||||||
|
ij_groovy_spaces_within_brackets = false
|
||||||
|
ij_groovy_spaces_within_cast_parentheses = false
|
||||||
|
ij_groovy_spaces_within_catch_parentheses = false
|
||||||
|
ij_groovy_spaces_within_for_parentheses = false
|
||||||
|
ij_groovy_spaces_within_gstring_injection_braces = false
|
||||||
|
ij_groovy_spaces_within_if_parentheses = false
|
||||||
|
ij_groovy_spaces_within_list_or_map = false
|
||||||
|
ij_groovy_spaces_within_method_call_parentheses = false
|
||||||
|
ij_groovy_spaces_within_method_parentheses = false
|
||||||
|
ij_groovy_spaces_within_parentheses = false
|
||||||
|
ij_groovy_spaces_within_switch_parentheses = false
|
||||||
|
ij_groovy_spaces_within_synchronized_parentheses = false
|
||||||
|
ij_groovy_spaces_within_try_parentheses = false
|
||||||
|
ij_groovy_spaces_within_tuple_expression = false
|
||||||
|
ij_groovy_spaces_within_while_parentheses = false
|
||||||
|
ij_groovy_special_else_if_treatment = true
|
||||||
|
ij_groovy_ternary_operation_wrap = off
|
||||||
|
ij_groovy_throws_keyword_wrap = off
|
||||||
|
ij_groovy_throws_list_wrap = off
|
||||||
|
ij_groovy_use_flying_geese_braces = false
|
||||||
|
ij_groovy_use_fq_class_names = false
|
||||||
|
ij_groovy_use_fq_class_names_in_javadoc = true
|
||||||
|
ij_groovy_use_relative_indents = false
|
||||||
|
ij_groovy_use_single_class_imports = true
|
||||||
|
ij_groovy_variable_annotation_wrap = off
|
||||||
|
ij_groovy_while_brace_force = never
|
||||||
|
ij_groovy_while_on_new_line = false
|
||||||
|
ij_groovy_wrap_chain_calls_after_dot = false
|
||||||
|
ij_groovy_wrap_long_lines = false
|
||||||
|
|
||||||
|
[{*.har,*.json,*.png.mcmeta,mcmod.info,pack.mcmeta}]
|
||||||
|
indent_size = 4
|
||||||
|
ij_json_array_wrapping = split_into_lines
|
||||||
|
ij_json_keep_blank_lines_in_code = 0
|
||||||
|
ij_json_keep_indents_on_empty_lines = false
|
||||||
|
ij_json_keep_line_breaks = true
|
||||||
|
ij_json_keep_trailing_comma = false
|
||||||
|
ij_json_object_wrapping = split_into_lines
|
||||||
|
ij_json_property_alignment = do_not_align
|
||||||
|
ij_json_space_after_colon = true
|
||||||
|
ij_json_space_after_comma = true
|
||||||
|
ij_json_space_before_colon = false
|
||||||
|
ij_json_space_before_comma = false
|
||||||
|
ij_json_spaces_within_braces = false
|
||||||
|
ij_json_spaces_within_brackets = false
|
||||||
|
ij_json_wrap_long_lines = false
|
||||||
|
|
||||||
|
[{*.htm,*.html,*.sht,*.shtm,*.shtml}]
|
||||||
|
ij_html_add_new_line_before_tags = body,div,p,form,h1,h2,h3
|
||||||
|
ij_html_align_attributes = true
|
||||||
|
ij_html_align_text = false
|
||||||
|
ij_html_attribute_wrap = normal
|
||||||
|
ij_html_block_comment_add_space = false
|
||||||
|
ij_html_block_comment_at_first_column = true
|
||||||
|
ij_html_do_not_align_children_of_min_lines = 0
|
||||||
|
ij_html_do_not_break_if_inline_tags = title,h1,h2,h3,h4,h5,h6,p
|
||||||
|
ij_html_do_not_indent_children_of_tags = html,body,thead,tbody,tfoot
|
||||||
|
ij_html_enforce_quotes = false
|
||||||
|
ij_html_inline_tags = a,abbr,acronym,b,basefont,bdo,big,br,cite,cite,code,dfn,em,font,i,img,input,kbd,label,q,s,samp,select,small,span,strike,strong,sub,sup,textarea,tt,u,var
|
||||||
|
ij_html_keep_blank_lines = 2
|
||||||
|
ij_html_keep_indents_on_empty_lines = false
|
||||||
|
ij_html_keep_line_breaks = true
|
||||||
|
ij_html_keep_line_breaks_in_text = true
|
||||||
|
ij_html_keep_whitespaces = false
|
||||||
|
ij_html_keep_whitespaces_inside = span,pre,textarea
|
||||||
|
ij_html_line_comment_at_first_column = true
|
||||||
|
ij_html_new_line_after_last_attribute = never
|
||||||
|
ij_html_new_line_before_first_attribute = never
|
||||||
|
ij_html_quote_style = double
|
||||||
|
ij_html_remove_new_line_before_tags = br
|
||||||
|
ij_html_space_after_tag_name = false
|
||||||
|
ij_html_space_around_equality_in_attribute = false
|
||||||
|
ij_html_space_inside_empty_tag = false
|
||||||
|
ij_html_text_wrap = normal
|
||||||
|
|
||||||
|
[{*.kt,*.kts}]
|
||||||
|
ij_kotlin_align_in_columns_case_branch = false
|
||||||
|
ij_kotlin_align_multiline_binary_operation = false
|
||||||
|
ij_kotlin_align_multiline_extends_list = false
|
||||||
|
ij_kotlin_align_multiline_method_parentheses = false
|
||||||
|
ij_kotlin_align_multiline_parameters = true
|
||||||
|
ij_kotlin_align_multiline_parameters_in_calls = false
|
||||||
|
ij_kotlin_allow_trailing_comma = false
|
||||||
|
ij_kotlin_allow_trailing_comma_on_call_site = false
|
||||||
|
ij_kotlin_assignment_wrap = off
|
||||||
|
ij_kotlin_blank_lines_after_class_header = 0
|
||||||
|
ij_kotlin_blank_lines_around_block_when_branches = 0
|
||||||
|
ij_kotlin_blank_lines_before_declaration_with_comment_or_annotation_on_separate_line = 1
|
||||||
|
ij_kotlin_block_comment_add_space = false
|
||||||
|
ij_kotlin_block_comment_at_first_column = true
|
||||||
|
ij_kotlin_call_parameters_new_line_after_left_paren = false
|
||||||
|
ij_kotlin_call_parameters_right_paren_on_new_line = false
|
||||||
|
ij_kotlin_call_parameters_wrap = off
|
||||||
|
ij_kotlin_catch_on_new_line = false
|
||||||
|
ij_kotlin_class_annotation_wrap = split_into_lines
|
||||||
|
ij_kotlin_continuation_indent_for_chained_calls = true
|
||||||
|
ij_kotlin_continuation_indent_for_expression_bodies = true
|
||||||
|
ij_kotlin_continuation_indent_in_argument_lists = true
|
||||||
|
ij_kotlin_continuation_indent_in_elvis = true
|
||||||
|
ij_kotlin_continuation_indent_in_if_conditions = true
|
||||||
|
ij_kotlin_continuation_indent_in_parameter_lists = true
|
||||||
|
ij_kotlin_continuation_indent_in_supertype_lists = true
|
||||||
|
ij_kotlin_else_on_new_line = false
|
||||||
|
ij_kotlin_enum_constants_wrap = off
|
||||||
|
ij_kotlin_extends_list_wrap = off
|
||||||
|
ij_kotlin_field_annotation_wrap = split_into_lines
|
||||||
|
ij_kotlin_finally_on_new_line = false
|
||||||
|
ij_kotlin_if_rparen_on_new_line = false
|
||||||
|
ij_kotlin_import_nested_classes = false
|
||||||
|
ij_kotlin_imports_layout = *,java.**,javax.**,kotlin.**,^
|
||||||
|
ij_kotlin_insert_whitespaces_in_simple_one_line_method = true
|
||||||
|
ij_kotlin_keep_blank_lines_before_right_brace = 2
|
||||||
|
ij_kotlin_keep_blank_lines_in_code = 2
|
||||||
|
ij_kotlin_keep_blank_lines_in_declarations = 2
|
||||||
|
ij_kotlin_keep_first_column_comment = true
|
||||||
|
ij_kotlin_keep_indents_on_empty_lines = false
|
||||||
|
ij_kotlin_keep_line_breaks = true
|
||||||
|
ij_kotlin_lbrace_on_next_line = false
|
||||||
|
ij_kotlin_line_break_after_multiline_when_entry = true
|
||||||
|
ij_kotlin_line_comment_add_space = false
|
||||||
|
ij_kotlin_line_comment_add_space_on_reformat = false
|
||||||
|
ij_kotlin_line_comment_at_first_column = true
|
||||||
|
ij_kotlin_method_annotation_wrap = split_into_lines
|
||||||
|
ij_kotlin_method_call_chain_wrap = off
|
||||||
|
ij_kotlin_method_parameters_new_line_after_left_paren = false
|
||||||
|
ij_kotlin_method_parameters_right_paren_on_new_line = false
|
||||||
|
ij_kotlin_method_parameters_wrap = off
|
||||||
|
ij_kotlin_name_count_to_use_star_import = 5
|
||||||
|
ij_kotlin_name_count_to_use_star_import_for_members = 3
|
||||||
|
ij_kotlin_packages_to_use_import_on_demand = java.util.*,kotlinx.android.synthetic.**,io.ktor.**
|
||||||
|
ij_kotlin_parameter_annotation_wrap = off
|
||||||
|
ij_kotlin_space_after_comma = true
|
||||||
|
ij_kotlin_space_after_extend_colon = true
|
||||||
|
ij_kotlin_space_after_type_colon = true
|
||||||
|
ij_kotlin_space_before_catch_parentheses = true
|
||||||
|
ij_kotlin_space_before_comma = false
|
||||||
|
ij_kotlin_space_before_extend_colon = true
|
||||||
|
ij_kotlin_space_before_for_parentheses = true
|
||||||
|
ij_kotlin_space_before_if_parentheses = true
|
||||||
|
ij_kotlin_space_before_lambda_arrow = true
|
||||||
|
ij_kotlin_space_before_type_colon = false
|
||||||
|
ij_kotlin_space_before_when_parentheses = true
|
||||||
|
ij_kotlin_space_before_while_parentheses = true
|
||||||
|
ij_kotlin_spaces_around_additive_operators = true
|
||||||
|
ij_kotlin_spaces_around_assignment_operators = true
|
||||||
|
ij_kotlin_spaces_around_equality_operators = true
|
||||||
|
ij_kotlin_spaces_around_function_type_arrow = true
|
||||||
|
ij_kotlin_spaces_around_logical_operators = true
|
||||||
|
ij_kotlin_spaces_around_multiplicative_operators = true
|
||||||
|
ij_kotlin_spaces_around_range = false
|
||||||
|
ij_kotlin_spaces_around_relational_operators = true
|
||||||
|
ij_kotlin_spaces_around_unary_operator = false
|
||||||
|
ij_kotlin_spaces_around_when_arrow = true
|
||||||
|
ij_kotlin_variable_annotation_wrap = off
|
||||||
|
ij_kotlin_while_on_new_line = false
|
||||||
|
ij_kotlin_wrap_elvis_expressions = 1
|
||||||
|
ij_kotlin_wrap_expression_body_functions = 0
|
||||||
|
ij_kotlin_wrap_first_method_in_call_chain = false
|
||||||
|
|
||||||
|
[{*.markdown,*.md}]
|
||||||
|
ij_markdown_force_one_space_after_blockquote_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_header_symbol = true
|
||||||
|
ij_markdown_force_one_space_after_list_bullet = true
|
||||||
|
ij_markdown_force_one_space_between_words = true
|
||||||
|
ij_markdown_format_tables = true
|
||||||
|
ij_markdown_insert_quote_arrows_on_wrap = true
|
||||||
|
ij_markdown_keep_indents_on_empty_lines = false
|
||||||
|
ij_markdown_keep_line_breaks_inside_text_blocks = true
|
||||||
|
ij_markdown_max_lines_around_block_elements = 1
|
||||||
|
ij_markdown_max_lines_around_header = 1
|
||||||
|
ij_markdown_max_lines_between_paragraphs = 1
|
||||||
|
ij_markdown_min_lines_around_block_elements = 1
|
||||||
|
ij_markdown_min_lines_around_header = 1
|
||||||
|
ij_markdown_min_lines_between_paragraphs = 1
|
||||||
|
ij_markdown_wrap_text_if_long = true
|
||||||
|
ij_markdown_wrap_text_inside_blockquotes = true
|
||||||
|
|
||||||
|
[{*.toml,Cargo.lock,Cargo.toml.orig,Gopkg.lock,Pipfile,poetry.lock}]
|
||||||
|
ij_toml_keep_indents_on_empty_lines = false
|
||||||
|
|
||||||
|
[{*.yaml,*.yml}]
|
||||||
|
indent_size = 4
|
||||||
|
ij_yaml_align_values_properties = do_not_align
|
||||||
|
ij_yaml_autoinsert_sequence_marker = true
|
||||||
|
ij_yaml_block_mapping_on_new_line = false
|
||||||
|
ij_yaml_indent_sequence_value = true
|
||||||
|
ij_yaml_keep_indents_on_empty_lines = false
|
||||||
|
ij_yaml_keep_line_breaks = true
|
||||||
|
ij_yaml_sequence_on_new_line = false
|
||||||
|
ij_yaml_space_before_colon = false
|
||||||
|
ij_yaml_spaces_within_braces = true
|
||||||
|
ij_yaml_spaces_within_brackets = true
|
||||||
+21
-28
@@ -1,31 +1,3 @@
|
|||||||
# eclipse
|
|
||||||
bin
|
|
||||||
*.launch
|
|
||||||
.settings
|
|
||||||
.metadata
|
|
||||||
.classpath
|
|
||||||
.project
|
|
||||||
|
|
||||||
# idea
|
|
||||||
out
|
|
||||||
*.ipr
|
|
||||||
*.iws
|
|
||||||
*.iml
|
|
||||||
.idea
|
|
||||||
|
|
||||||
# gradle
|
|
||||||
build
|
|
||||||
.gradle
|
|
||||||
|
|
||||||
# other
|
|
||||||
eclipse
|
|
||||||
run
|
|
||||||
|
|
||||||
# Files from Forge MDK
|
|
||||||
logs
|
|
||||||
forge*changelog.txt
|
|
||||||
|
|
||||||
.architectury-transformer/
|
|
||||||
build/
|
build/
|
||||||
*.ipr
|
*.ipr
|
||||||
run/
|
run/
|
||||||
@@ -33,9 +5,11 @@ run/
|
|||||||
out/
|
out/
|
||||||
*.iml
|
*.iml
|
||||||
.gradle/
|
.gradle/
|
||||||
|
.gradle-cache/
|
||||||
output/
|
output/
|
||||||
bin/
|
bin/
|
||||||
libs/
|
libs/
|
||||||
|
.architectury-transformer/
|
||||||
|
|
||||||
.classpath
|
.classpath
|
||||||
.project
|
.project
|
||||||
@@ -45,9 +19,28 @@ classes/
|
|||||||
.vscode
|
.vscode
|
||||||
.settings
|
.settings
|
||||||
*.launch
|
*.launch
|
||||||
|
hs_err_pid*
|
||||||
|
|
||||||
**/src/generated/
|
**/src/generated/
|
||||||
Merged/
|
Merged/
|
||||||
|
# Folder created by the buildAll scripts
|
||||||
|
buildAllJars/
|
||||||
|
|
||||||
|
relocate_natives/.venv/
|
||||||
|
relocate_natives/__pycache__/
|
||||||
|
relocate_natives/apple-codesign/
|
||||||
|
|
||||||
# file from notepad++
|
# file from notepad++
|
||||||
*.bak
|
*.bak
|
||||||
|
|
||||||
|
# file genearated via MC version switching using preprocessor
|
||||||
|
build.properties
|
||||||
|
|
||||||
|
# Sqlite databases
|
||||||
|
*.sqlite
|
||||||
|
*.sqlite-journal
|
||||||
|
*.sqlite-shm
|
||||||
|
*.sqlite-wal
|
||||||
|
|
||||||
|
# Don't add access transformers to git as they're dynamically generated
|
||||||
|
accesstransformer.cfg
|
||||||
|
|||||||
+89
-118
@@ -1,132 +1,103 @@
|
|||||||
# use Eclipse's JDK
|
# use Eclipse's JDK
|
||||||
image: gradle:eclipse-temurin
|
# The ci should always use a unix(-like) OS to work
|
||||||
|
image: eclipse-temurin:25
|
||||||
|
|
||||||
# all stages need to be defined here
|
# all stages need to be defined here
|
||||||
stages:
|
stages:
|
||||||
- gradleSetup
|
|
||||||
- build
|
- build
|
||||||
- merge
|
- api
|
||||||
|
- pages
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
# Disable the Gradle daemon for Continuous Integration servers as correctness
|
# Pull core when building
|
||||||
# is usually a priority over speed in CI environments. Using a fresh
|
GIT_SUBMODULE_STRATEGY: recursive
|
||||||
# runtime for each build is more reliable since the runtime is completely
|
|
||||||
# isolated from any previous builds.
|
|
||||||
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
|
|
||||||
# Pull core when building
|
|
||||||
GIT_SUBMODULE_STRATEGY: recursive
|
|
||||||
|
|
||||||
|
|
||||||
before_script:
|
# These can be extended so code is a bit less duplicated
|
||||||
- echo $CI_JOB_ID
|
.build_java:
|
||||||
# Writing GE_JOB_ID variable to environment file, will need the value in the next stage.
|
#image: eclipse-temurin:17
|
||||||
- echo GE_JOB_ID=$CI_JOB_ID >> generate_jars.env
|
cache:
|
||||||
|
key: "gradleCache_$CI_JOB_NAME_SLUG"
|
||||||
|
policy: pull-push
|
||||||
|
paths:
|
||||||
|
- .gradle
|
||||||
|
- cache/
|
||||||
|
allow_failure: true
|
||||||
|
retry:
|
||||||
|
max: 2
|
||||||
|
when:
|
||||||
|
- runner_system_failure
|
||||||
|
- stuck_or_timeout_failure
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# first stage
|
|
||||||
# This prevents us from re-downloading Gradle every stage
|
|
||||||
gradleSetup:
|
|
||||||
stage: gradleSetup
|
|
||||||
script: ./gradlew --build-cache --gradle-user-home cache/ check
|
|
||||||
# build using Java 17
|
|
||||||
image: eclipse-temurin:17
|
|
||||||
cache:
|
|
||||||
key:
|
|
||||||
files:
|
|
||||||
- gradle/wrapper/gradle-wrapper.properties
|
|
||||||
policy: push
|
|
||||||
paths:
|
|
||||||
- cache/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# second stage
|
|
||||||
build:
|
build:
|
||||||
stage: build
|
stage: build
|
||||||
script: ./gradlew build --gradle-user-home cache/
|
parallel:
|
||||||
# build using Java 17
|
matrix:
|
||||||
image: eclipse-temurin:17
|
- MC_VER: [
|
||||||
cache:
|
"1.26.1",
|
||||||
key: "$CI_COMMIT_REF_NAME"
|
"1.21.11", "1.21.10", "1.21.9", "1.21.8", "1.21.6", "1.21.5", "1.21.4", "1.21.3", "1.21.1",
|
||||||
policy: pull-push
|
"1.20.6", "1.20.4", "1.20.2", "1.20.1",
|
||||||
paths:
|
"1.19.4", "1.19.2",
|
||||||
- .architectury-transformer
|
"1.18.2",
|
||||||
- .gradle
|
"1.17.1",
|
||||||
- build
|
"1.16.5"
|
||||||
- common/.gradle
|
]
|
||||||
- common/build
|
script:
|
||||||
- core/.gradle
|
# this both runs the unit tests and assembles the code
|
||||||
- core/build
|
- ./gradlew clean -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
|
||||||
- fabric/.gradle
|
- ./gradlew build -PmcVer="${MC_VER}" -PinfoGitCommit="${CI_COMMIT_SHA}" -PinfoGitBranch="${CI_COMMIT_BRANCH}" -PinfoBuildSource="GitLab CI (${CI_PIPELINE_ID})" --gradle-user-home cache/;
|
||||||
- fabric/src/generated
|
- cp ./fabric/build/libs/* ./forge/build/libs/* ./neoforge/build/libs/* ./build/forgix/* . || true
|
||||||
- forge/.gradle
|
artifacts:
|
||||||
- forge/src/generated
|
name: "NightlyBuild_${MC_VER}-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
||||||
- build
|
paths:
|
||||||
- .gradle
|
- ./*.jar
|
||||||
- cache/
|
exclude:
|
||||||
artifacts:
|
- ./*-all.jar
|
||||||
name: "NightlyBuild-$CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
- ./*-dev.jar
|
||||||
paths:
|
- ./*-sources.jar
|
||||||
# relative to the root directory
|
expire_in: 14 days
|
||||||
- fabric/build/libs
|
when: always
|
||||||
- forge/build/libs
|
extends: .build_java
|
||||||
exclude:
|
|
||||||
- fabric/build/libs/*-dev.jar
|
|
||||||
- fabric/build/libs/*-dev-shadow.jar
|
|
||||||
- fabric/build/libs/*-sources-dev.jar
|
|
||||||
- fabric/build/libs/*-sources.jar
|
|
||||||
- forge/build/libs/*-dev.jar
|
|
||||||
- forge/build/libs/*-dev-shadow.jar
|
|
||||||
- forge/build/libs/*-sources-dev.jar
|
|
||||||
- forge/build/libs/*-sources.jar
|
|
||||||
reports:
|
|
||||||
# To ensure we've access to these files in the next stage
|
|
||||||
dotenv: generate_jars.env
|
|
||||||
expire_in: 1 day
|
|
||||||
|
|
||||||
# third stage
|
|
||||||
merge:
|
|
||||||
stage: merge
|
|
||||||
script: ./gradlew merge --gradle-user-home cache/
|
|
||||||
# build using Java 17
|
|
||||||
image: eclipse-temurin:17
|
|
||||||
cache:
|
|
||||||
key: "$CI_COMMIT_REF_NAME"
|
|
||||||
policy: pull-push
|
|
||||||
paths:
|
|
||||||
- build
|
|
||||||
- .gradle
|
|
||||||
- cache/
|
|
||||||
artifacts:
|
|
||||||
name: "Merged_NightlyBuild-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
|
||||||
paths:
|
|
||||||
# relative to the root directory
|
|
||||||
- Merged
|
|
||||||
expire_in: 1 day
|
|
||||||
|
|
||||||
|
|
||||||
## forth stage
|
api:
|
||||||
#deploy:
|
stage: api
|
||||||
# stage: deploy
|
needs: []
|
||||||
# image: registry.gitlab.com/gitlab-org/release-cli:latest
|
script:
|
||||||
# script:
|
# this should only run for the API
|
||||||
# - echo 'running release_job'
|
- ./gradlew api:clean --gradle-user-home cache/;
|
||||||
# - echo 'Previous Job ID is printed below'
|
# this also runs unit tests
|
||||||
# - echo $GE_JOB_ID
|
- ./gradlew api:build --gradle-user-home cache/;
|
||||||
# # Specifying that this job requires artifacts from the previous job to succeed
|
- ./gradlew api:addSourcesToCompiledJar --gradle-user-home cache/;
|
||||||
# needs:
|
- cp ./coreSubProjects/api/build/libs/merged/* .
|
||||||
# - job: build
|
artifacts:
|
||||||
# artifacts: true
|
name: "NightlyBuild_Api-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
||||||
# release:
|
paths:
|
||||||
# name: 'Unstable Jars for Latest Commit' #: $CI_COMMIT_SHORT_SHA'
|
- ./*.jar
|
||||||
# description: 'Created automatically using the release-cli.'
|
exclude:
|
||||||
# # tag_name is a mendatory field and can not be an empty string
|
- ./*-all.jar
|
||||||
# tag_name: 'Unstable-$CI_COMMIT_SHORT_SHA'
|
- ./*-dev.jar
|
||||||
# assets:
|
- ./*-sources.jar
|
||||||
# links:
|
expire_in: 1 day
|
||||||
# - name: 'Fabric Jars'
|
when: always
|
||||||
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/fabric/build/libs'
|
extends: .build_java
|
||||||
# - name: 'Forge Jars'
|
|
||||||
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/forge/build/libs'
|
|
||||||
|
# generate and publish API javadocs
|
||||||
|
pages:
|
||||||
|
stage: pages
|
||||||
|
needs: []
|
||||||
|
script:
|
||||||
|
# this should only run for the API
|
||||||
|
- ./gradlew api:clean --gradle-user-home cache/;
|
||||||
|
# this also runs unit tests
|
||||||
|
- ./gradlew api:build --gradle-user-home cache/;
|
||||||
|
- ./gradlew api:javadoc --gradle-user-home cache/;
|
||||||
|
- mkdir public
|
||||||
|
- cp -r $CI_PROJECT_DIR/coreSubProjects/api/build/docs/javadoc/. public
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- public
|
||||||
|
allow_failure: false
|
||||||
|
extends: .build_java
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
## Check off each item in this list before submitting:
|
||||||
|
|
||||||
|
<!--
|
||||||
|
To mark a section as complete either put an "x" in between the square brackets, example: "[x]"
|
||||||
|
Or click the checkbox once the issue has been created.
|
||||||
|
-->
|
||||||
|
|
||||||
|
1. [ ] Check the FAQ to see if your issue has already been reported and has a solution:
|
||||||
|
[Problems-and-solutions](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions)
|
||||||
|
|
||||||
|
2. [ ] Make sure you are not using any mods on the incompatible list:
|
||||||
|
[Mod support FAQ](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/4-mod-support/Mod-Support)
|
||||||
|
|
||||||
|
3. [ ] Check the existing issues to verify that your bug hasn't already been submitted:
|
||||||
|
[Issues](https://gitlab.com/distant-horizons-team/distant-horizons/-/issues)
|
||||||
|
|
||||||
|
4. [ ] Upload Minecraft's crash report and/or log. \
|
||||||
|
Minecraft crash reports are located in: `.minecraft/crash-reports` \
|
||||||
|
Minecraft logs are located in: `.minecraft/logs`
|
||||||
|
|
||||||
|
5. [ ] Upload your Distant Horizons Config. \
|
||||||
|
The config is found in: `.minecraft/configs/DistantHorizons.toml`
|
||||||
|
|
||||||
|
6. [ ] Fill out the information below:
|
||||||
|
|
||||||
|
* **minecraft version**:
|
||||||
|
|
||||||
|
* **Distant Horizons version**:
|
||||||
|
|
||||||
|
* **Mod loader**:
|
||||||
|
|
||||||
|
* **Installed mods (list the smallest number of mods that you can use to re-create the bug)**:
|
||||||
|
|
||||||
|
* **Describe the bug**:
|
||||||
|
|
||||||
|
* **Steps to reproduce the bug**:
|
||||||
|
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
## Check off each item in this list before submitting:
|
||||||
|
|
||||||
|
<!--
|
||||||
|
To mark a section as complete either put an "x" in between the square brackets, example: "[x]"
|
||||||
|
Or click the checkbox once the issue has been created.
|
||||||
|
-->
|
||||||
|
|
||||||
|
1. [ ] Check the FAQ to see if your issue has already been reported and has a solution:
|
||||||
|
[Problems-and-solutions](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/2-problems-and-solutions/Problems-and-Solutions)
|
||||||
|
|
||||||
|
2. [ ] Make sure you are not using any mods on the incompatible list:
|
||||||
|
[Mod support FAQ](https://gitlab.com/distant-horizons-team/distant-horizons/-/wikis/1-user-guide/1-frequently-asked-questions/4-mod-support/Mod-Support)
|
||||||
|
|
||||||
|
3. [ ] Check the existing issues to verify that your bug hasn't already been submitted:
|
||||||
|
[Issues](https://gitlab.com/distant-horizons-team/distant-horizons/-/issues)
|
||||||
|
|
||||||
|
4. [ ] Upload Minecraft's crash report and/or log. \
|
||||||
|
Minecraft crash reports are located in: `.minecraft/crash-reports` \
|
||||||
|
Minecraft logs are located in: `.minecraft/logs`
|
||||||
|
|
||||||
|
5. [ ] Upload your Distant Horizons Config. \
|
||||||
|
The config is found in: `.minecraft/configs/DistantHorizons.toml`
|
||||||
|
|
||||||
|
6. [ ] Fill out the information below:
|
||||||
|
|
||||||
|
* **minecraft version**:
|
||||||
|
|
||||||
|
* **Distant Horizons version**:
|
||||||
|
|
||||||
|
* **Mod loader**:
|
||||||
|
|
||||||
|
* **Installed mods (list the smallest number of mods that you can use to re-create the bug)**:
|
||||||
|
|
||||||
|
* **Describe the bug**:
|
||||||
|
|
||||||
|
* **Steps to reproduce the bug**:
|
||||||
|
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
- [ ] Check the existing [feature requests](https://gitlab.com/distant-horizons-team/distant-horizons/-/issues?sort=updated_desc&state=opened&label_name%5B%5D=Feature) to verify that your feature hasn't already been suggested.
|
||||||
|
|
||||||
|
1. **Describe the feature**:
|
||||||
|
|
||||||
|
2. **Describe why this feature should be added**:
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
1. Check the existing [improvement requests](https://gitlab.com/distant-horizons-team/distant-horizons/-/issues?sort=updated_desc&state=all&label_name%5B%5D=Improvement) to verify that your improvement hasn't already been suggested.
|
||||||
|
|
||||||
|
2. **Describe the improvement**:
|
||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
[submodule "core"]
|
[submodule "coreSubProjects"]
|
||||||
path = core
|
path = coreSubProjects
|
||||||
url = https://gitlab.com/jeseibel/distant-horizons-core.git
|
url = https://gitlab.com/jeseibel/distant-horizons-core.git
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
# See mailmap docs: https://git-scm.com/docs/gitmailmap
|
||||||
|
# Test with git shortlog --summary --email
|
||||||
|
# Keep sorted for easier editing and smaller diffs
|
||||||
|
|
||||||
|
Ada Aster <an.ada.poirier@gmail.com>
|
||||||
|
CodeF53 <fseusb@gmail.com> <37855219+CodeF53@users.noreply.github.com>
|
||||||
|
coolGi <me@coolgi.dev> <sasanaps@hotmail.com>
|
||||||
|
James Seibel <jeseibel@gondtc.com> <jseibel@vertsys.com>
|
||||||
|
Morippi <leoleo97@libero.it> <leoloe97@libero.it>
|
||||||
|
Morippi <leoleo97@libero.it> <Morippi>
|
||||||
|
Ran <43445785+Ran-Mewo@users.noreply.github.com> <10044908-_Ran@users.noreply.gitlab.com>
|
||||||
|
Ran <43445785+Ran-Mewo@users.noreply.github.com> <43445785+Ran-Mewo@users.noreply.github.com>
|
||||||
|
Ran <43445785+Ran-Mewo@users.noreply.github.com> <43445785+RanCraftPlayz@users.noreply.github.com>
|
||||||
|
TomTheFurry <tomlee92502@yahoo.com>
|
||||||
|
TomTheFurry <tomlee92502@yahoo.com> <46843632+TomTheFurry@users.noreply.github.com>
|
||||||
|
Yeshi <yeshi@newengine.org>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Fabric Client & Server" type="CompoundRunConfigurationType">
|
||||||
|
<toRun name="Fabric Client (:fabric)" type="Application" />
|
||||||
|
<toRun name="Fabric Server (:fabric)" type="Application" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Forge Client & Server" type="CompoundRunConfigurationType">
|
||||||
|
<toRun name="Forge Client (gradle)" type="GradleRunConfiguration" />
|
||||||
|
<toRun name="Forge Server (gradle)" type="GradleRunConfiguration" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Forge Client (gradle)" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="forge:runClient" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Forge Server (gradle)" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="forge:runServer" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Neoforge Client & Server" type="CompoundRunConfigurationType">
|
||||||
|
<toRun name="Neoforge Client (gradle)" type="GradleRunConfiguration" />
|
||||||
|
<toRun name="Neoforge Server (gradle)" type="GradleRunConfiguration" />
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Neoforge Client (gradle)" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="neoforge:runClient" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Neoforge Server (gradle)" type="GradleRunConfiguration" factoryName="Gradle">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="neoforge:runServer" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="distant-horizons [build]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="build" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="distant-horizons [clean]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="clean" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="distant-horizons [core:build]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="core:build" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="distant-horizons [fabric:runClient]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="fabric:runClient" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="distant-horizons [forge:runClient]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="forge:runClient" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="distant-horizons [mergeJars]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="mergeJars" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="distant-horizons [neoforge:runClient]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="neoforge:runClient" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="distant-horizons [test]" type="GradleRunConfiguration" factoryName="Gradle" nameIsGenerated="true">
|
||||||
|
<ExternalSystemSettings>
|
||||||
|
<option name="executionName" />
|
||||||
|
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||||
|
<option name="externalSystemIdString" value="GRADLE" />
|
||||||
|
<option name="scriptParameters" value="" />
|
||||||
|
<option name="taskDescriptions">
|
||||||
|
<list />
|
||||||
|
</option>
|
||||||
|
<option name="taskNames">
|
||||||
|
<list>
|
||||||
|
<option value="test" />
|
||||||
|
</list>
|
||||||
|
</option>
|
||||||
|
<option name="vmOptions" />
|
||||||
|
</ExternalSystemSettings>
|
||||||
|
<ExternalSystemDebugServerProcess>true</ExternalSystemDebugServerProcess>
|
||||||
|
<ExternalSystemReattachDebugProcess>true</ExternalSystemReattachDebugProcess>
|
||||||
|
<DebugAllEnabled>false</DebugAllEnabled>
|
||||||
|
<RunAsTest>false</RunAsTest>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
FROM eclipse-temurin:25-jdk
|
||||||
|
|
||||||
|
WORKDIR /home/build/
|
||||||
|
COPY ./gradlew .
|
||||||
|
RUN chmod +x ./gradlew
|
||||||
|
CMD echo "\r========== [CLEAN: $MC_VER] ==========" && \
|
||||||
|
./gradlew clean -PmcVer="$MC_VER" --gradle-user-home .gradle-cache/ && \
|
||||||
|
echo "\r========== [BUILD: $MC_VER] ==========" && \
|
||||||
|
./gradlew build -PmcVer="$MC_VER" --gradle-user-home .gradle-cache/ && \
|
||||||
|
echo "\r========== [MERGE: $MC_VER] ==========" && \
|
||||||
|
./gradlew mergeJars -PmcVer="$MC_VER" --gradle-user-home .gradle-cache/ && \
|
||||||
|
echo "\r========== [DONE: $MC_VER] =========="
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
Distant Horizons logos © 2024 by Pankakes are licensed under CC BY-SA 4.0
|
||||||
@@ -0,0 +1,165 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
|
||||||
|
This version of the GNU Lesser General Public License incorporates
|
||||||
|
the terms and conditions of version 3 of the GNU General Public
|
||||||
|
License, supplemented by the additional permissions listed below.
|
||||||
|
|
||||||
|
0. Additional Definitions.
|
||||||
|
|
||||||
|
As used herein, "this License" refers to version 3 of the GNU Lesser
|
||||||
|
General Public License, and the "GNU GPL" refers to version 3 of the GNU
|
||||||
|
General Public License.
|
||||||
|
|
||||||
|
"The Library" refers to a covered work governed by this License,
|
||||||
|
other than an Application or a Combined Work as defined below.
|
||||||
|
|
||||||
|
An "Application" is any work that makes use of an interface provided
|
||||||
|
by the Library, but which is not otherwise based on the Library.
|
||||||
|
Defining a subclass of a class defined by the Library is deemed a mode
|
||||||
|
of using an interface provided by the Library.
|
||||||
|
|
||||||
|
A "Combined Work" is a work produced by combining or linking an
|
||||||
|
Application with the Library. The particular version of the Library
|
||||||
|
with which the Combined Work was made is also called the "Linked
|
||||||
|
Version".
|
||||||
|
|
||||||
|
The "Minimal Corresponding Source" for a Combined Work means the
|
||||||
|
Corresponding Source for the Combined Work, excluding any source code
|
||||||
|
for portions of the Combined Work that, considered in isolation, are
|
||||||
|
based on the Application, and not on the Linked Version.
|
||||||
|
|
||||||
|
The "Corresponding Application Code" for a Combined Work means the
|
||||||
|
object code and/or source code for the Application, including any data
|
||||||
|
and utility programs needed for reproducing the Combined Work from the
|
||||||
|
Application, but excluding the System Libraries of the Combined Work.
|
||||||
|
|
||||||
|
1. Exception to Section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
You may convey a covered work under sections 3 and 4 of this License
|
||||||
|
without being bound by section 3 of the GNU GPL.
|
||||||
|
|
||||||
|
2. Conveying Modified Versions.
|
||||||
|
|
||||||
|
If you modify a copy of the Library, and, in your modifications, a
|
||||||
|
facility refers to a function or data to be supplied by an Application
|
||||||
|
that uses the facility (other than as an argument passed when the
|
||||||
|
facility is invoked), then you may convey a copy of the modified
|
||||||
|
version:
|
||||||
|
|
||||||
|
a) under this License, provided that you make a good faith effort to
|
||||||
|
ensure that, in the event an Application does not supply the
|
||||||
|
function or data, the facility still operates, and performs
|
||||||
|
whatever part of its purpose remains meaningful, or
|
||||||
|
|
||||||
|
b) under the GNU GPL, with none of the additional permissions of
|
||||||
|
this License applicable to that copy.
|
||||||
|
|
||||||
|
3. Object Code Incorporating Material from Library Header Files.
|
||||||
|
|
||||||
|
The object code form of an Application may incorporate material from
|
||||||
|
a header file that is part of the Library. You may convey such object
|
||||||
|
code under terms of your choice, provided that, if the incorporated
|
||||||
|
material is not limited to numerical parameters, data structure
|
||||||
|
layouts and accessors, or small macros, inline functions and templates
|
||||||
|
(ten or fewer lines in length), you do both of the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the object code that the
|
||||||
|
Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the object code with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
4. Combined Works.
|
||||||
|
|
||||||
|
You may convey a Combined Work under terms of your choice that,
|
||||||
|
taken together, effectively do not restrict modification of the
|
||||||
|
portions of the Library contained in the Combined Work and reverse
|
||||||
|
engineering for debugging such modifications, if you also do each of
|
||||||
|
the following:
|
||||||
|
|
||||||
|
a) Give prominent notice with each copy of the Combined Work that
|
||||||
|
the Library is used in it and that the Library and its use are
|
||||||
|
covered by this License.
|
||||||
|
|
||||||
|
b) Accompany the Combined Work with a copy of the GNU GPL and this license
|
||||||
|
document.
|
||||||
|
|
||||||
|
c) For a Combined Work that displays copyright notices during
|
||||||
|
execution, include the copyright notice for the Library among
|
||||||
|
these notices, as well as a reference directing the user to the
|
||||||
|
copies of the GNU GPL and this license document.
|
||||||
|
|
||||||
|
d) Do one of the following:
|
||||||
|
|
||||||
|
0) Convey the Minimal Corresponding Source under the terms of this
|
||||||
|
License, and the Corresponding Application Code in a form
|
||||||
|
suitable for, and under terms that permit, the user to
|
||||||
|
recombine or relink the Application with a modified version of
|
||||||
|
the Linked Version to produce a modified Combined Work, in the
|
||||||
|
manner specified by section 6 of the GNU GPL for conveying
|
||||||
|
Corresponding Source.
|
||||||
|
|
||||||
|
1) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (a) uses at run time
|
||||||
|
a copy of the Library already present on the user's computer
|
||||||
|
system, and (b) will operate properly with a modified version
|
||||||
|
of the Library that is interface-compatible with the Linked
|
||||||
|
Version.
|
||||||
|
|
||||||
|
e) Provide Installation Information, but only if you would otherwise
|
||||||
|
be required to provide such information under section 6 of the
|
||||||
|
GNU GPL, and only to the extent that such information is
|
||||||
|
necessary to install and execute a modified version of the
|
||||||
|
Combined Work produced by recombining or relinking the
|
||||||
|
Application with a modified version of the Linked Version. (If
|
||||||
|
you use option 4d0, the Installation Information must accompany
|
||||||
|
the Minimal Corresponding Source and Corresponding Application
|
||||||
|
Code. If you use option 4d1, you must provide the Installation
|
||||||
|
Information in the manner specified by section 6 of the GNU GPL
|
||||||
|
for conveying Corresponding Source.)
|
||||||
|
|
||||||
|
5. Combined Libraries.
|
||||||
|
|
||||||
|
You may place library facilities that are a work based on the
|
||||||
|
Library side by side in a single library together with other library
|
||||||
|
facilities that are not Applications and are not covered by this
|
||||||
|
License, and convey such a combined library under terms of your
|
||||||
|
choice, if you do both of the following:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work based
|
||||||
|
on the Library, uncombined with any other library facilities,
|
||||||
|
conveyed under the terms of this License.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library that part of it
|
||||||
|
is a work based on the Library, and explaining where to find the
|
||||||
|
accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
6. Revised Versions of the GNU Lesser General Public License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the GNU Lesser General Public License from time to time. Such new
|
||||||
|
versions will be similar in spirit to the present version, but may
|
||||||
|
differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Library as you received it specifies that a certain numbered version
|
||||||
|
of the GNU Lesser General Public License "or any later version"
|
||||||
|
applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that published version or of any later version
|
||||||
|
published by the Free Software Foundation. If the Library as you
|
||||||
|
received it does not specify a version number of the GNU Lesser
|
||||||
|
General Public License, you may choose any version of the GNU Lesser
|
||||||
|
General Public License ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Library as you received it specifies that a proxy can decide
|
||||||
|
whether future versions of the GNU Lesser General Public License shall
|
||||||
|
apply, that proxy's public statement of acceptance of any version is
|
||||||
|
permanent authorization for you to choose that version for the
|
||||||
|
Library.
|
||||||
@@ -1,87 +1,210 @@
|
|||||||
# Distant Horizons
|
# <img src="https://gitlab.com/distant-horizons-team/distant-horizons-core/-/raw/main/_Misc%20Files/logo%20files/new/SVG/Distant-Horizons.svg" height="128px">
|
||||||
|
_See farther without turning your game into a slide show._
|
||||||
|
|
||||||
This mod adds a Level Of Detail (LOD) system to Minecraft.\
|
<br>
|
||||||
This implementation renders simplified chunks outside the normal render distance\
|
|
||||||
allowing for an increased view distance without harming performance.
|
|
||||||
|
|
||||||
Or in other words: this mod lets you see farther without turning your game into a slide show.\
|
# What is Distant Horizons?
|
||||||
If you want to see a quick demo, check out a video covering the mod here:
|
|
||||||
|
|
||||||
<a href="https://www.youtube.com/watch?v=H2tnvEVbO1c" target="_blank"></a>
|
Distant Horizons is a mod which implements a [Level of Detail](https://en.wikipedia.org/wiki/Level_of_detail_(computer_graphics)) system to Minecraft.\
|
||||||
|
This allows for far greater render distances without harming performance by gradually lowering the quality of distant terrain.
|
||||||
|
|
||||||
Architectury version: 3.4-SNAPSHOT\
|
Below is a video demonstrating the system:
|
||||||
Forge version: 39.0.5 and 38.0.14\
|
|
||||||
Fabric version: 0.12.12\
|
|
||||||
Fabric API version: 0.44.0+1.18
|
|
||||||
|
|
||||||
Modmenu version: 3.0.0\
|
<a href="https://youtu.be/SxQdbtjGEsc" target="_blank"></a>
|
||||||
Sodium version: mc1.18-0.4.0-alpha5
|
|
||||||
|
|
||||||
Notes:\
|
<br>
|
||||||
This version has been confirmed to work in Eclipse and Retail Minecraft.\
|
|
||||||
(Retail running forge version 1.18.1-39.0.5 and fabric version 1.18-0.12.12 and 1.18.1-0.12.12)
|
|
||||||
|
|
||||||
|
## Minecraft and Library Versions
|
||||||
|
|
||||||
## source code installation
|
### This branch supports the following versions of Minecraft:
|
||||||
|
|
||||||
See the Fabric Documentation online for more detailed instructions:\
|
#### 1.20.4, 1.20.3 (Default)
|
||||||
https://fabricmc.net/wiki/tutorial:setup
|
Fabric: 0.15.1\
|
||||||
|
Fabric API: 0.91.2+1.20.4\
|
||||||
|
Forge: 49.0.30\
|
||||||
|
NeoForge: 118-beta\
|
||||||
|
Parchment: 1.20.2:2023.12.10\
|
||||||
|
Modmenu: 9.0.0-pre.1
|
||||||
|
|
||||||
|
#### 1.20.2
|
||||||
|
Fabric: 0.14.24\
|
||||||
|
Fabric API: 0.90.4+1.20.2\
|
||||||
|
Forge: 48.0.13\
|
||||||
|
Parchment: 1.20.1:2023.09.03\
|
||||||
|
Modmenu: 8.0.0
|
||||||
|
|
||||||
|
#### 1.20.1, 1.20
|
||||||
|
Fabric: 0.14.24\
|
||||||
|
Fabric API: 0.90.4+1.20.1\
|
||||||
|
Forge: 47.2.1\
|
||||||
|
Parchment: 1.20.1:2023.09.03\
|
||||||
|
Modmenu: 7.2.2
|
||||||
|
|
||||||
|
#### 1.19.4
|
||||||
|
Fabric: 0.14.24\
|
||||||
|
Fabric API: 0.87.1+1.19.4\
|
||||||
|
Forge: 45.2.4\
|
||||||
|
Parchment: 1.19.4:2023.06.26\
|
||||||
|
Modmenu: 6.3.1
|
||||||
|
|
||||||
|
#### 1.19.2
|
||||||
|
Fabric: 0.14.24\
|
||||||
|
Fabric API: 0.76.1+1.19.2\
|
||||||
|
Forge: 43.3.2\
|
||||||
|
Parchment: 1.19.2:2022.11.27\
|
||||||
|
Modmenu: 4.2.0-beta.2
|
||||||
|
|
||||||
|
#### 1.18.2
|
||||||
|
Fabric: 0.14.24\
|
||||||
|
Fabric API: 0.76.0+1.18.2\
|
||||||
|
Forge: 40.2.10\
|
||||||
|
Parchment: 1.18.2:2022.11.06\
|
||||||
|
Modmenu: 3.2.5
|
||||||
|
|
||||||
|
#### 1.17.1, 1.17
|
||||||
|
Fabric: 0.14.24\
|
||||||
|
Fabric API: 0.46.1+1.17\
|
||||||
|
Forge: 37.1.1\
|
||||||
|
Parchment: 1.17.1:2021.12.12\
|
||||||
|
Modmenu: 2.0.14
|
||||||
|
|
||||||
|
#### 1.16.5, 1.16.4
|
||||||
|
Fabric: 0.14.24\
|
||||||
|
Fabric API: 0.42.0+1.16\
|
||||||
|
Forge: 36.2.39\
|
||||||
|
Parchment: 1.16.5:2022.03.06\
|
||||||
|
Modmenu: 1.16.22
|
||||||
|
|
||||||
|
### Versions no longer supported
|
||||||
|
- 1.18.1, 1.18
|
||||||
|
- 1.19.1, 1.19
|
||||||
|
- 1.19.3
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
### Plugin and Library versions
|
||||||
|
|
||||||
|
Gradle: 8.5\
|
||||||
|
Fabric loom: 1.4-SNAPSHOT\
|
||||||
|
Architectury loom (Forge gradle replacement): 1.4-SNAPSHOT\
|
||||||
|
Sponge vanilla gradle: 0.2.1-SNAPSHOT\
|
||||||
|
Java Preprocessor plugin: Manifold Preprocessor
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## Source Code Installation
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
* A Java Development Kit (JDK) for Java 17 (recommended) or newer. Visit https://www.oracle.com/java/technologies/downloads/ for installers.
|
* A Java Development Kit (JDK) for Java 17 (recommended) or newer. <br>
|
||||||
* Git or someway to clone git projects. Visit https://git-scm.com/ for installers.
|
Visit https://www.oracle.com/java/technologies/downloads/ for installers.
|
||||||
* (Not required) Any Java IDE, for example Intellij IDEA and Eclipse. You may also use any other code editors, such as Visual Studio Code. (Optional)
|
* Git or someway to clone git projects. <br>
|
||||||
It's better to use IntelliJ IDEA since Eclipse is not supported by Architectury, but it still works.
|
Visit https://git-scm.com/ for installers.
|
||||||
|
* (Not required) Any Java IDE with plugins that support Manifold, for example IntelliJ IDEA.
|
||||||
|
|
||||||
**If using IntelliJ:**
|
**If using IntelliJ:**
|
||||||
1. open IDEA and import the build.gradle
|
1. Install the Manifold plugin
|
||||||
2. refresh the Gradle project in IDEA if required
|
2. Open IDEA and import the build.gradle
|
||||||
|
3. Refresh the Gradle project in IDEA if required
|
||||||
|
|
||||||
**If using Ecplise:**
|
**If using Eclipse: (Note that Eclipse doesn't support Manifold's preprocessor!)**
|
||||||
1. run the command: `./gradlew geneclipseruns`
|
1. Run the command: `./gradlew geneclipseruns`
|
||||||
2. run the command: `./gradlew eclipse`
|
2. Run the command: `./gradlew eclipse`
|
||||||
3. Make sure eclipse has the JDK 17 installed. (This is needed so that eclipse can run minecraft)
|
3. Make sure eclipse has the JDK 17 installed. (This is needed so that eclipse can run minecraft)
|
||||||
4. Import the project into eclipse
|
4. Import the project into eclipse
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## Switching Versions
|
||||||
|
|
||||||
|
To switch between different Minecraft versions, change `mcVer=1.?` in the `gradle.properties` file.
|
||||||
|
|
||||||
|
If running in an IDE, to ensure the IDE noticed the version change, run any gradle command to refresh gradle.\
|
||||||
|
In IntelliJ, you will also need to do a gradle sync if it didn't happen automatically.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
## Compiling
|
## Compiling
|
||||||
|
|
||||||
**Using GUI**
|
Prerequisites:
|
||||||
1. Open a command line in the project folder
|
- JDK 17 or newer
|
||||||
2. Run the command: `./gradlew build`
|
|
||||||
3. The compiled jar file will be in the folder `fabric/build/libs/` and `forge/build/libs/`
|
|
||||||
|
|
||||||
**If in terminal:**
|
From the File Explorer:
|
||||||
1. `git clone -b 1.18.X --recurse-submodules https://gitlab.com/jeseibel/minecraft-lod-mod.git`
|
1. Download and extract the project zip
|
||||||
2. `cd minecraft-lod-mod`
|
2. Download the core from https://gitlab.com/distant-horizons-team/distant-horizons-core and extract into a folder called `coreSubProjects`
|
||||||
3. `./gradlew assemble` or `./gradlew build`
|
3. Open a terminal emulator in the project folder (On Windows you can type `cmd` in the title bar)
|
||||||
4. The build should be in `fabric/build/libs/` and `forge/build/libs/`
|
4. Run the commands: `./gradlew assemble` (You may need to use a `.\` on Windows)
|
||||||
|
5. Merge the jars with `./gradlew mergeJars`
|
||||||
|
6. The compiled jar file will be in the folder `Merged`
|
||||||
|
|
||||||
|
From the command line:
|
||||||
|
1. `git clone --recurse-submodules https://gitlab.com/distant-horizons-team/distant-horizons.git`
|
||||||
|
2. `cd distant-horizons`
|
||||||
|
3. `./gradlew assemble`
|
||||||
|
4. `./gradlew mergeJars`
|
||||||
|
5. The compiled jar file will be in the folder `Merged`
|
||||||
|
|
||||||
|
Run tests with: `./gradlew test`
|
||||||
|
|
||||||
|
>Note: You can add the argument `-PmcVer=?` to tell gradle to build a selected MC version instead of having to modify the `gradle.properties` file.\
|
||||||
|
> For example: `./gradlew assemble -PmcVer=1.18.2`
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
|
## Compiling with Docker
|
||||||
|
|
||||||
|
`./compile <version>`
|
||||||
|
|
||||||
|
You can also locally compile the DH jars without a Java environment by using Docker. Where `<version>` is the version of Minecraft to compile for (ie `1.20.1`), or the keyword `all`. See [Versions](#minecraft-and-library-versions) for a list of all supported values.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
## Other commands
|
## Other commands
|
||||||
|
|
||||||
`./gradlew --refresh-dependencies` to refresh local dependencies.
|
`./gradlew --refresh-dependencies` to refresh local dependencies.
|
||||||
|
|
||||||
`./gradlew clean` to reset everything (this does not affect your code) and then start the process again.
|
`./gradlew clean` to delete any compiled code.
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
## Note to self
|
## Note to self
|
||||||
|
|
||||||
The Minecraft source code is NOT added to your workspace in an editable way. Minecraft is treated like a normal Library. Sources are there for documentation and research purposes only.
|
The Minecraft source code is NOT added to your workspace in an editable way. Minecraft is treated like a normal Library. Sources are there for documentation and research purposes only.
|
||||||
|
|
||||||
Source code uses Mojang mappings.
|
Source code uses Mojang mappings & [Parchment](https://parchmentmc.org/) mappings.
|
||||||
|
|
||||||
## Useful commands
|
To generate the source code run `./gradlew genSources` <br>
|
||||||
|
If your IDE fails to auto-detect the source jars when browsing Minecraft classes; manually select the JAR file ending with -sources.jar when prompted by your IDE. <br>
|
||||||
|
(In IntelliJ it's at the top where it says "choose sources" when browsing a Minecraft class)
|
||||||
|
|
||||||
Build only Fabric: `./gradlew fabric:assemble` or `./gradlew fabric:build`\
|
<br>
|
||||||
Build only Forge: `./gradlew fabric:assemble` or `./gradlew forge:build`\
|
|
||||||
Run the Fabric client (for debugging): `./gradlew fabric:runClient`\
|
## Other Useful commands
|
||||||
Run the Forge client (for debugging): `./gradlew forge:runClient`
|
|
||||||
|
Run the standalone jar: `./gradlew run` <br>
|
||||||
|
Build the standalone jar: `./gradlew core:build` <br>
|
||||||
|
Only build Fabric: `./gradlew fabric:assemble` or `./gradlew fabric:build` <br>
|
||||||
|
Only build Forge: `./gradlew forge:assemble` or `./gradlew forge:build` <br>
|
||||||
|
Run the Fabric client (for debugging): `./gradlew fabric:runClient` <br>
|
||||||
|
Run the Forge client (for debugging): `./gradlew forge:runClient` <br>
|
||||||
|
|
||||||
|
To build all versions: `./buildAll` (all builds will end up in the `Merged` folder)
|
||||||
|
|
||||||
|
<br>
|
||||||
|
|
||||||
## Open Source Acknowledgements
|
## Open Source Acknowledgements
|
||||||
|
|
||||||
XZ for Java (data compression)\
|
Forgix (To merge multiple mod versions into one jar) [_Formerly_ [_DHJarMerger_](https://github.com/Ran-helo/DHJarMerger)]\
|
||||||
https://tukaani.org/xz/java.html
|
https://github.com/PacifistMC/Forgix
|
||||||
|
|
||||||
DHJarMerger (To merge multiple mod versions into one jar)\
|
LZ4 for Java (data compression)\
|
||||||
https://github.com/Ran-helo/DHJarMerger
|
https://github.com/lz4/lz4-java
|
||||||
|
|
||||||
|
NightConfig for JSON & TOML (config handling)\
|
||||||
|
https://github.com/TheElectronWill/night-config
|
||||||
|
|
||||||
|
SVG Salamander for SVG support (not being used atm)\
|
||||||
|
https://github.com/blackears/svgSalamander
|
||||||
|
|
||||||
|
sqlite-jdbc\
|
||||||
|
https://github.com/xerial/sqlite-jdbc
|
||||||
|
|||||||
+4
-147
@@ -1,151 +1,8 @@
|
|||||||
import io.github.ran.jarmerger.JarMergerPlugin
|
|
||||||
|
|
||||||
buildscript {
|
|
||||||
dependencies{
|
|
||||||
classpath files('plugins/DHJarMerger-1.0.jar')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id "architectury-plugin" version "3.4-SNAPSHOT"
|
id 'root'
|
||||||
id "dev.architectury.loom" version "0.10.0-SNAPSHOT" apply false
|
id 'io.github.pacifistmc.forgix' version '2.+'
|
||||||
}
|
}
|
||||||
|
|
||||||
apply plugin: JarMergerPlugin
|
forgix {
|
||||||
|
autoRun = true
|
||||||
architectury {
|
|
||||||
minecraft = rootProject.minecraft_version
|
|
||||||
}
|
|
||||||
|
|
||||||
subprojects { p ->
|
|
||||||
apply plugin: "dev.architectury.loom"
|
|
||||||
|
|
||||||
loom {
|
|
||||||
silentMojangMappingsLicense()
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
common
|
|
||||||
shadowMe
|
|
||||||
implementation.extendsFrom shadowMe
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
|
|
||||||
// The following line declares the mojmap mappings
|
|
||||||
mappings loom.officialMojangMappings()
|
|
||||||
|
|
||||||
// Toml
|
|
||||||
implementation("com.electronwill.night-config:toml:${rootProject.toml_version}")
|
|
||||||
|
|
||||||
if (p != project(":forge")) {
|
|
||||||
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
|
|
||||||
// Do NOT use other classes from fabric loader unless working with fabric
|
|
||||||
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (p != project(":core")) {
|
|
||||||
common(project(":core")) { transitive false }
|
|
||||||
shadowMe(project(":core")) { transitive false }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects { p ->
|
|
||||||
apply plugin: "java"
|
|
||||||
apply plugin: "architectury-plugin"
|
|
||||||
apply plugin: "maven-publish"
|
|
||||||
|
|
||||||
archivesBaseName = rootProject.archives_base_name
|
|
||||||
version = rootProject.mod_version
|
|
||||||
group = rootProject.maven_group
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
// used to download and compile dependencies from git repos
|
|
||||||
maven { url 'https://jitpack.io' }
|
|
||||||
|
|
||||||
// Required for importing Modrinth mods
|
|
||||||
maven {
|
|
||||||
name = "Modrinth"
|
|
||||||
url = "https://api.modrinth.com/maven"
|
|
||||||
content {
|
|
||||||
includeGroup "maven.modrinth"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Required for importing CursedForge mods
|
|
||||||
maven {
|
|
||||||
url "https://www.cursemaven.com"
|
|
||||||
content {
|
|
||||||
includeGroup "curse.maven"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// These 2 are for importing mods that arnt on CursedForge, Modrinth, GitHub, GitLab or anywhere opensource
|
|
||||||
flatDir {
|
|
||||||
dirs "${rootDir}/mods/fabric"
|
|
||||||
content {
|
|
||||||
includeGroup "fabric-mod"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
flatDir {
|
|
||||||
dirs "${rootDir}/mods/forge"
|
|
||||||
content {
|
|
||||||
includeGroup "forge-mod"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Put stuff from gradle.properties into the mod info
|
|
||||||
processResources {
|
|
||||||
def resourceTargets = ["fabric.mod.json", "META-INF/mods.toml"] // Location of where to put
|
|
||||||
def intoTargets = ["$buildDir/resources/main/"] // Location of the built resources folder
|
|
||||||
def replaceProperties = [
|
|
||||||
version: mod_version,
|
|
||||||
mod_name: mod_name,
|
|
||||||
authors: mod_authors,
|
|
||||||
description: mod_description,
|
|
||||||
homepage: mod_homepage,
|
|
||||||
source: mod_source,
|
|
||||||
issues: mod_issues
|
|
||||||
] // The left side is what gets replaced in the mod info and the right side is where to get it from in the gradle.properties
|
|
||||||
|
|
||||||
inputs.properties replaceProperties
|
|
||||||
replaceProperties.put 'project', project
|
|
||||||
filesMatching(resourceTargets) {
|
|
||||||
expand replaceProperties
|
|
||||||
}
|
|
||||||
|
|
||||||
intoTargets.each { target ->
|
|
||||||
if (file(target).exists()) {
|
|
||||||
copy {
|
|
||||||
from(sourceSets.main.resources) {
|
|
||||||
include resourceTargets
|
|
||||||
expand replaceProperties
|
|
||||||
}
|
|
||||||
into target
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tasks.withType(JavaCompile) {
|
|
||||||
if (p != project(":core")) {
|
|
||||||
// Minecraft 1.18 (1.18-pre2) upwards uses Java 17.
|
|
||||||
options.release = 17
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
withSourcesJar()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == project(":core") || p == project(":common")) {
|
|
||||||
runClient.enabled = false
|
|
||||||
runServer.enabled = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
echo "==================== Note: All build jars will be in the folder called 'buildAllJars' ===================="
|
||||||
|
mkdir -p buildAllJars
|
||||||
|
rm -rf buildAllJars/*
|
||||||
|
|
||||||
|
# Loop trough everything in the version properties folder
|
||||||
|
for d in versionProperties/*; do
|
||||||
|
# Get the name of the version that is going to be compiled
|
||||||
|
version=$(echo "$d" | sed "s/versionProperties\///" | sed "s/.properties//")
|
||||||
|
|
||||||
|
# Clean out the folders, build it, and merge it
|
||||||
|
# (We could use "./" to run gradlew, but as it is a shell script im going to be running it with the "sh" command)
|
||||||
|
echo "==================== Cleaning workspace to build $version ===================="
|
||||||
|
sh gradlew clean -PmcVer=$version
|
||||||
|
if [ $? != 0 ]; then continue; fi
|
||||||
|
|
||||||
|
echo "====================Building $version ===================="
|
||||||
|
sh gradlew build -PmcVer=$version
|
||||||
|
if [ $? != 0 ]; then continue; fi
|
||||||
|
|
||||||
|
echo "==================== Merging $version ===================="
|
||||||
|
sh gradlew mergeJars -PmcVer=$version
|
||||||
|
if [ $? != 0 ]; then continue; fi
|
||||||
|
|
||||||
|
echo "==================== Moving jar ===================="
|
||||||
|
mv build/merged/*.jar buildAllJars/
|
||||||
|
done
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
@echo off & setlocal enabledelayedexpansion
|
||||||
|
@rem Note for devs: If this script doesnt work, please look at the unix buildAll script
|
||||||
|
@rem This script was originally created on linux, so there may be some problems with this translation
|
||||||
|
|
||||||
|
|
||||||
|
echo ==================== Note: All build jars will be in the folder called 'buildAllJars' ====================
|
||||||
|
mkdir buildAllJars
|
||||||
|
del buildAllJars/*
|
||||||
|
|
||||||
|
@rem Loop trough everything in the version properties folder
|
||||||
|
for %%f in (versionProperties\*) do (
|
||||||
|
@rem Get the name of the version that is going to be compiled
|
||||||
|
set version=%%~nf
|
||||||
|
|
||||||
|
@rem Clean out the folders, build it, and merge it
|
||||||
|
echo ==================== Cleaning workspace to build !version! ====================
|
||||||
|
call .\gradlew.bat clean
|
||||||
|
|
||||||
|
echo ==================== Building !version! ====================
|
||||||
|
call .\gradlew.bat build -PmcVer="!version!"
|
||||||
|
|
||||||
|
echo ==================== Merging !version! ====================
|
||||||
|
call .\gradlew.bat mergeJars -PmcVer="!version!"
|
||||||
|
|
||||||
|
echo ==================== Moving jar ====================
|
||||||
|
move build\merged\*.jar buildAllJars\
|
||||||
|
)
|
||||||
|
|
||||||
|
endlocal
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
plugins {
|
||||||
|
id 'groovy-gradle-plugin'
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
gradlePluginPortal()
|
||||||
|
mavenCentral()
|
||||||
|
maven { url = 'https://maven.wagyourtail.xyz/releases' } // Jvmdowngrader & unimined libs
|
||||||
|
maven { url = 'https://maven.outlands.top/releases' } // Hosts the kappa fork of unimined
|
||||||
|
maven { url = 'https://maven.wagyourtail.xyz/snapshots' } // The manifold gradle plugin we use
|
||||||
|
maven { url = 'https://maven.architectury.dev/' } // Minecraft mod libs
|
||||||
|
maven { url = 'https://maven.fabricmc.net/' } // Fabric
|
||||||
|
maven { url = 'https://maven.neoforged.net/releases/' } // NeoForge
|
||||||
|
maven { url = 'https://maven.minecraftforge.net/' } // Forge
|
||||||
|
maven { url = 'https://repo.spongepowered.org/repository/maven-public/' } // Hosts minecraft libs
|
||||||
|
maven { url = 'https://oss.sonatype.org/content/repositories/snapshots/' } // Hosts a few dependencies we use
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation 'com.gradleup.shadow:shadow-gradle-plugin:9.0.0'
|
||||||
|
implementation 'xyz.wagyourtail.unimined:xyz.wagyourtail.unimined.gradle.plugin:1.4.17-kappa'
|
||||||
|
implementation 'xyz.wagyourtail:manifold-gradle:1.0.0-SNAPSHOT'
|
||||||
|
implementation 'xyz.wagyourtail.jvmdowngrader:xyz.wagyourtail.jvmdowngrader.gradle.plugin:1.3.4'
|
||||||
|
}
|
||||||
@@ -0,0 +1,467 @@
|
|||||||
|
import com.github.jengelman.gradle.plugins.shadow.transformers.ResourceTransformer
|
||||||
|
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
|
||||||
|
import org.apache.tools.zip.ZipEntry
|
||||||
|
import org.apache.tools.zip.ZipOutputStream
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull
|
||||||
|
import java.util.function.Function
|
||||||
|
import java.util.function.Predicate
|
||||||
|
|
||||||
|
// Convention plugin for all MC-facing subprojects (common + loaders).
|
||||||
|
// Common uses this directly; loaders use it via unimined-fabric/forge/neoforge.
|
||||||
|
// IMPORTANT: unimined MUST be applied before shadow/jvmdowngrader
|
||||||
|
// so its afterEvaluate runs first and can modify configs.
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
id 'maven-publish'
|
||||||
|
id 'xyz.wagyourtail.unimined'
|
||||||
|
id 'com.gradleup.shadow'
|
||||||
|
id 'xyz.wagyourtail.manifold'
|
||||||
|
id 'xyz.wagyourtail.jvmdowngrader'
|
||||||
|
}
|
||||||
|
|
||||||
|
def isNotCommonProject = project.name != "common"
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Version Properties ====================
|
||||||
|
|
||||||
|
project.gradle.ext.getProperties().each { prop ->
|
||||||
|
rootProject.ext.set(prop.key, prop.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
manifold {
|
||||||
|
version = rootProject.manifold_version
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Repositories ====================
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven { url "https://libraries.minecraft.net/" }
|
||||||
|
mavenCentral()
|
||||||
|
maven { url "https://repo.enonic.com/public/" }
|
||||||
|
maven { url "https://maven.parchmentmc.org" }
|
||||||
|
maven { url "https://maven.architectury.dev" }
|
||||||
|
maven { url "https://jitpack.io" }
|
||||||
|
maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
|
||||||
|
maven {
|
||||||
|
name = "Modrinth"
|
||||||
|
url = "https://api.modrinth.com/maven"
|
||||||
|
content { includeGroup "maven.modrinth" }
|
||||||
|
}
|
||||||
|
maven {
|
||||||
|
url "https://www.cursemaven.com"
|
||||||
|
content { includeGroup "curse.maven" }
|
||||||
|
}
|
||||||
|
maven { url "https://repo.spongepowered.org/maven/" }
|
||||||
|
maven { url "https://maven.terraformersmc.com/" }
|
||||||
|
maven { url "https://maven.neoforged.net/releases/" }
|
||||||
|
flatDir {
|
||||||
|
dirs "${rootDir}/mods/fabric"
|
||||||
|
content { includeGroup "fabric-mod" }
|
||||||
|
}
|
||||||
|
flatDir {
|
||||||
|
dirs "${rootDir}/mods/quilt"
|
||||||
|
content { includeGroup "quilt-mod" }
|
||||||
|
}
|
||||||
|
flatDir {
|
||||||
|
dirs "${rootDir}/mods/forge"
|
||||||
|
content { includeGroup "forge-mod" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Java Config ====================
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
options.release = rootProject.java_version as Integer
|
||||||
|
options.encoding = "UTF-8"
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
sourceCompatibility = JavaVersion.toVersion(gradle.ext.java_version as Integer)
|
||||||
|
targetCompatibility = JavaVersion.toVersion(gradle.ext.java_version as Integer)
|
||||||
|
withSourcesJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Loader-Only Config ====================
|
||||||
|
|
||||||
|
if (isNotCommonProject) {
|
||||||
|
base { archivesName = rootProject.mod_name }
|
||||||
|
rootProject.ext.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version
|
||||||
|
version = project.name + "-" + rootProject.versionStr
|
||||||
|
group = rootProject.maven_group
|
||||||
|
|
||||||
|
javadoc.title = rootProject.mod_name + "-" + project.name
|
||||||
|
|
||||||
|
tasks.withType(GenerateModuleMetadata).configureEach {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
tasks.withType(Test).configureEach {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
compileTestJava.enabled = false
|
||||||
|
tasks.withType(Sign).configureEach {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
from "LICENSE.txt"
|
||||||
|
manifest {
|
||||||
|
attributes(
|
||||||
|
'Implementation-Title': rootProject.mod_name,
|
||||||
|
'Implementation-Version': rootProject.mod_version,
|
||||||
|
'Multi-Release': true,
|
||||||
|
'Main-Class': 'com.seibel.distanthorizons.core.jar.JarMain',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Unimined Minecraft Config ====================
|
||||||
|
|
||||||
|
unimined.minecraft(sourceSets.main, true) {
|
||||||
|
version gradle.ext.minecraft_version
|
||||||
|
|
||||||
|
if (gradle.ext.minecraft_version.startsWith("1.")) { // 26.1+ doesn't use obfuscation
|
||||||
|
mappings {
|
||||||
|
mojmap()
|
||||||
|
devNamespace "mojmap"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNotCommonProject) {
|
||||||
|
// Mixin remapping and common project wiring
|
||||||
|
unimined.minecraft(sourceSets.main, true) {
|
||||||
|
mods.modImplementation {
|
||||||
|
mixinRemap {
|
||||||
|
reset()
|
||||||
|
enableBaseMixin()
|
||||||
|
enableMixinExtra()
|
||||||
|
}
|
||||||
|
// Some Fabric API modules ship AW in 'named' namespace instead of 'intermediary'
|
||||||
|
catchAWNamespaceAssertion()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":common"))
|
||||||
|
}
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
from project(":common").sourceSets.main.resources
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile).configureEach {
|
||||||
|
source(project(":common").sourceSets.main.allSource)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Common: fabric for compilation + access widener, no jar remapping or runs
|
||||||
|
unimined.minecraft {
|
||||||
|
fabric {
|
||||||
|
loader gradle.ext.fabric_loader_version
|
||||||
|
accessWidener project.file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
|
||||||
|
}
|
||||||
|
defaultRemapJar = false
|
||||||
|
runs.off = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Configurations ====================
|
||||||
|
|
||||||
|
evaluationDependsOn(":core")
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
shadowMe
|
||||||
|
coreProjects
|
||||||
|
shadowMe.extendsFrom(coreProjects)
|
||||||
|
implementation.extendsFrom(shadowMe)
|
||||||
|
|
||||||
|
common
|
||||||
|
implementation.extendsFrom(common)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Dependencies ====================
|
||||||
|
|
||||||
|
// Copy core's compileOnly deps so MC-provided deps are visible without redeclaring them.
|
||||||
|
project(":core").configurations.compileOnly.allDependencies.each { dep ->
|
||||||
|
if (!(dep instanceof ProjectDependency))
|
||||||
|
dependencies.add("compileOnly", dep)
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Manifold preprocessor & strings
|
||||||
|
annotationProcessor(manifold.module("preprocessor"))
|
||||||
|
|
||||||
|
// NightConfig: implementation in core (bundled) but Unimined strips it from compile classpath
|
||||||
|
compileOnly("com.electronwill.night-config:toml:${rootProject.nightconfig_version}")
|
||||||
|
|
||||||
|
// Core & API projects — bundled into shadow jar
|
||||||
|
coreProjects(project(":core"))
|
||||||
|
coreProjects(project(":api"))
|
||||||
|
|
||||||
|
// JOML: shadow for old MC versions that don't bundle it (core has it compileOnly already)
|
||||||
|
if (project.hasProperty("embed_joml") && embed_joml == "true")
|
||||||
|
shadowMe("org.joml:joml:${rootProject.joml_version}")
|
||||||
|
|
||||||
|
// Common project dependency
|
||||||
|
if (isNotCommonProject)
|
||||||
|
common(project(":common")) { transitive false }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== NativeTransformer ====================
|
||||||
|
|
||||||
|
class NativeTransformer implements ResourceTransformer {
|
||||||
|
private Predicate<String> fileMatcher
|
||||||
|
private Function<String, String> filePathMapper
|
||||||
|
|
||||||
|
private final HashMap<String, String> replacements = new HashMap()
|
||||||
|
private final HashMap<String, byte[]> rewrittenFiles = new HashMap()
|
||||||
|
private nativeRelocator
|
||||||
|
|
||||||
|
public File rootDir
|
||||||
|
|
||||||
|
void matchFiles(Predicate<String> matcher) {
|
||||||
|
fileMatcher = matcher
|
||||||
|
}
|
||||||
|
|
||||||
|
void mapPaths(Function<String, String> mapper) {
|
||||||
|
filePathMapper = mapper
|
||||||
|
}
|
||||||
|
|
||||||
|
void relocateNative(String target, String replacement) {
|
||||||
|
if (replacement.length() > target.length()) {
|
||||||
|
throw new GradleException("Length of value \"${replacement}\" exceeds the length of \"${target}\": ${replacement.length()} > ${target.length()}")
|
||||||
|
}
|
||||||
|
replacements.put(target, replacement)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean canTransformResource(@Nonnull FileTreeElement element) {
|
||||||
|
return fileMatcher != null && fileMatcher.test(element.relativePath.pathString)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void transform(@Nonnull TransformerContext context) {
|
||||||
|
byte[] content = context.inputStream.readAllBytes()
|
||||||
|
|
||||||
|
if (nativeRelocator == null) {
|
||||||
|
nativeRelocator = new NativeRelocator(rootDir.toPath().resolve("relocate_natives"))
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
String path = filePathMapper != null
|
||||||
|
? filePathMapper.apply(context.path)
|
||||||
|
: context.path
|
||||||
|
content = nativeRelocator.processBinary(path, content, replacements)
|
||||||
|
rewrittenFiles.put(path, content)
|
||||||
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
throw new GradleException("Failed to relocate", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
boolean hasTransformedResource() { return !rewrittenFiles.isEmpty() }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void modifyOutputStream(@Nonnull ZipOutputStream os, boolean preserveFileTimestamps) {
|
||||||
|
for (Map.Entry<String, byte[]> rewrittenFile : rewrittenFiles.entrySet()) {
|
||||||
|
os.putNextEntry(new ZipEntry(rewrittenFile.key))
|
||||||
|
os.write(rewrittenFile.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Shadow JAR (loaders only) ====================
|
||||||
|
|
||||||
|
if (isNotCommonProject) {
|
||||||
|
shadowJar {
|
||||||
|
configurations = [project.configurations.shadowMe]
|
||||||
|
relocate "com.seibel.distanthorizons.common", "loaderCommon.${project.name}.com.seibel.distanthorizons.common"
|
||||||
|
def librariesLocation = "DistantHorizons.libraries"
|
||||||
|
|
||||||
|
// LZ4
|
||||||
|
relocate "net.jpountz", "${librariesLocation}.jpountz"
|
||||||
|
|
||||||
|
// SLF4J
|
||||||
|
relocate "org.slf4j", "${librariesLocation}.slf4j"
|
||||||
|
|
||||||
|
// SQLite
|
||||||
|
relocate "org.sqlite", "dh_sqlite", { exclude "org/sqlite/native/**" }
|
||||||
|
relocate "jdbc:sqlite", "jdbc:dh_sqlite"
|
||||||
|
|
||||||
|
transform(NativeTransformer) {
|
||||||
|
rootDir = project.rootDir
|
||||||
|
matchFiles { it.startsWith("org/sqlite") }
|
||||||
|
mapPaths { it.replace("org/sqlite", "dh_sqlite") }
|
||||||
|
relocateNative "org/sqlite", "dh_sqlite"
|
||||||
|
relocateNative "org_sqlite", "dh_1sqlite"
|
||||||
|
}
|
||||||
|
|
||||||
|
// ZStd
|
||||||
|
relocate "com.github.luben", "dhcomgithubluben"
|
||||||
|
relocate "libzstd-jni", "libzstd-jni_dh"
|
||||||
|
relocate "zstd-jni", "zstd-jni_dh"
|
||||||
|
|
||||||
|
transform(NativeTransformer) {
|
||||||
|
rootDir = project.rootDir
|
||||||
|
matchFiles { it.contains("libzstd-jni") && !it.contains("aix/ppc64") }
|
||||||
|
mapPaths { it.replace("libzstd-jni", "libzstd-jni_dh") }
|
||||||
|
relocateNative "com/github/luben", "dhcomgithubluben"
|
||||||
|
relocateNative "com_github_luben", "dhcomgithubluben"
|
||||||
|
}
|
||||||
|
|
||||||
|
// JOML (conditional)
|
||||||
|
if (project.hasProperty("embed_joml") && embed_joml == "true")
|
||||||
|
relocate "org.joml", "${librariesLocation}.joml"
|
||||||
|
|
||||||
|
// NightConfig
|
||||||
|
relocate "com.electronwill.nightconfig", "${librariesLocation}.electronwill.nightconfig"
|
||||||
|
|
||||||
|
mergeServiceFiles()
|
||||||
|
}
|
||||||
|
afterEvaluate {
|
||||||
|
tasks.named("remapJar").configure {
|
||||||
|
dependsOn(shadowJar)
|
||||||
|
inputFile.set(shadowJar.archiveFile)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make run tasks use the shadow jar so relocated deps work in dev.
|
||||||
|
// Filter out jars bundled in the shadow jar, but keep jars that the loader also
|
||||||
|
// needs (e.g. NightConfig — DH relocates it, but NeoForge needs the original).
|
||||||
|
def shadowedPaths = configurations.shadowMe.resolve().collect { it.path }.toSet()
|
||||||
|
def loaderPaths = configurations.minecraftLibraries.resolve().collect { it.path }.toSet()
|
||||||
|
tasks.withType(JavaExec).configureEach { runTask ->
|
||||||
|
dependsOn(shadowJar)
|
||||||
|
classpath = files(shadowJar.archiveFile) + classpath.filter { file ->
|
||||||
|
!file.path.contains(project.buildDir.path) &&
|
||||||
|
!file.path.contains("core${File.separator}build") &&
|
||||||
|
!file.path.contains("api${File.separator}build") &&
|
||||||
|
!file.path.contains("common${File.separator}build") &&
|
||||||
|
!(shadowedPaths.contains(file.path) && !loaderPaths.contains(file.path))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shared run directory so all loaders use the same worlds
|
||||||
|
def isClient = runTask.name.toLowerCase().contains("client")
|
||||||
|
runTask.workingDir = rootProject.file("run/${isClient ? 'client' : 'server'}")
|
||||||
|
|
||||||
|
// JVM args
|
||||||
|
runTask.jvmArgs(
|
||||||
|
"-Dio.netty.leakDetection.level=advanced",
|
||||||
|
//"-XX:+UseZGC",
|
||||||
|
//"-XX:+ZGenerational",
|
||||||
|
)
|
||||||
|
if (isClient) {
|
||||||
|
runTask.jvmArgs(
|
||||||
|
"-Dminecraft.api.auth.host=https://nope.invalid",
|
||||||
|
"-Dminecraft.api.account.host=https://nope.invalid",
|
||||||
|
"-Dminecraft.api.session.host=https://nope.invalid",
|
||||||
|
"-Dminecraft.api.services.host=https://nope.invalid",
|
||||||
|
)
|
||||||
|
runTask.args("--username", "Dev", "--renderDebugLabels", "--tracy")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Process Resources (loaders only) ====================
|
||||||
|
|
||||||
|
if (isNotCommonProject) {
|
||||||
|
processResources {
|
||||||
|
def resourceTargets = [
|
||||||
|
"build_info.json",
|
||||||
|
"fabric.mod.json",
|
||||||
|
"quilt.mod.json",
|
||||||
|
"META-INF/mods.toml",
|
||||||
|
"META-INF/neoforge.mods.toml",
|
||||||
|
]
|
||||||
|
|
||||||
|
def compatible_forgemc_versions = "${rootProject.compatible_minecraft_versions}".replaceAll("\"", "").replaceAll("]", ",)")
|
||||||
|
|
||||||
|
// Quilt contributors
|
||||||
|
def quilt_contributors = []
|
||||||
|
def mod_author_list = rootProject.mod_authors.replaceAll("\"", "").replace("[", "").replace("]", "").split(",")
|
||||||
|
for (dev in mod_author_list) {
|
||||||
|
quilt_contributors.push("\"${dev.strip()}\": \"Developer\"")
|
||||||
|
}
|
||||||
|
quilt_contributors.reverse()
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (rootProject.infoGitCommit == "null")
|
||||||
|
rootProject.ext.infoGitCommit = 'git rev-parse --verify HEAD'.execute().text.trim()
|
||||||
|
if (rootProject.infoGitBranch == "null")
|
||||||
|
rootProject.ext.infoGitBranch = 'git symbolic-ref --short HEAD'.execute().text.trim()
|
||||||
|
} catch (Exception e) {
|
||||||
|
rootProject.ext.infoGitCommit = "Git not found"
|
||||||
|
rootProject.ext.infoGitBranch = "Git not found"
|
||||||
|
}
|
||||||
|
|
||||||
|
def replaceProperties = [
|
||||||
|
version : rootProject.mod_version,
|
||||||
|
mod_name : rootProject.mod_readable_name,
|
||||||
|
group : rootProject.maven_group,
|
||||||
|
authors : rootProject.mod_authors,
|
||||||
|
description : rootProject.mod_description,
|
||||||
|
homepage : rootProject.mod_homepage,
|
||||||
|
source : rootProject.mod_source,
|
||||||
|
issues : rootProject.mod_issues,
|
||||||
|
discord : rootProject.mod_discord,
|
||||||
|
minecraft_version : rootProject.minecraft_version,
|
||||||
|
compatible_minecraft_versions: rootProject.compatible_minecraft_versions,
|
||||||
|
compatible_forgemc_versions : compatible_forgemc_versions,
|
||||||
|
java_version : rootProject.java_version,
|
||||||
|
quilt_contributors : "{" + quilt_contributors.join(", ") + "}",
|
||||||
|
info_git_commit : rootProject.infoGitBranch,
|
||||||
|
info_git_branch : rootProject.infoGitCommit,
|
||||||
|
info_build_source : rootProject.infoBuildSource,
|
||||||
|
fabric_incompatibility_list : rootProject.fabric_incompatibility_list,
|
||||||
|
fabric_recommend_list : rootProject.fabric_recommend_list,
|
||||||
|
neoforge_version_range : rootProject.neoforge_version_range,
|
||||||
|
]
|
||||||
|
|
||||||
|
inputs.properties replaceProperties
|
||||||
|
replaceProperties.put "project", project
|
||||||
|
filesMatching(resourceTargets) {
|
||||||
|
expand replaceProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove unused access wideners
|
||||||
|
exclude { file ->
|
||||||
|
if (file.name.contains(".distanthorizons.accesswidener") && file.name != "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== Resource Copy Tasks ====================
|
||||||
|
|
||||||
|
task copyCommonLoaderResources(type: Copy) {
|
||||||
|
from project(":common").file("src/main/resources/${rootProject.accessWidenerVersion}.distanthorizons.accesswidener")
|
||||||
|
into(file(project.file("build/resources/main")))
|
||||||
|
rename "${rootProject.accessWidenerVersion}.distanthorizons.accesswidener", "distanthorizons.accesswidener"
|
||||||
|
}
|
||||||
|
|
||||||
|
task copyCoreResources(type: Copy) {
|
||||||
|
from fileTree(project(":core").file("src/main/resources"))
|
||||||
|
into project.file("build/resources/main")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ==================== JVMDowngrader ====================
|
||||||
|
|
||||||
|
jvmdg.downgradeTo = JavaVersion.toVersion(rootProject.java_version)
|
||||||
|
downgradeJar.archiveClassifier.set(null)
|
||||||
|
shadeDowngradedApi.archiveClassifier.set(null)
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer version properties from settings.gradle to project
|
||||||
|
project.gradle.ext.getProperties().each { prop ->
|
||||||
|
rootProject.ext.set(prop.key, prop.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Version string for archives
|
||||||
|
rootProject.ext.versionStr = rootProject.mod_version + "-" + rootProject.minecraft_version
|
||||||
|
rootProject.allprojects {
|
||||||
|
version = (it == rootProject ? "" : it.name + "-") + rootProject.versionStr
|
||||||
|
group = rootProject.maven_group
|
||||||
|
|
||||||
|
// Custom javadoc tags for all subprojects
|
||||||
|
plugins.withType(JavaPlugin) {
|
||||||
|
javadoc {
|
||||||
|
options.tags(
|
||||||
|
'todo:X"',
|
||||||
|
'apiNote:a:API Note:',
|
||||||
|
'implSpec:a:Implementation Requirements:',
|
||||||
|
'implNote:a:Implementation Note:'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create build.properties with preprocessor definitions
|
||||||
|
def writePreprocessorDefinitions() {
|
||||||
|
StringBuilder sb = new StringBuilder()
|
||||||
|
sb.append("# DON'T TOUCH THIS FILE, This is handled by the build script\n")
|
||||||
|
|
||||||
|
gradle.ext.mcVers.eachWithIndex { ver, idx ->
|
||||||
|
sb.append("MC_${ver.replace('.', '_')}=${idx}\n")
|
||||||
|
if (gradle.ext.mcIndex == idx)
|
||||||
|
sb.append("MC_VER=${idx}\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rootProject.mod_version.toLowerCase().contains("dev")) {
|
||||||
|
sb.append("DEV_BUILD=\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
new File(rootDir, "build.properties").text = sb.toString()
|
||||||
|
}
|
||||||
|
writePreprocessorDefinitions()
|
||||||
|
|
||||||
|
// Wire JVMDowngrader to process remapped jars
|
||||||
|
gradle.projectsEvaluated {
|
||||||
|
rootProject.subprojects.each {
|
||||||
|
if (it.tasks.findByName('remapJar') == null) return
|
||||||
|
it.tasks.downgradeJar.inputFile = it.tasks.remapJar.archiveFile
|
||||||
|
it.tasks.jar.finalizedBy(it.tasks.remapJar)
|
||||||
|
it.tasks.remapJar.finalizedBy(it.tasks.shadeDowngradedApi)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
plugins {
|
||||||
|
id 'dh-loader'
|
||||||
|
}
|
||||||
|
|
||||||
|
unimined.minecraft {
|
||||||
|
fabric {
|
||||||
|
loader gradle.ext.fabric_loader_version
|
||||||
|
accessWidener project(":common").file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runClient.javaLauncher = null
|
||||||
|
runServer.javaLauncher = null
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
plugins {
|
||||||
|
id 'dh-loader'
|
||||||
|
}
|
||||||
|
|
||||||
|
def awFile = project(":common").file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
|
||||||
|
|
||||||
|
unimined.minecraft {
|
||||||
|
forge {
|
||||||
|
loader gradle.ext.forge_version
|
||||||
|
useToolchains = false
|
||||||
|
mixinConfig("DistantHorizons.forge.mixins.json")
|
||||||
|
accessTransformer aw2at(awFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runClient.javaLauncher = null
|
||||||
|
runServer.javaLauncher = null
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
plugins {
|
||||||
|
id 'dh-loader'
|
||||||
|
}
|
||||||
|
|
||||||
|
def awFile = project(":common").file("src/main/resources/${gradle.ext.accessWidenerVersion}.distanthorizons.accesswidener")
|
||||||
|
|
||||||
|
unimined.minecraft {
|
||||||
|
neoForged {
|
||||||
|
loader gradle.ext.neoforge_version
|
||||||
|
useToolchains = false
|
||||||
|
accessTransformer aw2at(awFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
runClient.javaLauncher = null
|
||||||
|
runServer.javaLauncher = null
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
import java.io.*;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class AWToAT {
|
||||||
|
private static final Map<String, String> ACCESS_POINT_MAP = new HashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
ACCESS_POINT_MAP.put("accessible", "public");
|
||||||
|
ACCESS_POINT_MAP.put("extendable", "public-f");
|
||||||
|
ACCESS_POINT_MAP.put("mutable", "public-f");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String minecraftVersion;
|
||||||
|
|
||||||
|
public File remap(File file, String minecraftVersion) {
|
||||||
|
this.minecraftVersion = minecraftVersion.replace("_", ".");
|
||||||
|
File atFile = createATFile(file);
|
||||||
|
processFile(file, atFile);
|
||||||
|
return atFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private File createATFile(File file) {
|
||||||
|
File metaInf = new File(file.getParentFile(), "META-INF");
|
||||||
|
if (!metaInf.exists() && !metaInf.mkdir()) throw new RuntimeException("Error creating META-INF folder");
|
||||||
|
File atFile = new File(metaInf, "accesstransformer.cfg");
|
||||||
|
try {
|
||||||
|
atFile.createNewFile();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("Error creating new file", e);
|
||||||
|
}
|
||||||
|
return atFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processFile(File file, File atFile) {
|
||||||
|
/* Validates if we need to recreate the Access Transformer file if it's out of date */
|
||||||
|
// Get the hash of the file
|
||||||
|
String fileHash = getFileHash(file);
|
||||||
|
try (Scanner atScanner = new Scanner(atFile)) {
|
||||||
|
// Check if the AT file is up-to-date by comparing the hash of the file with the hash stored in the AT file
|
||||||
|
boolean hashFound = false;
|
||||||
|
while (atScanner.hasNextLine()) {
|
||||||
|
String line = atScanner.nextLine();
|
||||||
|
if (hashCheck(line, fileHash)) {
|
||||||
|
hashFound = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the AT file is up-to-date, print a message and return
|
||||||
|
if (hashFound) {
|
||||||
|
System.out.println("Access Transformer file is already up to date.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (FileNotFoundException ignored) {
|
||||||
|
// If the AT file does not exist, continue
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Creates the Access Transformer file */
|
||||||
|
// Opens a scanner for reading the Access Widener file and a writer for writing to the Access Transformer file
|
||||||
|
try (Scanner scanner = new Scanner(file); FileWriter writer = new FileWriter(atFile)) {
|
||||||
|
// Create an ExecutorService with a fixed thread pool size equal to the number of available processors
|
||||||
|
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||||
|
// List to hold Future objects representing results of computation
|
||||||
|
List<Future<String>> futures = new ArrayList<>();
|
||||||
|
|
||||||
|
// Write the hash of the file to the AT file
|
||||||
|
writer.write("#DH_MAPPING_HASH:" + fileHash + "\n");
|
||||||
|
|
||||||
|
// Read each line from the file
|
||||||
|
while (scanner.hasNextLine()) {
|
||||||
|
String line = scanner.nextLine();
|
||||||
|
// Skip lines starting with "accessWidener", "#" or blank lines
|
||||||
|
if (line.startsWith("accessWidener") || line.startsWith("#") || line.isBlank()) continue;
|
||||||
|
|
||||||
|
// Submit the line to the executor service for processing
|
||||||
|
// The processing is done by the processLine method
|
||||||
|
futures.add(executor.submit(() -> processLine(line.split(" "))));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write the results to the output file
|
||||||
|
// The results are obtained by calling the get method on each Future
|
||||||
|
for (Future<String> future : futures) {
|
||||||
|
writer.write(future.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shutdown the executor service to free up resources
|
||||||
|
executor.shutdown();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error reading or writing to file", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String processLine(String[] fields) {
|
||||||
|
// fields[0] = access point like "accessible", "extendable", "mutable"
|
||||||
|
// fields[1] = type like "field", "method", "class"
|
||||||
|
// fields[2] = class name
|
||||||
|
// fields[3] = field/method name
|
||||||
|
// fields[4] = field/method descriptor
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Store the original field/method name
|
||||||
|
String originalName = "";
|
||||||
|
|
||||||
|
// If there is a class name, replace the slashes with dots in the package name
|
||||||
|
if (fields.length > 2) fields[2] = fields[2].replace("/", ".");
|
||||||
|
|
||||||
|
// If there is a field/method name, store the original name and remap it to SRG
|
||||||
|
if (fields.length > 3) {
|
||||||
|
originalName = fields[3];
|
||||||
|
fields[3] = remapToSRG(fields[2], fields[3]);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder line = new StringBuilder(ACCESS_POINT_MAP.getOrDefault(fields[0], "public")).append(" ");
|
||||||
|
switch (fields[1]) {
|
||||||
|
case "field":
|
||||||
|
line.append(fields[2]).append(" ").append(fields[3]).append(" #").append(originalName);
|
||||||
|
// It'll be like: access-point class-name field-name-SRG # field-name-Mojmap
|
||||||
|
// Eg: public net.minecraft.client.Minecraft f_90981_ # instance
|
||||||
|
break;
|
||||||
|
case "method":
|
||||||
|
line.append(fields[2]).append(" ").append(fields[3]).append(fields[4]).append(" #").append(originalName);
|
||||||
|
// It'll be like: access-point class-name method-name-SRG method-descriptor # method-name-Mojmap
|
||||||
|
// Eg: public net.minecraft.client.Minecraft m_172797_()Lnet/minecraft/client/Minecraft; # getInstance
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
line.append(fields[2]);
|
||||||
|
// It'll be like: access-point class-name
|
||||||
|
// Eg: public net.minecraft.client.Minecraft
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
line.append("\n");
|
||||||
|
return line.toString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error processing line", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean hashCheck(String line, String fileHash) {
|
||||||
|
if (line.startsWith("#DH_MAPPING_HASH:")) {
|
||||||
|
String hash = line.substring(17);
|
||||||
|
return hash.equals(fileHash);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFileHash(File file) {
|
||||||
|
try {
|
||||||
|
MessageDigest shaDigest = MessageDigest.getInstance("SHA-256");
|
||||||
|
try (InputStream fis = new FileInputStream(file)) {
|
||||||
|
byte[] byteArray = new byte[1024];
|
||||||
|
int bytesCount;
|
||||||
|
|
||||||
|
// Read file data and update in message digest
|
||||||
|
while ((bytesCount = fis.read(byteArray)) != -1) {
|
||||||
|
shaDigest.update(byteArray, 0, bytesCount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] bytes = shaDigest.digest();
|
||||||
|
|
||||||
|
// Convert byte array into signum representation
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (byte aByte : bytes) {
|
||||||
|
sb.append(Integer.toString((aByte & 0xff) + 0x100, 16).substring(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return complete hash
|
||||||
|
return sb.toString();
|
||||||
|
} catch (NoSuchAlgorithmException | IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// WARNING: BELOW LIES HIGHLY CURSED CODE AND MIGHT EVEN BE ILLEGAL
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Flag to track if there was an error in the GET request
|
||||||
|
boolean error = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns a field or method name from Mojang mappings as SRG mappings.
|
||||||
|
* It makes a GET request to the Linkie API to fetch the SRG name.
|
||||||
|
*
|
||||||
|
* @param clazz The class name
|
||||||
|
* @param name The field or method name
|
||||||
|
* @return The SRG name
|
||||||
|
* @throws Exception If there is an error in the GET request or the SRG name is not found in the response
|
||||||
|
*/
|
||||||
|
private String remapToSRG(String clazz, String name) throws Exception {
|
||||||
|
// Encode the class and field/method name to be used in the URL
|
||||||
|
String query = URLEncoder.encode(clazz + "." + name, StandardCharsets.UTF_8);
|
||||||
|
// Construct the URL for the GET request
|
||||||
|
String urlString = "https://linkieapi.shedaniel.me/api/search?namespace=mojang&query=" + query + "&version=" + this.minecraftVersion + "&limit=1&allowClasses=false&allowFields=true&allowMethods=true&translate=mojang_srg";
|
||||||
|
URL url = new URI(urlString).toURL();
|
||||||
|
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
|
||||||
|
conn.setRequestMethod("GET");
|
||||||
|
int responseCode = conn.getResponseCode();
|
||||||
|
if (responseCode == HttpURLConnection.HTTP_OK) {
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
|
||||||
|
String inputLine;
|
||||||
|
StringBuilder content = new StringBuilder();
|
||||||
|
// Read the response line by line
|
||||||
|
while ((inputLine = in.readLine()) != null) {
|
||||||
|
content.append(inputLine);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
conn.disconnect();
|
||||||
|
// Regex to find the SRG name in the response
|
||||||
|
Pattern pattern = Pattern.compile("\"l\"\\s*:\\s*\\{[^}]*\"i\"\\s*:\\s*\"([^\"]*)\"");
|
||||||
|
Matcher matcher = pattern.matcher(content.toString());
|
||||||
|
if (matcher.find()) return matcher.group(1);
|
||||||
|
else throw new Exception("Couldn't find the SRG mapping for name: " + name + "\nCould not find 'i' in 'l' object in the response"); // `i` is the SRG name which is stored in the `l` JSON object
|
||||||
|
} else {
|
||||||
|
if (error) {
|
||||||
|
// If there was an error in the GET request, and we already tried again, throw an exception
|
||||||
|
throw new Exception("The GET request failed");
|
||||||
|
}
|
||||||
|
// If there was an error in the GET request, wait 2.5 seconds and try again as we probably got rate limited
|
||||||
|
error = true;
|
||||||
|
Thread.sleep(2500);
|
||||||
|
return remapToSRG(clazz, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,214 @@
|
|||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
class NativeRelocator
|
||||||
|
{
|
||||||
|
private final Path rootDirectory;
|
||||||
|
private final Path cacheRoot;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the NativeRelocator by preparing the environment if necessary.
|
||||||
|
* Executes the appropriate preparation script based on the OS.
|
||||||
|
*/
|
||||||
|
NativeRelocator(Path rootDirectory)
|
||||||
|
{
|
||||||
|
this.rootDirectory = rootDirectory;
|
||||||
|
this.cacheRoot = this.rootDirectory.resolve("cache");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void prepare() throws Exception
|
||||||
|
{
|
||||||
|
if (this.rootDirectory.resolve(".venv").toFile().exists())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||||
|
processBuilder.directory(this.rootDirectory.toFile());
|
||||||
|
|
||||||
|
String os = System.getProperty("os.name").toLowerCase();
|
||||||
|
if (os.contains("win"))
|
||||||
|
{
|
||||||
|
processBuilder.command("powershell", "-ExecutionPolicy", "Bypass", "./prepare.ps1");
|
||||||
|
}
|
||||||
|
else if (os.contains("nix")
|
||||||
|
|| os.contains("nux")
|
||||||
|
|| os.contains("mac")
|
||||||
|
|| os.contains("freebsd"))
|
||||||
|
{
|
||||||
|
processBuilder.command("./prepare.sh");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Unsupported operating system: " + os);
|
||||||
|
}
|
||||||
|
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
CompletableFuture<Void> outputFuture = readOutputStreams(process);
|
||||||
|
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
outputFuture.get();
|
||||||
|
|
||||||
|
if (exitCode != 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Prepare failed: " + exitCode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads and prints the output and error streams of a process asynchronously.
|
||||||
|
*
|
||||||
|
* @param process The process whose streams should be read.
|
||||||
|
* @return A CompletableFuture that completes once all output has been processed.
|
||||||
|
*/
|
||||||
|
private static CompletableFuture<Void> readOutputStreams(Process process)
|
||||||
|
{
|
||||||
|
return CompletableFuture.runAsync(() -> {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (process.isAlive() || process.getInputStream().available() > 0 || process.getErrorStream().available() > 0)
|
||||||
|
{
|
||||||
|
if (process.getInputStream().available() > 0)
|
||||||
|
{
|
||||||
|
byte[] data = new byte[process.getInputStream().available()];
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
process.getInputStream().read(data);
|
||||||
|
System.out.write(data);
|
||||||
|
}
|
||||||
|
if (process.getErrorStream().available() > 0)
|
||||||
|
{
|
||||||
|
byte[] data = new byte[process.getErrorStream().available()];
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
process.getErrorStream().read(data);
|
||||||
|
System.err.write(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection BusyWait
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable ignored)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces occurrences of a target string in a byte array, ensuring null termination.
|
||||||
|
*
|
||||||
|
* @param byteArray The byte array where replacements should occur.
|
||||||
|
* @param target The string to replace.
|
||||||
|
* @param replacement The replacement string (must not be longer than the target).
|
||||||
|
* @throws IllegalArgumentException if the replacement is longer than the target.
|
||||||
|
*/
|
||||||
|
private void replaceInNullTerminatedStrings(byte[] byteArray, String target, String replacement)
|
||||||
|
{
|
||||||
|
if (target.length() < replacement.length())
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Replacement must be the same length or shorter than the target.");
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] targetBytes = target.getBytes(StandardCharsets.US_ASCII);
|
||||||
|
byte[] replacementBytes = replacement.getBytes(StandardCharsets.US_ASCII);
|
||||||
|
|
||||||
|
byte nullByte = 0;
|
||||||
|
|
||||||
|
for (int endPos = 0; endPos < byteArray.length - targetBytes.length - 1; endPos++)
|
||||||
|
{
|
||||||
|
int startPos = endPos;
|
||||||
|
int targetPos = 0;
|
||||||
|
while (targetPos < targetBytes.length && byteArray[endPos] == targetBytes[targetPos])
|
||||||
|
{
|
||||||
|
targetPos++;
|
||||||
|
endPos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetPos == targetBytes.length)
|
||||||
|
{
|
||||||
|
System.arraycopy(replacementBytes, 0, byteArray, startPos, replacementBytes.length);
|
||||||
|
|
||||||
|
startPos = startPos + replacementBytes.length;
|
||||||
|
while (byteArray[endPos] != nullByte)
|
||||||
|
{
|
||||||
|
byteArray[startPos] = byteArray[endPos];
|
||||||
|
endPos++;
|
||||||
|
startPos++;
|
||||||
|
}
|
||||||
|
byteArray[startPos] = nullByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runs an external script to fix a modified binary and returns the processed content.
|
||||||
|
*
|
||||||
|
* @param outputFilePath Path to store the processed binary.
|
||||||
|
* @param content The original binary content.
|
||||||
|
* @return The modified binary content.
|
||||||
|
* @throws Exception if the process execution fails.
|
||||||
|
*/
|
||||||
|
public byte[] fixModifiedBinary(Path outputFilePath, byte[] content) throws Exception
|
||||||
|
{
|
||||||
|
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||||
|
processBuilder.directory(this.rootDirectory.toFile());
|
||||||
|
|
||||||
|
processBuilder.command(
|
||||||
|
this.rootDirectory.resolve(".venv/Scripts").toFile().exists()
|
||||||
|
? this.rootDirectory.resolve(".venv/Scripts/python.exe").toString()
|
||||||
|
: this.rootDirectory.resolve(".venv/bin/python").toString(),
|
||||||
|
"./fix_modified_binary.py",
|
||||||
|
outputFilePath.toString()
|
||||||
|
);
|
||||||
|
|
||||||
|
Process process = processBuilder.start();
|
||||||
|
CompletableFuture<Void> outputFuture = readOutputStreams(process);
|
||||||
|
|
||||||
|
process.getOutputStream().write(content);
|
||||||
|
process.getOutputStream().close();
|
||||||
|
|
||||||
|
int exitCode = process.waitFor();
|
||||||
|
outputFuture.get();
|
||||||
|
|
||||||
|
if (exitCode != 0)
|
||||||
|
{
|
||||||
|
throw new Exception("Process failed: " + exitCode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Files.readAllBytes(outputFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Processes a binary file, applying string replacements and fixing modifications.
|
||||||
|
*
|
||||||
|
* @param outputPath The output file path relative to the cache directory.
|
||||||
|
* @param content The binary content to process.
|
||||||
|
* @param replacements A map of string replacements to apply.
|
||||||
|
* @return The modified binary content.
|
||||||
|
* @throws Exception if processing fails.
|
||||||
|
*/
|
||||||
|
public byte[] processBinary(String outputPath, byte[] content, Map<String, String> replacements) throws Exception
|
||||||
|
{
|
||||||
|
Path outputFilePath = this.cacheRoot.resolve(outputPath);
|
||||||
|
//noinspection ResultOfMethodCallIgnored
|
||||||
|
outputFilePath.getParent().toFile().mkdirs();
|
||||||
|
|
||||||
|
if (outputFilePath.toFile().exists())
|
||||||
|
{
|
||||||
|
return Files.readAllBytes(outputFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("Relocating to " + outputPath + "...");
|
||||||
|
this.prepare();
|
||||||
|
|
||||||
|
for (Map.Entry<String, String> replacement : replacements.entrySet())
|
||||||
|
{
|
||||||
|
this.replaceInNullTerminatedStrings(content, replacement.getKey(), replacement.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.fixModifiedBinary(outputFilePath, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
|
||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as
|
||||||
|
contributors and maintainers pledge to make participation in our project and
|
||||||
|
our community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, disability, ethnicity, sex characteristics, gender identity and expression,
|
||||||
|
level of experience, education, socio-economic status, nationality, personal
|
||||||
|
appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment
|
||||||
|
include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||||
|
advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic
|
||||||
|
address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable
|
||||||
|
behavior and are expected to take appropriate and fair corrective action in
|
||||||
|
response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or
|
||||||
|
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||||
|
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||||
|
permanently any contributor for other behaviors that they deem inappropriate,
|
||||||
|
threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all project spaces, and it also applies when
|
||||||
|
an individual is representing the project or its community in public spaces.
|
||||||
|
Examples of representing a project or community include using an official
|
||||||
|
project e-mail address, posting via an official social media account, or acting
|
||||||
|
as an appointed representative at an online or offline event. Representation of
|
||||||
|
a project may be further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported by contacting the team lead James Seibel through Discord at `@backsun`. All
|
||||||
|
complaints will be reviewed and investigated and will result in a response that
|
||||||
|
is deemed necessary and appropriate to the circumstances. The project team is
|
||||||
|
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||||
|
Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||||
|
faith may face temporary or permanent repercussions as determined by other
|
||||||
|
members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||||
|
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see
|
||||||
|
https://www.contributor-covenant.org/faq
|
||||||
|
|
||||||
+2
-28
@@ -1,29 +1,3 @@
|
|||||||
loom {
|
plugins {
|
||||||
accessWidenerPath.set(file("src/main/resources/lod.accesswidener"))
|
id 'dh-loader'
|
||||||
}
|
|
||||||
|
|
||||||
architectury {
|
|
||||||
common()
|
|
||||||
}
|
|
||||||
|
|
||||||
afterEvaluate {
|
|
||||||
tasks {
|
|
||||||
remapJar {
|
|
||||||
remapAccessWidener.set(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
publications {
|
|
||||||
mavenCommon(MavenPublication) {
|
|
||||||
artifactId = rootProject.archives_base_name
|
|
||||||
from components.java
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
|
||||||
repositories {
|
|
||||||
// Add repositories to publish to here.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,414 @@
|
|||||||
|
package com.seibel.distanthorizons.common;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiRenderApi;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDhInitEvent;
|
||||||
|
import com.seibel.distanthorizons.common.commands.CommandInitializer;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.DependencySetup;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.gui.DhDebugScreenEntry;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftServerWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||||
|
import com.seibel.distanthorizons.core.config.eventHandlers.presets.ThreadPresetConfigEventHandler;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.enums.MinecraftTextFormat;
|
||||||
|
import com.seibel.distanthorizons.core.jar.ModJarInfo;
|
||||||
|
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.StubDebugWireframeRenderer;
|
||||||
|
import com.seibel.distanthorizons.core.util.NativeDialogUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.threading.DhThreadFactory;
|
||||||
|
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModAccessor;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||||
|
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||||
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base for all mod loader initializers
|
||||||
|
* and handles most setup.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractModInitializer
|
||||||
|
{
|
||||||
|
protected static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private CommandInitializer commandInitializer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==================//
|
||||||
|
// abstract methods //
|
||||||
|
//==================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
protected abstract void createInitialSharedBindings();
|
||||||
|
protected abstract void createInitialClientBindings();
|
||||||
|
protected abstract IEventProxy createClientProxy();
|
||||||
|
protected abstract IEventProxy createServerProxy(boolean isDedicated);
|
||||||
|
protected abstract void initializeModCompat();
|
||||||
|
|
||||||
|
protected abstract void subscribeRegisterCommandsEvent(Consumer<CommandDispatcher<CommandSourceStack>> eventHandler);
|
||||||
|
|
||||||
|
protected abstract void subscribeClientStartedEvent(Runnable eventHandler);
|
||||||
|
protected abstract void subscribeServerStartingEvent(Consumer<MinecraftServer> eventHandler);
|
||||||
|
protected abstract void runDelayedSetup();
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================//
|
||||||
|
// initialize events //
|
||||||
|
//===================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public void onInitializeClient()
|
||||||
|
{
|
||||||
|
DependencySetup.createClientBindings();
|
||||||
|
this.createInitialClientBindings();
|
||||||
|
|
||||||
|
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " client, firing DhApiBeforeDhInitEvent...");
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
|
||||||
|
|
||||||
|
this.startup();
|
||||||
|
this.logBuildInfo();
|
||||||
|
|
||||||
|
this.createClientProxy().registerEvents();
|
||||||
|
this.createServerProxy(false).registerEvents();
|
||||||
|
|
||||||
|
this.initializeModCompat();
|
||||||
|
|
||||||
|
// Client uses config for auto-updater, so it's initialized here instead of post-init stage
|
||||||
|
this.initConfig();
|
||||||
|
logModIncompatibilityWarnings(); // needs to be called after config loading
|
||||||
|
|
||||||
|
LOGGER.info(ModInfo.READABLE_NAME + " client Initialized.");
|
||||||
|
|
||||||
|
#if MC_VER < MC_1_21_9
|
||||||
|
// debug screen rendering handled via a mixin
|
||||||
|
#else
|
||||||
|
DhDebugScreenEntry.register();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
this.subscribeClientStartedEvent(this::postInit);
|
||||||
|
this.subscribeClientStartedEvent(this::postClientInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onInitializeServer()
|
||||||
|
{
|
||||||
|
DependencySetup.createServerBindings();
|
||||||
|
|
||||||
|
LOGGER.info("Initializing " + ModInfo.READABLE_NAME + " server, firing DhApiBeforeDhInitEvent event...");
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeDhInitEvent.class, null);
|
||||||
|
|
||||||
|
this.startup();
|
||||||
|
this.logBuildInfo();
|
||||||
|
|
||||||
|
// This prevents returning uninitialized Config values,
|
||||||
|
// resulting from a circular reference mid-initialization in a static class
|
||||||
|
// noinspection ResultOfMethodCallIgnored
|
||||||
|
ThreadPresetConfigEventHandler.INSTANCE.toString();
|
||||||
|
|
||||||
|
this.createServerProxy(true).registerEvents();
|
||||||
|
|
||||||
|
this.initializeModCompat();
|
||||||
|
|
||||||
|
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized, adding event subscribers...");
|
||||||
|
this.commandInitializer = new CommandInitializer();
|
||||||
|
this.subscribeRegisterCommandsEvent(dispatcher -> { this.commandInitializer.initCommands(dispatcher); });
|
||||||
|
|
||||||
|
this.subscribeServerStartingEvent(server ->
|
||||||
|
{
|
||||||
|
MinecraftServerWrapper.INSTANCE.dedicatedServer = (DedicatedServer)server;
|
||||||
|
|
||||||
|
this.initConfig();
|
||||||
|
this.postInit();
|
||||||
|
this.postServerInit();
|
||||||
|
this.commandInitializer.onServerReady();
|
||||||
|
|
||||||
|
this.checkForUpdates();
|
||||||
|
|
||||||
|
LOGGER.info(ModInfo.READABLE_NAME + " server Initialized at " + server.getServerDirectory());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========================//
|
||||||
|
// inner initializer methods //
|
||||||
|
//===========================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private void startup()
|
||||||
|
{
|
||||||
|
DependencySetup.createSharedBindings();
|
||||||
|
SharedApi.init();
|
||||||
|
this.createInitialSharedBindings();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logBuildInfo()
|
||||||
|
{
|
||||||
|
LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
|
||||||
|
|
||||||
|
// if the build is stable the branch/commit/etc shouldn't be needed
|
||||||
|
if (ModInfo.IS_DEV_BUILD)
|
||||||
|
{
|
||||||
|
LOGGER.info("DH Branch: " + ModJarInfo.Git_Branch);
|
||||||
|
LOGGER.info("DH Commit: " + ModJarInfo.Git_Commit);
|
||||||
|
LOGGER.info("DH Jar Build Source: " + ModJarInfo.Build_Source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <T extends IModAccessor> void tryCreateModCompatAccessor(String modId, Class<? super T> accessorClass, Supplier<T> accessorConstructor)
|
||||||
|
{
|
||||||
|
IModChecker modChecker = SingletonInjector.INSTANCE.get(IModChecker.class);
|
||||||
|
if (modChecker.isModLoaded(modId))
|
||||||
|
{
|
||||||
|
//noinspection unchecked
|
||||||
|
ModAccessorInjector.INSTANCE.bind((Class<? extends IModAccessor>) accessorClass, accessorConstructor.get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGGER.debug("Skipping mod compatibility accessor for: ["+modId+"]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initConfig()
|
||||||
|
{
|
||||||
|
ConfigHandler.tryRunFirstTimeSetup();
|
||||||
|
Config.completeDelayedSetup();
|
||||||
|
DhLogger.runDelayedConfigSetup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkForUpdates()
|
||||||
|
{
|
||||||
|
if (Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get())
|
||||||
|
{
|
||||||
|
if (Config.Client.Advanced.AutoUpdater.enableSilentUpdates.get())
|
||||||
|
{
|
||||||
|
LOGGER.info("Silent updates are not allowed for dedicated servers; force disabling.");
|
||||||
|
Config.Client.Advanced.AutoUpdater.enableSilentUpdates.set(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
SelfUpdater.onStart();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postInit()
|
||||||
|
{
|
||||||
|
LOGGER.info("Running Delayed setup...");
|
||||||
|
this.runDelayedSetup();
|
||||||
|
|
||||||
|
if (ConfigHandler.INSTANCE == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Config was not initialized. Make sure to call LodCommonMain.initConfig() before calling this method.");
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("Delayed setup complete, firing DhApiAfterDhInitEvent event...");
|
||||||
|
|
||||||
|
// should be fired after all delayed setup so singletons and config can be accessed
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterDhInitEvent.class, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void postClientInit()
|
||||||
|
{
|
||||||
|
CompletableFuture<Void> future = new CompletableFuture<>();
|
||||||
|
|
||||||
|
// This method may be called from either the render thread,
|
||||||
|
// or some other random setup thread depending on the mod loader.
|
||||||
|
// In order to avoid confusion/inconsistent problems, we're always going
|
||||||
|
// to run setup on our own thread.
|
||||||
|
Thread dhSetupThread = new Thread(() ->
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DependencySetup.setRenderingApiBindings();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
future.completeExceptionally(e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
future.complete(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
dhSetupThread.setName(ThreadUtil.THREAD_NAME_PREFIX + "PostClientInit Thread");
|
||||||
|
dhSetupThread.start();
|
||||||
|
|
||||||
|
future.join();
|
||||||
|
}
|
||||||
|
private void postServerInit() { SingletonInjector.INSTANCE.bind(AbstractDebugWireframeRenderer.class, new StubDebugWireframeRenderer()); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==================================//
|
||||||
|
// mod partial compatibility checks //
|
||||||
|
//==================================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some mods will work with a few tweaks
|
||||||
|
* or will partially work but have some known issues we can't solve.
|
||||||
|
* This method will log (and display to chat if enabled)
|
||||||
|
* these warnings and potential fixes.
|
||||||
|
*/
|
||||||
|
private static void logModIncompatibilityWarnings()
|
||||||
|
{
|
||||||
|
boolean showChatWarnings = Config.Common.Logging.Warning.showModCompatibilityWarningsOnStartup.get();
|
||||||
|
IModChecker modChecker = SingletonInjector.INSTANCE.get(IModChecker.class);
|
||||||
|
|
||||||
|
String startingString = "Partially Incompatible Distant Horizons mod detected: ";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Alex's caves
|
||||||
|
//region
|
||||||
|
if (modChecker.isModLoaded("alexscaves"))
|
||||||
|
{
|
||||||
|
// There've been a few reports about this mod breaking DH at a few different points in time
|
||||||
|
// the fixes for said breakage changes depending on the version so unfortunately
|
||||||
|
// all we can do is log a warning so the user can handle it.
|
||||||
|
|
||||||
|
if (showChatWarnings)
|
||||||
|
{
|
||||||
|
String message =
|
||||||
|
MinecraftTextFormat.ORANGE + "Distant Horizons: Alex's Cave detected." + MinecraftTextFormat.CLEAR_FORMATTING +
|
||||||
|
"You may have to change Alex's config for DH to render. ";
|
||||||
|
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.warn(startingString + "[Alex's Caves] may require some config changes in order to render Distant Horizons correctly.");
|
||||||
|
}
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
// William Wythers' Overhauled Overworld (WWOO)
|
||||||
|
//region
|
||||||
|
if (modChecker.isModLoaded("wwoo"))
|
||||||
|
{
|
||||||
|
// WWOO has a bug with it's world gen that can't be fixed by DH or WWOO
|
||||||
|
// (at least that is what James learned after talking with WWOO)
|
||||||
|
// WWOO will cause grid lines to appear in the world when DH generates the chunks
|
||||||
|
// this might be due to how WWOO uses features for everything when generating
|
||||||
|
// and said features don't always get to the edge of said chunks.
|
||||||
|
|
||||||
|
String wwooWarning = "LODs generated by DH may have grid lines between sections. Disabling either WWOO or DH's distant generator will fix the problem.";
|
||||||
|
|
||||||
|
if (showChatWarnings)
|
||||||
|
{
|
||||||
|
String message =
|
||||||
|
MinecraftTextFormat.ORANGE + "Distant Horizons: WWOO detected." + MinecraftTextFormat.CLEAR_FORMATTING + "\n" +
|
||||||
|
wwooWarning;
|
||||||
|
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.warn(startingString + "[WWOO] "+ wwooWarning);
|
||||||
|
}
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
// Chunky //
|
||||||
|
//region
|
||||||
|
|
||||||
|
boolean chunkyPresent = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Class.forName("org.popcraft.chunky.api.ChunkyAPI");
|
||||||
|
chunkyPresent = true;
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException ignore) { }
|
||||||
|
|
||||||
|
if (chunkyPresent)
|
||||||
|
{
|
||||||
|
// Chunky can generate chunks faster than DH can process them,
|
||||||
|
// causing holes in the LODs.
|
||||||
|
// Generally it's better and faster to use DH's world generator.
|
||||||
|
|
||||||
|
String chunkyWarning = "Chunky can cause DH LODs to have holes " +
|
||||||
|
"since Chunky can generate chunks faster than DH can process them. \n" +
|
||||||
|
"Using DH's distant generator instead of chunky or increasing DH's CPU thread count can resolve the issue.";
|
||||||
|
|
||||||
|
if (showChatWarnings)
|
||||||
|
{
|
||||||
|
String message =
|
||||||
|
MinecraftTextFormat.ORANGE + "Distant Horizons: Chunky detected." + MinecraftTextFormat.CLEAR_FORMATTING + "\n" +
|
||||||
|
chunkyWarning;
|
||||||
|
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.warn(startingString + "[Chunky] "+ chunkyWarning);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
// iris //
|
||||||
|
//region
|
||||||
|
|
||||||
|
IIrisAccessor iris = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class);
|
||||||
|
if (iris != null)
|
||||||
|
{
|
||||||
|
// get the currently selected rendering API
|
||||||
|
EDhApiRenderApi renderApi = Config.Client.Advanced.Graphics.Experimental.renderingApi.get();
|
||||||
|
if (renderApi == EDhApiRenderApi.AUTO)
|
||||||
|
{
|
||||||
|
IVersionConstants versionConstants = SingletonInjector.INSTANCE.get(IVersionConstants.class);
|
||||||
|
renderApi = versionConstants.getDefaultRenderingApi();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iris only supports nataive OpenGL
|
||||||
|
if (renderApi != EDhApiRenderApi.OPEN_GL)
|
||||||
|
{
|
||||||
|
String irisUnsupportedMessage = "Iris doesn't support DH when using the ["+EDhApiRenderApi.BLAZE_3D+"] rendering API, this will need to be fixed on Iris' end. As a temporary fix please change the rendering API to ["+EDhApiRenderApi.OPEN_GL+"] in DH's config file.";
|
||||||
|
LOGGER.fatal(irisUnsupportedMessage);
|
||||||
|
NativeDialogUtil.showDialog(ModInfo.READABLE_NAME, irisUnsupportedMessage, "ok", "error");
|
||||||
|
|
||||||
|
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
|
String errorMessage = "loading Distant Horizons. "+irisUnsupportedMessage;
|
||||||
|
String exceptionError = "Distant Horizons conditional mod config Exception";
|
||||||
|
mc.crashMinecraft(errorMessage, new Exception(exceptionError));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper classes //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public interface IEventProxy
|
||||||
|
{
|
||||||
|
void registerEvents();
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+138
@@ -0,0 +1,138 @@
|
|||||||
|
package com.seibel.distanthorizons.common;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.network.event.internal.IncompatibleMessageInternalEvent;
|
||||||
|
import com.seibel.distanthorizons.core.network.event.internal.ProtocolErrorInternalEvent;
|
||||||
|
import com.seibel.distanthorizons.core.network.messages.MessageRegistry;
|
||||||
|
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||||
|
import com.seibel.distanthorizons.core.network.messages.base.CloseReasonMessage;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||||
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
|
import io.netty.buffer.ByteBufUtil;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
#else
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public abstract class AbstractPluginPacketSender implements IPluginPacketSender
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logNetworkEventToFile)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_20_6
|
||||||
|
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = new ResourceLocation(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
|
||||||
|
#elif MC_VER <= MC_1_21_10
|
||||||
|
public static final ResourceLocation WRAPPER_PACKET_RESOURCE = ResourceLocation.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
|
||||||
|
#else
|
||||||
|
public static final Identifier WRAPPER_PACKET_RESOURCE = Identifier.fromNamespaceAndPath(ModInfo.RESOURCE_NAMESPACE, ModInfo.WRAPPER_PACKET_PATH);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// "Forge byte" is an unused packet ID. We have our own system which works with all mod loaders,
|
||||||
|
// so we're just accounting for it by reading the protocol version as a byte instead of a short in Forge, to keep cross-loader compatibility
|
||||||
|
private final boolean forgeByteInProtocolVersion;
|
||||||
|
|
||||||
|
|
||||||
|
public AbstractPluginPacketSender() { this(false); }
|
||||||
|
public AbstractPluginPacketSender(boolean forgeByteInProtocolVersion)
|
||||||
|
{
|
||||||
|
this.forgeByteInProtocolVersion = forgeByteInProtocolVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final void sendToClient(IServerPlayerWrapper serverPlayer, AbstractNetworkMessage message)
|
||||||
|
{
|
||||||
|
this.sendToClient((ServerPlayer) serverPlayer.getWrappedMcObject(), message);
|
||||||
|
}
|
||||||
|
public abstract void sendToClient(ServerPlayer serverPlayer, AbstractNetworkMessage message);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public abstract void sendToServer(AbstractNetworkMessage message);
|
||||||
|
|
||||||
|
public AbstractNetworkMessage decodeMessage(FriendlyByteBuf in)
|
||||||
|
{
|
||||||
|
AbstractNetworkMessage message = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
in.markReaderIndex();
|
||||||
|
|
||||||
|
int protocolVersion = this.forgeByteInProtocolVersion ? in.readByte() : in.readShort();
|
||||||
|
if (protocolVersion != ModInfo.PROTOCOL_VERSION)
|
||||||
|
{
|
||||||
|
return new IncompatibleMessageInternalEvent(protocolVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
message = MessageRegistry.INSTANCE.createMessage(in.readUnsignedShort());
|
||||||
|
message.decode(in);
|
||||||
|
|
||||||
|
if (in.isReadable())
|
||||||
|
{
|
||||||
|
throw new IOException("Buffer has not been fully read");
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
in.resetReaderIndex();
|
||||||
|
|
||||||
|
LOGGER.error("Failed to decode message", e);
|
||||||
|
LOGGER.error("Buffer: ["+in+"]");
|
||||||
|
LOGGER.error("Buffer contents: ["+ByteBufUtil.hexDump(in)+"]");
|
||||||
|
|
||||||
|
return new ProtocolErrorInternalEvent(e, message, true);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// Prevent connection crashing if not entire buffer has been read
|
||||||
|
in.readerIndex(in.writerIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void encodeMessage(FriendlyByteBuf out, AbstractNetworkMessage message)
|
||||||
|
{
|
||||||
|
// This is intentionally unhandled, because errors related to this are unlikely to appear in wild
|
||||||
|
Objects.requireNonNull(message);
|
||||||
|
|
||||||
|
if (this.forgeByteInProtocolVersion)
|
||||||
|
{
|
||||||
|
out.writeByte(ModInfo.PROTOCOL_VERSION);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out.writeShort(ModInfo.PROTOCOL_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
out.markWriterIndex();
|
||||||
|
out.writeShort(MessageRegistry.INSTANCE.getMessageId(message));
|
||||||
|
message.encode(out);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOGGER.error("Failed to encode message", e);
|
||||||
|
LOGGER.error("Message: ["+message+"]");
|
||||||
|
|
||||||
|
message.getSession().tryHandleMessage(new ProtocolErrorInternalEvent(e, message, false));
|
||||||
|
|
||||||
|
// Encode close reason message instead
|
||||||
|
out.resetWriterIndex();
|
||||||
|
message = new CloseReasonMessage("Internal error on other side");
|
||||||
|
out.writeShort(MessageRegistry.INSTANCE.getMessageId(message));
|
||||||
|
message.encode(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.seibel.distanthorizons.common;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_20_6
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IPluginPacketSender;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.network.codec.StreamCodec;
|
||||||
|
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public record CommonPacketPayload(@Nullable AbstractNetworkMessage message) implements CustomPacketPayload
|
||||||
|
{
|
||||||
|
public static final Type<CommonPacketPayload> TYPE = new Type<>(AbstractPluginPacketSender.WRAPPER_PACKET_RESOURCE);
|
||||||
|
private static final AbstractPluginPacketSender PACKET_SENDER = (AbstractPluginPacketSender) SingletonInjector.INSTANCE.get(IPluginPacketSender.class);
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public Type<? extends CustomPacketPayload> type() { return TYPE; }
|
||||||
|
|
||||||
|
|
||||||
|
public static class Codec implements StreamCodec<FriendlyByteBuf, CommonPacketPayload>
|
||||||
|
{
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public CommonPacketPayload decode(@NotNull FriendlyByteBuf in)
|
||||||
|
{ return new CommonPacketPayload(PACKET_SENDER.decodeMessage(in)); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void encode(@NotNull FriendlyByteBuf out, CommonPacketPayload payload)
|
||||||
|
{ PACKET_SENDER.encodeMessage(out, payload.message()); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
package com.seibel.distanthorizons.common.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.misc.ServerPlayerWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
|
||||||
|
#if MC_VER >= MC_1_19_2
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
#else // < 1.19.2
|
||||||
|
import net.minecraft.network.chat.TranslatableComponent;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract class providing common functionality for DH's commands.
|
||||||
|
*/
|
||||||
|
public abstract class AbstractCommand
|
||||||
|
{
|
||||||
|
public abstract LiteralArgumentBuilder<CommandSourceStack> buildCommand();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a success response to the player with the given text.
|
||||||
|
*
|
||||||
|
* @param commandContext The command context to send the response to.
|
||||||
|
* @param text The text to display in the success message.
|
||||||
|
* @return 1, indicating that the command was successful.
|
||||||
|
*/
|
||||||
|
protected int sendSuccessResponse(CommandContext<CommandSourceStack> commandContext, String text, boolean notifyAdmins)
|
||||||
|
{
|
||||||
|
#if MC_VER >= MC_1_20_1
|
||||||
|
commandContext.getSource().sendSuccess(() -> Component.literal(text), notifyAdmins);
|
||||||
|
#elif MC_VER >= MC_1_19_2
|
||||||
|
commandContext.getSource().sendSuccess(Component.literal(text), notifyAdmins);
|
||||||
|
#else
|
||||||
|
commandContext.getSource().sendSuccess(new TranslatableComponent(text), notifyAdmins);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a failure response to the player with the given text.
|
||||||
|
*
|
||||||
|
* @param commandContext The command context to send the response to.
|
||||||
|
* @param text The text to display in the failure message.
|
||||||
|
* @return 1, indicating that the command was successful.
|
||||||
|
*/
|
||||||
|
protected int sendFailureResponse(CommandContext<CommandSourceStack> commandContext, String text)
|
||||||
|
{
|
||||||
|
#if MC_VER >= MC_1_20_1
|
||||||
|
commandContext.getSource().sendFailure(Component.literal(text));
|
||||||
|
#elif MC_VER >= MC_1_19_2
|
||||||
|
commandContext.getSource().sendFailure(Component.literal(text));
|
||||||
|
#else
|
||||||
|
commandContext.getSource().sendFailure(new TranslatableComponent(text));
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the server player from a command context.
|
||||||
|
*
|
||||||
|
* @param commandContext The command context to get the server player from.
|
||||||
|
* @return The server player wrapper for the player who sent the command.
|
||||||
|
*/
|
||||||
|
protected IServerPlayerWrapper getSourcePlayer(CommandContext<CommandSourceStack> commandContext) #if MC_VER < MC_1_19_2 throws CommandSyntaxException #endif
|
||||||
|
{
|
||||||
|
#if MC_VER >= MC_1_19_2
|
||||||
|
return ServerPlayerWrapper.getWrapper(Objects.requireNonNull(commandContext.getSource().getPlayer()));
|
||||||
|
#else
|
||||||
|
return ServerPlayerWrapper.getWrapper(commandContext.getSource().getPlayerOrException());
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the source of a command is a player.
|
||||||
|
*
|
||||||
|
* @param source The source of the command to check.
|
||||||
|
* @return True if the source is a player, false otherwise.
|
||||||
|
*/
|
||||||
|
protected boolean isPlayerSource(CommandSourceStack source)
|
||||||
|
{
|
||||||
|
#if MC_VER >= MC_1_19_2
|
||||||
|
return source.isPlayer();
|
||||||
|
#else
|
||||||
|
try
|
||||||
|
{
|
||||||
|
source.getPlayerOrException();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (CommandSyntaxException e)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+84
@@ -0,0 +1,84 @@
|
|||||||
|
package com.seibel.distanthorizons.common.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import static com.seibel.distanthorizons.core.network.messages.MessageRegistry.DEBUG_CODEC_CRASH_MESSAGE;
|
||||||
|
import static net.minecraft.commands.Commands.literal;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
#else
|
||||||
|
import net.minecraft.server.permissions.PermissionCheck;
|
||||||
|
import net.minecraft.server.permissions.Permissions;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
public class CommandInitializer
|
||||||
|
{
|
||||||
|
private boolean serverReady = false;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
private static final int REQUIRED_PERMISSION_LEVEL = 4;
|
||||||
|
#else
|
||||||
|
private static final PermissionCheck COMMAND_PERMISSION_CHECK = new PermissionCheck.Require(Permissions.COMMANDS_OWNER);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A received command dispatcher, which is held until the server is ready to initialize the commands.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
private CommandDispatcher<CommandSourceStack> commandDispatcher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify the command initializer that the game is ready to accept commands.
|
||||||
|
* If {@link CommandInitializer#initCommands(CommandDispatcher)} has been fired before it was ready, it will also initialize the commands.
|
||||||
|
*/
|
||||||
|
public void onServerReady()
|
||||||
|
{
|
||||||
|
this.serverReady = true;
|
||||||
|
if (this.commandDispatcher != null)
|
||||||
|
{
|
||||||
|
this.initCommands(this.commandDispatcher);
|
||||||
|
this.commandDispatcher = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes all available commands.
|
||||||
|
* If the game is not ready yet, it stores the dispatcher to initialize the commands later.
|
||||||
|
*
|
||||||
|
* @param commandDispatcher The command dispatcher to register commands to.
|
||||||
|
*/
|
||||||
|
public void initCommands(CommandDispatcher<CommandSourceStack> commandDispatcher)
|
||||||
|
{
|
||||||
|
if (!this.serverReady)
|
||||||
|
{
|
||||||
|
this.commandDispatcher = commandDispatcher;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteralArgumentBuilder<CommandSourceStack> builder = literal("dh")
|
||||||
|
.requires((source) ->
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
return source.hasPermission(REQUIRED_PERMISSION_LEVEL);
|
||||||
|
#else
|
||||||
|
return COMMAND_PERMISSION_CHECK.check(source.permissions());
|
||||||
|
#endif
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.then(new ConfigCommand().buildCommand());
|
||||||
|
builder.then(new DebugCommand().buildCommand());
|
||||||
|
builder.then(new PregenCommand().buildCommand());
|
||||||
|
|
||||||
|
if (DEBUG_CODEC_CRASH_MESSAGE)
|
||||||
|
{
|
||||||
|
builder.then(new CrashCommand().buildCommand());
|
||||||
|
}
|
||||||
|
|
||||||
|
commandDispatcher.register(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,154 @@
|
|||||||
|
package com.seibel.distanthorizons.common.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.*;
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.seibel.distanthorizons.core.config.ConfigHandler;
|
||||||
|
import com.seibel.distanthorizons.core.config.types.AbstractConfigBase;
|
||||||
|
import com.seibel.distanthorizons.core.config.types.ConfigEntry;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.function.ToIntBiFunction;
|
||||||
|
|
||||||
|
import static com.mojang.brigadier.arguments.DoubleArgumentType.doubleArg;
|
||||||
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||||
|
import static net.minecraft.commands.Commands.argument;
|
||||||
|
import static net.minecraft.commands.Commands.literal;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command for managing config.
|
||||||
|
*/
|
||||||
|
public class ConfigCommand extends AbstractCommand
|
||||||
|
{
|
||||||
|
private static final List<CommandArgumentData<?>> commandArguments = Arrays.asList(
|
||||||
|
new CommandArgumentData<>(Integer.class, configEntry -> integer(configEntry.getMin(), configEntry.getMax()), IntegerArgumentType::getInteger),
|
||||||
|
new CommandArgumentData<>(Double.class, configEntry -> doubleArg(configEntry.getMin(), configEntry.getMax()), DoubleArgumentType::getDouble),
|
||||||
|
new CommandArgumentData<>(Boolean.class, BoolArgumentType::bool, BoolArgumentType::getBool),
|
||||||
|
new CommandArgumentData<>(String.class, StringArgumentType::string, StringArgumentType::getString)
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds a command tree.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
|
||||||
|
{
|
||||||
|
LiteralArgumentBuilder<CommandSourceStack> builder = literal("config");
|
||||||
|
HashSet<String> addedCommands = new HashSet<>();
|
||||||
|
|
||||||
|
for (AbstractConfigBase<?> type : ConfigHandler.INSTANCE.configBaseList)
|
||||||
|
{
|
||||||
|
// Skip non-config entries
|
||||||
|
if (!(type instanceof ConfigEntry))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection PatternVariableCanBeUsed
|
||||||
|
ConfigEntry configEntry = (ConfigEntry) type;
|
||||||
|
if (configEntry.getChatCommandName() == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addedCommands.add(configEntry.getChatCommandName()))
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Duplicate command name: " + configEntry.getChatCommandName());
|
||||||
|
}
|
||||||
|
|
||||||
|
LiteralArgumentBuilder<CommandSourceStack> subcommand = literal(configEntry.getChatCommandName())
|
||||||
|
.executes(commandContext -> this.sendSuccessResponse(commandContext,
|
||||||
|
"\n" +
|
||||||
|
"Description of §l" + configEntry.getChatCommandName() + "§r:\n" +
|
||||||
|
"§o" + configEntry.getComment().trim() + "§r\n" +
|
||||||
|
"§7Config file name: §f" + configEntry.name + "§7, category: §f" + configEntry.category + "\n" +
|
||||||
|
"\n" +
|
||||||
|
"Current value of " + configEntry.getChatCommandName() + " is §n" + configEntry.get() + "§r",
|
||||||
|
false
|
||||||
|
));
|
||||||
|
|
||||||
|
ToIntBiFunction<CommandContext<CommandSourceStack>, Object> updateConfigValue = (commandContext, value) -> {
|
||||||
|
configEntry.set(value);
|
||||||
|
return this.sendSuccessResponse(commandContext, "Changed the value of [" + configEntry.getChatCommandName() + "] to [" + value + "]", true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Enum type needs a special case since enums aren't represented by existing argument type
|
||||||
|
// and need literals for each individual value
|
||||||
|
if (Enum.class.isAssignableFrom(configEntry.getType()))
|
||||||
|
{
|
||||||
|
for (Object choice : configEntry.getType().getEnumConstants())
|
||||||
|
{
|
||||||
|
subcommand.then(
|
||||||
|
literal(choice.toString())
|
||||||
|
.executes(c -> updateConfigValue.applyAsInt(c, choice))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
boolean setterAdded = false;
|
||||||
|
for (CommandArgumentData<?> commandArgumentData : commandArguments)
|
||||||
|
{
|
||||||
|
if (!commandArgumentData.argumentClass.isAssignableFrom(configEntry.getType()))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
subcommand.then(argument("value", commandArgumentData.getArgumentType(configEntry))
|
||||||
|
.executes(c -> updateConfigValue.applyAsInt(c, commandArgumentData.getValue(c, "value"))));
|
||||||
|
|
||||||
|
setterAdded = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!setterAdded)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Config type of " + type.getName() + " is not supported: " + configEntry.getType().getSimpleName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.then(subcommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static class CommandArgumentData<T>
|
||||||
|
{
|
||||||
|
public final Class<T> argumentClass;
|
||||||
|
public final Function<ConfigEntry<T>, ArgumentType<T>> argumentTypeFunction;
|
||||||
|
private final BiFunction<CommandContext<CommandSourceStack>, String, T> valueGetter;
|
||||||
|
|
||||||
|
public CommandArgumentData(Class<T> argumentClass, Supplier<ArgumentType<T>> argumentTypeSupplier, BiFunction<CommandContext<CommandSourceStack>, String, T> valueGetter)
|
||||||
|
{
|
||||||
|
this(argumentClass, configEntry -> argumentTypeSupplier.get(), valueGetter);
|
||||||
|
}
|
||||||
|
public CommandArgumentData(Class<T> argumentClass, Function<ConfigEntry<T>, ArgumentType<T>> argumentTypeFunction, BiFunction<CommandContext<CommandSourceStack>, String, T> valueGetter)
|
||||||
|
{
|
||||||
|
this.argumentClass = argumentClass;
|
||||||
|
this.argumentTypeFunction = argumentTypeFunction;
|
||||||
|
this.valueGetter = valueGetter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArgumentType<T> getArgumentType(ConfigEntry<T> configEntry)
|
||||||
|
{
|
||||||
|
return this.argumentTypeFunction.apply(configEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T getValue(CommandContext<CommandSourceStack> commandContext, String argumentName)
|
||||||
|
{
|
||||||
|
return this.valueGetter.apply(commandContext, argumentName);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.seibel.distanthorizons.common.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
|
import com.seibel.distanthorizons.core.multiplayer.server.ServerPlayerState;
|
||||||
|
import com.seibel.distanthorizons.core.network.messages.base.CodecCrashMessage;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
|
||||||
|
import static net.minecraft.commands.Commands.literal;
|
||||||
|
|
||||||
|
public class CrashCommand extends AbstractCommand
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
|
||||||
|
{
|
||||||
|
return literal("crash")
|
||||||
|
.requires(this::isPlayerSource)
|
||||||
|
.then(literal("encode")
|
||||||
|
.executes(c -> {
|
||||||
|
assert SharedApi.tryGetDhServerWorld() != null;
|
||||||
|
|
||||||
|
ServerPlayerState serverPlayerState = SharedApi.tryGetDhServerWorld().getServerPlayerStateManager()
|
||||||
|
.getConnectedPlayer(this.getSourcePlayer(c));
|
||||||
|
if (serverPlayerState != null)
|
||||||
|
{
|
||||||
|
serverPlayerState.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.ENCODE));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}))
|
||||||
|
.then(literal("decode")
|
||||||
|
.executes(c -> {
|
||||||
|
assert SharedApi.tryGetDhServerWorld() != null;
|
||||||
|
|
||||||
|
ServerPlayerState serverPlayerState = SharedApi.tryGetDhServerWorld().getServerPlayerStateManager()
|
||||||
|
.getConnectedPlayer(this.getSourcePlayer(c));
|
||||||
|
if (serverPlayerState != null)
|
||||||
|
{
|
||||||
|
serverPlayerState.networkSession.sendMessage(new CodecCrashMessage(CodecCrashMessage.ECrashPhase.DECODE));
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.seibel.distanthorizons.common.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static net.minecraft.commands.Commands.literal;
|
||||||
|
|
||||||
|
public class DebugCommand extends AbstractCommand
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
|
||||||
|
{
|
||||||
|
return literal("debug")
|
||||||
|
.executes(c -> {
|
||||||
|
List<String> lines = new ArrayList<>();
|
||||||
|
F3Screen.addStringToDisplay(lines);
|
||||||
|
return this.sendSuccessResponse(c, String.join("\n", lines), false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package com.seibel.distanthorizons.common.commands;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
|
import com.seibel.distanthorizons.core.generation.PregenManager;
|
||||||
|
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos2D;
|
||||||
|
import com.seibel.distanthorizons.core.world.DhServerWorld;
|
||||||
|
import net.minecraft.commands.CommandSourceStack;
|
||||||
|
import net.minecraft.commands.arguments.DimensionArgument;
|
||||||
|
import net.minecraft.commands.arguments.coordinates.ColumnPosArgument;
|
||||||
|
import net.minecraft.server.level.ColumnPos;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.CancellationException;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.getInteger;
|
||||||
|
import static com.mojang.brigadier.arguments.IntegerArgumentType.integer;
|
||||||
|
import static net.minecraft.commands.Commands.argument;
|
||||||
|
import static net.minecraft.commands.Commands.literal;
|
||||||
|
|
||||||
|
public class PregenCommand extends AbstractCommand
|
||||||
|
{
|
||||||
|
private PregenManager getPregenManager()
|
||||||
|
{
|
||||||
|
DhServerWorld world = (DhServerWorld) Objects.requireNonNull(SharedApi.getAbstractDhWorld());
|
||||||
|
return world.getPregenManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LiteralArgumentBuilder<CommandSourceStack> buildCommand()
|
||||||
|
{
|
||||||
|
LiteralArgumentBuilder<CommandSourceStack> statusCommand = literal("status")
|
||||||
|
.executes(this::pregenStatus);
|
||||||
|
|
||||||
|
LiteralArgumentBuilder<CommandSourceStack> startCommand = literal("start")
|
||||||
|
.then(argument("dimension", DimensionArgument.dimension())
|
||||||
|
.then(argument("origin", ColumnPosArgument.columnPos())
|
||||||
|
.then(argument("chunkRadius", integer(32))
|
||||||
|
.executes(this::pregenStart))));
|
||||||
|
|
||||||
|
LiteralArgumentBuilder<CommandSourceStack> stopCommand = literal("stop")
|
||||||
|
.executes(this::pregenStop);
|
||||||
|
|
||||||
|
return literal("pregen")
|
||||||
|
.then(statusCommand)
|
||||||
|
.then(startCommand)
|
||||||
|
.then(stopCommand);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private int pregenStatus(CommandContext<CommandSourceStack> c)
|
||||||
|
{
|
||||||
|
String statusString = this.getPregenManager().getStatusString();
|
||||||
|
//noinspection ReplaceNullCheck
|
||||||
|
if (statusString != null)
|
||||||
|
{
|
||||||
|
return this.sendSuccessResponse(c, statusString, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return this.sendSuccessResponse(c, "Pregen is not running", false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pregenStart(CommandContext<CommandSourceStack> c) throws CommandSyntaxException
|
||||||
|
{
|
||||||
|
this.sendSuccessResponse(c, "Starting pregen. Progress will be in the server console.", true);
|
||||||
|
|
||||||
|
ServerLevel level = DimensionArgument.getDimension(c, "dimension");
|
||||||
|
ColumnPos origin = ColumnPosArgument.getColumnPos(c, "origin");
|
||||||
|
int chunkRadius = getInteger(c, "chunkRadius");
|
||||||
|
|
||||||
|
CompletableFuture<Void> future = this.getPregenManager().startPregen(
|
||||||
|
ServerLevelWrapper.getWrapper(level),
|
||||||
|
new DhBlockPos2D(#if MC_VER >= MC_1_19_2 origin.x(), origin.z() #else origin.x, origin.z #endif),
|
||||||
|
chunkRadius
|
||||||
|
);
|
||||||
|
|
||||||
|
future.whenComplete((result, throwable) -> {
|
||||||
|
if (throwable instanceof CancellationException)
|
||||||
|
{
|
||||||
|
this.sendSuccessResponse(c, "Pregen is cancelled", true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (throwable != null)
|
||||||
|
{
|
||||||
|
this.sendFailureResponse(c, "Pregen failed: " + throwable.getMessage() + "\n Check the logs for more details.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sendSuccessResponse(c, "Pregen is complete", true);
|
||||||
|
});
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int pregenStop(CommandContext<CommandSourceStack> c)
|
||||||
|
{
|
||||||
|
CompletableFuture<Void> runningPregen = this.getPregenManager().getRunningPregen();
|
||||||
|
if (runningPregen == null)
|
||||||
|
{
|
||||||
|
return this.sendFailureResponse(c, "Pregen is not running");
|
||||||
|
}
|
||||||
|
|
||||||
|
runningPregen.cancel(true);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+88
@@ -0,0 +1,88 @@
|
|||||||
|
package com.seibel.distanthorizons.common.commonMixins;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiUpdateBranch;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.gui.updater.UpdateModScreen;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.jar.installer.GitlabGetter;
|
||||||
|
import com.seibel.distanthorizons.core.jar.installer.ModrinthGetter;
|
||||||
|
import com.seibel.distanthorizons.core.jar.updater.SelfUpdater;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.screens.TitleScreen;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class DhUpdateScreenBase
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final Minecraft MC = Minecraft.getInstance();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void tryShowUpdateScreenAndRunAutoUpdateStartup(Runnable runnable)
|
||||||
|
{
|
||||||
|
// always needs to be called, otherwise auto update setup won't be completed
|
||||||
|
boolean newUpdateAvailable = SelfUpdater.onStart();
|
||||||
|
if (!newUpdateAvailable)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Config.Client.Advanced.AutoUpdater.enableAutoUpdater.get())
|
||||||
|
{
|
||||||
|
LOGGER.info("Auto update disabled, ignoring new version...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
runnable = () ->
|
||||||
|
{
|
||||||
|
String versionId;
|
||||||
|
EDhApiUpdateBranch updateBranch = EDhApiUpdateBranch.convertAutoToStableOrNightly(Config.Client.Advanced.AutoUpdater.updateBranch.get());
|
||||||
|
if (updateBranch == EDhApiUpdateBranch.STABLE)
|
||||||
|
{
|
||||||
|
versionId = ModrinthGetter.getLatestIDForVersion(SingletonInjector.INSTANCE.get(IVersionConstants.class).getMinecraftVersion());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ArrayList<com.electronwill.nightconfig.core.Config> pipelines = GitlabGetter.INSTANCE.projectPipelines;
|
||||||
|
if (pipelines != null
|
||||||
|
&& pipelines.size() > 0)
|
||||||
|
{
|
||||||
|
versionId = pipelines.get(0).get("sha");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
versionId = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (versionId == null)
|
||||||
|
{
|
||||||
|
LOGGER.info("Unable to find new DH update for the ["+updateBranch+"] branch. Assuming DH is up to date...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MC.setScreen(new UpdateModScreen(
|
||||||
|
new TitleScreen(false),
|
||||||
|
versionId
|
||||||
|
));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
// info instead of error since this can be ignored and probably just means
|
||||||
|
// there isn't a new DH version available
|
||||||
|
LOGGER.info("Unable to show DH update screen, reason: ["+e.getMessage()+"].");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
package com.seibel.distanthorizons.common.commonMixins;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.world.ServerLevelWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.ServerApi;
|
||||||
|
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||||
|
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
public class MixinChunkMapCommon
|
||||||
|
{
|
||||||
|
|
||||||
|
public static void onChunkSave(ServerLevel level, ChunkAccess chunk, CallbackInfoReturnable<Boolean> ci)
|
||||||
|
{
|
||||||
|
IServerLevelWrapper levelWrapper = ServerLevelWrapper.getWrapper(level);
|
||||||
|
|
||||||
|
int chunkPosX;
|
||||||
|
int chunkPosZ;
|
||||||
|
#if MC_VER <= MC_1_21_11
|
||||||
|
chunkPosX = chunk.getPos().x;
|
||||||
|
chunkPosZ = chunk.getPos().z;
|
||||||
|
#else
|
||||||
|
chunkPosX = chunk.getPos().x();
|
||||||
|
chunkPosZ = chunk.getPos().z();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// is this position already being updated?
|
||||||
|
if (SharedApi.isChunkAtChunkPosAlreadyUpdating(levelWrapper, chunkPosX, chunkPosZ))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// is this chunk being saved to disk?
|
||||||
|
boolean savingChunkToDisk = ci.getReturnValue();
|
||||||
|
// true means a chunk was saved to disk
|
||||||
|
if (!savingChunkToDisk)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// corrupt/incomplete chunk validation //
|
||||||
|
|
||||||
|
// MC has a tendency to try saving incomplete or corrupted chunks (which show up as empty or black chunks)
|
||||||
|
// this logic should prevent that from happening
|
||||||
|
#if MC_VER <= MC_1_17_1
|
||||||
|
if (chunk.isUnsaved() || chunk.getUpgradeData() != null || !chunk.isLightCorrect())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (chunk.isUnsaved() || chunk.isUpgrading() || !chunk.isLightCorrect() || chunk instanceof ProtoChunk)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// biome validation //
|
||||||
|
|
||||||
|
// some chunks may be missing their biomes, which cause issues when attempting to save them
|
||||||
|
#if MC_VER <= MC_1_17_1
|
||||||
|
if (chunk.getBiomes() == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// this will throw an exception if the biomes aren't set up
|
||||||
|
chunk.getNoiseBiome(0,0,0);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// submit the update event
|
||||||
|
ServerApi.INSTANCE.serverChunkSaveEvent(
|
||||||
|
new ChunkWrapper(chunk, levelWrapper),
|
||||||
|
levelWrapper
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+331
@@ -0,0 +1,331 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.blaze;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDebugWireframeRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140Builder;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140SizeCalculator;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.platform.PolygonMode;
|
||||||
|
import com.mojang.blaze3d.shaders.UniformType;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderPass;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeUniformUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeDhVertexFormatUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles rendering the wireframe particles
|
||||||
|
* that are used for seeing what the system's doing.
|
||||||
|
*/
|
||||||
|
public class BlazeDebugWireframeRenderer extends AbstractDebugWireframeRenderer
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
|
||||||
|
public static BlazeDebugWireframeRenderer INSTANCE = new BlazeDebugWireframeRenderer();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** A box from 0,0,0 to 1,1,1 */
|
||||||
|
private static final float[] BOX_VERTICES = {
|
||||||
|
//region
|
||||||
|
// Pos x y z
|
||||||
|
0, 0, 0,
|
||||||
|
1, 0, 0,
|
||||||
|
1, 1, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 0, 1,
|
||||||
|
1, 0, 1,
|
||||||
|
1, 1, 1,
|
||||||
|
0, 1, 1,
|
||||||
|
//endregion
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final int[] BOX_OUTLINE_INDICES = {
|
||||||
|
//region
|
||||||
|
0, 1,
|
||||||
|
1, 2,
|
||||||
|
2, 3,
|
||||||
|
3, 0,
|
||||||
|
|
||||||
|
4, 5,
|
||||||
|
5, 6,
|
||||||
|
6, 7,
|
||||||
|
7, 4,
|
||||||
|
|
||||||
|
0, 4,
|
||||||
|
1, 5,
|
||||||
|
2, 6,
|
||||||
|
3, 7,
|
||||||
|
//endregion
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// rendering setup
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
private RenderPipeline pipeline;
|
||||||
|
|
||||||
|
private GpuBuffer boxVertexBuffer;
|
||||||
|
private GpuBuffer boxIndexBuffer;
|
||||||
|
|
||||||
|
private GpuBuffer uniformBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public BlazeDebugWireframeRenderer() { }
|
||||||
|
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init = true;
|
||||||
|
|
||||||
|
this.createPipelines();
|
||||||
|
this.createBuffers();
|
||||||
|
|
||||||
|
}
|
||||||
|
private void createPipelines()
|
||||||
|
{
|
||||||
|
RenderPipelineBuilderWrapper pipelineBuilder = new RenderPipelineBuilderWrapper();
|
||||||
|
{
|
||||||
|
pipelineBuilder.withFaceCulling(false);
|
||||||
|
pipelineBuilder.withDepthWrite(true);
|
||||||
|
pipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.LESS);
|
||||||
|
pipelineBuilder.withColorWrite(true);
|
||||||
|
pipelineBuilder.withoutBlend();
|
||||||
|
pipelineBuilder.withPolygonMode(RenderPipelineBuilderWrapper.EDhPolygonMode.WIREFRAME);
|
||||||
|
pipelineBuilder.withName("debug_wireframe_renderer");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexShader("debug/blaze/vert");
|
||||||
|
pipelineBuilder.withFragmentShader("debug/blaze/frag");
|
||||||
|
|
||||||
|
pipelineBuilder.withUniformBuffer("uniformBlock");
|
||||||
|
|
||||||
|
|
||||||
|
VertexFormat vertexFormat = VertexFormat.builder()
|
||||||
|
.add("vPosition", BlazeDhVertexFormatUtil.FLOAT_XYZ_POS)
|
||||||
|
.build();
|
||||||
|
pipelineBuilder.withVertexFormat(vertexFormat);
|
||||||
|
pipelineBuilder.withVertexMode(RenderPipelineBuilderWrapper.EDhVertexMode.LINES);
|
||||||
|
}
|
||||||
|
this.pipeline = pipelineBuilder.build();
|
||||||
|
|
||||||
|
}
|
||||||
|
private void createBuffers()
|
||||||
|
{
|
||||||
|
GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
|
||||||
|
// box vertices
|
||||||
|
ByteBuffer boxVerticesBuffer = MemoryUtil.memAlloc(BOX_VERTICES.length * Float.BYTES);
|
||||||
|
boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES);
|
||||||
|
boxVerticesBuffer.rewind();
|
||||||
|
MemoryUtil.memFree(boxVerticesBuffer);
|
||||||
|
|
||||||
|
// upload vertex data
|
||||||
|
{
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_VERTEX;
|
||||||
|
int size = BOX_VERTICES.length * Float.BYTES;
|
||||||
|
this.boxVertexBuffer = GPU_DEVICE.createBuffer(() -> "distantHorizons:McDebugWireframeBox", usage, size);
|
||||||
|
|
||||||
|
{
|
||||||
|
int length = BOX_VERTICES.length * Float.BYTES;
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.boxVertexBuffer, /*offset*/ 0, length);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(BOX_VERTICES.length * Float.BYTES);
|
||||||
|
byteBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
byteBuffer.asFloatBuffer().put(BOX_VERTICES);
|
||||||
|
byteBuffer.rewind();
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, byteBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// box vertex indexes
|
||||||
|
{
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(BOX_OUTLINE_INDICES.length * Integer.BYTES);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
buffer.asIntBuffer().put(BOX_OUTLINE_INDICES);
|
||||||
|
buffer.rewind();
|
||||||
|
|
||||||
|
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_VERTEX
|
||||||
|
| GpuBuffer.USAGE_INDEX
|
||||||
|
| GpuBuffer.USAGE_UNIFORM;
|
||||||
|
this.boxIndexBuffer = GPU_DEVICE.createBuffer(() -> "DH Debug Index Buffer", usage, buffer.capacity());
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.boxIndexBuffer, offset, buffer.capacity());
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========//
|
||||||
|
// rendering //
|
||||||
|
//===========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderBox(Box box)
|
||||||
|
{
|
||||||
|
this.init();
|
||||||
|
|
||||||
|
//if (BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.isEmpty()
|
||||||
|
// || BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.isEmpty())
|
||||||
|
//{
|
||||||
|
// return;
|
||||||
|
//}
|
||||||
|
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
if (box == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// delayed getters since this class may be initialized before
|
||||||
|
// the GPU device has been set
|
||||||
|
GpuDevice gpuDevice = RenderSystem.getDevice();
|
||||||
|
CommandEncoder commandEncoder = gpuDevice.createCommandEncoder();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// uniforms
|
||||||
|
{
|
||||||
|
int uniformBufferSize = new Std140SizeCalculator()
|
||||||
|
.putMat4f() // uTransform
|
||||||
|
.putVec4() // uColor
|
||||||
|
.get();
|
||||||
|
|
||||||
|
|
||||||
|
// create data //
|
||||||
|
|
||||||
|
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||||
|
Vec3f camPosFloatThisFrame = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z);
|
||||||
|
|
||||||
|
Mat4f boxTransform = Mat4f.createTranslateMatrix(
|
||||||
|
box.minPos.x - camPosFloatThisFrame.x,
|
||||||
|
box.minPos.y - camPosFloatThisFrame.y,
|
||||||
|
box.minPos.z - camPosFloatThisFrame.z);
|
||||||
|
boxTransform.multiply(Mat4f.createScaleMatrix(
|
||||||
|
box.maxPos.x - box.minPos.x,
|
||||||
|
box.maxPos.y - box.minPos.y,
|
||||||
|
box.maxPos.z - box.minPos.z));
|
||||||
|
|
||||||
|
Mat4f transformMatrix = this.dhMvmProjMatrixThisFrame.copy();
|
||||||
|
transformMatrix.multiply(boxTransform);
|
||||||
|
|
||||||
|
|
||||||
|
// upload data //
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(uniformBufferSize);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
buffer = Std140Builder.intoBuffer(buffer)
|
||||||
|
.putMat4f(transformMatrix.createJomlMatrix()) // uTransform
|
||||||
|
.putVec4(
|
||||||
|
box.color.getRed() / 255.0f,
|
||||||
|
box.color.getGreen() / 255.0f,
|
||||||
|
box.color.getBlue() / 255.0f,
|
||||||
|
box.color.getAlpha() / 255.0f) // uColor
|
||||||
|
.get()
|
||||||
|
;
|
||||||
|
|
||||||
|
this.uniformBuffer = BlazeUniformUtil.createBuffer("uniformBlock", uniformBufferSize, this.uniformBuffer);
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.uniformBuffer, 0, uniformBufferSize);
|
||||||
|
|
||||||
|
commandEncoder.writeToBuffer(bufferSlice, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// render //
|
||||||
|
|
||||||
|
//try (RenderPass renderPass = commandEncoder.createRenderPass(
|
||||||
|
// this::getRenderPassName,
|
||||||
|
// BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
|
||||||
|
// /*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
|
// BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
|
||||||
|
// /*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||||
|
//{
|
||||||
|
// // Bind instance data //
|
||||||
|
// renderPass.setUniform("uniformBlock", this.uniformBuffer);
|
||||||
|
//
|
||||||
|
// renderPass.setPipeline(this.pipeline);
|
||||||
|
// renderPass.setIndexBuffer(this.boxIndexBuffer, VertexFormat.IndexType.INT);
|
||||||
|
//
|
||||||
|
// renderPass.setVertexBuffer(0, this.boxVertexBuffer);
|
||||||
|
//
|
||||||
|
// renderPass.drawIndexed(
|
||||||
|
// /*indexStart*/ 0,
|
||||||
|
// /*firstIndex*/0,
|
||||||
|
// /*indexCount*/BOX_OUTLINE_INDICES.length,
|
||||||
|
// /*instanceCount*/1);
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
private String getRenderPassName() { return "distantHorizons:McDebugRenderer"; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+624
@@ -0,0 +1,624 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.blaze;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhGenericObjectRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140Builder;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140SizeCalculator;
|
||||||
|
import com.mojang.blaze3d.pipeline.BlendFunction;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.platform.PolygonMode;
|
||||||
|
import com.mojang.blaze3d.shaders.UniformType;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderPass;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||||
|
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
||||||
|
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericObjectRenderEvent;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericRenderCleanupEvent;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericRenderSetupEvent;
|
||||||
|
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||||
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||||
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.objects.BlazeGenericObjectVertexContainer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeDhVertexFormatUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeUniformUtil;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup;
|
||||||
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||||
|
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||||
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles rendering generic groups of {@link DhApiRenderableBox}.
|
||||||
|
*
|
||||||
|
* @see IDhApiCustomRenderRegister
|
||||||
|
* @see DhApiRenderableBox
|
||||||
|
*/
|
||||||
|
public class BlazeDhGenericObjectRenderer implements IDhGenericRenderer
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
private static final DhApiRenderableBoxGroupShading DEFAULT_SHADING = DhApiRenderableBoxGroupShading.getUnshaded();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to troubleshoot the renderer.
|
||||||
|
* If enabled several debug objects will render around (0,150,0).
|
||||||
|
*/
|
||||||
|
public static final boolean RENDER_DEBUG_OBJECTS = false;
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<Long, RenderableBoxGroup> boxGroupById = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
// rendering setup
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
private RenderPipeline pipeline;
|
||||||
|
|
||||||
|
private GpuBuffer vertUniformBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public BlazeDhGenericObjectRenderer() { }
|
||||||
|
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init = true;
|
||||||
|
|
||||||
|
this.createPipelines();
|
||||||
|
|
||||||
|
if (RENDER_DEBUG_OBJECTS)
|
||||||
|
{
|
||||||
|
this.addGenericDebugObjects();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void createPipelines()
|
||||||
|
{
|
||||||
|
RenderPipelineBuilderWrapper pipelineBuilder = new RenderPipelineBuilderWrapper();
|
||||||
|
{
|
||||||
|
pipelineBuilder.withFaceCulling(true);
|
||||||
|
pipelineBuilder.withDepthWrite(true);
|
||||||
|
pipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.LESS);
|
||||||
|
pipelineBuilder.withBlend(BlendFunction.TRANSLUCENT); // TRANSLUCENT = new BlendFunction(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||||
|
pipelineBuilder.withColorWrite(true);
|
||||||
|
pipelineBuilder.withPolygonMode(RenderPipelineBuilderWrapper.EDhPolygonMode.FILL);
|
||||||
|
pipelineBuilder.withName("generic_objects");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexShader("generic/blaze/vert");
|
||||||
|
pipelineBuilder.withFragmentShader("generic/blaze/frag");
|
||||||
|
|
||||||
|
pipelineBuilder.withSampler("uLightMap");
|
||||||
|
|
||||||
|
pipelineBuilder.withUniformBuffer("vertUniformBlock");
|
||||||
|
|
||||||
|
VertexFormat vertexFormat = VertexFormat.builder()
|
||||||
|
.add("vPosition", BlazeDhVertexFormatUtil.FLOAT_XYZ_POS)
|
||||||
|
.add("aColor", BlazeDhVertexFormatUtil.RGBA_UBYTE_COLOR)
|
||||||
|
.add("aMaterial", BlazeDhVertexFormatUtil.IRIS_MATERIAL)
|
||||||
|
|
||||||
|
.add("paddingOne", BlazeDhVertexFormatUtil.BYTE_PAD)
|
||||||
|
.add("paddingTwo", BlazeDhVertexFormatUtil.BYTE_PAD)
|
||||||
|
.add("paddingThree", BlazeDhVertexFormatUtil.BYTE_PAD)
|
||||||
|
.build();
|
||||||
|
pipelineBuilder.withVertexFormat(vertexFormat);
|
||||||
|
pipelineBuilder.withVertexMode(RenderPipelineBuilderWrapper.EDhVertexMode.TRIANGLES);
|
||||||
|
}
|
||||||
|
this.pipeline = pipelineBuilder.build();
|
||||||
|
}
|
||||||
|
private void addGenericDebugObjects()
|
||||||
|
{
|
||||||
|
GenericRenderObjectFactory factory = GenericRenderObjectFactory.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
// single giant box
|
||||||
|
IDhApiRenderableBoxGroup singleGiantBoxGroup = factory.createForSingleBox(
|
||||||
|
ModInfo.NAME + ":CyanChunkBox",
|
||||||
|
new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(0,0,0), new DhApiVec3d(16,190,16),
|
||||||
|
new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125),
|
||||||
|
EDhApiBlockMaterial.WATER)
|
||||||
|
);
|
||||||
|
singleGiantBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||||
|
singleGiantBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||||
|
this.add(singleGiantBoxGroup);
|
||||||
|
|
||||||
|
|
||||||
|
// single slender box
|
||||||
|
IDhApiRenderableBoxGroup singleTallBoxGroup = factory.createForSingleBox(
|
||||||
|
ModInfo.NAME + ":GreenBeacon",
|
||||||
|
new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(16,0,31), new DhApiVec3d(17,2000,32),
|
||||||
|
new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125),
|
||||||
|
EDhApiBlockMaterial.ILLUMINATED)
|
||||||
|
);
|
||||||
|
singleTallBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||||
|
singleTallBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||||
|
this.add(singleTallBoxGroup);
|
||||||
|
|
||||||
|
|
||||||
|
// absolute box group
|
||||||
|
ArrayList<DhApiRenderableBox> absBoxList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 18; i++)
|
||||||
|
{
|
||||||
|
absBoxList.add(new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(i,150+i,24), new DhApiVec3d(1+i,151+i,25),
|
||||||
|
new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()),
|
||||||
|
EDhApiBlockMaterial.LAVA
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(ModInfo.NAME + ":OrangeStairs", absBoxList);
|
||||||
|
this.add(absolutePosBoxGroup);
|
||||||
|
|
||||||
|
|
||||||
|
// relative box group
|
||||||
|
ArrayList<DhApiRenderableBox> relBoxList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 8; i+=2)
|
||||||
|
{
|
||||||
|
relBoxList.add(new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(0,i,0), new DhApiVec3d(1,1+i,1),
|
||||||
|
new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()),
|
||||||
|
EDhApiBlockMaterial.METAL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
IDhApiRenderableBoxGroup relativePosBoxGroup = factory.createRelativePositionedGroup(
|
||||||
|
ModInfo.NAME + ":MovingMagentaGroup",
|
||||||
|
new DhApiVec3d(24, 140, 24),
|
||||||
|
relBoxList);
|
||||||
|
relativePosBoxGroup.setPreRenderFunc((event) ->
|
||||||
|
{
|
||||||
|
DhApiVec3d pos = relativePosBoxGroup.getOriginBlockPos();
|
||||||
|
pos.x += event.partialTicks / 2;
|
||||||
|
pos.x %= 32;
|
||||||
|
relativePosBoxGroup.setOriginBlockPos(pos);
|
||||||
|
});
|
||||||
|
this.add(relativePosBoxGroup);
|
||||||
|
|
||||||
|
|
||||||
|
// massive relative box group
|
||||||
|
ArrayList<DhApiRenderableBox> massRelBoxList = new ArrayList<>();
|
||||||
|
for (int x = 0; x < 50*2; x+=2)
|
||||||
|
{
|
||||||
|
for (int z = 0; z < 50*2; z+=2)
|
||||||
|
{
|
||||||
|
massRelBoxList.add(new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(-x, 0, -z), new DhApiVec3d(1-x, 1, 1-z),
|
||||||
|
new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()),
|
||||||
|
EDhApiBlockMaterial.TERRACOTTA
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IDhApiRenderableBoxGroup massRelativePosBoxGroup = factory.createRelativePositionedGroup(
|
||||||
|
ModInfo.NAME + ":MassRedGroup",
|
||||||
|
new DhApiVec3d(-25, 140, 0),
|
||||||
|
massRelBoxList);
|
||||||
|
massRelativePosBoxGroup.setPreRenderFunc((event) ->
|
||||||
|
{
|
||||||
|
DhApiVec3d blockPos = massRelativePosBoxGroup.getOriginBlockPos();
|
||||||
|
blockPos.y += event.partialTicks / 4;
|
||||||
|
if (blockPos.y > 150f)
|
||||||
|
{
|
||||||
|
blockPos.y = 140f;
|
||||||
|
|
||||||
|
Color newColor = (massRelativePosBoxGroup.get(0).color == Color.RED) ? Color.RED.darker() : Color.RED;
|
||||||
|
massRelativePosBoxGroup.forEach((box) -> { box.color = newColor; });
|
||||||
|
massRelativePosBoxGroup.triggerBoxChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
massRelativePosBoxGroup.setOriginBlockPos(blockPos);
|
||||||
|
});
|
||||||
|
this.add(massRelativePosBoxGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// registration //
|
||||||
|
//==============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(IDhApiRenderableBoxGroup iBoxGroup) throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
if (!(iBoxGroup instanceof RenderableBoxGroup))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"], type received: ["+(iBoxGroup != null ? iBoxGroup.getClass() : "NULL")+"].");
|
||||||
|
}
|
||||||
|
RenderableBoxGroup boxGroup = (RenderableBoxGroup) iBoxGroup;
|
||||||
|
if (boxGroup.size() != 0)
|
||||||
|
{
|
||||||
|
// trigger a box change to make sure the initial data is uploaded
|
||||||
|
boxGroup.triggerBoxChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
long id = boxGroup.getId();
|
||||||
|
if (this.boxGroupById.containsKey(id))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("A box group with the ID [" + id + "] is already present.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.boxGroupById.put(id, boxGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IDhApiRenderableBoxGroup remove(long id) { return this.boxGroupById.remove(id); }
|
||||||
|
|
||||||
|
public void clear() { this.boxGroupById.clear(); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========//
|
||||||
|
// rendering //
|
||||||
|
//===========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param renderingWithSsao
|
||||||
|
* if true that means this render call is happening before the SSAO pass
|
||||||
|
* and any objects rendered in this pass will have SSAO applied to them.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void render(RenderParams renderEventParam, IProfilerWrapper profiler, boolean renderingWithSsao)
|
||||||
|
{
|
||||||
|
//==============//
|
||||||
|
// render setup //
|
||||||
|
//==============//
|
||||||
|
//#region
|
||||||
|
|
||||||
|
profiler.push("setup");
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderSetupEvent.class, renderEventParam);
|
||||||
|
|
||||||
|
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
if (BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.isEmpty()
|
||||||
|
|| BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========//
|
||||||
|
// rendering //
|
||||||
|
//===========//
|
||||||
|
//#region
|
||||||
|
|
||||||
|
Collection<RenderableBoxGroup> boxList = this.boxGroupById.values();
|
||||||
|
for (RenderableBoxGroup boxGroup : boxList)
|
||||||
|
{
|
||||||
|
// validation //
|
||||||
|
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
if (boxGroup == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip boxes that shouldn't render this pass
|
||||||
|
if (boxGroup.ssaoEnabled != renderingWithSsao)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
profiler.popPush("render prep");
|
||||||
|
boxGroup.preRender(renderEventParam); // called even if the group is inactive, so the group can be activate if desired
|
||||||
|
|
||||||
|
// ignore inactive groups
|
||||||
|
if (!boxGroup.active)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow API users to cancel this object's rendering
|
||||||
|
boolean cancelRendering = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericObjectRenderEvent.class, new DhApiBeforeGenericObjectRenderEvent.EventParam(renderEventParam, boxGroup));
|
||||||
|
if (cancelRendering)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update instanced data if needed
|
||||||
|
{
|
||||||
|
boxGroup.tryUpdateInstancedDataAsync();
|
||||||
|
|
||||||
|
// skip groups that haven't been uploaded yet
|
||||||
|
if (boxGroup.vertexBufferContainer.getState() != IDhGenericObjectVertexBufferContainer.EState.RENDER)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||||
|
if (shading == null)
|
||||||
|
{
|
||||||
|
shading = DEFAULT_SHADING;
|
||||||
|
}
|
||||||
|
|
||||||
|
// uniforms
|
||||||
|
{
|
||||||
|
int uniformBufferSize = new Std140SizeCalculator()
|
||||||
|
.putIVec3() // uOffsetChunk
|
||||||
|
.putVec3() // uOffsetSubChunk
|
||||||
|
.putIVec3() // uCameraPosChunk
|
||||||
|
.putVec3() // uCameraPosSubChunk
|
||||||
|
|
||||||
|
.putVec3() // aTranslateChunk
|
||||||
|
.putVec3() // aTranslateSubChunk
|
||||||
|
|
||||||
|
.putMat4f() // uProjectionMvm
|
||||||
|
.putInt() // uSkyLight
|
||||||
|
.putInt() // uBlockLight
|
||||||
|
|
||||||
|
.putFloat() // uNorthShading
|
||||||
|
.putFloat() // uSouthShading
|
||||||
|
.putFloat() // uEastShading
|
||||||
|
.putFloat() // uWestShading
|
||||||
|
.putFloat() // uTopShading
|
||||||
|
.putFloat() // uBottomShading
|
||||||
|
.get();
|
||||||
|
|
||||||
|
|
||||||
|
// create data //
|
||||||
|
|
||||||
|
Mat4f projectionMvmMatrix = new Mat4f(renderEventParam.dhProjectionMatrix);
|
||||||
|
projectionMvmMatrix.multiply(renderEventParam.dhModelViewMatrix);
|
||||||
|
|
||||||
|
|
||||||
|
// upload data //
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(uniformBufferSize);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
buffer = Std140Builder.intoBuffer(buffer)
|
||||||
|
.putIVec3(
|
||||||
|
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||||
|
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||||
|
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||||
|
) // uOffsetChunk
|
||||||
|
.putVec3(
|
||||||
|
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||||
|
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||||
|
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||||
|
) // uOffsetSubChunk
|
||||||
|
.putIVec3(
|
||||||
|
LodUtil.getChunkPosFromDouble(camPos.x),
|
||||||
|
LodUtil.getChunkPosFromDouble(camPos.y),
|
||||||
|
LodUtil.getChunkPosFromDouble(camPos.z)
|
||||||
|
) // uCameraPosChunk
|
||||||
|
.putVec3(
|
||||||
|
LodUtil.getSubChunkPosFromDouble(camPos.x),
|
||||||
|
LodUtil.getSubChunkPosFromDouble(camPos.y),
|
||||||
|
LodUtil.getSubChunkPosFromDouble(camPos.z)
|
||||||
|
) // uCameraPosSubChunk
|
||||||
|
|
||||||
|
.putMat4f(projectionMvmMatrix.createJomlMatrix()) // uProjectionMvm
|
||||||
|
.putInt(boxGroup.getSkyLight()) // uSkyLight
|
||||||
|
.putInt(boxGroup.getBlockLight()) // uBlockLight
|
||||||
|
|
||||||
|
.putFloat(shading.north)
|
||||||
|
.putFloat(shading.south)
|
||||||
|
.putFloat(shading.east)
|
||||||
|
.putFloat(shading.west)
|
||||||
|
.putFloat(shading.top)
|
||||||
|
.putFloat(shading.bottom)
|
||||||
|
|
||||||
|
.get()
|
||||||
|
;
|
||||||
|
|
||||||
|
this.vertUniformBuffer = BlazeUniformUtil.createBuffer("vertUniformBlock", uniformBufferSize, this.vertUniformBuffer);
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vertUniformBuffer, 0, uniformBufferSize);
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// render //
|
||||||
|
|
||||||
|
profiler.popPush("rendering");
|
||||||
|
profiler.push(boxGroup.getResourceLocationNamespace());
|
||||||
|
profiler.push(boxGroup.getResourceLocationPath());
|
||||||
|
|
||||||
|
this.renderBoxGroupInstanced(renderEventParam, boxGroup, profiler);
|
||||||
|
|
||||||
|
profiler.pop(); // resource path
|
||||||
|
profiler.pop(); // resource namespace
|
||||||
|
|
||||||
|
boxGroup.postRender(renderEventParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========//
|
||||||
|
// clean up //
|
||||||
|
//==========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
profiler.popPush("cleanup");
|
||||||
|
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderCleanupEvent.class, renderEventParam);
|
||||||
|
|
||||||
|
profiler.pop();
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
}
|
||||||
|
private String getRenderPassName() { return "distantHorizons:McGenericObjectRenderer"; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=====================//
|
||||||
|
// instanced rendering //
|
||||||
|
//=====================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private void renderBoxGroupInstanced(
|
||||||
|
RenderParams renderEventParam,
|
||||||
|
RenderableBoxGroup boxGroup,
|
||||||
|
IProfilerWrapper profiler)
|
||||||
|
{
|
||||||
|
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||||
|
this::getRenderPassName,
|
||||||
|
BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
|
||||||
|
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
|
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
|
||||||
|
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||||
|
{
|
||||||
|
|
||||||
|
// update instance data //
|
||||||
|
|
||||||
|
profiler.push("vertex setup");
|
||||||
|
|
||||||
|
BlazeGenericObjectVertexContainer container = (BlazeGenericObjectVertexContainer) boxGroup.vertexBufferContainer;
|
||||||
|
|
||||||
|
LightMapWrapper lightMapWrapper = (LightMapWrapper) renderEventParam.lightmap;
|
||||||
|
BlazeTextureViewWrapper lightmapTextureViewWrapper = lightMapWrapper.getTextureViewWrapper();
|
||||||
|
renderPass.bindTexture("uLightMap", lightmapTextureViewWrapper.textureView, lightmapTextureViewWrapper.textureSampler);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Bind instance data //
|
||||||
|
profiler.popPush("binding");
|
||||||
|
|
||||||
|
|
||||||
|
renderPass.setUniform("vertUniformBlock", this.vertUniformBuffer);
|
||||||
|
|
||||||
|
// set pipeline
|
||||||
|
renderPass.setPipeline(this.pipeline);
|
||||||
|
renderPass.setIndexBuffer(container.indexGpuBuffer, VertexFormat.IndexType.INT);
|
||||||
|
|
||||||
|
renderPass.setVertexBuffer(0, container.vboGpuBuffer);
|
||||||
|
|
||||||
|
// Draw instanced
|
||||||
|
profiler.popPush("render");
|
||||||
|
if (container.uploadedBoxCount > 0)
|
||||||
|
{
|
||||||
|
renderPass.drawIndexed(
|
||||||
|
/*indexStart*/ 0,
|
||||||
|
/*firstIndex*/0,
|
||||||
|
/*indexCount*/container.uploadedBoxCount * 36, // 36 = 6 faces * 6 verticies per face
|
||||||
|
/*instanceCount*/1);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
profiler.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// F3 menu //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public String getVboRenderDebugMenuString()
|
||||||
|
{
|
||||||
|
// get counts
|
||||||
|
int totalGroupCount = this.boxGroupById.size();
|
||||||
|
int totalBoxCount = 0;
|
||||||
|
|
||||||
|
int activeGroupCount = 0;
|
||||||
|
int activeBoxCount = 0;
|
||||||
|
|
||||||
|
for (long key : this.boxGroupById.keySet())
|
||||||
|
{
|
||||||
|
RenderableBoxGroup renderGroup = this.boxGroupById.get(key);
|
||||||
|
if (renderGroup.active)
|
||||||
|
{
|
||||||
|
activeGroupCount++;
|
||||||
|
activeBoxCount += renderGroup.size();
|
||||||
|
}
|
||||||
|
totalBoxCount += renderGroup.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return "Generic Obj #: " + F3Screen.NUMBER_FORMAT.format(activeGroupCount) + "/" + F3Screen.NUMBER_FORMAT.format(totalGroupCount) + ", " +
|
||||||
|
"Cube #: " + F3Screen.NUMBER_FORMAT.format(activeBoxCount) + "/" + F3Screen.NUMBER_FORMAT.format(totalBoxCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhMetaRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.textures.GpuTexture;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.apply.BlazeDhApplyRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhMetaRenderer;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
|
||||||
|
public class BlazeDhMetaRenderer implements IDhMetaRenderer
|
||||||
|
{
|
||||||
|
public static final BlazeDhMetaRenderer INSTANCE = new BlazeDhMetaRenderer();
|
||||||
|
|
||||||
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
|
||||||
|
|
||||||
|
private BlazeDhApplyRenderer applyRenderer;
|
||||||
|
|
||||||
|
public final BlazeTextureWrapper dhDepthTextureWrapper = BlazeTextureWrapper.createDepth("DhDepthTexture");
|
||||||
|
public final BlazeTextureWrapper dhColorTextureWrapper = BlazeTextureWrapper.createColor("DhColorTexture");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private BlazeDhMetaRenderer()
|
||||||
|
{
|
||||||
|
this.applyRenderer = new BlazeDhApplyRenderer(
|
||||||
|
"dh_apply_to_mc",
|
||||||
|
null,
|
||||||
|
"apply/blaze/vert", "apply/blaze/frag"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=================//
|
||||||
|
// pre/post render //
|
||||||
|
//=================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runRenderPassSetup(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
// textures
|
||||||
|
this.dhDepthTextureWrapper.tryCreateOrResize();
|
||||||
|
this.dhColorTextureWrapper.tryCreateOrResize();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runRenderPassCleanup(RenderParams renderParams) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyToMcTexture(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
GpuTexture mcColorTexture = Minecraft.getInstance().getMainRenderTarget().getColorTexture();
|
||||||
|
this.applyRenderer.render(this.dhColorTextureWrapper.texture, this.dhDepthTextureWrapper.texture, mcColorTexture);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// clear textures //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearDhDepthAndColorTextures(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
this.dhDepthTextureWrapper.clearDepth(1.0f);
|
||||||
|
|
||||||
|
Color color = MC_RENDER.getSkyColor();
|
||||||
|
this.dhColorTextureWrapper.clearColor(ColorUtil.toColorInt(color));
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhRenderApiDefinition {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.objects.BlazeGenericObjectVertexContainer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.postProcessing.BlazeDhFarFadeRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.postProcessing.BlazeDhFogRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.postProcessing.BlazeDhSsaoRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.postProcessing.BlazeVanillaFadeRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.test.BlazeDhTestTriangleRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.buffer.BlazeVertexBufferWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.uniform.BlazeLodUniformBufferWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.ILodContainerUniformBufferWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.*;
|
||||||
|
|
||||||
|
public class BlazeDhRenderApiDefinition extends AbstractDhRenderApiDefinition
|
||||||
|
{
|
||||||
|
//=========//
|
||||||
|
// getters //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public String getApiName() { return "Blaze3D"; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============//
|
||||||
|
// singletons //
|
||||||
|
//============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override public IDhMetaRenderer getMetaRenderer() { return BlazeDhMetaRenderer.INSTANCE; }
|
||||||
|
@Override public IDhTerrainRenderer getTerrainRenderer() { return BlazeDhTerrainRenderer.INSTANCE; }
|
||||||
|
@Override public IDhSsaoRenderer getSsaoRenderer() { return BlazeDhSsaoRenderer.INSTANCE; }
|
||||||
|
@Override public IDhFogRenderer getFogRenderer() { return BlazeDhFogRenderer.INSTANCE; }
|
||||||
|
@Override public IDhFarFadeRenderer getFarFadeRenderer() { return BlazeDhFarFadeRenderer.INSTANCE; }
|
||||||
|
@Override public AbstractDebugWireframeRenderer getDebugWireframeRenderer() { return BlazeDebugWireframeRenderer.INSTANCE; }
|
||||||
|
|
||||||
|
@Override public IDhVanillaFadeRenderer getVanillaFadeRenderer() { return BlazeVanillaFadeRenderer.INSTANCE; }
|
||||||
|
@Override public IDhTestTriangleRenderer getTestTriangleRenderer() { return BlazeDhTestTriangleRenderer.INSTANCE; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========//
|
||||||
|
// factories //
|
||||||
|
//===========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override public IDhGenericRenderer createGenericRenderer() { return new BlazeDhGenericObjectRenderer(); }
|
||||||
|
|
||||||
|
@Override public IVertexBufferWrapper createVboWrapper(String name) { return new BlazeVertexBufferWrapper(name); }
|
||||||
|
@Override public ILodContainerUniformBufferWrapper createLodContainerUniformWrapper() { return new BlazeLodUniformBufferWrapper(); }
|
||||||
|
@Override public IDhGenericObjectVertexBufferContainer createGenericVboContainer() { return new BlazeGenericObjectVertexContainer(); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+367
@@ -0,0 +1,367 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhTerrainRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140Builder;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140SizeCalculator;
|
||||||
|
import com.mojang.blaze3d.pipeline.BlendFunction;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.platform.PolygonMode;
|
||||||
|
import com.mojang.blaze3d.shaders.UniformType;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderPass;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeBufferRenderEvent;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeDhVertexFormatUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeUniformUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.uniform.BlazeLodUniformBufferWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.buffer.BlazeVertexBufferWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||||
|
import com.seibel.distanthorizons.core.util.objects.SortedArraySet;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTerrainRenderer;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
|
||||||
|
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
/** Renders rendering DH's LOD terrain. */
|
||||||
|
public class BlazeDhTerrainRenderer implements IDhTerrainRenderer
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
public static final BlazeDhTerrainRenderer INSTANCE = new BlazeDhTerrainRenderer();
|
||||||
|
|
||||||
|
|
||||||
|
private RenderPipeline opaquePipeline;
|
||||||
|
private RenderPipeline transparentPipeline;
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
private GpuBuffer fragUniformBuffer;
|
||||||
|
private GpuBuffer vertSharedUniformBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private BlazeDhTerrainRenderer() { }
|
||||||
|
|
||||||
|
private void tryInit()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RenderPipelineBuilderWrapper pipelineBuilder = new RenderPipelineBuilderWrapper();
|
||||||
|
{
|
||||||
|
pipelineBuilder.withFaceCulling(true);
|
||||||
|
pipelineBuilder.withDepthWrite(true);
|
||||||
|
pipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.LESS);
|
||||||
|
pipelineBuilder.withColorWrite(true);
|
||||||
|
pipelineBuilder.withPolygonMode(RenderPipelineBuilderWrapper.EDhPolygonMode.FILL);
|
||||||
|
pipelineBuilder.withName("terrain");
|
||||||
|
|
||||||
|
pipelineBuilder.withSampler("uLightMap");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexShader("lod/blaze/vert");
|
||||||
|
pipelineBuilder.withFragmentShader("lod/blaze/frag");
|
||||||
|
|
||||||
|
pipelineBuilder.withUniformBuffer("vertUniqueUniformBlock");
|
||||||
|
pipelineBuilder.withUniformBuffer("vertSharedUniformBlock");
|
||||||
|
pipelineBuilder.withUniformBuffer("fragUniformBlock");
|
||||||
|
|
||||||
|
VertexFormat vertexFormat = VertexFormat.builder()
|
||||||
|
.add("vPosition", BlazeDhVertexFormatUtil.SHORT_XYZ_POS)
|
||||||
|
.add("meta", BlazeDhVertexFormatUtil.META)
|
||||||
|
.add("vColor", BlazeDhVertexFormatUtil.RGBA_UBYTE_COLOR)
|
||||||
|
.add("irisMaterial", BlazeDhVertexFormatUtil.IRIS_MATERIAL)
|
||||||
|
.add("irisNormal", BlazeDhVertexFormatUtil.IRIS_NORMAL)
|
||||||
|
.add("paddingTwo", BlazeDhVertexFormatUtil.BYTE_PAD)
|
||||||
|
.add("paddingThree", BlazeDhVertexFormatUtil.BYTE_PAD) // padding is to make sure the format is a multiple of 4
|
||||||
|
.build();
|
||||||
|
pipelineBuilder.withVertexFormat(vertexFormat);
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexMode(RenderPipelineBuilderWrapper.EDhVertexMode.TRIANGLES);
|
||||||
|
}
|
||||||
|
|
||||||
|
// opaque
|
||||||
|
{
|
||||||
|
pipelineBuilder.withoutBlend();
|
||||||
|
this.opaquePipeline = pipelineBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
// transparent
|
||||||
|
{
|
||||||
|
// TRANSLUCENT = new BlendFunction(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ONE_MINUS_SRC_ALPHA);
|
||||||
|
pipelineBuilder.withBlend(BlendFunction.TRANSLUCENT);
|
||||||
|
this.transparentPipeline = pipelineBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.init = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// render //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(
|
||||||
|
RenderParams renderEventParam,
|
||||||
|
boolean opaquePass,
|
||||||
|
SortedArraySet<LodBufferContainer> bufferContainers,
|
||||||
|
IProfilerWrapper profiler)
|
||||||
|
{
|
||||||
|
this.tryInit();
|
||||||
|
|
||||||
|
|
||||||
|
profiler.push("vert unique uniforms");
|
||||||
|
{
|
||||||
|
// create data //
|
||||||
|
|
||||||
|
for (int lodIndex = 0; lodIndex < bufferContainers.size(); lodIndex++)
|
||||||
|
{
|
||||||
|
LodBufferContainer bufferContainer = bufferContainers.get(lodIndex);
|
||||||
|
bufferContainer.uniformContainer.tryUpload();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
profiler.popPush("vert share uniforms");
|
||||||
|
{
|
||||||
|
Mat4f combinedMatrix = new Mat4f(renderEventParam.dhProjectionMatrix);
|
||||||
|
combinedMatrix.multiply(renderEventParam.dhModelViewMatrix);
|
||||||
|
|
||||||
|
float earthCurveRatio = Config.Client.Advanced.Graphics.Experimental.earthCurveRatio.get();
|
||||||
|
if (earthCurveRatio < -1.0f || earthCurveRatio > 1.0f)
|
||||||
|
{
|
||||||
|
earthCurveRatio = /*6371KM*/ 6371000.0f / earthCurveRatio;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// disable curvature if the config value is between -1 and 1
|
||||||
|
earthCurveRatio = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// upload data //
|
||||||
|
|
||||||
|
int uniformBufferSize = new Std140SizeCalculator()
|
||||||
|
.putInt() // uIsWhiteWorld
|
||||||
|
|
||||||
|
.putFloat() // uWorldYOffset
|
||||||
|
.putFloat() // uMircoOffset
|
||||||
|
.putFloat() // uEarthRadius
|
||||||
|
|
||||||
|
.putVec3() // uCameraPos
|
||||||
|
.putMat4f() // uCombinedMatrix
|
||||||
|
.get();
|
||||||
|
|
||||||
|
ByteBuffer buffer = MemoryUtil.memAlloc(uniformBufferSize);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
Std140Builder.intoBuffer(buffer)
|
||||||
|
.putInt(0) // uIsWhiteWorld
|
||||||
|
|
||||||
|
.putFloat((float) renderEventParam.worldYOffset) // uWorldYOffset
|
||||||
|
.putFloat(0.01f) // uMircoOffset // 0.01 block offset
|
||||||
|
.putFloat(earthCurveRatio) // uEarthRadius
|
||||||
|
|
||||||
|
.putVec3(
|
||||||
|
(float)renderEventParam.exactCameraPosition.x,
|
||||||
|
(float)renderEventParam.exactCameraPosition.y,
|
||||||
|
(float)renderEventParam.exactCameraPosition.z) // uCameraPos
|
||||||
|
.putMat4f(combinedMatrix.createJomlMatrix()) // uCombinedMatrix
|
||||||
|
.get();
|
||||||
|
|
||||||
|
this.vertSharedUniformBuffer = BlazeUniformUtil.createBuffer("vertSharedUniformBlock", uniformBufferSize, this.vertSharedUniformBuffer);
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vertSharedUniformBuffer, 0, uniformBufferSize);
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||||
|
|
||||||
|
MemoryUtil.memFree(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
profiler.popPush("set frag uniforms");
|
||||||
|
{
|
||||||
|
int uniformBufferSize = new Std140SizeCalculator()
|
||||||
|
.putFloat() // uClipDistance
|
||||||
|
.putFloat() // uNoiseIntensity
|
||||||
|
.putInt() // uNoiseSteps
|
||||||
|
.putInt() // uNoiseDropoff
|
||||||
|
.putInt() // uDitherDhRendering
|
||||||
|
.putInt() // uNoiseEnabled
|
||||||
|
.get();
|
||||||
|
|
||||||
|
|
||||||
|
// create data //
|
||||||
|
|
||||||
|
float dhNearClipDistance = RenderUtil.getNearClipPlaneInBlocks();
|
||||||
|
if (!Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||||
|
{
|
||||||
|
// this added value prevents the near clip plane and discard circle from touching, which looks bad
|
||||||
|
dhNearClipDistance += 16f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// upload data //
|
||||||
|
|
||||||
|
ByteBuffer buffer = MemoryUtil.memAlloc(uniformBufferSize);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
buffer = Std140Builder.intoBuffer(buffer)
|
||||||
|
.putFloat(dhNearClipDistance) // uClipDistance
|
||||||
|
.putFloat(Config.Client.Advanced.Graphics.NoiseTexture.noiseIntensity.get()) // uNoiseIntensity
|
||||||
|
.putInt(Config.Client.Advanced.Graphics.NoiseTexture.noiseSteps.get()) // uNoiseSteps
|
||||||
|
.putInt(Config.Client.Advanced.Graphics.NoiseTexture.noiseDropoff.get()) // uNoiseDropoff
|
||||||
|
.putInt(Config.Client.Advanced.Graphics.Quality.ditherDhFade.get() ? 1 : 0) // uDitherDhRendering
|
||||||
|
.putInt(Config.Client.Advanced.Graphics.NoiseTexture.enableNoiseTexture.get() ? 1 : 0) // uNoiseEnabled
|
||||||
|
.get()
|
||||||
|
;
|
||||||
|
|
||||||
|
this.fragUniformBuffer = BlazeUniformUtil.createBuffer("fragUniformBlock", uniformBufferSize, this.fragUniformBuffer);
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.fragUniformBuffer, 0, uniformBufferSize);
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||||
|
MemoryUtil.memFree(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// render pass setup
|
||||||
|
{
|
||||||
|
profiler.popPush("setup");
|
||||||
|
|
||||||
|
// create a render pass
|
||||||
|
try(RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||||
|
this::getRenderPassName,
|
||||||
|
BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView,
|
||||||
|
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
|
BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView,
|
||||||
|
/*optionalDepthValueAsDouble*/ OptionalDouble.empty())
|
||||||
|
)
|
||||||
|
{
|
||||||
|
LightMapWrapper lightMapWrapper = (LightMapWrapper) renderEventParam.lightmap;
|
||||||
|
BlazeTextureViewWrapper lightmapTextureViewWrapper = lightMapWrapper.getTextureViewWrapper();
|
||||||
|
renderPass.bindTexture("uLightMap", lightmapTextureViewWrapper.textureView, lightmapTextureViewWrapper.textureSampler);
|
||||||
|
|
||||||
|
// set pipeline
|
||||||
|
renderPass.setPipeline(opaquePass ? this.opaquePipeline : this.transparentPipeline);
|
||||||
|
|
||||||
|
// shared uniforms
|
||||||
|
renderPass.setUniform("fragUniformBlock", this.fragUniformBuffer);
|
||||||
|
renderPass.setUniform("vertSharedUniformBlock", this.vertSharedUniformBuffer);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (int lodIndex = 0; lodIndex < bufferContainers.size(); lodIndex++)
|
||||||
|
{
|
||||||
|
profiler.popPush("binding");
|
||||||
|
|
||||||
|
LodBufferContainer bufferContainer = bufferContainers.get(lodIndex);
|
||||||
|
BlazeLodUniformBufferWrapper uniformWrapper = (BlazeLodUniformBufferWrapper)bufferContainer.uniformContainer;
|
||||||
|
|
||||||
|
boolean columnBuilderDebugEnabled = Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugEnable.get();
|
||||||
|
if (columnBuilderDebugEnabled)
|
||||||
|
{
|
||||||
|
if (DhSectionPos.getDetailLevel(bufferContainer.pos) == Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugDetailLevel.get()
|
||||||
|
&& DhSectionPos.getX(bufferContainer.pos) == Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugXPos.get()
|
||||||
|
&& DhSectionPos.getZ(bufferContainer.pos) == Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugZPos.get())
|
||||||
|
{
|
||||||
|
int breakpoint = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPass.setUniform("vertUniqueUniformBlock", uniformWrapper.gpuBuffer);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
profiler.popPush("rendering");
|
||||||
|
|
||||||
|
// render each buffer
|
||||||
|
IVertexBufferWrapper[] bufferWrapperList = opaquePass ? bufferContainer.vboOpaqueWrappers : bufferContainer.vboTransparentWrappers;
|
||||||
|
for (int i = 0; i < bufferWrapperList.length; i++)
|
||||||
|
{
|
||||||
|
BlazeVertexBufferWrapper bufferWrapper = (BlazeVertexBufferWrapper) bufferWrapperList[i];
|
||||||
|
if (!bufferWrapper.uploaded
|
||||||
|
|| bufferWrapper.vertexCount == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// fire render event
|
||||||
|
{
|
||||||
|
Vec3d camPos = renderEventParam.exactCameraPosition;
|
||||||
|
Vec3f modelPos = new Vec3f(
|
||||||
|
(float) (bufferContainer.minCornerBlockPos.getX() - camPos.x),
|
||||||
|
(float) (bufferContainer.minCornerBlockPos.getY() - camPos.y),
|
||||||
|
(float) (bufferContainer.minCornerBlockPos.getZ() - camPos.z));
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeBufferRenderEvent.class, new DhApiBeforeBufferRenderEvent.EventParam(renderEventParam, modelPos));
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPass.setIndexBuffer(bufferWrapper.getIndexGpuBuffer(), VertexFormat.IndexType.INT);
|
||||||
|
renderPass.setVertexBuffer(0, bufferWrapper.vertexGpuBuffer); // vertex buffer can only be "0" lol
|
||||||
|
|
||||||
|
if (!bufferWrapper.vertexGpuBuffer.isClosed())
|
||||||
|
{
|
||||||
|
renderPass.drawIndexed(
|
||||||
|
/*indexStart*/ 0,
|
||||||
|
/*firstIndex*/0,
|
||||||
|
/*indexCount*/bufferWrapper.indexCount,
|
||||||
|
/*instanceCount*/1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
profiler.pop();
|
||||||
|
}
|
||||||
|
private String getIndexBufferName() { return "distantHorizons:LodIndexBuffer"; }
|
||||||
|
private String getRenderPassName() { return "distantHorizons:McLodRenderer"; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+270
@@ -0,0 +1,270 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.blaze.apply;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhApplyRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.pipeline.BlendFunction;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderPass;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.textures.*;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeDhVertexFormatUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazePostProcessUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies the given color texture
|
||||||
|
* where the depth (or another attribute) is valid.
|
||||||
|
* Often used to apply post processing effects or
|
||||||
|
* the DH texture to MC's color texture. <br><br>
|
||||||
|
*
|
||||||
|
* @see BlazeDhCopyRenderer
|
||||||
|
*/
|
||||||
|
public class BlazeDhApplyRenderer
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
private RenderPipeline pipeline;
|
||||||
|
|
||||||
|
protected GpuBuffer vboGpuBuffer;
|
||||||
|
|
||||||
|
protected final String name;
|
||||||
|
protected final String identifierName;
|
||||||
|
public String getIdentifierName() { return this.identifierName; }
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private final BlendFunction blendFunction;
|
||||||
|
private final String vertexShaderPath;
|
||||||
|
private final String fragmentShaderPath;
|
||||||
|
|
||||||
|
private final BlazeTextureViewWrapper sourceColorTextureViewWrapper = new BlazeTextureViewWrapper();
|
||||||
|
private final BlazeTextureViewWrapper sourceDepthTextureViewWrapper = new BlazeTextureViewWrapper();
|
||||||
|
|
||||||
|
private final BlazeTextureViewWrapper destinationColorTextureViewWrapper = new BlazeTextureViewWrapper();
|
||||||
|
/** We don't want to actually write any depth data, but blaze3D complains if we don't bind a depth texture. */
|
||||||
|
private final BlazeTextureWrapper dummyDepthTextureWrapper = BlazeTextureWrapper.createDepth("apply_dummy_depth");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be set for special application shaders that need
|
||||||
|
* extra information. <br><br>
|
||||||
|
*
|
||||||
|
* will be an empty array if unneeded
|
||||||
|
*/
|
||||||
|
private final String[] uniformNames;
|
||||||
|
/** will be an empty array if unneeded */
|
||||||
|
private final GpuBuffer[] uniformBuffers;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
public BlazeDhApplyRenderer(
|
||||||
|
String name,
|
||||||
|
@Nullable BlendFunction blendFunction,
|
||||||
|
String vertexShaderPath, String fragmentShaderPath
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this(
|
||||||
|
name,
|
||||||
|
blendFunction,
|
||||||
|
vertexShaderPath, fragmentShaderPath,
|
||||||
|
new String[0] // no extra uniforms
|
||||||
|
);
|
||||||
|
}
|
||||||
|
public BlazeDhApplyRenderer(
|
||||||
|
String name,
|
||||||
|
@Nullable BlendFunction blendFunction,
|
||||||
|
String vertexShaderPath, String fragmentShaderPath,
|
||||||
|
String[] uniformNames
|
||||||
|
)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.identifierName = "distanthorizons:"+this.name;
|
||||||
|
this.blendFunction = blendFunction;
|
||||||
|
|
||||||
|
this.vertexShaderPath = vertexShaderPath;
|
||||||
|
this.fragmentShaderPath = fragmentShaderPath;
|
||||||
|
|
||||||
|
this.uniformNames = uniformNames;
|
||||||
|
this.uniformBuffers = new GpuBuffer[this.uniformNames.length];
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryInit(
|
||||||
|
GpuTexture sourceColorTexture,
|
||||||
|
GpuTexture sourceDepthTexture,
|
||||||
|
GpuTexture destinationColorTexture)
|
||||||
|
{
|
||||||
|
// one-time setup
|
||||||
|
if (this.pipeline == null)
|
||||||
|
{
|
||||||
|
this.createPipeline();
|
||||||
|
this.vboGpuBuffer = BlazePostProcessUtil.createAndUploadScreenVertexData(this.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sourceColorTextureViewWrapper.tryWrap(sourceColorTexture);
|
||||||
|
this.sourceDepthTextureViewWrapper.tryWrap(sourceDepthTexture);
|
||||||
|
|
||||||
|
this.destinationColorTextureViewWrapper.tryWrap(destinationColorTexture);
|
||||||
|
|
||||||
|
}
|
||||||
|
private void createPipeline()
|
||||||
|
{
|
||||||
|
RenderPipelineBuilderWrapper pipelineBuilder = new RenderPipelineBuilderWrapper();
|
||||||
|
{
|
||||||
|
pipelineBuilder.withFaceCulling(false);
|
||||||
|
pipelineBuilder.withDepthWrite(false);
|
||||||
|
pipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.NONE);
|
||||||
|
pipelineBuilder.withColorWrite(true);
|
||||||
|
|
||||||
|
if (this.blendFunction != null)
|
||||||
|
{
|
||||||
|
pipelineBuilder.withBlend(this.blendFunction);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pipelineBuilder.withoutBlend();
|
||||||
|
}
|
||||||
|
|
||||||
|
pipelineBuilder.withPolygonMode(RenderPipelineBuilderWrapper.EDhPolygonMode.FILL);
|
||||||
|
pipelineBuilder.withName(this.name);
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexShader(this.vertexShaderPath);
|
||||||
|
pipelineBuilder.withFragmentShader(this.fragmentShaderPath);
|
||||||
|
|
||||||
|
for (int i = 0; i < this.uniformNames.length; i++)
|
||||||
|
{
|
||||||
|
String uniformName = this.uniformNames[i];
|
||||||
|
pipelineBuilder.withUniformBuffer(uniformName);
|
||||||
|
}
|
||||||
|
|
||||||
|
pipelineBuilder.withSampler("uSourceColorTexture");
|
||||||
|
pipelineBuilder.withSampler("uSourceDepthTexture");
|
||||||
|
|
||||||
|
VertexFormat vertexFormat = VertexFormat.builder()
|
||||||
|
.add("vPosition", BlazeDhVertexFormatUtil.SCREEN_POS)
|
||||||
|
.build();
|
||||||
|
pipelineBuilder.withVertexFormat(vertexFormat);
|
||||||
|
pipelineBuilder.withVertexMode(RenderPipelineBuilderWrapper.EDhVertexMode.TRIANGLE_FAN);
|
||||||
|
}
|
||||||
|
this.pipeline = pipelineBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// render //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public void setUniform(String uniformName, GpuBuffer uniformBuffer)
|
||||||
|
{
|
||||||
|
// the uniform array should be short enough (less than 10 items)
|
||||||
|
// where a sequential search should be plenty fast
|
||||||
|
for (int i = 0; i < this.uniformNames.length; i++)
|
||||||
|
{
|
||||||
|
String nameAtIndex = this.uniformNames[i];
|
||||||
|
if (nameAtIndex.equals(uniformName))
|
||||||
|
{
|
||||||
|
this.uniformBuffers[i] = uniformBuffer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void render(
|
||||||
|
GpuTexture sourceColorTexture,
|
||||||
|
GpuTexture sourceDepthTexture,
|
||||||
|
GpuTexture destinationColorTexture)
|
||||||
|
{
|
||||||
|
this.tryInit(sourceColorTexture, sourceDepthTexture, destinationColorTexture);
|
||||||
|
|
||||||
|
this.dummyDepthTextureWrapper.tryCreateOrResize();
|
||||||
|
|
||||||
|
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||||
|
this::getIdentifierName,
|
||||||
|
this.destinationColorTextureViewWrapper.textureView,
|
||||||
|
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
|
this.dummyDepthTextureWrapper.textureView,
|
||||||
|
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||||
|
{
|
||||||
|
renderPass.bindTexture("uSourceColorTexture", this.sourceColorTextureViewWrapper.textureView, this.sourceColorTextureViewWrapper.textureSampler);
|
||||||
|
renderPass.bindTexture("uSourceDepthTexture", this.sourceDepthTextureViewWrapper.textureView, this.sourceDepthTextureViewWrapper.textureSampler);
|
||||||
|
|
||||||
|
for (int i = 0; i < this.uniformNames.length; i++)
|
||||||
|
{
|
||||||
|
String uniformName = this.uniformNames[i];
|
||||||
|
GpuBuffer uniformBuffer = this.uniformBuffers[i];
|
||||||
|
if (uniformBuffer == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Missing uniform ["+uniformName+"], please set the uniform before rendering.");
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPass.setUniform(uniformName, uniformBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderPass.setVertexBuffer(0, this.vboGpuBuffer);
|
||||||
|
renderPass.setPipeline(this.pipeline);
|
||||||
|
|
||||||
|
renderPass.draw(/*indexStart*/ 0, /*indexCount*/ 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// clear the uniforms after rendering
|
||||||
|
// so we can check if they're missing during next frame's rendering
|
||||||
|
if (ModInfo.IS_DEV_BUILD)
|
||||||
|
{
|
||||||
|
Arrays.fill(this.uniformBuffers, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+168
@@ -0,0 +1,168 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.blaze.apply;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhCopyRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderPass;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.textures.*;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazePostProcessUtil;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Blindly copies one texture into another.
|
||||||
|
*
|
||||||
|
* @see BlazeDhApplyRenderer
|
||||||
|
*/
|
||||||
|
public class BlazeDhCopyRenderer
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
public static final BlazeDhCopyRenderer INSTANCE = new BlazeDhCopyRenderer();
|
||||||
|
|
||||||
|
private RenderPipeline pipeline;
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
private GpuBuffer vboGpuBuffer;
|
||||||
|
|
||||||
|
private BlazeTextureWrapper dummyDepthTextureWrapper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private BlazeDhCopyRenderer() { }
|
||||||
|
|
||||||
|
private void tryInit()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init = true;
|
||||||
|
|
||||||
|
|
||||||
|
this.dummyDepthTextureWrapper = BlazeTextureWrapper.createDepth("dh_copy_depth_texture");
|
||||||
|
|
||||||
|
RenderPipelineBuilderWrapper pipelineBuilder = new RenderPipelineBuilderWrapper();
|
||||||
|
{
|
||||||
|
pipelineBuilder.withFaceCulling(false);
|
||||||
|
pipelineBuilder.withDepthWrite(false);
|
||||||
|
pipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.NONE);
|
||||||
|
pipelineBuilder.withColorWrite(true);
|
||||||
|
pipelineBuilder.withoutBlend();
|
||||||
|
pipelineBuilder.withPolygonMode(RenderPipelineBuilderWrapper.EDhPolygonMode.FILL);
|
||||||
|
pipelineBuilder.withName("copy");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexShader("copy/blaze/vert");
|
||||||
|
pipelineBuilder.withFragmentShader("copy/blaze/frag");
|
||||||
|
|
||||||
|
pipelineBuilder.withSampler("uCopyTexture");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexFormat(BlazePostProcessUtil.createVertexFormat());
|
||||||
|
pipelineBuilder.withVertexMode(RenderPipelineBuilderWrapper.EDhVertexMode.TRIANGLE_FAN);
|
||||||
|
}
|
||||||
|
this.pipeline = pipelineBuilder.build();
|
||||||
|
|
||||||
|
|
||||||
|
this.vboGpuBuffer = BlazePostProcessUtil.createAndUploadScreenVertexData("McCopyRenderer");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// render //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public void render(
|
||||||
|
BlazeTextureWrapper sourceColorTextureWrapper,
|
||||||
|
BlazeTextureViewWrapper destinationColorTextureWrapper)
|
||||||
|
{
|
||||||
|
this.render(
|
||||||
|
sourceColorTextureWrapper.textureView, sourceColorTextureWrapper.textureSampler,
|
||||||
|
destinationColorTextureWrapper.textureView);
|
||||||
|
}
|
||||||
|
public void render(
|
||||||
|
BlazeTextureWrapper sourceColorTextureWrapper,
|
||||||
|
BlazeTextureWrapper destinationColorTextureWrapper)
|
||||||
|
{
|
||||||
|
this.render(
|
||||||
|
sourceColorTextureWrapper.textureView, sourceColorTextureWrapper.textureSampler,
|
||||||
|
destinationColorTextureWrapper.textureView);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void render(
|
||||||
|
GpuTextureView sourceTextureView,
|
||||||
|
GpuSampler sourceTextureSampler,
|
||||||
|
GpuTextureView destinationTextureView)
|
||||||
|
{
|
||||||
|
this.tryInit();
|
||||||
|
|
||||||
|
this.dummyDepthTextureWrapper.tryCreateOrResize();
|
||||||
|
|
||||||
|
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||||
|
this::getRenderPassName,
|
||||||
|
destinationTextureView,
|
||||||
|
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
|
this.dummyDepthTextureWrapper.textureView,
|
||||||
|
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||||
|
{
|
||||||
|
renderPass.bindTexture("uCopyTexture", sourceTextureView, sourceTextureSampler);
|
||||||
|
|
||||||
|
renderPass.setVertexBuffer(0, this.vboGpuBuffer); // vertex buffer can only be "0" lol
|
||||||
|
|
||||||
|
renderPass.setPipeline(this.pipeline);
|
||||||
|
renderPass.draw(/*indexStart*/ 0, /*indexCount*/ 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getRenderPassName() { return "distantHorizons:McCopyRenderer"; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+299
@@ -0,0 +1,299 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze.objects;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeGenericObjectVertexContainer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.enums.GLEnums;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup;
|
||||||
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For use by {@link RenderableBoxGroup}
|
||||||
|
*
|
||||||
|
* @see RenderableBoxGroup
|
||||||
|
*/
|
||||||
|
public class BlazeGenericObjectVertexContainer implements IDhGenericObjectVertexBufferContainer
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
private static final int[] BOX_INDICES = {
|
||||||
|
//region
|
||||||
|
// min X, vertical face
|
||||||
|
2, 1, 0,
|
||||||
|
0, 3, 2,
|
||||||
|
// max X, vertical face
|
||||||
|
6, 5, 4,
|
||||||
|
4, 7, 6,
|
||||||
|
|
||||||
|
// min Z, vertical face
|
||||||
|
10, 9, 8,
|
||||||
|
8, 11, 10,
|
||||||
|
// max Z, vertical face
|
||||||
|
14, 13, 12,
|
||||||
|
12, 15, 14,
|
||||||
|
|
||||||
|
// min Y, horizontal face
|
||||||
|
18, 17, 16,
|
||||||
|
16, 19, 18,
|
||||||
|
// max Y, horizontal face
|
||||||
|
20, 21, 22,
|
||||||
|
22, 23, 20,
|
||||||
|
//endregion
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public GpuBuffer vboGpuBuffer;
|
||||||
|
public GpuBuffer indexGpuBuffer;
|
||||||
|
|
||||||
|
private ByteBuffer vertexBuffer = ByteBuffer.allocateDirect(0);
|
||||||
|
private ByteBuffer indexBuffer = ByteBuffer.allocateDirect(0);
|
||||||
|
|
||||||
|
public int uploadedBoxCount = 0;
|
||||||
|
|
||||||
|
private EState state = EState.NEW;
|
||||||
|
@Override
|
||||||
|
public IDhGenericObjectVertexBufferContainer.EState getState() { return this.state; }
|
||||||
|
@Override
|
||||||
|
public void setState(IDhGenericObjectVertexBufferContainer.EState state) { this.state = state; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========================//
|
||||||
|
// render building/uploading //
|
||||||
|
//===========================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateVertexData(List<DhApiRenderableBox> uploadBoxList)
|
||||||
|
{
|
||||||
|
int boxCount = uploadBoxList.size();
|
||||||
|
|
||||||
|
// recreate the data arrays if their size is different
|
||||||
|
if (this.uploadedBoxCount != boxCount)
|
||||||
|
{
|
||||||
|
this.uploadedBoxCount = boxCount;
|
||||||
|
|
||||||
|
int vertexBufferSize = this.vertexBufferSize();
|
||||||
|
this.vertexBuffer = ByteBuffer.allocateDirect(vertexBufferSize);
|
||||||
|
this.vertexBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
|
||||||
|
int indexBufferSize = this.indexBufferSize();
|
||||||
|
this.indexBuffer = ByteBuffer.allocateDirect(indexBufferSize);
|
||||||
|
this.indexBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
}
|
||||||
|
this.vertexBuffer.position(0);
|
||||||
|
this.indexBuffer.position(0);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (int boxIndex = 0; boxIndex < boxCount; boxIndex++)
|
||||||
|
{
|
||||||
|
// index
|
||||||
|
int indexOffset = (boxIndex * 24 /*24 is the number of vertices in a box*/);
|
||||||
|
for (int i = 0; i < BOX_INDICES.length; i++)
|
||||||
|
{
|
||||||
|
this.indexBuffer.putInt(BOX_INDICES[i] + indexOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// vertex
|
||||||
|
DhApiRenderableBox box = uploadBoxList.get(boxIndex);
|
||||||
|
|
||||||
|
final double[] boxVertices =
|
||||||
|
{
|
||||||
|
//region
|
||||||
|
// Pos x y z
|
||||||
|
|
||||||
|
// min X, vertical face
|
||||||
|
box.minPos.x, box.minPos.y, box.minPos.z,
|
||||||
|
box.maxPos.x, box.minPos.y, box.minPos.z,
|
||||||
|
box.maxPos.x, box.maxPos.y, box.minPos.z,
|
||||||
|
box.minPos.x, box.maxPos.y, box.minPos.z,
|
||||||
|
// max X, vertical face
|
||||||
|
box.minPos.x, box.maxPos.y, box.maxPos.z,
|
||||||
|
box.maxPos.x, box.maxPos.y, box.maxPos.z,
|
||||||
|
box.maxPos.x, box.minPos.y, box.maxPos.z,
|
||||||
|
box.minPos.x, box.minPos.y, box.maxPos.z,
|
||||||
|
|
||||||
|
// min Z, vertical face
|
||||||
|
box.minPos.x, box.minPos.y, box.maxPos.z,
|
||||||
|
box.minPos.x, box.minPos.y, box.minPos.z,
|
||||||
|
box.minPos.x, box.maxPos.y, box.minPos.z,
|
||||||
|
box.minPos.x, box.maxPos.y, box.maxPos.z,
|
||||||
|
// max Z, vertical face
|
||||||
|
box.maxPos.x, box.minPos.y, box.maxPos.z,
|
||||||
|
box.maxPos.x, box.maxPos.y, box.maxPos.z,
|
||||||
|
box.maxPos.x, box.maxPos.y, box.minPos.z,
|
||||||
|
box.maxPos.x, box.minPos.y, box.minPos.z,
|
||||||
|
|
||||||
|
// min Y, horizontal face
|
||||||
|
box.minPos.x, box.minPos.y, box.maxPos.z,
|
||||||
|
box.maxPos.x, box.minPos.y, box.maxPos.z,
|
||||||
|
box.maxPos.x, box.minPos.y, box.minPos.z,
|
||||||
|
box.minPos.x, box.minPos.y, box.minPos.z,
|
||||||
|
// max Y, horizontal face
|
||||||
|
box.minPos.x, box.maxPos.y, box.maxPos.z,
|
||||||
|
box.maxPos.x, box.maxPos.y, box.maxPos.z,
|
||||||
|
box.maxPos.x, box.maxPos.y, box.minPos.z,
|
||||||
|
box.minPos.x, box.maxPos.y, box.minPos.z,
|
||||||
|
//endregion
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int vertexIndex = 0; vertexIndex < boxVertices.length; vertexIndex+=3)
|
||||||
|
{
|
||||||
|
this.vertexBuffer.putFloat((float)boxVertices[vertexIndex]); // x
|
||||||
|
this.vertexBuffer.putFloat((float)boxVertices[vertexIndex+1]); // y
|
||||||
|
this.vertexBuffer.putFloat((float)boxVertices[vertexIndex+2]); // z
|
||||||
|
|
||||||
|
int color = ColorUtil.toColorInt(box.color);
|
||||||
|
byte r = (byte) ColorUtil.getRed(color);
|
||||||
|
byte g = (byte) ColorUtil.getGreen(color);
|
||||||
|
byte b = (byte) ColorUtil.getBlue(color);
|
||||||
|
byte a = (byte) ColorUtil.getAlpha(color);
|
||||||
|
this.vertexBuffer.put(r);
|
||||||
|
this.vertexBuffer.put(g);
|
||||||
|
this.vertexBuffer.put(b);
|
||||||
|
this.vertexBuffer.put(a);
|
||||||
|
|
||||||
|
this.vertexBuffer.put(box.material);
|
||||||
|
|
||||||
|
// padding so the vertex format's byte count is a multiple of 4
|
||||||
|
this.vertexBuffer.put((byte)0);
|
||||||
|
this.vertexBuffer.put((byte)0);
|
||||||
|
this.vertexBuffer.put((byte)0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.vertexBuffer.flip();
|
||||||
|
this.indexBuffer.flip();
|
||||||
|
}
|
||||||
|
|
||||||
|
private int vertexBufferSize()
|
||||||
|
{
|
||||||
|
// minimum of 1 box to prevent trying to create a buffer of size 0
|
||||||
|
int boxCount = Math.max(this.uploadedBoxCount, 1);
|
||||||
|
|
||||||
|
int faceCount = boxCount * 6; // 6 faces on a cube
|
||||||
|
int vertexCount = faceCount * 6; // 6 vertices per cube
|
||||||
|
|
||||||
|
int byteSize = vertexCount * 3 * Float.BYTES; // x,y,z
|
||||||
|
byteSize += vertexCount * 4; // r,g,b,a
|
||||||
|
byteSize += 1; // material
|
||||||
|
return byteSize;
|
||||||
|
}
|
||||||
|
private int indexBufferSize()
|
||||||
|
{
|
||||||
|
// minimum of 1 box to prevent trying to create a buffer of size 0
|
||||||
|
int boxCount = Math.max(this.uploadedBoxCount, 1);
|
||||||
|
|
||||||
|
int quadCount = boxCount * 6 * 6; // 6 faces with 6 vertices each
|
||||||
|
int byteSize = quadCount * GLEnums.getTypeSize(GL32.GL_UNSIGNED_INT);
|
||||||
|
return byteSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadDataToGpu()
|
||||||
|
{
|
||||||
|
// vertex
|
||||||
|
{
|
||||||
|
int totalVertexByteSize = this.vertexBufferSize();
|
||||||
|
if (this.vboGpuBuffer == null
|
||||||
|
// recreating if the size changes is always necessary (even if we only need a smaller amount)
|
||||||
|
// due to a bug on Mac where it will attempt to render anything allocated in the buffer
|
||||||
|
|| this.vboGpuBuffer.size() != totalVertexByteSize)
|
||||||
|
{
|
||||||
|
if (this.vboGpuBuffer != null)
|
||||||
|
{
|
||||||
|
this.vboGpuBuffer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_VERTEX;
|
||||||
|
this.vboGpuBuffer = GPU_DEVICE.createBuffer(this::getVertexBufferName, usage, totalVertexByteSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vboGpuBuffer, /*offset*/0, totalVertexByteSize);
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, this.vertexBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// index
|
||||||
|
{
|
||||||
|
int totalVertexByteSize = this.indexBufferSize();
|
||||||
|
if (this.indexGpuBuffer == null
|
||||||
|
// recreating if the size changes is always necessary (even if we only need a smaller amount)
|
||||||
|
// due to a bug on Mac where it will attempt to render anything allocated in the buffer
|
||||||
|
|| this.indexGpuBuffer.size() != totalVertexByteSize)
|
||||||
|
{
|
||||||
|
if (this.indexGpuBuffer != null)
|
||||||
|
{
|
||||||
|
this.indexGpuBuffer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_INDEX;
|
||||||
|
this.indexGpuBuffer = GPU_DEVICE.createBuffer(this::getIndexBufferName, usage, totalVertexByteSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
int offset = 0;
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.indexGpuBuffer, offset, totalVertexByteSize);
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, this.indexBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String getVertexBufferName() { return "distantHorizons:GenericVertexBuffer"; }
|
||||||
|
private String getIndexBufferName() { return "distantHorizons:GenericIndexBuffer"; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("BlazeGenericObjectVertexContainer close", () ->
|
||||||
|
{
|
||||||
|
if (this.vboGpuBuffer != null)
|
||||||
|
{
|
||||||
|
this.vboGpuBuffer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.indexGpuBuffer != null)
|
||||||
|
{
|
||||||
|
this.indexGpuBuffer.close();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+237
@@ -0,0 +1,237 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.blaze.postProcessing;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhFarFadeRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140Builder;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140SizeCalculator;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderPass;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.BlazeDhMetaRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.apply.BlazeDhCopyRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazePostProcessUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeUniformUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhFarFadeRenderer;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fades out DH's far clip plane
|
||||||
|
*/
|
||||||
|
public class BlazeDhFarFadeRenderer implements IDhFarFadeRenderer
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
public static final BlazeDhFarFadeRenderer INSTANCE = new BlazeDhFarFadeRenderer();
|
||||||
|
|
||||||
|
private RenderPipeline pipeline;
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
private GpuBuffer fragUniformBuffer;
|
||||||
|
|
||||||
|
private GpuBuffer vboGpuBuffer;
|
||||||
|
|
||||||
|
private final BlazeTextureWrapper dhFadeColorTextureWrapper = BlazeTextureWrapper.createColor("dh_far_fade_color_texture");
|
||||||
|
/** We don't want to actually write any depth data, but blaze3D complains if we don't bind a depth texture. */
|
||||||
|
private final BlazeTextureWrapper dhFadeDepthTextureWrapper = BlazeTextureWrapper.createDepth("dh_far_fade_depth_texture");
|
||||||
|
|
||||||
|
private final BlazeTextureViewWrapper mcColorTextureViewWrapper = new BlazeTextureViewWrapper();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private BlazeDhFarFadeRenderer() { }
|
||||||
|
|
||||||
|
private void tryInit()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RenderPipelineBuilderWrapper pipelineBuilder = new RenderPipelineBuilderWrapper();
|
||||||
|
{
|
||||||
|
pipelineBuilder.withFaceCulling(false);
|
||||||
|
pipelineBuilder.withDepthWrite(false);
|
||||||
|
pipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.NONE);
|
||||||
|
pipelineBuilder.withColorWrite(true);
|
||||||
|
pipelineBuilder.withoutBlend();
|
||||||
|
pipelineBuilder.withPolygonMode(RenderPipelineBuilderWrapper.EDhPolygonMode.FILL);
|
||||||
|
pipelineBuilder.withName("far_fade");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexShader("fade/blaze/vert");
|
||||||
|
pipelineBuilder.withFragmentShader("fade/blaze/dh_fade");
|
||||||
|
|
||||||
|
pipelineBuilder.withSampler("uMcColorTexture");
|
||||||
|
|
||||||
|
pipelineBuilder.withSampler("uDhDepthTexture");
|
||||||
|
pipelineBuilder.withSampler("uDhColorTexture");
|
||||||
|
|
||||||
|
pipelineBuilder.withUniformBuffer("fragUniformBlock");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexFormat(BlazePostProcessUtil.createVertexFormat());
|
||||||
|
pipelineBuilder.withVertexMode(RenderPipelineBuilderWrapper.EDhVertexMode.TRIANGLE_FAN);
|
||||||
|
}
|
||||||
|
this.pipeline = pipelineBuilder.build();
|
||||||
|
|
||||||
|
|
||||||
|
this.vboGpuBuffer = BlazePostProcessUtil.createAndUploadScreenVertexData("McFadeRenderer");
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// render //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
this.tryInit();
|
||||||
|
|
||||||
|
|
||||||
|
if (BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.isEmpty()
|
||||||
|
|| BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// textures
|
||||||
|
this.dhFadeColorTextureWrapper.tryCreateOrResize();
|
||||||
|
this.mcColorTextureViewWrapper.tryWrap(Minecraft.getInstance().getMainRenderTarget().getColorTexture());
|
||||||
|
|
||||||
|
this.dhFadeDepthTextureWrapper.tryCreateOrResize();
|
||||||
|
|
||||||
|
{
|
||||||
|
int uniformBufferSize = new Std140SizeCalculator()
|
||||||
|
.putFloat() // uStartFadeBlockDistance
|
||||||
|
.putFloat() // uEndFadeBlockDistance
|
||||||
|
.putMat4f() // uDhInvMvmProj
|
||||||
|
.get();
|
||||||
|
|
||||||
|
|
||||||
|
// create data //
|
||||||
|
|
||||||
|
float dhFarClipDistance = RenderUtil.getFarClipPlaneDistanceInBlocks();
|
||||||
|
float fadeStartDistance = dhFarClipDistance * 0.5f;
|
||||||
|
float fadeEndDistance = dhFarClipDistance * 0.9f;
|
||||||
|
|
||||||
|
|
||||||
|
Mat4f dhProjectionMatrix = RenderUtil.createLodProjectionMatrix(renderParams.mcProjectionMatrix);
|
||||||
|
Mat4f dhModelViewMatrix = RenderUtil.createLodModelViewMatrix(renderParams.mcModelViewMatrix);
|
||||||
|
|
||||||
|
Mat4f inverseDhMvmProjMatrix = new Mat4f(dhProjectionMatrix);
|
||||||
|
inverseDhMvmProjMatrix.multiply(dhModelViewMatrix);
|
||||||
|
inverseDhMvmProjMatrix.invert();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// upload data //
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(uniformBufferSize);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
buffer = Std140Builder.intoBuffer(buffer)
|
||||||
|
.putFloat(fadeStartDistance) // uStartFadeBlockDistance
|
||||||
|
.putFloat(fadeEndDistance) // uEndFadeBlockDistance
|
||||||
|
.putMat4f(inverseDhMvmProjMatrix.createJomlMatrix()) // uDhInvMvmProj
|
||||||
|
.get()
|
||||||
|
;
|
||||||
|
|
||||||
|
this.fragUniformBuffer = BlazeUniformUtil.createBuffer("fragUniformBlock", uniformBufferSize, this.fragUniformBuffer);
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.fragUniformBuffer, 0, uniformBufferSize);
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.renderFadeToTexture();
|
||||||
|
BlazeDhCopyRenderer.INSTANCE.render(this.dhFadeColorTextureWrapper, BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderFadeToTexture()
|
||||||
|
{
|
||||||
|
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||||
|
this::getRenderPassName,
|
||||||
|
this.dhFadeColorTextureWrapper.textureView,
|
||||||
|
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
|
this.dhFadeDepthTextureWrapper.textureView,
|
||||||
|
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||||
|
{
|
||||||
|
// MC texture
|
||||||
|
renderPass.bindTexture("uMcColorTexture", this.mcColorTextureViewWrapper.textureView, this.mcColorTextureViewWrapper.textureSampler);
|
||||||
|
|
||||||
|
// DH textures
|
||||||
|
renderPass.bindTexture("uDhDepthTexture", BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView, BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureSampler);
|
||||||
|
renderPass.bindTexture("uDhColorTexture", BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView, BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureSampler);
|
||||||
|
|
||||||
|
renderPass.setUniform("fragUniformBlock", this.fragUniformBuffer);
|
||||||
|
|
||||||
|
renderPass.setVertexBuffer(0, this.vboGpuBuffer); // vertex buffer can only be "0" lol
|
||||||
|
renderPass.setPipeline(this.pipeline);
|
||||||
|
|
||||||
|
renderPass.draw(/*indexStart*/ 0, /*indexCount*/ 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String getRenderPassName() { return "distantHorizons:McFadeRenderer"; }
|
||||||
|
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+362
@@ -0,0 +1,362 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.blaze.postProcessing;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhFogRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140Builder;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140SizeCalculator;
|
||||||
|
import com.mojang.blaze3d.pipeline.BlendFunction;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.platform.DestFactor;
|
||||||
|
import com.mojang.blaze3d.platform.SourceFactor;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderPass;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogColorMode;
|
||||||
|
import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogDirection;
|
||||||
|
import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogMixMode;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.BlazeDhMetaRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.apply.BlazeDhApplyRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazePostProcessUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeUniformUtil;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhFogRenderer;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders fog onto the LODs.
|
||||||
|
*/
|
||||||
|
public class BlazeDhFogRenderer implements IDhFogRenderer
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
public static final BlazeDhFogRenderer INSTANCE = new BlazeDhFogRenderer();
|
||||||
|
|
||||||
|
|
||||||
|
private BlazeDhApplyRenderer applyRenderer;
|
||||||
|
|
||||||
|
private RenderPipeline pipeline;
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
private GpuBuffer fragUniformBuffer;
|
||||||
|
|
||||||
|
private GpuBuffer vboGpuBuffer;
|
||||||
|
|
||||||
|
private final BlazeTextureWrapper fogColorTextureWrapper = BlazeTextureWrapper.createColor("dh_fog_color_texture");
|
||||||
|
/** We don't want to actually write any depth data, but blaze3D complains if we don't bind a depth texture. */
|
||||||
|
private final BlazeTextureWrapper fogDepthTextureWrapper = BlazeTextureWrapper.createDepth("dh_fog_depth_texture");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private BlazeDhFogRenderer() { }
|
||||||
|
|
||||||
|
private void tryInit()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.applyRenderer = new BlazeDhApplyRenderer(
|
||||||
|
"fog_apply_to_dh",
|
||||||
|
new BlendFunction(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA, SourceFactor.ONE, DestFactor.ONE_MINUS_SRC_ALPHA),
|
||||||
|
"apply/blaze/vert", "apply/blaze/frag"
|
||||||
|
);
|
||||||
|
|
||||||
|
RenderPipelineBuilderWrapper pipelineBuilder = new RenderPipelineBuilderWrapper();
|
||||||
|
{
|
||||||
|
pipelineBuilder.withFaceCulling(false);
|
||||||
|
pipelineBuilder.withDepthWrite(false);
|
||||||
|
pipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.NONE);
|
||||||
|
pipelineBuilder.withColorWrite(true);
|
||||||
|
pipelineBuilder.withoutBlend();
|
||||||
|
pipelineBuilder.withPolygonMode(RenderPipelineBuilderWrapper.EDhPolygonMode.FILL);
|
||||||
|
pipelineBuilder.withName("fog_render");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexShader("fog/blaze/vert");
|
||||||
|
pipelineBuilder.withFragmentShader("fog/blaze/frag");
|
||||||
|
|
||||||
|
pipelineBuilder.withSampler("uDhDepthTexture");
|
||||||
|
|
||||||
|
pipelineBuilder.withUniformBuffer("fragUniformBlock");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexFormat(BlazePostProcessUtil.createVertexFormat());
|
||||||
|
pipelineBuilder.withVertexMode(RenderPipelineBuilderWrapper.EDhVertexMode.TRIANGLE_FAN);
|
||||||
|
}
|
||||||
|
this.pipeline = pipelineBuilder.build();
|
||||||
|
|
||||||
|
|
||||||
|
this.vboGpuBuffer = BlazePostProcessUtil.createAndUploadScreenVertexData("McFogRenderer");
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// render //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
this.tryInit();
|
||||||
|
|
||||||
|
|
||||||
|
if (BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.isEmpty()
|
||||||
|
|| BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.fogColorTextureWrapper.tryCreateOrResize();
|
||||||
|
this.fogDepthTextureWrapper.tryCreateOrResize();
|
||||||
|
|
||||||
|
{
|
||||||
|
int uniformBufferSize = new Std140SizeCalculator()
|
||||||
|
|
||||||
|
// fog uniforms
|
||||||
|
.putVec4() // uFogColor
|
||||||
|
.putFloat() //uFogScale
|
||||||
|
.putFloat() //uFogVerticalScale
|
||||||
|
// only used for debugging
|
||||||
|
.putInt() //uFogDebugMode // 1 = render everything with fog color // 7 = use debug rendering
|
||||||
|
.putInt() //uFogFalloffType
|
||||||
|
|
||||||
|
// fog config
|
||||||
|
.putFloat() // uFarFogStart
|
||||||
|
.putFloat() // uFarFogLength
|
||||||
|
.putFloat() // uFarFogMin
|
||||||
|
.putFloat() // uFarFogRange
|
||||||
|
.putFloat() // uFarFogDensity
|
||||||
|
|
||||||
|
// height fog config
|
||||||
|
.putFloat() // uHeightFogStart
|
||||||
|
.putFloat() // uHeightFogLength
|
||||||
|
.putFloat() // uHeightFogMin
|
||||||
|
.putFloat() // uHeightFogRange
|
||||||
|
.putFloat() // uHeightFogDensity
|
||||||
|
|
||||||
|
// ??
|
||||||
|
.putInt() // uHeightFogEnabled
|
||||||
|
.putInt() // uHeightFogFalloffType
|
||||||
|
.putInt() // uHeightBasedOnCamera
|
||||||
|
.putFloat() // uHeightFogBaseHeight
|
||||||
|
.putInt() // uHeightFogAppliesUp
|
||||||
|
.putInt() // uHeightFogAppliesDown
|
||||||
|
.putInt() // uUseSphericalFog
|
||||||
|
.putInt() // uHeightFogMixingMode
|
||||||
|
.putFloat() // uCameraBlockYPos
|
||||||
|
|
||||||
|
.putMat4f() // uInvMvmProj
|
||||||
|
|
||||||
|
.get();
|
||||||
|
|
||||||
|
|
||||||
|
// create data //
|
||||||
|
|
||||||
|
|
||||||
|
int lodDrawDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistanceRadius.get() * LodUtil.CHUNK_WIDTH;
|
||||||
|
|
||||||
|
|
||||||
|
Mat4f inverseMvmProjMatrix = new Mat4f(renderParams.dhMvmProjMatrix);
|
||||||
|
inverseMvmProjMatrix.invert();
|
||||||
|
|
||||||
|
if (renderParams.dhMvmProjMatrix == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Color fogColor = this.getFogColor(renderParams.partialTicks);
|
||||||
|
|
||||||
|
// fog config
|
||||||
|
float farFogStart = Config.Client.Advanced.Graphics.Fog.farFogStart.get();
|
||||||
|
float farFogEnd = Config.Client.Advanced.Graphics.Fog.farFogEnd.get();
|
||||||
|
float farFogMin = Config.Client.Advanced.Graphics.Fog.farFogMin.get();
|
||||||
|
float farFogMax = Config.Client.Advanced.Graphics.Fog.farFogMax.get();
|
||||||
|
float farFogDensity = Config.Client.Advanced.Graphics.Fog.farFogDensity.get();
|
||||||
|
|
||||||
|
// override fog if underwater
|
||||||
|
if (MC_RENDER.isFogStateSpecial())
|
||||||
|
{
|
||||||
|
// hide everything behind fog
|
||||||
|
farFogStart = 0.0f;
|
||||||
|
farFogEnd = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// height config
|
||||||
|
EDhApiHeightFogMixMode heightFogMixingMode = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMixMode.get();
|
||||||
|
boolean heightFogEnabled = heightFogMixingMode != EDhApiHeightFogMixMode.SPHERICAL && heightFogMixingMode != EDhApiHeightFogMixMode.CYLINDRICAL;
|
||||||
|
boolean useSphericalFog = heightFogMixingMode == EDhApiHeightFogMixMode.SPHERICAL;
|
||||||
|
EDhApiHeightFogDirection heightFogCameraDirection = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogDirection.get();
|
||||||
|
|
||||||
|
float heightFogStart = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogStart.get();
|
||||||
|
float heightFogEnd = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogEnd.get();
|
||||||
|
float heightFogMin = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMin.get();
|
||||||
|
float heightFogMax = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMax.get();
|
||||||
|
float heightFogDensity = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogDensity.get();
|
||||||
|
|
||||||
|
|
||||||
|
// upload data //
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(uniformBufferSize);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
buffer = Std140Builder.intoBuffer(buffer)
|
||||||
|
|
||||||
|
// fog uniforms
|
||||||
|
.putVec4(
|
||||||
|
fogColor.getRed() / 255.0f,
|
||||||
|
fogColor.getGreen() / 255.0f,
|
||||||
|
fogColor.getBlue() / 255.0f,
|
||||||
|
fogColor.getAlpha() / 255.0f) // uFogColor
|
||||||
|
.putFloat(1.f / lodDrawDistance) //uFogScale
|
||||||
|
.putFloat(1.f / MC.getWrappedClientLevel().getMaxHeight()) //uFogVerticalScale
|
||||||
|
// only used for debugging
|
||||||
|
.putInt(0) //uFogDebugMode // 1 = render everything with fog color // 7 = use debug rendering
|
||||||
|
.putInt(Config.Client.Advanced.Graphics.Fog.farFogFalloff.get().value) //uFogFalloffType
|
||||||
|
|
||||||
|
// fog config
|
||||||
|
.putFloat(farFogStart) // uFarFogStart
|
||||||
|
.putFloat(farFogEnd - farFogStart) // uFarFogLength
|
||||||
|
.putFloat(farFogMin) // uFarFogMin
|
||||||
|
.putFloat(farFogMax - farFogMin) // uFarFogRange
|
||||||
|
.putFloat(farFogDensity) // uFarFogDensity
|
||||||
|
|
||||||
|
// height fog config
|
||||||
|
.putFloat(heightFogStart) // uHeightFogStart
|
||||||
|
.putFloat(heightFogEnd - heightFogStart) // uHeightFogLength
|
||||||
|
.putFloat(heightFogMin) // uHeightFogMin
|
||||||
|
.putFloat(heightFogMax - heightFogMin) // uHeightFogRange
|
||||||
|
.putFloat(heightFogDensity) // uHeightFogDensity
|
||||||
|
|
||||||
|
// ??
|
||||||
|
.putInt(heightFogEnabled ? 1 : 0) // uHeightFogEnabled
|
||||||
|
.putInt(Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogFalloff.get().value) // uHeightFogFalloffType
|
||||||
|
.putInt(heightFogCameraDirection.basedOnCamera ? 1 : 0) // uHeightBasedOnCamera
|
||||||
|
.putFloat(Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogBaseHeight.get()) // uHeightFogBaseHeight
|
||||||
|
.putInt(heightFogCameraDirection.fogAppliesUp ? 1 : 0) // uHeightFogAppliesUp
|
||||||
|
.putInt(heightFogCameraDirection.fogAppliesDown ? 1 : 0) // uHeightFogAppliesDown
|
||||||
|
.putInt(useSphericalFog ? 1 : 0) // uUseSphericalFog
|
||||||
|
.putInt(heightFogMixingMode.value) // uHeightFogMixingMode
|
||||||
|
.putFloat((float)MC_RENDER.getCameraExactPosition().y) // uCameraBlockYPos
|
||||||
|
|
||||||
|
.putMat4f(inverseMvmProjMatrix.createJomlMatrix()) // uInvMvmProj
|
||||||
|
|
||||||
|
.get()
|
||||||
|
;
|
||||||
|
|
||||||
|
this.fragUniformBuffer = BlazeUniformUtil.createBuffer("fragUniformBlock", uniformBufferSize, this.fragUniformBuffer);
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.fragUniformBuffer, 0, uniformBufferSize);
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.renderFogToTexture();
|
||||||
|
this.applyRenderer.render(this.fogColorTextureWrapper.texture, BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.texture, BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.texture);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Color getFogColor(float partialTicks)
|
||||||
|
{
|
||||||
|
Color fogColor;
|
||||||
|
|
||||||
|
if (Config.Client.Advanced.Graphics.Fog.colorMode.get() == EDhApiFogColorMode.USE_SKY_COLOR)
|
||||||
|
{
|
||||||
|
fogColor = MC_RENDER.getSkyColor();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fogColor = MC_RENDER.getFogColor(partialTicks);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fogColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderFogToTexture()
|
||||||
|
{
|
||||||
|
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||||
|
this::getRenderPassName,
|
||||||
|
this.fogColorTextureWrapper.textureView,
|
||||||
|
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
|
this.fogDepthTextureWrapper.textureView,
|
||||||
|
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||||
|
{
|
||||||
|
renderPass.bindTexture("uDhDepthTexture", BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView, BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureSampler);
|
||||||
|
|
||||||
|
renderPass.setUniform("fragUniformBlock", this.fragUniformBuffer);
|
||||||
|
|
||||||
|
renderPass.setVertexBuffer(0, this.vboGpuBuffer); // vertex buffer can only be "0" lol
|
||||||
|
renderPass.setPipeline(this.pipeline);
|
||||||
|
|
||||||
|
renderPass.draw(/*indexStart*/ 0, /*indexCount*/ 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String getRenderPassName() { return "distantHorizons:McFogRenderer"; }
|
||||||
|
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+283
@@ -0,0 +1,283 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.blaze.postProcessing;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhSsaoRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140Builder;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140SizeCalculator;
|
||||||
|
import com.mojang.blaze3d.pipeline.BlendFunction;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.platform.DestFactor;
|
||||||
|
import com.mojang.blaze3d.platform.SourceFactor;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderPass;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.BlazeDhMetaRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.apply.BlazeDhApplyRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazePostProcessUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeUniformUtil;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhSsaoRenderer;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
/** Renders SSAO to the DH LODs. */
|
||||||
|
public class BlazeDhSsaoRenderer implements IDhSsaoRenderer
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
public static final BlazeDhSsaoRenderer INSTANCE = new BlazeDhSsaoRenderer();
|
||||||
|
|
||||||
|
|
||||||
|
private BlazeDhApplyRenderer applyRenderer;
|
||||||
|
|
||||||
|
private RenderPipeline pipeline;
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
private GpuBuffer fragUniformBuffer;
|
||||||
|
private GpuBuffer applyFragUniformBuffer;
|
||||||
|
|
||||||
|
private GpuBuffer vboGpuBuffer;
|
||||||
|
|
||||||
|
private final BlazeTextureWrapper ssaoColorTextureWrapper = BlazeTextureWrapper.createColor("dh_ssao_color_texture");
|
||||||
|
/** We don't want to actually write any depth data, but blaze3D complains if we don't bind a depth texture. */
|
||||||
|
private final BlazeTextureWrapper ssaoDepthTextureWrapper = BlazeTextureWrapper.createDepth("dh_ssao_depth_texture");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private BlazeDhSsaoRenderer() { }
|
||||||
|
|
||||||
|
private void tryInit()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init = true;
|
||||||
|
|
||||||
|
|
||||||
|
this.applyRenderer = new BlazeDhApplyRenderer(
|
||||||
|
"ssao_apply_to_dh",
|
||||||
|
new BlendFunction(SourceFactor.ZERO, DestFactor.SRC_ALPHA, SourceFactor.ZERO, DestFactor.ONE),
|
||||||
|
"apply/blaze/vert", "ssao/blaze/apply",
|
||||||
|
/*uniforms*/ new String[] { "applyFragUniformBlock" }
|
||||||
|
);
|
||||||
|
|
||||||
|
RenderPipelineBuilderWrapper pipelineBuilder = new RenderPipelineBuilderWrapper();
|
||||||
|
{
|
||||||
|
pipelineBuilder.withFaceCulling(false);
|
||||||
|
pipelineBuilder.withDepthWrite(false);
|
||||||
|
pipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.NONE);
|
||||||
|
pipelineBuilder.withColorWrite(true);
|
||||||
|
pipelineBuilder.withoutBlend();
|
||||||
|
pipelineBuilder.withPolygonMode(RenderPipelineBuilderWrapper.EDhPolygonMode.FILL);
|
||||||
|
pipelineBuilder.withName("ssao_render");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexShader("ssao/blaze/vert");
|
||||||
|
pipelineBuilder.withFragmentShader("ssao/blaze/frag");
|
||||||
|
|
||||||
|
pipelineBuilder.withSampler("uDhDepthTexture");
|
||||||
|
|
||||||
|
pipelineBuilder.withUniformBuffer("fragUniformBlock");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexFormat(BlazePostProcessUtil.createVertexFormat());
|
||||||
|
pipelineBuilder.withVertexMode(RenderPipelineBuilderWrapper.EDhVertexMode.TRIANGLE_FAN);
|
||||||
|
}
|
||||||
|
this.pipeline = pipelineBuilder.build();
|
||||||
|
|
||||||
|
|
||||||
|
this.vboGpuBuffer = BlazePostProcessUtil.createAndUploadScreenVertexData("McSsao");
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// render //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
this.tryInit();
|
||||||
|
|
||||||
|
|
||||||
|
if (BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.isEmpty()
|
||||||
|
|| BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// textures
|
||||||
|
this.ssaoColorTextureWrapper.tryCreateOrResize();
|
||||||
|
this.ssaoDepthTextureWrapper.tryCreateOrResize();
|
||||||
|
|
||||||
|
// frag uniforms
|
||||||
|
{
|
||||||
|
int uniformBufferSize = new Std140SizeCalculator()
|
||||||
|
.putInt() // uSampleCount\
|
||||||
|
|
||||||
|
.putFloat() // uRadius
|
||||||
|
.putFloat() // uStrength
|
||||||
|
.putFloat() // uMinLight
|
||||||
|
.putFloat() // uBias
|
||||||
|
.putFloat() // uFadeDistanceInBlocks
|
||||||
|
|
||||||
|
.putMat4f() // uInvProj
|
||||||
|
.putMat4f() // uProj
|
||||||
|
.get();
|
||||||
|
|
||||||
|
|
||||||
|
// create data //
|
||||||
|
|
||||||
|
Mat4f projMatrix = new Mat4f(renderParams.dhProjectionMatrix);
|
||||||
|
Mat4f invertedProjMatrix = new Mat4f(renderParams.dhProjectionMatrix);
|
||||||
|
invertedProjMatrix.invert();
|
||||||
|
|
||||||
|
|
||||||
|
// upload data //
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(uniformBufferSize);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
buffer = Std140Builder.intoBuffer(buffer)
|
||||||
|
.putInt(6) // uSampleCount
|
||||||
|
|
||||||
|
.putFloat(4.0f) // uRadius
|
||||||
|
.putFloat(0.2f) // uStrength
|
||||||
|
.putFloat(0.25f) // uMinLight
|
||||||
|
.putFloat(0.02f) // uBias
|
||||||
|
.putFloat(1_600.0f) // uFadeDistanceInBlocks
|
||||||
|
|
||||||
|
.putMat4f(invertedProjMatrix.createJomlMatrix())
|
||||||
|
.putMat4f(projMatrix.createJomlMatrix())
|
||||||
|
.get()
|
||||||
|
;
|
||||||
|
|
||||||
|
this.fragUniformBuffer = BlazeUniformUtil.createBuffer("fragUniformBlock", uniformBufferSize, this.fragUniformBuffer);
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.fragUniformBuffer, 0, uniformBufferSize);
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply frag uniforms
|
||||||
|
{
|
||||||
|
int uniformBufferSize = new Std140SizeCalculator()
|
||||||
|
.putVec2() // uViewSize
|
||||||
|
.putInt() // uBlurRadius
|
||||||
|
.putFloat() // uNearClipPlane
|
||||||
|
.putFloat() // uFarClipPlane
|
||||||
|
.get();
|
||||||
|
|
||||||
|
|
||||||
|
// create data //
|
||||||
|
|
||||||
|
float viewWidth = (float)MC_RENDER.getTargetFramebufferViewportWidth();
|
||||||
|
float viewHeight = (float)MC_RENDER.getTargetFramebufferViewportHeight();
|
||||||
|
|
||||||
|
float nearClipPlane = RenderUtil.getNearClipPlaneInBlocks();
|
||||||
|
float farClipPlane = RenderUtil.getFarClipPlaneDistanceInBlocks();
|
||||||
|
|
||||||
|
|
||||||
|
// upload data //
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(uniformBufferSize);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
buffer = Std140Builder.intoBuffer(buffer)
|
||||||
|
.putVec2(viewWidth, viewHeight) // uViewSize
|
||||||
|
.putInt(2) // uBlurRadius
|
||||||
|
.putFloat(nearClipPlane) // uNearClipPlane
|
||||||
|
.putFloat(farClipPlane) // uFarClipPlane
|
||||||
|
.get()
|
||||||
|
;
|
||||||
|
|
||||||
|
this.applyFragUniformBuffer = BlazeUniformUtil.createBuffer("applyFragUniformBlock", uniformBufferSize, this.applyFragUniformBuffer);
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.applyFragUniformBuffer, 0, uniformBufferSize);
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.renderSsaoToTexture();
|
||||||
|
|
||||||
|
this.applyRenderer.setUniform("applyFragUniformBlock", this.applyFragUniformBuffer);
|
||||||
|
this.applyRenderer.render(this.ssaoColorTextureWrapper.texture, BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.texture, BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.texture);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderSsaoToTexture()
|
||||||
|
{
|
||||||
|
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||||
|
this::getRenderPassName,
|
||||||
|
this.ssaoColorTextureWrapper.textureView,
|
||||||
|
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
|
this.ssaoDepthTextureWrapper.textureView,
|
||||||
|
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||||
|
{
|
||||||
|
renderPass.bindTexture("uDhDepthTexture", BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView, BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureSampler);
|
||||||
|
|
||||||
|
renderPass.setUniform("fragUniformBlock", this.fragUniformBuffer);
|
||||||
|
|
||||||
|
renderPass.setVertexBuffer(0, this.vboGpuBuffer); // vertex buffer can only be "0" lol
|
||||||
|
|
||||||
|
renderPass.setPipeline(this.pipeline);
|
||||||
|
renderPass.draw(/*indexStart*/ 0, /*indexCount*/ 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String getRenderPassName() { return "distantHorizons:McSsaoRenderer"; }
|
||||||
|
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+267
@@ -0,0 +1,267 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.blaze.postProcessing;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeVanillaFadeRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140Builder;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140SizeCalculator;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.platform.PolygonMode;
|
||||||
|
import com.mojang.blaze3d.shaders.UniformType;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderPass;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.BlazeDhMetaRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.apply.BlazeDhCopyRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazePostProcessUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeUniformUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhVanillaFadeRenderer;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fades the vanilla chunks
|
||||||
|
* into DH's LODs.
|
||||||
|
*/
|
||||||
|
public class BlazeVanillaFadeRenderer implements IDhVanillaFadeRenderer
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
public static final BlazeVanillaFadeRenderer INSTANCE = new BlazeVanillaFadeRenderer();
|
||||||
|
|
||||||
|
private RenderPipeline pipeline;
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
private GpuBuffer fragUniformBuffer;
|
||||||
|
|
||||||
|
private GpuBuffer vboGpuBuffer;
|
||||||
|
|
||||||
|
public final BlazeTextureWrapper fadeColorTextureWrapper = BlazeTextureWrapper.createColor("DhVanillaFadeColorTexture");
|
||||||
|
/** We don't want to actually write any depth data, but blaze3D complains if we don't bind a depth texture. */
|
||||||
|
private final BlazeTextureWrapper fadeDepthTextureWrapper = BlazeTextureWrapper.createDepth("DhVanillaFadeDepthTexture");
|
||||||
|
|
||||||
|
|
||||||
|
public final BlazeTextureViewWrapper mcDepthTextureWrapper = new BlazeTextureViewWrapper();
|
||||||
|
public final BlazeTextureViewWrapper mcColorTextureWrapper = new BlazeTextureViewWrapper();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private BlazeVanillaFadeRenderer() { }
|
||||||
|
|
||||||
|
private void tryInit()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
RenderPipelineBuilderWrapper pipelineBuilder = new RenderPipelineBuilderWrapper();
|
||||||
|
{
|
||||||
|
pipelineBuilder.withFaceCulling(false);
|
||||||
|
pipelineBuilder.withDepthWrite(false);
|
||||||
|
pipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.NONE);
|
||||||
|
pipelineBuilder.withColorWrite(true);
|
||||||
|
pipelineBuilder.withoutBlend();
|
||||||
|
pipelineBuilder.withPolygonMode(RenderPipelineBuilderWrapper.EDhPolygonMode.FILL);
|
||||||
|
pipelineBuilder.withName("vanilla_fade");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexShader("fade/blaze/vert");
|
||||||
|
pipelineBuilder.withFragmentShader("fade/blaze/vanilla_fade");
|
||||||
|
|
||||||
|
pipelineBuilder.withSampler("uMcDepthTexture");
|
||||||
|
pipelineBuilder.withSampler("uCombinedMcDhColorTexture");
|
||||||
|
|
||||||
|
pipelineBuilder.withSampler("uDhDepthTexture");
|
||||||
|
pipelineBuilder.withSampler("uDhColorTexture");
|
||||||
|
|
||||||
|
pipelineBuilder.withUniformBuffer("fragUniformBlock");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexFormat(BlazePostProcessUtil.createVertexFormat());
|
||||||
|
pipelineBuilder.withVertexMode(RenderPipelineBuilderWrapper.EDhVertexMode.TRIANGLE_FAN);
|
||||||
|
}
|
||||||
|
this.pipeline = pipelineBuilder.build();
|
||||||
|
|
||||||
|
|
||||||
|
this.vboGpuBuffer = BlazePostProcessUtil.createAndUploadScreenVertexData("McFadeRenderer");
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// render //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
this.tryInit();
|
||||||
|
|
||||||
|
if (BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.isEmpty()
|
||||||
|
|| BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.isEmpty())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// textures
|
||||||
|
this.fadeColorTextureWrapper.tryCreateOrResize();
|
||||||
|
this.fadeDepthTextureWrapper.tryCreateOrResize();
|
||||||
|
|
||||||
|
this.mcDepthTextureWrapper.tryWrap(Minecraft.getInstance().getMainRenderTarget().getDepthTexture());
|
||||||
|
this.mcColorTextureWrapper.tryWrap(Minecraft.getInstance().getMainRenderTarget().getColorTexture());
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
int uniformBufferSize = new Std140SizeCalculator()
|
||||||
|
.putInt() // uOnlyRenderLods
|
||||||
|
.putFloat() // uStartFadeBlockDistance
|
||||||
|
.putFloat() // uEndFadeBlockDistance
|
||||||
|
.putFloat() // uMaxLevelHeight
|
||||||
|
.putMat4f() // uDhInvMvmProj
|
||||||
|
.putMat4f() // uMcInvMvmProj
|
||||||
|
.get();
|
||||||
|
|
||||||
|
|
||||||
|
// create data //
|
||||||
|
|
||||||
|
float dhNearClipDistance = RenderUtil.getNearClipPlaneInBlocks();
|
||||||
|
// this added value prevents the near clip plane and discard circle from touching, which looks bad
|
||||||
|
dhNearClipDistance += 16f;
|
||||||
|
|
||||||
|
// measured in blocks
|
||||||
|
// these multipliers in James' tests should provide a fairly smooth transition
|
||||||
|
// without having underdraw issues
|
||||||
|
float fadeStartDistance = dhNearClipDistance * 1.5f;
|
||||||
|
float fadeEndDistance = dhNearClipDistance * 1.9f;
|
||||||
|
|
||||||
|
|
||||||
|
Mat4f inverseMcModelViewProjectionMatrix = new Mat4f(renderParams.mcProjectionMatrix);
|
||||||
|
inverseMcModelViewProjectionMatrix.multiply(renderParams.mcModelViewMatrix);
|
||||||
|
inverseMcModelViewProjectionMatrix.invert();
|
||||||
|
Mat4f inverseMcMvmProjMatrix = inverseMcModelViewProjectionMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
Mat4f dhProjectionMatrix = RenderUtil.createLodProjectionMatrix(renderParams.mcProjectionMatrix);
|
||||||
|
Mat4f dhModelViewMatrix = RenderUtil.createLodModelViewMatrix(renderParams.mcModelViewMatrix);
|
||||||
|
|
||||||
|
Mat4f inverseDhModelViewProjectionMatrix = new Mat4f(dhProjectionMatrix);
|
||||||
|
inverseDhModelViewProjectionMatrix.multiply(dhModelViewMatrix);
|
||||||
|
inverseDhModelViewProjectionMatrix.invert();
|
||||||
|
Mat4f inverseDhMvmProjMatrix = inverseDhModelViewProjectionMatrix;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// upload data //
|
||||||
|
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocateDirect(uniformBufferSize);
|
||||||
|
buffer.order(ByteOrder.nativeOrder());
|
||||||
|
buffer = Std140Builder.intoBuffer(buffer)
|
||||||
|
.putInt(Config.Client.Advanced.Debugging.lodOnlyMode.get() ? 1 : 0) // uOnlyRenderLods
|
||||||
|
.putFloat(fadeStartDistance) // uStartFadeBlockDistance
|
||||||
|
.putFloat(fadeEndDistance) // uEndFadeBlockDistance
|
||||||
|
.putFloat(renderParams.clientLevelWrapper.getMaxHeight()) // uMaxLevelHeight
|
||||||
|
.putMat4f(inverseDhMvmProjMatrix.createJomlMatrix()) // uDhInvMvmProj
|
||||||
|
.putMat4f(inverseMcMvmProjMatrix.createJomlMatrix()) // uMcInvMvmProj
|
||||||
|
.get()
|
||||||
|
;
|
||||||
|
|
||||||
|
this.fragUniformBuffer = BlazeUniformUtil.createBuffer("fragUniformBlock", uniformBufferSize, this.fragUniformBuffer);
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.fragUniformBuffer, 0, uniformBufferSize);
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.renderFadeToTexture();
|
||||||
|
BlazeDhCopyRenderer.INSTANCE.render(this.fadeColorTextureWrapper, this.mcColorTextureWrapper);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderFadeToTexture()
|
||||||
|
{
|
||||||
|
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||||
|
this::getRenderPassName,
|
||||||
|
this.fadeColorTextureWrapper.textureView,
|
||||||
|
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
|
this.fadeDepthTextureWrapper.textureView,
|
||||||
|
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||||
|
{
|
||||||
|
renderPass.bindTexture("uMcDepthTexture", this.mcDepthTextureWrapper.textureView, this.mcDepthTextureWrapper.textureSampler);
|
||||||
|
renderPass.bindTexture("uCombinedMcDhColorTexture", this.mcColorTextureWrapper.textureView, this.mcColorTextureWrapper.textureSampler);
|
||||||
|
|
||||||
|
renderPass.bindTexture("uDhDepthTexture", BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureView, BlazeDhMetaRenderer.INSTANCE.dhDepthTextureWrapper.textureSampler);
|
||||||
|
renderPass.bindTexture("uDhColorTexture", BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureView, BlazeDhMetaRenderer.INSTANCE.dhColorTextureWrapper.textureSampler);
|
||||||
|
|
||||||
|
renderPass.setUniform("fragUniformBlock", this.fragUniformBuffer);
|
||||||
|
|
||||||
|
renderPass.setVertexBuffer(0, this.vboGpuBuffer); // vertex buffer can only be "0" lol
|
||||||
|
|
||||||
|
renderPass.setPipeline(this.pipeline);
|
||||||
|
renderPass.draw(/*indexStart*/ 0, /*indexCount*/ 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String getRenderPassName() { return "distantHorizons:McFadeRenderer"; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+189
@@ -0,0 +1,189 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.blaze.test;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhTestTriangleRenderer {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.platform.PolygonMode;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderPass;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.textures.*;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.util.BlazeDhVertexFormatUtil;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.RenderPipelineBuilderWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.render.blaze.wrappers.texture.BlazeTextureViewWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTestTriangleRenderer;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_11
|
||||||
|
#else
|
||||||
|
import com.mojang.blaze3d.pipeline.DepthStencilState;
|
||||||
|
import com.mojang.blaze3d.platform.CompareOp;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the OpenGL/Vulkan triangle
|
||||||
|
* to the center of the screen to confirm DH's
|
||||||
|
* apply shader is running correctly
|
||||||
|
*/
|
||||||
|
public class BlazeDhTestTriangleRenderer implements IDhTestTriangleRenderer
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
public static final BlazeDhTestTriangleRenderer INSTANCE = new BlazeDhTestTriangleRenderer();
|
||||||
|
|
||||||
|
private RenderPipeline pipeline;
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
public final BlazeTextureViewWrapper mcColorTextureViewWrapper = new BlazeTextureViewWrapper();
|
||||||
|
public final BlazeTextureViewWrapper mcDepthTextureViewWrapper = new BlazeTextureViewWrapper();
|
||||||
|
|
||||||
|
private GpuBuffer vboGpuBuffer;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private BlazeDhTestTriangleRenderer() { }
|
||||||
|
|
||||||
|
private void tryInit()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init = true;
|
||||||
|
|
||||||
|
RenderPipelineBuilderWrapper pipelineBuilder = new RenderPipelineBuilderWrapper();
|
||||||
|
{
|
||||||
|
pipelineBuilder.withFaceCulling(false);
|
||||||
|
pipelineBuilder.withDepthWrite(false);
|
||||||
|
pipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.NONE);
|
||||||
|
pipelineBuilder.withColorWrite(true);
|
||||||
|
pipelineBuilder.withoutBlend();
|
||||||
|
pipelineBuilder.withName("triangle_test");
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexShader("test/blaze/vert");
|
||||||
|
pipelineBuilder.withFragmentShader("test/blaze/frag");
|
||||||
|
|
||||||
|
VertexFormat vertexFormat = VertexFormat.builder()
|
||||||
|
.add("vPosition", BlazeDhVertexFormatUtil.SCREEN_POS)
|
||||||
|
.add("vColor", BlazeDhVertexFormatUtil.RGBA_FLOAT_COLOR)
|
||||||
|
.build();
|
||||||
|
pipelineBuilder.withVertexFormat(vertexFormat);
|
||||||
|
|
||||||
|
pipelineBuilder.withVertexMode(RenderPipelineBuilderWrapper.EDhVertexMode.TRIANGLES);
|
||||||
|
}
|
||||||
|
this.pipeline = pipelineBuilder.build();
|
||||||
|
|
||||||
|
this.uploadVertexData();
|
||||||
|
}
|
||||||
|
private void uploadVertexData()
|
||||||
|
{
|
||||||
|
// vertices for the OpenGL/Vulkan Triangle
|
||||||
|
float[] vertices = new float[]
|
||||||
|
{
|
||||||
|
// PosX,Y, ColorR,G,B,A
|
||||||
|
-0.5f, -0.5f, 1.0f, 0.0f, 0.0f, 1.0f,
|
||||||
|
0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f,
|
||||||
|
0.0f, 0.5f, 0.0f, 0.0f, 1.0f, 1.0f,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_VERTEX;
|
||||||
|
int size = vertices.length * Float.BYTES;
|
||||||
|
this.vboGpuBuffer = GPU_DEVICE.createBuffer(this::getRenderPassName, usage, size);
|
||||||
|
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
int length = vertices.length * Float.BYTES;
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vboGpuBuffer, offset, length);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(vertices.length * Float.BYTES);
|
||||||
|
// Fill buffer with vertices.
|
||||||
|
byteBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
byteBuffer.asFloatBuffer().put(vertices);
|
||||||
|
byteBuffer.rewind();
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, byteBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// render //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
this.tryInit();
|
||||||
|
|
||||||
|
this.mcColorTextureViewWrapper.tryWrap(Minecraft.getInstance().getMainRenderTarget().getColorTexture());
|
||||||
|
this.mcDepthTextureViewWrapper.tryWrap(Minecraft.getInstance().getMainRenderTarget().getDepthTexture());
|
||||||
|
|
||||||
|
try (RenderPass renderPass = COMMAND_ENCODER.createRenderPass(
|
||||||
|
this::getRenderPassName,
|
||||||
|
this.mcColorTextureViewWrapper.textureView,
|
||||||
|
/*optionalClearColorAsInt*/ OptionalInt.empty(),
|
||||||
|
this.mcDepthTextureViewWrapper.textureView,
|
||||||
|
/*optionalDepthValueAsDouble*/ OptionalDouble.empty()))
|
||||||
|
{
|
||||||
|
renderPass.setVertexBuffer(0, this.vboGpuBuffer);
|
||||||
|
renderPass.setPipeline(this.pipeline);
|
||||||
|
renderPass.draw(/*indexStart*/ 0, /*indexCount*/ 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String getRenderPassName() { return "distantHorizons:DhTestRenderer"; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+122
@@ -0,0 +1,122 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze.util;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeDhVertexFormatUtil {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormatElement;
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiRenderApi;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodQuadBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.IVersionConstants;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see LodQuadBuilder
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("DataFlowIssue") // ignore null setter warnings in the static constructor (those will only be null if the render API is GL and in that case we should never use these objects)
|
||||||
|
public class BlazeDhVertexFormatUtil
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
|
@NotNull public static final VertexFormatElement SCREEN_POS;
|
||||||
|
@NotNull public static final VertexFormatElement RGBA_FLOAT_COLOR;
|
||||||
|
|
||||||
|
@NotNull public static final VertexFormatElement SHORT_XYZ_POS;
|
||||||
|
@NotNull public static final VertexFormatElement BYTE_PAD;
|
||||||
|
/** contains light and micro-offset */
|
||||||
|
@NotNull public static final VertexFormatElement META;
|
||||||
|
@NotNull public static final VertexFormatElement RGBA_UBYTE_COLOR;
|
||||||
|
@NotNull public static final VertexFormatElement IRIS_MATERIAL;
|
||||||
|
@NotNull public static final VertexFormatElement IRIS_NORMAL;
|
||||||
|
|
||||||
|
@NotNull public static final VertexFormatElement FLOAT_XYZ_POS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
EDhApiRenderApi renderingApi = Config.Client.Advanced.Graphics.Experimental.renderingApi.get();
|
||||||
|
if (renderingApi == EDhApiRenderApi.AUTO)
|
||||||
|
{
|
||||||
|
IVersionConstants versionConstants = SingletonInjector.INSTANCE.get(IVersionConstants.class);
|
||||||
|
renderingApi = versionConstants.getDefaultRenderingApi();
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean register = (renderingApi == EDhApiRenderApi.BLAZE_3D);
|
||||||
|
if (register)
|
||||||
|
{
|
||||||
|
LOGGER.debug("Attempting to register ["+VertexFormatElement.class.getSimpleName()+"]...");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_21_11
|
||||||
|
SCREEN_POS = VertexFormatElement.register(/*id*/22, /*index*/0, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.POSITION, /*count*/ 2);
|
||||||
|
RGBA_FLOAT_COLOR = VertexFormatElement.register(/*id*/23, /*index*/0, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.COLOR, /*count*/ 4);
|
||||||
|
|
||||||
|
SHORT_XYZ_POS = VertexFormatElement.register(/*id*/24, /*index*/0, VertexFormatElement.Type.USHORT, VertexFormatElement.Usage.POSITION, /*count*/ 3);
|
||||||
|
BYTE_PAD = VertexFormatElement.register(/*id*/25, /*index*/0, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.GENERIC, /*count*/ 1);
|
||||||
|
|
||||||
|
META = VertexFormatElement.register(/*id*/26, /*index*/0, VertexFormatElement.Type.USHORT, VertexFormatElement.Usage.GENERIC, /*count*/ 1);
|
||||||
|
RGBA_UBYTE_COLOR = VertexFormatElement.register(/*id*/27, /*index*/0, VertexFormatElement.Type.UBYTE, VertexFormatElement.Usage.COLOR, /*count*/ 4);
|
||||||
|
IRIS_MATERIAL = VertexFormatElement.register(/*id*/28, /*index*/0, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.GENERIC, /*count*/ 1);
|
||||||
|
IRIS_NORMAL = VertexFormatElement.register(/*id*/29, /*index*/0, VertexFormatElement.Type.BYTE, VertexFormatElement.Usage.GENERIC, /*count*/ 1);
|
||||||
|
|
||||||
|
FLOAT_XYZ_POS = VertexFormatElement.register(/*id*/30, /*index*/0, VertexFormatElement.Type.FLOAT, VertexFormatElement.Usage.POSITION, /*count*/ 3);
|
||||||
|
#else
|
||||||
|
SCREEN_POS = VertexFormatElement.register(/*id*/22, /*index*/0, VertexFormatElement.Type.FLOAT, false, /*count*/ 2);
|
||||||
|
RGBA_FLOAT_COLOR = VertexFormatElement.register(/*id*/23, /*index*/0, VertexFormatElement.Type.FLOAT, false, /*count*/ 4);
|
||||||
|
|
||||||
|
SHORT_XYZ_POS = VertexFormatElement.register(/*id*/24, /*index*/0, VertexFormatElement.Type.USHORT, false, /*count*/ 3);
|
||||||
|
BYTE_PAD = VertexFormatElement.register(/*id*/25, /*index*/0, VertexFormatElement.Type.BYTE, false, /*count*/ 1);
|
||||||
|
|
||||||
|
META = VertexFormatElement.register(/*id*/26, /*index*/0, VertexFormatElement.Type.USHORT, false, /*count*/ 1);
|
||||||
|
RGBA_UBYTE_COLOR = VertexFormatElement.register(/*id*/27, /*index*/0, VertexFormatElement.Type.UBYTE, true, /*count*/ 4);
|
||||||
|
IRIS_MATERIAL = VertexFormatElement.register(/*id*/28, /*index*/0, VertexFormatElement.Type.BYTE, false, /*count*/ 1);
|
||||||
|
IRIS_NORMAL = VertexFormatElement.register(/*id*/29, /*index*/0, VertexFormatElement.Type.BYTE, false, /*count*/ 1);
|
||||||
|
|
||||||
|
FLOAT_XYZ_POS = VertexFormatElement.register(/*id*/30, /*index*/0, VertexFormatElement.Type.FLOAT, false, /*count*/ 3);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
String message = "Unable to register one or more ["+VertexFormatElement.class.getSimpleName()+"] this is likely caused by another mod registering their own custom ["+VertexFormatElement.class.getSimpleName()+"]'s. This should be fixed in the next major Minecraft version.";
|
||||||
|
|
||||||
|
IMinecraftClientWrapper mc = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
|
mc.crashMinecraft(message, new Exception(message, e));
|
||||||
|
|
||||||
|
// here to make the compiler happy, the process should shut down before this
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.debug("Successfully registered ["+VertexFormatElement.class.getSimpleName()+"].");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// set to null so we can fail fast with a null pointer if we ever attempt to incorrectly use these
|
||||||
|
SCREEN_POS = null;
|
||||||
|
RGBA_FLOAT_COLOR = null;
|
||||||
|
|
||||||
|
SHORT_XYZ_POS = null;
|
||||||
|
BYTE_PAD = null;
|
||||||
|
|
||||||
|
META = null;
|
||||||
|
RGBA_UBYTE_COLOR = null;
|
||||||
|
IRIS_MATERIAL = null;
|
||||||
|
IRIS_NORMAL = null;
|
||||||
|
|
||||||
|
FLOAT_XYZ_POS = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+81
@@ -0,0 +1,81 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze.util;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazePostProcessUtil {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/** Contains code that's used by all post-processing effects. */
|
||||||
|
public class BlazePostProcessUtil
|
||||||
|
{
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
// vertices for a full-screen quad
|
||||||
|
private static final float[] VERTICES = new float[]
|
||||||
|
{
|
||||||
|
// PosX,Y,
|
||||||
|
-1f, -1f,
|
||||||
|
1f, -1f,
|
||||||
|
1f, 1f,
|
||||||
|
-1f, 1f,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// methods //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public static GpuBuffer createAndUploadScreenVertexData(String name)
|
||||||
|
{
|
||||||
|
Supplier<String> labelSupplier = () -> "distantHorizons:"+name;
|
||||||
|
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_VERTEX;
|
||||||
|
int size = VERTICES.length * Float.BYTES;
|
||||||
|
GpuBuffer vboGpuBuffer = GPU_DEVICE.createBuffer(labelSupplier, usage, size);
|
||||||
|
|
||||||
|
{
|
||||||
|
int length = VERTICES.length * Float.BYTES;
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(vboGpuBuffer, /*offset*/ 0, length);
|
||||||
|
|
||||||
|
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(VERTICES.length * Float.BYTES);
|
||||||
|
// Fill buffer with vertices.
|
||||||
|
byteBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
byteBuffer.asFloatBuffer().put(VERTICES);
|
||||||
|
byteBuffer.rewind();
|
||||||
|
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, byteBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vboGpuBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static VertexFormat createVertexFormat()
|
||||||
|
{
|
||||||
|
VertexFormat vertexFormat = VertexFormat.builder()
|
||||||
|
.add("vPosition", BlazeDhVertexFormatUtil.SCREEN_POS)
|
||||||
|
.build();
|
||||||
|
return vertexFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze.util;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeUniformUtil {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
|
||||||
|
public class BlazeUniformUtil
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
|
||||||
|
public static GpuBuffer createBuffer(String uniformName, int size, GpuBuffer vboGpuBuffer)
|
||||||
|
{
|
||||||
|
// create VBO if needed
|
||||||
|
if (vboGpuBuffer == null
|
||||||
|
|| vboGpuBuffer.size() < size)
|
||||||
|
{
|
||||||
|
if (vboGpuBuffer != null)
|
||||||
|
{
|
||||||
|
vboGpuBuffer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_VERTEX
|
||||||
|
| GpuBuffer.USAGE_UNIFORM;
|
||||||
|
vboGpuBuffer = GPU_DEVICE.createBuffer(() -> uniformName, usage, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return vboGpuBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+351
@@ -0,0 +1,351 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze.wrappers;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.pipeline.BlendFunction;
|
||||||
|
import com.mojang.blaze3d.pipeline.ColorTargetState;
|
||||||
|
import com.mojang.blaze3d.pipeline.DepthStencilState;
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||||
|
import com.mojang.blaze3d.platform.CompareOp;
|
||||||
|
import com.mojang.blaze3d.platform.PolygonMode;
|
||||||
|
import com.mojang.blaze3d.shaders.UniformType;
|
||||||
|
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||||
|
import net.minecraft.resources.Identifier;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class RenderPipelineBuilderWrapper
|
||||||
|
{
|
||||||
|
public static final String NAME_PREFIX = "distanthorizons:";
|
||||||
|
|
||||||
|
private static final String SHADER_RESOURCE_FOLDER = "assets/distanthorizons/shaders/";
|
||||||
|
|
||||||
|
private static final ClassLoader CLASS_LOADER = RenderPipelineBuilderWrapper.class.getClassLoader();
|
||||||
|
|
||||||
|
|
||||||
|
private final RenderPipeline.Builder blazePipelineBuilder;
|
||||||
|
|
||||||
|
// variables for specific builder options should be put next to their builder methods for simpler organization
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public RenderPipelineBuilderWrapper()
|
||||||
|
{
|
||||||
|
this.blazePipelineBuilder = RenderPipeline.builder();
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========//
|
||||||
|
// building //
|
||||||
|
//==========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private boolean writeDepth = false;
|
||||||
|
public RenderPipelineBuilderWrapper withDepthWrite(boolean write)
|
||||||
|
{
|
||||||
|
this.writeDepth = write;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean writeColor = false;
|
||||||
|
public RenderPipelineBuilderWrapper withColorWrite(boolean write)
|
||||||
|
{
|
||||||
|
this.writeColor = write;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlendFunction blendFunction = null;
|
||||||
|
public RenderPipelineBuilderWrapper withBlend(BlendFunction blendFunction)
|
||||||
|
{
|
||||||
|
this.blendFunction = blendFunction;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public RenderPipelineBuilderWrapper withoutBlend()
|
||||||
|
{
|
||||||
|
this.blendFunction = null;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EDhDepthTest depthTest;
|
||||||
|
public RenderPipelineBuilderWrapper withDepthTest(EDhDepthTest depthTest)
|
||||||
|
{
|
||||||
|
this.depthTest = depthTest;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderPipelineBuilderWrapper withFaceCulling(boolean culling)
|
||||||
|
{
|
||||||
|
this.blazePipelineBuilder.withCull(culling);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderPipelineBuilderWrapper withPolygonMode(EDhPolygonMode dhMode)
|
||||||
|
{
|
||||||
|
PolygonMode blazeMode;
|
||||||
|
switch (dhMode)
|
||||||
|
{
|
||||||
|
case FILL:
|
||||||
|
blazeMode = PolygonMode.FILL;
|
||||||
|
break;
|
||||||
|
case WIREFRAME:
|
||||||
|
blazeMode = PolygonMode.WIREFRAME;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("No polygonMode defined for type ["+dhMode+"].");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.blazePipelineBuilder.withPolygonMode(blazeMode);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderPipelineBuilderWrapper withName(String name) throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
// Identifiers must be of a specific format
|
||||||
|
if (!isValidIdentifier(name))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Non [a-z0-9/._-] character in name: ["+name+"].");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.blazePipelineBuilder.withLocation(Identifier.parse(NAME_PREFIX + name));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderPipelineBuilderWrapper withSampler(String name) throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
this.blazePipelineBuilder.withSampler(name);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderPipelineBuilderWrapper withUniformBuffer(String name) throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
this.blazePipelineBuilder.withUniform(name, UniformType.UNIFORM_BUFFER);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private VertexFormat vertexFormat = null;
|
||||||
|
public RenderPipelineBuilderWrapper withVertexFormat(VertexFormat vertexFormat)
|
||||||
|
{
|
||||||
|
this.vertexFormat = vertexFormat;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private EDhVertexMode vertexMode = null;
|
||||||
|
public RenderPipelineBuilderWrapper withVertexMode(EDhVertexMode vertexMode)
|
||||||
|
{
|
||||||
|
this.vertexMode = vertexMode;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenderPipelineBuilderWrapper withVertexShader(String scriptResourcePath) { return this.withShader(EDhShaderType.VERTEX, scriptResourcePath); }
|
||||||
|
public RenderPipelineBuilderWrapper withFragmentShader(String scriptResourcePath) { return this.withShader(EDhShaderType.FRAGMENT, scriptResourcePath); }
|
||||||
|
private RenderPipelineBuilderWrapper withShader(EDhShaderType shaderType, String scriptResourcePath)
|
||||||
|
{
|
||||||
|
String fullShaderResourcePath = SHADER_RESOURCE_FOLDER + scriptResourcePath + shaderType.fileExtension;
|
||||||
|
|
||||||
|
// confirm the shader file exists
|
||||||
|
try (InputStream scriptListInputStream = CLASS_LOADER.getResourceAsStream(fullShaderResourcePath))
|
||||||
|
{
|
||||||
|
if (scriptListInputStream == null)
|
||||||
|
{
|
||||||
|
throw new NullPointerException("Failed to find the SQL Script list file [" + fullShaderResourcePath + "], no auto update scripts can be run.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
throw new RuntimeException("Unexpected issue closing resource stream for shader type: ["+shaderType+"] at: ["+fullShaderResourcePath+"], error: ["+e.getMessage()+"].", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (shaderType == EDhShaderType.VERTEX)
|
||||||
|
{
|
||||||
|
this.blazePipelineBuilder.withVertexShader(Identifier.parse(NAME_PREFIX + scriptResourcePath));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.blazePipelineBuilder.withFragmentShader(Identifier.parse(NAME_PREFIX + scriptResourcePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=====//
|
||||||
|
// end //
|
||||||
|
//=====//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public RenderPipeline build() throws UnsupportedOperationException
|
||||||
|
{
|
||||||
|
// depth/color
|
||||||
|
{
|
||||||
|
#if MC_VER <= MC_1_21_11
|
||||||
|
|
||||||
|
this.blazePipelineBuilder.withDepthWrite(this.writeDepth);
|
||||||
|
this.blazePipelineBuilder.withColorWrite(this.writeColor);
|
||||||
|
|
||||||
|
if (this.blendFunction != null)
|
||||||
|
{
|
||||||
|
this.blazePipelineBuilder.withBlend(this.blendFunction);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.blazePipelineBuilder.withoutBlend();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (this.depthTest)
|
||||||
|
{
|
||||||
|
case NONE:
|
||||||
|
|
||||||
|
break;
|
||||||
|
case LESS:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.blazepipelineBuilder.withDepthTest(RenderPipelineBuilderWrapper.EDhDepthTest.NONE);
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
CompareOp compareOp;
|
||||||
|
switch (this.depthTest)
|
||||||
|
{
|
||||||
|
case NONE:
|
||||||
|
compareOp = CompareOp.ALWAYS_PASS;
|
||||||
|
break;
|
||||||
|
case LESS:
|
||||||
|
compareOp = CompareOp.LESS_THAN;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("No depth test defined for type ["+this.depthTest+"].");
|
||||||
|
}
|
||||||
|
this.blazePipelineBuilder.withDepthStencilState(new DepthStencilState(compareOp, this.writeDepth));
|
||||||
|
|
||||||
|
this.blazePipelineBuilder.withColorTargetState(
|
||||||
|
new ColorTargetState(
|
||||||
|
Optional.ofNullable(this.blendFunction),
|
||||||
|
this.writeColor ? ColorTargetState.WRITE_ALL : ColorTargetState.WRITE_NONE
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// vertex format
|
||||||
|
{
|
||||||
|
VertexFormat.Mode blazeVertexMode;
|
||||||
|
switch (this.vertexMode)
|
||||||
|
{
|
||||||
|
case TRIANGLES:
|
||||||
|
blazeVertexMode = VertexFormat.Mode.TRIANGLES;
|
||||||
|
break;
|
||||||
|
case TRIANGLE_FAN:
|
||||||
|
blazeVertexMode = VertexFormat.Mode.TRIANGLE_FAN;
|
||||||
|
break;
|
||||||
|
case LINES:
|
||||||
|
blazeVertexMode = VertexFormat.Mode.DEBUG_LINES;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
throw new UnsupportedOperationException("No vertex mode defined for type ["+this.vertexMode+"].");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.blazePipelineBuilder.withVertexFormat(vertexFormat, blazeVertexMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.blazePipelineBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper methods //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private static boolean isValidIdentifier(String identifier)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < identifier.length(); i++)
|
||||||
|
{
|
||||||
|
char ch = identifier.charAt(i);
|
||||||
|
if (!isValidNamespaceChar(ch))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private static boolean isValidNamespaceChar(final char ch)
|
||||||
|
{
|
||||||
|
return ch == '_'
|
||||||
|
|| ch == '-'
|
||||||
|
// only lower case characters
|
||||||
|
|| (ch >= 'a' && ch <= 'z')
|
||||||
|
|| (ch >= '0' && ch <= '9')
|
||||||
|
|| ch == '.';
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper classes //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public enum EDhPolygonMode
|
||||||
|
{
|
||||||
|
FILL,
|
||||||
|
WIREFRAME;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum EDhVertexMode
|
||||||
|
{
|
||||||
|
TRIANGLES,
|
||||||
|
TRIANGLE_FAN,
|
||||||
|
LINES;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum EDhDepthTest
|
||||||
|
{
|
||||||
|
NONE,
|
||||||
|
LESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum EDhShaderType
|
||||||
|
{
|
||||||
|
FRAGMENT(".fsh"),
|
||||||
|
VERTEX(".vsh");
|
||||||
|
|
||||||
|
|
||||||
|
public final String fileExtension;
|
||||||
|
|
||||||
|
EDhShaderType(String fileExtension)
|
||||||
|
{
|
||||||
|
this.fileExtension = fileExtension;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+219
@@ -0,0 +1,219 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze.wrappers.buffer;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeVertexBufferWrapper {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.IndexBufferBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodQuadBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class BlazeVertexBufferWrapper implements IVertexBufferWrapper
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final AbstractDhRenderApiDefinition RENDER_DEF = SingletonInjector.INSTANCE.get(AbstractDhRenderApiDefinition.class);
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
private static final AtomicInteger BUFFER_COUNT_REF = new AtomicInteger(0);
|
||||||
|
|
||||||
|
|
||||||
|
public final String name;
|
||||||
|
public String getName() { return this.name; }
|
||||||
|
|
||||||
|
public GpuBuffer vertexGpuBuffer = null;
|
||||||
|
|
||||||
|
public int vertexCount = -1;
|
||||||
|
public int indexCount = -1;
|
||||||
|
public boolean uploaded = false;
|
||||||
|
|
||||||
|
|
||||||
|
private GpuBuffer indexGpuBuffer = null;
|
||||||
|
private static GpuBuffer GLOBAL_INDEX_GPU_BUFFER = null;
|
||||||
|
public GpuBuffer getIndexGpuBuffer()
|
||||||
|
{
|
||||||
|
if (RENDER_DEF.useSingleIbo())
|
||||||
|
{
|
||||||
|
return GLOBAL_INDEX_GPU_BUFFER;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return this.indexGpuBuffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
if (RENDER_DEF.useSingleIbo())
|
||||||
|
{
|
||||||
|
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("Global IBO Creation", () ->
|
||||||
|
{
|
||||||
|
int maxSize = LodQuadBuilder.getMaxBufferByteSize();
|
||||||
|
int maxVertexCount = maxSize / LodQuadBuilder.BYTES_PER_VERTEX;
|
||||||
|
int maxQuadCount = (maxVertexCount / 4);
|
||||||
|
ByteBuffer indexBuffer = IndexBufferBuilder.createBuffer(maxQuadCount);
|
||||||
|
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_INDEX;
|
||||||
|
GLOBAL_INDEX_GPU_BUFFER = GPU_DEVICE.createBuffer(BlazeVertexBufferWrapper::getIndexBufferName, usage, indexBuffer.capacity());
|
||||||
|
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(GLOBAL_INDEX_GPU_BUFFER, /*offset*/ 0, indexBuffer.capacity());
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, indexBuffer);
|
||||||
|
|
||||||
|
MemoryUtil.memFree(indexBuffer);
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlazeVertexBufferWrapper(String name) { this.name = name; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// upload //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadVertexBuffer(ByteBuffer vertexBuffer, int vertexCount)
|
||||||
|
{
|
||||||
|
int oldVertexCount = this.vertexCount;
|
||||||
|
|
||||||
|
this.vertexCount = vertexCount;
|
||||||
|
// 4 vertices per face, but 6 indices (IE 2 triangles) per face, aka need to multiply by 1.5
|
||||||
|
this.indexCount = (int)(vertexCount * 1.5);
|
||||||
|
this.uploaded = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (this.vertexGpuBuffer == null
|
||||||
|
// recreating if the size changes is always necessary (even if we only need a smaller amount)
|
||||||
|
// due to a bug on Mac where it will attempt to render anything allocated in the buffer
|
||||||
|
|| oldVertexCount != vertexCount)
|
||||||
|
{
|
||||||
|
if (this.vertexGpuBuffer == null)
|
||||||
|
{
|
||||||
|
BUFFER_COUNT_REF.incrementAndGet();
|
||||||
|
//LOGGER.info("Create, count: ["+BUFFER_COUNT_REF.get()+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.vertexGpuBuffer != null)
|
||||||
|
{
|
||||||
|
this.vertexGpuBuffer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_VERTEX;
|
||||||
|
int byteSize = (vertexBuffer.limit() - vertexBuffer.position());
|
||||||
|
this.vertexGpuBuffer = GPU_DEVICE.createBuffer(this::getName, usage, byteSize);
|
||||||
|
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.vertexGpuBuffer, /*offset*/0, byteSize);
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, vertexBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadIndexBuffer(ByteBuffer buffer, int vertexCount)
|
||||||
|
{
|
||||||
|
int oldIndexCount = this.indexCount;
|
||||||
|
// 4 vertices per face, but 6 indices (IE 2 triangles) per face, aka need to multiply by 1.5
|
||||||
|
this.indexCount = (int)(vertexCount * 1.5);
|
||||||
|
|
||||||
|
if (RENDER_DEF.useSingleIbo())
|
||||||
|
{
|
||||||
|
// ignore index uploading when running a single IBO
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// recreating if the size changes is always necessary (even if we only need a smaller amount)
|
||||||
|
// due to a bug on Mac where it will attempt to render anything allocated in the buffer
|
||||||
|
if (this.indexGpuBuffer == null
|
||||||
|
|| oldIndexCount != this.indexCount)
|
||||||
|
{
|
||||||
|
if (this.indexGpuBuffer == null)
|
||||||
|
{
|
||||||
|
BUFFER_COUNT_REF.incrementAndGet();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.indexGpuBuffer != null)
|
||||||
|
{
|
||||||
|
this.indexGpuBuffer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer indexBuffer = IndexBufferBuilder.createBuffer(this.vertexCount);
|
||||||
|
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_INDEX;
|
||||||
|
this.indexGpuBuffer = GPU_DEVICE.createBuffer(BlazeVertexBufferWrapper::getIndexBufferName, usage, indexBuffer.capacity());
|
||||||
|
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.indexGpuBuffer, /*offset*/ 0, indexBuffer.capacity());
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, indexBuffer);
|
||||||
|
|
||||||
|
MemoryUtil.memFree(indexBuffer);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static String getIndexBufferName() { return "distantHorizons:LodIndexBuffer"; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
if (this.vertexGpuBuffer != null)
|
||||||
|
{
|
||||||
|
BUFFER_COUNT_REF.decrementAndGet();
|
||||||
|
this.vertexGpuBuffer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.indexGpuBuffer != null)
|
||||||
|
{
|
||||||
|
BUFFER_COUNT_REF.decrementAndGet();
|
||||||
|
this.indexGpuBuffer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
//LOGGER.info("Close, count: ["+BUFFER_COUNT_REF.get()+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze.wrappers.texture;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeTextureViewWrapper {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.textures.*;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
|
||||||
|
public class BlazeTextureViewWrapper
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
|
||||||
|
public GpuTextureView textureView = null;
|
||||||
|
public GpuSampler textureSampler = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=======//
|
||||||
|
// setup //
|
||||||
|
//=======//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/** does nothing if the texture is already wrapped */
|
||||||
|
public void tryWrap(GpuTexture texture)
|
||||||
|
{
|
||||||
|
this.tryRecreateTextureView(texture);
|
||||||
|
this.tryCreateSampler();
|
||||||
|
}
|
||||||
|
private void tryRecreateTextureView(GpuTexture texture)
|
||||||
|
{
|
||||||
|
if (this.textureView == null
|
||||||
|
|| this.textureView.texture() != texture)
|
||||||
|
{
|
||||||
|
if (this.textureView != null)
|
||||||
|
{
|
||||||
|
this.textureView.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.textureView = GPU_DEVICE.createTextureView(texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void tryCreateSampler()
|
||||||
|
{
|
||||||
|
if (this.textureSampler == null)
|
||||||
|
{
|
||||||
|
this.textureSampler = GPU_DEVICE.createSampler(
|
||||||
|
AddressMode.CLAMP_TO_EDGE, AddressMode.CLAMP_TO_EDGE, // U,V
|
||||||
|
FilterMode.LINEAR, FilterMode.LINEAR, // minFilter, magFilter
|
||||||
|
1, // maxAnisotropy
|
||||||
|
OptionalDouble.empty() // maxLod
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+167
@@ -0,0 +1,167 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze.wrappers.texture;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeTextureWrapper {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.textures.*;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
|
||||||
|
import java.util.OptionalDouble;
|
||||||
|
|
||||||
|
public class BlazeTextureWrapper
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
|
||||||
|
public final String name;
|
||||||
|
public final TextureFormat textureFormat;
|
||||||
|
|
||||||
|
public GpuTexture texture = null;
|
||||||
|
public GpuTextureView textureView = null;
|
||||||
|
public GpuSampler textureSampler = null;
|
||||||
|
|
||||||
|
private int width = -1;
|
||||||
|
private int height = -1;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// constructors //
|
||||||
|
//==============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public static BlazeTextureWrapper createDepth(String name) { return new BlazeTextureWrapper(name, TextureFormat.DEPTH32); }
|
||||||
|
public static BlazeTextureWrapper createColor(String name) { return new BlazeTextureWrapper(name, TextureFormat.RGBA8); }
|
||||||
|
|
||||||
|
private BlazeTextureWrapper(String name, TextureFormat textureFormat)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.textureFormat = textureFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// getters //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public boolean isEmpty() { return this.texture == null; }
|
||||||
|
|
||||||
|
/** @return -1 if the texture is null */
|
||||||
|
public int getWidth() { return this.width; }
|
||||||
|
/** @return -1 if the texture is null */
|
||||||
|
public int getHeight() { return this.height; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=======//
|
||||||
|
// setup //
|
||||||
|
//=======//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/** does nothing if the texture is already created and the correct size */
|
||||||
|
public void tryCreateOrResize()
|
||||||
|
{
|
||||||
|
this.tryCreateTexture();
|
||||||
|
this.tryCreateSampler();
|
||||||
|
}
|
||||||
|
private void tryCreateTexture()
|
||||||
|
{
|
||||||
|
int viewWidth = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||||
|
int viewHeight = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||||
|
|
||||||
|
if (this.texture == null
|
||||||
|
|| this.width != viewWidth
|
||||||
|
|| this.height != viewHeight)
|
||||||
|
{
|
||||||
|
if (this.texture != null)
|
||||||
|
{
|
||||||
|
this.texture.close();
|
||||||
|
this.textureView.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.width = viewWidth;
|
||||||
|
this.height = viewHeight;
|
||||||
|
|
||||||
|
int usage = GpuTexture.USAGE_COPY_DST
|
||||||
|
| GpuTexture.USAGE_TEXTURE_BINDING
|
||||||
|
| GpuTexture.USAGE_COPY_SRC
|
||||||
|
| GpuTexture.USAGE_RENDER_ATTACHMENT;
|
||||||
|
this.texture = GPU_DEVICE.createTexture(this.name,
|
||||||
|
usage,
|
||||||
|
this.textureFormat,
|
||||||
|
viewWidth, viewHeight,
|
||||||
|
/*depthOrLayers*/ 1, /*mipLevels*/ 1
|
||||||
|
);
|
||||||
|
this.textureView = GPU_DEVICE.createTextureView(this.texture);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void tryCreateSampler()
|
||||||
|
{
|
||||||
|
if (this.textureSampler == null)
|
||||||
|
{
|
||||||
|
this.textureSampler = GPU_DEVICE.createSampler(
|
||||||
|
AddressMode.CLAMP_TO_EDGE, AddressMode.CLAMP_TO_EDGE, // U,V
|
||||||
|
FilterMode.LINEAR, FilterMode.LINEAR, // minFilter, magFilter
|
||||||
|
1, // maxAnisotropy
|
||||||
|
OptionalDouble.empty() // maxLod
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========//
|
||||||
|
// clearing //
|
||||||
|
//==========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will throw an exception if not a color texture.
|
||||||
|
* @see ColorUtil#argbToInt
|
||||||
|
*/
|
||||||
|
public void clearColor(int clearArgbColor)
|
||||||
|
{
|
||||||
|
if (this.texture != null)
|
||||||
|
{
|
||||||
|
COMMAND_ENCODER.clearColorTexture(this.texture, clearArgbColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Will throw an exception if not a depth texture. */
|
||||||
|
public void clearDepth(float depth)
|
||||||
|
{
|
||||||
|
if (this.texture != null)
|
||||||
|
{
|
||||||
|
COMMAND_ENCODER.clearDepthTexture(this.texture, depth);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+78
@@ -0,0 +1,78 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze.wrappers.uniform;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeLodUniformBufferWrapper {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.Std140Builder;
|
||||||
|
import com.mojang.blaze3d.buffers.Std140SizeCalculator;
|
||||||
|
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.ILodContainerUniformBufferWrapper;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class BlazeLodUniformBufferWrapper extends BlazeUniformBufferWrapper implements ILodContainerUniformBufferWrapper
|
||||||
|
{
|
||||||
|
|
||||||
|
private boolean uploaded = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public BlazeLodUniformBufferWrapper() { super(BlazeLodUniformBufferWrapper.class.getName()); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// upload //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createUniformData(LodBufferContainer bufferContainer)
|
||||||
|
{
|
||||||
|
Vec3f modelOffset = new Vec3f(
|
||||||
|
(float) (bufferContainer.minCornerBlockPos.getX()),
|
||||||
|
(float) (bufferContainer.minCornerBlockPos.getY()),
|
||||||
|
(float) (bufferContainer.minCornerBlockPos.getZ()));
|
||||||
|
|
||||||
|
// upload data //
|
||||||
|
|
||||||
|
int uniformBufferSize = new Std140SizeCalculator()
|
||||||
|
.putVec3() // uModelOffset
|
||||||
|
.get();
|
||||||
|
|
||||||
|
ByteBuffer buffer = this.getOrCreateBuffer(uniformBufferSize);
|
||||||
|
Std140Builder.intoBuffer(buffer)
|
||||||
|
.putVec3(modelOffset.x, modelOffset.y, modelOffset.z) // uModelOffset
|
||||||
|
.get();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tryUpload()
|
||||||
|
{
|
||||||
|
if (this.uploaded)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.upload();
|
||||||
|
|
||||||
|
this.uploaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+130
@@ -0,0 +1,130 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.blaze.wrappers.uniform;
|
||||||
|
|
||||||
|
#if MC_VER <= MC_1_21_10
|
||||||
|
public class BlazeUniformBufferWrapper {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBuffer;
|
||||||
|
import com.mojang.blaze3d.buffers.GpuBufferSlice;
|
||||||
|
import com.mojang.blaze3d.systems.CommandEncoder;
|
||||||
|
import com.mojang.blaze3d.systems.GpuDevice;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IUniformBufferWrapper;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
|
public class BlazeUniformBufferWrapper implements IUniformBufferWrapper
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final GpuDevice GPU_DEVICE = RenderSystem.getDevice();
|
||||||
|
private static final CommandEncoder COMMAND_ENCODER = GPU_DEVICE.createCommandEncoder();
|
||||||
|
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
private int cpuBufferSize = 0;
|
||||||
|
private int gpuBufferSize = 0;
|
||||||
|
|
||||||
|
private ByteBuffer cpuBuffer = null;
|
||||||
|
public GpuBuffer gpuBuffer = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public BlazeUniformBufferWrapper(String name) { this.name = name; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// render //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
protected ByteBuffer getOrCreateBuffer(int size)
|
||||||
|
{
|
||||||
|
if (this.cpuBuffer == null
|
||||||
|
|| this.cpuBufferSize != size)
|
||||||
|
{
|
||||||
|
this.cpuBuffer = ByteBuffer.allocateDirect(size);
|
||||||
|
this.cpuBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
|
||||||
|
this.cpuBufferSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.cpuBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void upload() throws IllegalStateException
|
||||||
|
{
|
||||||
|
if (this.cpuBuffer == null)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Upload called before buffer was created");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.gpuBuffer == null
|
||||||
|
|| this.gpuBufferSize != this.cpuBufferSize)
|
||||||
|
{
|
||||||
|
if (this.gpuBuffer != null)
|
||||||
|
{
|
||||||
|
this.gpuBuffer.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
int usage = GpuBuffer.USAGE_COPY_DST
|
||||||
|
| GpuBuffer.USAGE_VERTEX
|
||||||
|
| GpuBuffer.USAGE_UNIFORM;
|
||||||
|
this.gpuBuffer = GPU_DEVICE.createBuffer(this::getBufferName, usage, this.cpuBufferSize);
|
||||||
|
|
||||||
|
this.gpuBufferSize = this.cpuBufferSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int byteSize = (this.cpuBuffer.limit() - this.cpuBuffer.position());
|
||||||
|
GpuBufferSlice bufferSlice = new GpuBufferSlice(this.gpuBuffer, /*offset*/0, byteSize);
|
||||||
|
if (!bufferSlice.buffer().isClosed())
|
||||||
|
{
|
||||||
|
COMMAND_ENCODER.writeToBuffer(bufferSlice, this.cpuBuffer);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOGGER.warn("Uploading to buffer ["+this.name+"] failed due to already being closed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private String getBufferName() { return this.name; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
if (this.gpuBuffer != null)
|
||||||
|
{
|
||||||
|
this.gpuBuffer.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
+197
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLIndexBuffer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLVertexBuffer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.shader.GlShaderProgram;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.vertexAttribute.GlAbstractVertexAttribute;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.vertexAttribute.GlVertexPointer;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.nio.ByteOrder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles rendering the wireframe particles
|
||||||
|
* that are used for seeing what the system's doing.
|
||||||
|
*/
|
||||||
|
public class GlDhDebugWireframeRenderer extends AbstractDebugWireframeRenderer
|
||||||
|
{
|
||||||
|
public static GlDhDebugWireframeRenderer INSTANCE = new GlDhDebugWireframeRenderer();
|
||||||
|
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// rendering setup
|
||||||
|
private GlShaderProgram basicShader;
|
||||||
|
private GLVertexBuffer vertexBuffer;
|
||||||
|
private GLIndexBuffer indexBuffer;
|
||||||
|
private GlAbstractVertexAttribute va;
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** A box from 0,0,0 to 1,1,1 */
|
||||||
|
private static final float[] BOX_VERTICES = {
|
||||||
|
//region
|
||||||
|
// Pos x y z
|
||||||
|
0, 0, 0,
|
||||||
|
1, 0, 0,
|
||||||
|
1, 1, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 0, 1,
|
||||||
|
1, 0, 1,
|
||||||
|
1, 1, 1,
|
||||||
|
0, 1, 1,
|
||||||
|
//endregion
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final int[] BOX_OUTLINE_INDICES = {
|
||||||
|
//region
|
||||||
|
0, 1,
|
||||||
|
1, 2,
|
||||||
|
2, 3,
|
||||||
|
3, 0,
|
||||||
|
|
||||||
|
4, 5,
|
||||||
|
5, 6,
|
||||||
|
6, 7,
|
||||||
|
7, 4,
|
||||||
|
|
||||||
|
0, 4,
|
||||||
|
1, 5,
|
||||||
|
2, 6,
|
||||||
|
3, 7,
|
||||||
|
//endregion
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private GlDhDebugWireframeRenderer() { }
|
||||||
|
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init = true;
|
||||||
|
|
||||||
|
this.va = GlAbstractVertexAttribute.create();
|
||||||
|
this.va.bind();
|
||||||
|
// Pos
|
||||||
|
this.va.setVertexAttribute(0, 0, GlVertexPointer.addVec3Pointer(false));
|
||||||
|
this.va.completeAndCheck(Float.BYTES * 3);
|
||||||
|
this.basicShader = new GlShaderProgram(
|
||||||
|
"assets/distanthorizons/shaders/debug/gl/vert.vert",
|
||||||
|
"assets/distanthorizons/shaders/debug/gl/frag.frag",
|
||||||
|
"vPosition"
|
||||||
|
);
|
||||||
|
this.createBuffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createBuffer()
|
||||||
|
{
|
||||||
|
// box vertices
|
||||||
|
ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICES.length * Float.BYTES);
|
||||||
|
boxVerticesBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES);
|
||||||
|
boxVerticesBuffer.rewind();
|
||||||
|
this.vertexBuffer = new GLVertexBuffer(false);
|
||||||
|
this.vertexBuffer.bind();
|
||||||
|
this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES);
|
||||||
|
|
||||||
|
|
||||||
|
// outline vertex indexes
|
||||||
|
ByteBuffer boxOutlineBuffer = ByteBuffer.allocateDirect(BOX_OUTLINE_INDICES.length * Integer.BYTES);
|
||||||
|
boxOutlineBuffer.order(ByteOrder.nativeOrder());
|
||||||
|
boxOutlineBuffer.asIntBuffer().put(BOX_OUTLINE_INDICES);
|
||||||
|
boxOutlineBuffer.rewind();
|
||||||
|
this.indexBuffer = new GLIndexBuffer(false);
|
||||||
|
this.indexBuffer.uploadBuffer(boxOutlineBuffer, EDhApiGpuUploadMethod.DATA, BOX_OUTLINE_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========//
|
||||||
|
// rendering //
|
||||||
|
//===========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
this.init();
|
||||||
|
|
||||||
|
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE);
|
||||||
|
GLMC.enableDepthTest();
|
||||||
|
|
||||||
|
this.basicShader.bind();
|
||||||
|
this.va.bind();
|
||||||
|
this.va.bindBufferToAllBindingPoints(this.vertexBuffer.getId());
|
||||||
|
|
||||||
|
this.indexBuffer.bind();
|
||||||
|
|
||||||
|
super.render(renderParams);
|
||||||
|
|
||||||
|
// revert to prevent issues with the following passes
|
||||||
|
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderBox(Box box)
|
||||||
|
{
|
||||||
|
Mat4f boxTransform = Mat4f.createTranslateMatrix(box.minPos.x - this.camPosFloatThisFrame.x, box.minPos.y - this.camPosFloatThisFrame.y, box.minPos.z - this.camPosFloatThisFrame.z);
|
||||||
|
boxTransform.multiply(Mat4f.createScaleMatrix(box.maxPos.x - box.minPos.x, box.maxPos.y - box.minPos.y, box.maxPos.z - box.minPos.z));
|
||||||
|
|
||||||
|
Mat4f transformMatrix = this.dhMvmProjMatrixThisFrame.copy();
|
||||||
|
transformMatrix.multiply(boxTransform);
|
||||||
|
this.basicShader.setUniform(this.basicShader.getUniformLocation("uTransform"), transformMatrix);
|
||||||
|
|
||||||
|
this.basicShader.setUniform(this.basicShader.getUniformLocation("uColor"), box.color);
|
||||||
|
|
||||||
|
GL32.glDrawElements(GL32.GL_LINES, BOX_OUTLINE_INDICES.length, GL32.GL_UNSIGNED_INT, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+468
@@ -0,0 +1,468 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
|
||||||
|
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer;
|
||||||
|
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShaderProgram;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiTextureCreatedParam;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.GlDhFramebuffer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.texture.*;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.postProcessing.apply.GlDhApplyShader;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.terrain.GlDhTerrainShaderProgram;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhMetaRenderer;
|
||||||
|
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||||
|
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
public class GlDhMetaRenderer implements IDhMetaRenderer
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logRendererEventToFile)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final DhLogger RATE_LIMITED_LOGGER = new DhLoggerBuilder()
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logRendererEventToFile)
|
||||||
|
.maxCountPerSecond(4)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final GlDhMetaRenderer INSTANCE = new GlDhMetaRenderer();
|
||||||
|
|
||||||
|
|
||||||
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
private int activeFramebufferId = -1;
|
||||||
|
private int activeColorTextureId = -1;
|
||||||
|
private int activeDepthTextureId = -1;
|
||||||
|
private int textureWidth;
|
||||||
|
private int textureHeight;
|
||||||
|
|
||||||
|
|
||||||
|
// framebuffer and texture ID's for this renderer
|
||||||
|
private IDhApiFramebuffer framebuffer;
|
||||||
|
/** will be null if MC's framebuffer is being used since MC already has a color texture */
|
||||||
|
@Nullable
|
||||||
|
private GlDhColorTexture nullableColorTexture;
|
||||||
|
private GlDhDepthTexture depthTexture;
|
||||||
|
/**
|
||||||
|
* If true the {@link GlDhMetaRenderer#framebuffer} is the same as MC's.
|
||||||
|
* This should only be true in the case of Optifine so LODs won't be overwritten when shaders are enabled.
|
||||||
|
*/
|
||||||
|
private boolean usingMcFramebuffer = false;
|
||||||
|
|
||||||
|
private boolean renderObjectsCreated = false;
|
||||||
|
/** used in case there's an API override */
|
||||||
|
public IDhApiShaderProgram shaderProgramForThisFrame;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============//
|
||||||
|
// pre render //
|
||||||
|
//============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runRenderPassSetup(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
boolean firstPass =
|
||||||
|
(renderParams.renderPass == EDhApiRenderPass.OPAQUE
|
||||||
|
|| renderParams.renderPass == EDhApiRenderPass.OPAQUE_AND_TRANSPARENT);
|
||||||
|
|
||||||
|
if (!this.renderObjectsCreated)
|
||||||
|
{
|
||||||
|
boolean setupSuccess = this.createRenderObjects();
|
||||||
|
if (!setupSuccess)
|
||||||
|
{
|
||||||
|
// shouldn't normally happen, but just in case
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.renderObjectsCreated = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.shaderProgramForThisFrame = GlDhTerrainRenderer.INSTANCE.getTerrainShaderProgram();
|
||||||
|
IDhApiShaderProgram lodShaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class);
|
||||||
|
if (lodShaderProgramOverride != null && this.shaderProgramForThisFrame.overrideThisFrame())
|
||||||
|
{
|
||||||
|
this.shaderProgramForThisFrame = lodShaderProgramOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.setGLState(renderParams, firstPass);
|
||||||
|
|
||||||
|
this.bindLightmap(renderParams.lightmap);
|
||||||
|
}
|
||||||
|
private void setGLState(
|
||||||
|
DhApiRenderParam renderEventParam,
|
||||||
|
boolean firstPass)
|
||||||
|
{
|
||||||
|
//===================//
|
||||||
|
// framebuffer setup //
|
||||||
|
//===================//
|
||||||
|
|
||||||
|
// get the active framebuffer
|
||||||
|
IDhApiFramebuffer framebuffer = this.framebuffer;
|
||||||
|
IDhApiFramebuffer framebufferOverride = OverrideInjector.INSTANCE.get(IDhApiFramebuffer.class);
|
||||||
|
if (framebufferOverride != null && framebufferOverride.overrideThisFrame())
|
||||||
|
{
|
||||||
|
framebuffer = framebufferOverride;
|
||||||
|
}
|
||||||
|
this.setActiveFramebufferId(framebuffer.getId());
|
||||||
|
framebuffer.bind();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========//
|
||||||
|
// bindings //
|
||||||
|
//==========//
|
||||||
|
|
||||||
|
// by default draw everything as triangles
|
||||||
|
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||||
|
GLMC.enableFaceCulling();
|
||||||
|
|
||||||
|
GLMC.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
GLMC.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ZERO);
|
||||||
|
|
||||||
|
GL32.glDisable(GL32.GL_SCISSOR_TEST);
|
||||||
|
|
||||||
|
// Enable depth test and depth mask
|
||||||
|
GLMC.enableDepthTest();
|
||||||
|
GLMC.glDepthFunc(GL32.GL_LESS);
|
||||||
|
GLMC.enableDepthMask();
|
||||||
|
|
||||||
|
// This is required for MC versions 1.21.5+
|
||||||
|
// due to MC updating the lightmap by changing the viewport size
|
||||||
|
GL32.glViewport(0, 0, this.textureWidth, this.textureHeight);
|
||||||
|
|
||||||
|
this.shaderProgramForThisFrame.bind();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========//
|
||||||
|
// uniforms //
|
||||||
|
//==========//
|
||||||
|
|
||||||
|
IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class);
|
||||||
|
if (shaderProgramOverride != null)
|
||||||
|
{
|
||||||
|
shaderProgramOverride.fillUniformData(renderEventParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.shaderProgramForThisFrame.fillUniformData(renderEventParam);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===============//
|
||||||
|
// texture setup //
|
||||||
|
//===============//
|
||||||
|
|
||||||
|
// resize the textures if needed
|
||||||
|
if (MC_RENDER.getTargetFramebufferViewportWidth() != this.textureWidth
|
||||||
|
|| MC_RENDER.getTargetFramebufferViewportHeight() != this.textureHeight)
|
||||||
|
{
|
||||||
|
// just resizing the textures doesn't work when Optifine is present,
|
||||||
|
// so recreate the textures with the new size instead
|
||||||
|
this.createAndBindTextures();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// set the active textures
|
||||||
|
int depthTextureId = this.depthTexture.getTextureId();
|
||||||
|
this.setActiveDepthTextureId(depthTextureId);
|
||||||
|
|
||||||
|
if (this.nullableColorTexture != null)
|
||||||
|
{
|
||||||
|
int colorTextureId = this.nullableColorTexture.getTextureId();
|
||||||
|
this.setActiveColorTextureId(colorTextureId);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// get MC's color texture
|
||||||
|
int colorTextureId = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||||
|
this.setActiveColorTextureId(colorTextureId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// needs to be fired after all the textures have been created/bound
|
||||||
|
boolean clearTextures = !ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeTextureClearEvent.class, renderEventParam);
|
||||||
|
if (clearTextures)
|
||||||
|
{
|
||||||
|
GL32.glClearDepth(1.0);
|
||||||
|
|
||||||
|
float[] clearColorValues = new float[4];
|
||||||
|
GL32.glGetFloatv(GL32.GL_COLOR_CLEAR_VALUE, clearColorValues);
|
||||||
|
GL32.glClearColor(clearColorValues[0], clearColorValues[1], clearColorValues[2], 1.0f);
|
||||||
|
|
||||||
|
if (this.usingMcFramebuffer && framebufferOverride == null)
|
||||||
|
{
|
||||||
|
// Due to using MC/Optifine's framebuffer we need to re-bind the depth texture,
|
||||||
|
// otherwise we'll be writing to MC/Optifine's depth texture which causes rendering issues
|
||||||
|
framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EGlDhDepthBufferFormat.DEPTH32F.isCombinedStencil());
|
||||||
|
|
||||||
|
|
||||||
|
// don't clear the color texture, that removes the sky
|
||||||
|
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
else if (firstPass)
|
||||||
|
{
|
||||||
|
GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean createRenderObjects()
|
||||||
|
{
|
||||||
|
if (this.renderObjectsCreated)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Renderer setup called but it has already completed setup!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// GLProxy should have already been created by this point, but just in case create it now
|
||||||
|
GLProxy.getInstance();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LOGGER.info("Setting up renderer");
|
||||||
|
|
||||||
|
|
||||||
|
// create or get the frame buffer
|
||||||
|
if (AbstractOptifineAccessor.optifinePresent())
|
||||||
|
{
|
||||||
|
// use MC/Optifine's default Framebuffer so shaders won't remove the LODs
|
||||||
|
int currentFramebufferId = MC_RENDER.getTargetFramebuffer();
|
||||||
|
this.framebuffer = new GlDhFramebuffer(currentFramebufferId);
|
||||||
|
this.usingMcFramebuffer = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// normal use case
|
||||||
|
this.framebuffer = new GlDhFramebuffer();
|
||||||
|
this.usingMcFramebuffer = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create and bind the necessary textures
|
||||||
|
this.createAndBindTextures();
|
||||||
|
|
||||||
|
if(this.framebuffer.getStatus() != GL32.GL_FRAMEBUFFER_COMPLETE)
|
||||||
|
{
|
||||||
|
// This generally means something wasn't bound, IE missing either the color or depth texture
|
||||||
|
LOGGER.warn("Framebuffer ["+this.framebuffer.getId()+"] isn't complete.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
LOGGER.info("Renderer setup complete");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( "deprecation" ) // done to ignore DhApiColorDepthTextureCreatedEvent
|
||||||
|
private void createAndBindTextures()
|
||||||
|
{
|
||||||
|
int oldWidth = this.textureWidth;
|
||||||
|
int oldHeight = this.textureHeight;
|
||||||
|
this.textureWidth = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||||
|
this.textureHeight = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||||
|
|
||||||
|
DhApiTextureCreatedParam textureCreatedParam = new DhApiTextureCreatedParam(
|
||||||
|
oldWidth, oldHeight,
|
||||||
|
this.textureWidth, this.textureHeight
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// DhApiColorDepthTextureCreatedEvent needs to be kept around since old versions of Iris need it
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiColorDepthTextureCreatedEvent.class, new DhApiColorDepthTextureCreatedEvent.EventParam(textureCreatedParam));
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeColorDepthTextureCreatedEvent.class, textureCreatedParam);
|
||||||
|
|
||||||
|
|
||||||
|
// also update the framebuffer override if present
|
||||||
|
IDhApiFramebuffer framebufferOverride = OverrideInjector.INSTANCE.get(IDhApiFramebuffer.class);
|
||||||
|
|
||||||
|
|
||||||
|
this.depthTexture = new GlDhDepthTexture(this.textureWidth, this.textureHeight, EGlDhDepthBufferFormat.DEPTH32F);
|
||||||
|
this.framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EGlDhDepthBufferFormat.DEPTH32F.isCombinedStencil());
|
||||||
|
if (framebufferOverride != null)
|
||||||
|
{
|
||||||
|
framebufferOverride.addDepthAttachment(this.depthTexture.getTextureId(), EGlDhDepthBufferFormat.DEPTH32F.isCombinedStencil());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if we are using MC's frame buffer, a color texture is already present and shouldn't need to be bound
|
||||||
|
if (!this.usingMcFramebuffer)
|
||||||
|
{
|
||||||
|
this.nullableColorTexture = GlDhColorTexture.builder()
|
||||||
|
.setDimensions(this.textureWidth, this.textureHeight)
|
||||||
|
.setInternalFormat(EGlDhInternalTextureFormat.RGBA8)
|
||||||
|
.setPixelType(EGlDhPixelType.UNSIGNED_BYTE)
|
||||||
|
.setPixelFormat(EGlDhPixelFormat.RGBA)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
this.framebuffer.addColorAttachment(0, this.nullableColorTexture.getTextureId());
|
||||||
|
if (framebufferOverride != null)
|
||||||
|
{
|
||||||
|
framebufferOverride.addColorAttachment(0, this.nullableColorTexture.getTextureId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.nullableColorTexture = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterColorDepthTextureCreatedEvent.class, textureCreatedParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// post render //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void runRenderPassCleanup(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
boolean runningDeferredPass = (renderParams.renderPass == EDhApiRenderPass.TRANSPARENT);
|
||||||
|
if (!runningDeferredPass)
|
||||||
|
{
|
||||||
|
//===================//
|
||||||
|
// optifine clean up //
|
||||||
|
//===================//
|
||||||
|
|
||||||
|
if (this.usingMcFramebuffer)
|
||||||
|
{
|
||||||
|
// If MC's framebuffer is being used the depth needs to be cleared to prevent rendering on top of MC.
|
||||||
|
// This should only happen when Optifine shaders are being used.
|
||||||
|
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
this.unbindLightmap();
|
||||||
|
this.shaderProgramForThisFrame.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void applyToMcTexture(RenderParams renderParams) { GlDhApplyShader.INSTANCE.render(renderParams); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// clear textures //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clearDhDepthAndColorTextures(RenderParams renderParams)
|
||||||
|
{
|
||||||
|
IDhApiFramebuffer framebufferOverride = OverrideInjector.INSTANCE.get(IDhApiFramebuffer.class);
|
||||||
|
|
||||||
|
boolean firstPass =
|
||||||
|
(renderParams.renderPass == EDhApiRenderPass.OPAQUE
|
||||||
|
|| renderParams.renderPass == EDhApiRenderPass.OPAQUE_AND_TRANSPARENT);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// needs to be fired after all the textures have been created/bound
|
||||||
|
boolean clearTextures = !ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeTextureClearEvent.class, renderParams);
|
||||||
|
if (clearTextures)
|
||||||
|
{
|
||||||
|
GL32.glClearDepth(1.0);
|
||||||
|
|
||||||
|
float[] clearColorValues = new float[4];
|
||||||
|
GL32.glGetFloatv(GL32.GL_COLOR_CLEAR_VALUE, clearColorValues);
|
||||||
|
GL32.glClearColor(clearColorValues[0], clearColorValues[1], clearColorValues[2], 1.0f);
|
||||||
|
|
||||||
|
if (this.usingMcFramebuffer
|
||||||
|
&& framebufferOverride == null)
|
||||||
|
{
|
||||||
|
//// Due to using MC/Optifine's framebuffer we need to re-bind the depth texture,
|
||||||
|
//// otherwise we'll be writing to MC/Optifine's depth texture which causes rendering issues
|
||||||
|
//this.framebuffer.addDepthAttachment(this.depthTexture.getTextureId(), EDhDepthBufferFormat.DEPTH32F.isCombinedStencil());
|
||||||
|
|
||||||
|
|
||||||
|
// don't clear the color texture, that removes the sky
|
||||||
|
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
else if (firstPass)
|
||||||
|
{
|
||||||
|
GL32.glClear(GL32.GL_COLOR_BUFFER_BIT | GL32.GL_DEPTH_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===============//
|
||||||
|
// API functions //
|
||||||
|
//===============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public void setActiveFramebufferId(int id) { this.activeFramebufferId = id; }
|
||||||
|
/** @return -1 if no frame buffer has been bound yet */
|
||||||
|
public int getActiveFramebufferId() { return this.activeFramebufferId; }
|
||||||
|
|
||||||
|
public void setActiveColorTextureId(int id)
|
||||||
|
{
|
||||||
|
this.activeColorTextureId = id;
|
||||||
|
DhApiRenderProxy.activeOpenGlDhColorTextureId = id;
|
||||||
|
}
|
||||||
|
/** @return -1 if no texture has been bound yet */
|
||||||
|
public int getActiveColorTextureId() { return this.activeColorTextureId; }
|
||||||
|
|
||||||
|
public void setActiveDepthTextureId(int id)
|
||||||
|
{
|
||||||
|
this.activeDepthTextureId = id;
|
||||||
|
DhApiRenderProxy.activeOpenGlDhDepthTextureId = id;
|
||||||
|
}
|
||||||
|
/** @return -1 if no texture has been bound yet */
|
||||||
|
public int getActiveDepthTextureId() { return this.activeDepthTextureId; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper methods //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public void bindLightmap(ILightMapWrapper lightMapWrapper)
|
||||||
|
{
|
||||||
|
LightMapWrapper lightMap = (LightMapWrapper)lightMapWrapper;
|
||||||
|
GLMC.glActiveTexture(GL32.GL_TEXTURE0 + LightMapWrapper.GL_BOUND_INDEX);
|
||||||
|
GLMC.glBindTexture(lightMap.getOpenGlId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void unbindLightmap()
|
||||||
|
{
|
||||||
|
// strange that we don't call "glActiveTexture" here but since it's working James isn't going to change it right now (2026-03-10)
|
||||||
|
GLMC.glBindTexture(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.generic.GlGenericObjectRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.generic.GlGenericObjectVertexContainer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.GlDummyUniformData;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLVertexBuffer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.postProcessing.fade.GlDhFarFadeRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.postProcessing.fade.GlVanillaFadeRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.postProcessing.fog.GlDhFogRenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.postProcessing.ssao.GlDhSSAORenderer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.terrain.GlDhTerrainShaderProgram;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.test.GlTestTriangleRenderer;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.AbstractDebugWireframeRenderer;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.ILodContainerUniformBufferWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.*;
|
||||||
|
|
||||||
|
public class GlDhRenderApiDefinition extends AbstractDhRenderApiDefinition
|
||||||
|
{
|
||||||
|
//=========//
|
||||||
|
// getters //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public String getApiName() { return "OpenGL"; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============//
|
||||||
|
// singletons //
|
||||||
|
//============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override public IDhMetaRenderer getMetaRenderer() { return GlDhMetaRenderer.INSTANCE; }
|
||||||
|
@Override public IDhTerrainRenderer getTerrainRenderer() { return GlDhTerrainRenderer.INSTANCE; }
|
||||||
|
@Override public IDhSsaoRenderer getSsaoRenderer() { return GlDhSSAORenderer.INSTANCE; }
|
||||||
|
@Override public IDhFogRenderer getFogRenderer() { return GlDhFogRenderer.INSTANCE; }
|
||||||
|
@Override public IDhFarFadeRenderer getFarFadeRenderer() { return GlDhFarFadeRenderer.INSTANCE; }
|
||||||
|
@Override public AbstractDebugWireframeRenderer getDebugWireframeRenderer() { return GlDhDebugWireframeRenderer.INSTANCE; }
|
||||||
|
|
||||||
|
@Override public IDhVanillaFadeRenderer getVanillaFadeRenderer() { return GlVanillaFadeRenderer.INSTANCE; }
|
||||||
|
@Override public IDhTestTriangleRenderer getTestTriangleRenderer() { return GlTestTriangleRenderer.INSTANCE; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========//
|
||||||
|
// factories //
|
||||||
|
//===========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override public IDhGenericRenderer createGenericRenderer() { return new GlGenericObjectRenderer(); }
|
||||||
|
|
||||||
|
@Override public IVertexBufferWrapper createVboWrapper(String name) { return new GLVertexBuffer(); }
|
||||||
|
@Override public ILodContainerUniformBufferWrapper createLodContainerUniformWrapper() { return new GlDummyUniformData(); }
|
||||||
|
@Override public IDhGenericObjectVertexBufferContainer createGenericVboContainer() { return new GlGenericObjectVertexContainer(); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.terrain.GlDhTerrainShaderProgram;
|
||||||
|
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.util.objects.SortedArraySet;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTerrainRenderer;
|
||||||
|
|
||||||
|
public class GlDhTerrainRenderer implements IDhTerrainRenderer
|
||||||
|
{
|
||||||
|
public static final GlDhTerrainRenderer INSTANCE = new GlDhTerrainRenderer();
|
||||||
|
|
||||||
|
private GlDhTerrainShaderProgram terrainShaderProgram = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private GlDhTerrainRenderer() {}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// getters //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/** must be called on the render thread the first time so GL can run it's setup */
|
||||||
|
public GlDhTerrainShaderProgram getTerrainShaderProgram()
|
||||||
|
{
|
||||||
|
if (this.terrainShaderProgram == null)
|
||||||
|
{
|
||||||
|
this.terrainShaderProgram = new GlDhTerrainShaderProgram();
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.terrainShaderProgram;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========//
|
||||||
|
// render //
|
||||||
|
//========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(RenderParams renderEventParam, boolean opaquePass, SortedArraySet<LodBufferContainer> bufferContainers, IProfilerWrapper profiler)
|
||||||
|
{
|
||||||
|
this.getTerrainShaderProgram();
|
||||||
|
|
||||||
|
this.terrainShaderProgram.tryInit();
|
||||||
|
this.terrainShaderProgram.render(renderEventParam, opaquePass, bufferContainers, profiler);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+754
@@ -0,0 +1,754 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl.generic;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||||
|
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||||
|
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
|
||||||
|
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||||
|
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
||||||
|
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
|
||||||
|
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;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLIndexBuffer;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.buffer.GLVertexBuffer;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderParams;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.GenericRenderObjectFactory;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup;
|
||||||
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhGenericRenderer;
|
||||||
|
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||||
|
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
||||||
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
|
import org.lwjgl.opengl.ARBInstancedArrays;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
import org.lwjgl.opengl.GL33;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles rendering generic groups of {@link DhApiRenderableBox}.
|
||||||
|
*
|
||||||
|
* @see IDhApiCustomRenderRegister
|
||||||
|
* @see DhApiRenderableBox
|
||||||
|
*/
|
||||||
|
public class GlGenericObjectRenderer implements IDhGenericRenderer
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||||
|
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||||
|
|
||||||
|
private static final DhApiRenderableBoxGroupShading DEFAULT_SHADING = DhApiRenderableBoxGroupShading.getUnshaded();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can be used to troubleshoot the renderer.
|
||||||
|
* If enabled several debug objects will render around (0,150,0).
|
||||||
|
*/
|
||||||
|
public static final boolean RENDER_DEBUG_OBJECTS = false;
|
||||||
|
|
||||||
|
|
||||||
|
// rendering setup
|
||||||
|
private boolean init = false;
|
||||||
|
|
||||||
|
private IDhApiGenericObjectShaderProgram instancedShaderProgram;
|
||||||
|
private IDhApiGenericObjectShaderProgram directShaderProgram;
|
||||||
|
private GLVertexBuffer boxVertexBuffer;
|
||||||
|
private GLIndexBuffer boxIndexBuffer;
|
||||||
|
|
||||||
|
private boolean instancedRenderingAvailable;
|
||||||
|
private boolean vertexAttribDivisorSupported;
|
||||||
|
private boolean instancedArraysSupported;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<Long, RenderableBoxGroup> boxGroupById = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** A box from 0,0,0 to 1,1,1 */
|
||||||
|
private static final float[] BOX_VERTICES = {
|
||||||
|
//region
|
||||||
|
// Pos x y z
|
||||||
|
|
||||||
|
// min X, vertical face
|
||||||
|
0, 0, 0,
|
||||||
|
1, 0, 0,
|
||||||
|
1, 1, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
// max X, vertical face
|
||||||
|
0, 1, 1,
|
||||||
|
1, 1, 1,
|
||||||
|
1, 0, 1,
|
||||||
|
0, 0, 1,
|
||||||
|
|
||||||
|
// min Z, vertical face
|
||||||
|
0, 0, 1,
|
||||||
|
0, 0, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
0, 1, 1,
|
||||||
|
// max Z, vertical face
|
||||||
|
1, 0, 1,
|
||||||
|
1, 1, 1,
|
||||||
|
1, 1, 0,
|
||||||
|
1, 0, 0,
|
||||||
|
|
||||||
|
// min Y, horizontal face
|
||||||
|
0, 0, 1,
|
||||||
|
1, 0, 1,
|
||||||
|
1, 0, 0,
|
||||||
|
0, 0, 0,
|
||||||
|
// max Y, horizontal face
|
||||||
|
0, 1, 1,
|
||||||
|
1, 1, 1,
|
||||||
|
1, 1, 0,
|
||||||
|
0, 1, 0,
|
||||||
|
//endregion
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
private static final int[] BOX_INDICES = {
|
||||||
|
//region
|
||||||
|
// min X, vertical face
|
||||||
|
2, 1, 0,
|
||||||
|
0, 3, 2,
|
||||||
|
// max X, vertical face
|
||||||
|
6, 5, 4,
|
||||||
|
4, 7, 6,
|
||||||
|
|
||||||
|
// min Z, vertical face
|
||||||
|
10, 9, 8,
|
||||||
|
8, 11, 10,
|
||||||
|
// max Z, vertical face
|
||||||
|
14, 13, 12,
|
||||||
|
12, 15, 14,
|
||||||
|
|
||||||
|
// min Y, horizontal face
|
||||||
|
18, 17, 16,
|
||||||
|
16, 19, 18,
|
||||||
|
// max Y, horizontal face
|
||||||
|
20, 21, 22,
|
||||||
|
22, 23, 20,
|
||||||
|
//endregion
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public GlGenericObjectRenderer() { }
|
||||||
|
|
||||||
|
public void init()
|
||||||
|
{
|
||||||
|
if (this.init)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.init = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===================================//
|
||||||
|
// is instanced rendering available? //
|
||||||
|
//===================================//
|
||||||
|
|
||||||
|
this.vertexAttribDivisorSupported = GLProxy.getInstance().vertexAttribDivisorSupported;
|
||||||
|
this.instancedArraysSupported = GLProxy.getInstance().instancedArraysSupported;
|
||||||
|
boolean isMac = (EPlatform.get() == EPlatform.MACOS);
|
||||||
|
if (isMac)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Generic rendering not supported by Mac. Clouds, beacons, and some other effects will be disabled.");
|
||||||
|
Config.Client.Advanced.Graphics.GenericRendering.enableGenericRendering.setApiValue(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.instancedRenderingAvailable = (this.vertexAttribDivisorSupported || this.instancedArraysSupported) && !isMac;
|
||||||
|
if (!this.instancedRenderingAvailable)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering will be slow and some effects may be disabled.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//======================//
|
||||||
|
// startup the renderer //
|
||||||
|
//======================//
|
||||||
|
|
||||||
|
this.instancedShaderProgram = new GlGenericObjectShaderProgram(true);
|
||||||
|
this.directShaderProgram = new GlGenericObjectShaderProgram(false);
|
||||||
|
|
||||||
|
this.createBuffers();
|
||||||
|
|
||||||
|
if (RENDER_DEBUG_OBJECTS)
|
||||||
|
{
|
||||||
|
this.addGenericDebugObjects();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private void createBuffers()
|
||||||
|
{
|
||||||
|
// box vertices
|
||||||
|
ByteBuffer boxVerticesBuffer = MemoryUtil.memAlloc(BOX_VERTICES.length * Float.BYTES);
|
||||||
|
boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES);
|
||||||
|
boxVerticesBuffer.rewind();
|
||||||
|
this.boxVertexBuffer = new GLVertexBuffer(false);
|
||||||
|
this.boxVertexBuffer.bind();
|
||||||
|
this.boxVertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES);
|
||||||
|
MemoryUtil.memFree(boxVerticesBuffer);
|
||||||
|
|
||||||
|
// box vertex indexes
|
||||||
|
ByteBuffer solidIndexBuffer = MemoryUtil.memAlloc(BOX_INDICES.length * Integer.BYTES);
|
||||||
|
solidIndexBuffer.asIntBuffer().put(BOX_INDICES);
|
||||||
|
solidIndexBuffer.rewind();
|
||||||
|
this.boxIndexBuffer = new GLIndexBuffer(false);
|
||||||
|
this.boxIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
|
||||||
|
this.boxIndexBuffer.bind();
|
||||||
|
MemoryUtil.memFree(solidIndexBuffer);
|
||||||
|
}
|
||||||
|
private void addGenericDebugObjects()
|
||||||
|
{
|
||||||
|
GenericRenderObjectFactory factory = GenericRenderObjectFactory.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
// single giant box
|
||||||
|
IDhApiRenderableBoxGroup singleGiantBoxGroup = factory.createForSingleBox(
|
||||||
|
ModInfo.NAME + ":CyanChunkBox",
|
||||||
|
new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(0,0,0), new DhApiVec3d(16,190,16),
|
||||||
|
new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125),
|
||||||
|
EDhApiBlockMaterial.WATER)
|
||||||
|
);
|
||||||
|
singleGiantBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||||
|
singleGiantBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||||
|
this.add(singleGiantBoxGroup);
|
||||||
|
|
||||||
|
|
||||||
|
// single slender box
|
||||||
|
IDhApiRenderableBoxGroup singleTallBoxGroup = factory.createForSingleBox(
|
||||||
|
ModInfo.NAME + ":GreenBeacon",
|
||||||
|
new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(16,0,31), new DhApiVec3d(17,2000,32),
|
||||||
|
new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125),
|
||||||
|
EDhApiBlockMaterial.ILLUMINATED)
|
||||||
|
);
|
||||||
|
singleTallBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||||
|
singleTallBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||||
|
this.add(singleTallBoxGroup);
|
||||||
|
|
||||||
|
|
||||||
|
// absolute box group
|
||||||
|
ArrayList<DhApiRenderableBox> absBoxList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 18; i++)
|
||||||
|
{
|
||||||
|
absBoxList.add(new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(i,150+i,24), new DhApiVec3d(1+i,151+i,25),
|
||||||
|
new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()),
|
||||||
|
EDhApiBlockMaterial.LAVA
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(ModInfo.NAME + ":OrangeStairs", absBoxList);
|
||||||
|
this.add(absolutePosBoxGroup);
|
||||||
|
|
||||||
|
|
||||||
|
// relative box group
|
||||||
|
ArrayList<DhApiRenderableBox> relBoxList = new ArrayList<>();
|
||||||
|
for (int i = 0; i < 8; i+=2)
|
||||||
|
{
|
||||||
|
relBoxList.add(new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(0,i,0), new DhApiVec3d(1,1+i,1),
|
||||||
|
new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()),
|
||||||
|
EDhApiBlockMaterial.METAL
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
IDhApiRenderableBoxGroup relativePosBoxGroup = factory.createRelativePositionedGroup(
|
||||||
|
ModInfo.NAME + ":MovingMagentaGroup",
|
||||||
|
new DhApiVec3d(24, 140, 24),
|
||||||
|
relBoxList);
|
||||||
|
relativePosBoxGroup.setPreRenderFunc((event) ->
|
||||||
|
{
|
||||||
|
DhApiVec3d pos = relativePosBoxGroup.getOriginBlockPos();
|
||||||
|
pos.x += event.partialTicks / 2;
|
||||||
|
pos.x %= 32;
|
||||||
|
relativePosBoxGroup.setOriginBlockPos(pos);
|
||||||
|
});
|
||||||
|
this.add(relativePosBoxGroup);
|
||||||
|
|
||||||
|
|
||||||
|
// massive relative box group
|
||||||
|
ArrayList<DhApiRenderableBox> massRelBoxList = new ArrayList<>();
|
||||||
|
for (int x = 0; x < 50*2; x+=2)
|
||||||
|
{
|
||||||
|
for (int z = 0; z < 50*2; z+=2)
|
||||||
|
{
|
||||||
|
massRelBoxList.add(new DhApiRenderableBox(
|
||||||
|
new DhApiVec3d(-x, 0, -z), new DhApiVec3d(1-x, 1, 1-z),
|
||||||
|
new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()),
|
||||||
|
EDhApiBlockMaterial.TERRACOTTA
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IDhApiRenderableBoxGroup massRelativePosBoxGroup = factory.createRelativePositionedGroup(
|
||||||
|
ModInfo.NAME + ":MassRedGroup",
|
||||||
|
new DhApiVec3d(-25, 140, 0),
|
||||||
|
massRelBoxList);
|
||||||
|
massRelativePosBoxGroup.setPreRenderFunc((event) ->
|
||||||
|
{
|
||||||
|
DhApiVec3d blockPos = massRelativePosBoxGroup.getOriginBlockPos();
|
||||||
|
blockPos.y += event.partialTicks / 4;
|
||||||
|
if (blockPos.y > 150f)
|
||||||
|
{
|
||||||
|
blockPos.y = 140f;
|
||||||
|
|
||||||
|
Color newColor = (massRelativePosBoxGroup.get(0).color == Color.RED) ? Color.RED.darker() : Color.RED;
|
||||||
|
massRelativePosBoxGroup.forEach((box) -> { box.color = newColor; });
|
||||||
|
massRelativePosBoxGroup.triggerBoxChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
massRelativePosBoxGroup.setOriginBlockPos(blockPos);
|
||||||
|
});
|
||||||
|
this.add(massRelativePosBoxGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// registration //
|
||||||
|
//==============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(IDhApiRenderableBoxGroup iBoxGroup) throws IllegalArgumentException
|
||||||
|
{
|
||||||
|
if (!(iBoxGroup instanceof RenderableBoxGroup))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"], type received: ["+(iBoxGroup != null ? iBoxGroup.getClass() : "NULL")+"].");
|
||||||
|
}
|
||||||
|
RenderableBoxGroup boxGroup = (RenderableBoxGroup) iBoxGroup;
|
||||||
|
if (boxGroup.size() != 0)
|
||||||
|
{
|
||||||
|
// trigger a box change to make sure the initial data is uploaded
|
||||||
|
boxGroup.triggerBoxChange();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
long id = boxGroup.getId();
|
||||||
|
if (this.boxGroupById.containsKey(id))
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("A box group with the ID [" + id + "] is already present.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.boxGroupById.put(id, boxGroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IDhApiRenderableBoxGroup remove(long id) { return this.boxGroupById.remove(id); }
|
||||||
|
|
||||||
|
public void clear() { this.boxGroupById.clear(); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========//
|
||||||
|
// rendering //
|
||||||
|
//===========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param renderingWithSsao
|
||||||
|
* if true that means this render call is happening before the SSAO pass
|
||||||
|
* and any objects rendered in this pass will have SSAO applied to them.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void render(RenderParams renderEventParam, IProfilerWrapper profiler, boolean renderingWithSsao)
|
||||||
|
{
|
||||||
|
// generic rendering (both instanced and direct) is extremely unstable on Mac, so don't render anything
|
||||||
|
if (EPlatform.get() == EPlatform.MACOS)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// render setup //
|
||||||
|
profiler.push("setup");
|
||||||
|
|
||||||
|
this.init();
|
||||||
|
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderSetupEvent.class, renderEventParam);
|
||||||
|
|
||||||
|
|
||||||
|
boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get();
|
||||||
|
if (renderWireframe)
|
||||||
|
{
|
||||||
|
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE);
|
||||||
|
GLMC.disableFaceCulling();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||||
|
GLMC.enableFaceCulling();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLMC.enableBlend();
|
||||||
|
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||||
|
GLMC.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||||
|
|
||||||
|
IDhApiGenericObjectShaderProgram shaderProgram = this.instancedRenderingAvailable ? this.instancedShaderProgram : this.directShaderProgram;
|
||||||
|
IDhApiGenericObjectShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiGenericObjectShaderProgram.class);
|
||||||
|
if (shaderProgramOverride != null && shaderProgram.overrideThisFrame())
|
||||||
|
{
|
||||||
|
shaderProgram = shaderProgramOverride;
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderProgram.bind(renderEventParam);
|
||||||
|
shaderProgram.bindVertexBuffer(this.boxVertexBuffer.getId());
|
||||||
|
|
||||||
|
this.boxIndexBuffer.bind();
|
||||||
|
|
||||||
|
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// rendering //
|
||||||
|
|
||||||
|
Collection<RenderableBoxGroup> boxList = this.boxGroupById.values();
|
||||||
|
for (RenderableBoxGroup boxGroup : boxList)
|
||||||
|
{
|
||||||
|
// validation //
|
||||||
|
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
if (boxGroup == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip boxes that shouldn't render this pass
|
||||||
|
if (boxGroup.ssaoEnabled != renderingWithSsao)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
profiler.popPush("render prep");
|
||||||
|
boxGroup.preRender(renderEventParam); // called even if the group is inactive, so the group can be activate if desired
|
||||||
|
|
||||||
|
// ignore inactive groups
|
||||||
|
if (!boxGroup.active)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow API users to cancel this object's rendering
|
||||||
|
boolean cancelRendering = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericObjectRenderEvent.class, new DhApiBeforeGenericObjectRenderEvent.EventParam(renderEventParam, boxGroup));
|
||||||
|
if (cancelRendering)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// update instanced data if needed
|
||||||
|
if (this.instancedRenderingAvailable)
|
||||||
|
{
|
||||||
|
boxGroup.tryUpdateInstancedDataAsync();
|
||||||
|
|
||||||
|
// skip groups that haven't been uploaded yet
|
||||||
|
if (boxGroup.vertexBufferContainer.getState() != GlGenericObjectVertexContainer.EState.RENDER)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// render //
|
||||||
|
|
||||||
|
profiler.popPush("rendering");
|
||||||
|
profiler.push(boxGroup.getResourceLocationNamespace());
|
||||||
|
profiler.push(boxGroup.getResourceLocationPath());
|
||||||
|
if (this.instancedRenderingAvailable)
|
||||||
|
{
|
||||||
|
this.renderBoxGroupInstanced(shaderProgram, renderEventParam, boxGroup, camPos, profiler);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.renderBoxGroupDirect(shaderProgram, renderEventParam, boxGroup, camPos, profiler);
|
||||||
|
}
|
||||||
|
profiler.pop(); // resource path
|
||||||
|
profiler.pop(); // resource namespace
|
||||||
|
|
||||||
|
boxGroup.postRender(renderEventParam);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========//
|
||||||
|
// clean up //
|
||||||
|
//==========//
|
||||||
|
|
||||||
|
profiler.popPush("cleanup");
|
||||||
|
|
||||||
|
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderCleanupEvent.class, renderEventParam);
|
||||||
|
|
||||||
|
if (renderWireframe)
|
||||||
|
{
|
||||||
|
// default back to GL_FILL since all other rendering uses it
|
||||||
|
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||||
|
GLMC.enableFaceCulling();
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderProgram.unbind();
|
||||||
|
|
||||||
|
profiler.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=====================//
|
||||||
|
// instanced rendering //
|
||||||
|
//=====================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private void renderBoxGroupInstanced(
|
||||||
|
IDhApiGenericObjectShaderProgram shaderProgram, DhApiRenderParam renderEventParam,
|
||||||
|
RenderableBoxGroup boxGroup, Vec3d camPos,
|
||||||
|
IProfilerWrapper profiler)
|
||||||
|
{
|
||||||
|
// update instance data //
|
||||||
|
|
||||||
|
profiler.push("vertex setup");
|
||||||
|
|
||||||
|
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||||
|
if (shading == null)
|
||||||
|
{
|
||||||
|
shading = DEFAULT_SHADING;
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderProgram.fillIndirectUniformData(
|
||||||
|
renderEventParam,
|
||||||
|
shading, boxGroup,
|
||||||
|
camPos);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Bind instance data //
|
||||||
|
profiler.popPush("binding");
|
||||||
|
|
||||||
|
GlGenericObjectVertexContainer container = (GlGenericObjectVertexContainer)(boxGroup.vertexBufferContainer);
|
||||||
|
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.color);
|
||||||
|
GL32.glEnableVertexAttribArray(1);
|
||||||
|
GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0);
|
||||||
|
this.vertexAttribDivisor(1, 1);
|
||||||
|
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.scale);
|
||||||
|
GL32.glEnableVertexAttribArray(2);
|
||||||
|
this.vertexAttribDivisor(2, 1);
|
||||||
|
GL32.glVertexAttribPointer(2, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0);
|
||||||
|
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.chunkPos);
|
||||||
|
GL32.glEnableVertexAttribArray(3);
|
||||||
|
this.vertexAttribDivisor(3, 1);
|
||||||
|
GL32.glVertexAttribIPointer(3, 3, GL32.GL_INT, 3 * Integer.BYTES, 0);
|
||||||
|
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.subChunkPos);
|
||||||
|
GL32.glEnableVertexAttribArray(4);
|
||||||
|
this.vertexAttribDivisor(4, 1);
|
||||||
|
GL32.glVertexAttribPointer(4, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0);
|
||||||
|
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, container.material);
|
||||||
|
GL32.glEnableVertexAttribArray(5);
|
||||||
|
this.vertexAttribDivisor(5, 1);
|
||||||
|
GL32.glVertexAttribIPointer(5, 1, GL32.GL_BYTE, Byte.BYTES, 0);
|
||||||
|
|
||||||
|
|
||||||
|
// Draw instanced
|
||||||
|
profiler.popPush("render");
|
||||||
|
if (container.uploadedBoxCount > 0)
|
||||||
|
{
|
||||||
|
GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, container.uploadedBoxCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
profiler.popPush("cleanup");
|
||||||
|
|
||||||
|
GL32.glDisableVertexAttribArray(1);
|
||||||
|
GL32.glDisableVertexAttribArray(2);
|
||||||
|
GL32.glDisableVertexAttribArray(3);
|
||||||
|
GL32.glDisableVertexAttribArray(4);
|
||||||
|
GL32.glDisableVertexAttribArray(5);
|
||||||
|
|
||||||
|
profiler.pop();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Clean way to handle both {@link GL33#glVertexAttribDivisor} and {@link ARBInstancedArrays#glVertexAttribDivisorARB}
|
||||||
|
* based on which one is supported.
|
||||||
|
*/
|
||||||
|
private void vertexAttribDivisor(int index, int divisor)
|
||||||
|
{
|
||||||
|
if (this.vertexAttribDivisorSupported)
|
||||||
|
{
|
||||||
|
GL33.glVertexAttribDivisor(index, divisor);
|
||||||
|
}
|
||||||
|
else if(this.instancedArraysSupported)
|
||||||
|
{
|
||||||
|
ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Instanced rendering isn't supported by this machine. Direct rendering should have been used instead.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==================//
|
||||||
|
// direct rendering //
|
||||||
|
//==================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private void renderBoxGroupDirect(
|
||||||
|
IDhApiGenericObjectShaderProgram shaderProgram,
|
||||||
|
DhApiRenderParam renderEventParam,
|
||||||
|
RenderableBoxGroup boxGroup, Vec3d camPos,
|
||||||
|
IProfilerWrapper profiler)
|
||||||
|
{
|
||||||
|
profiler.popPush("shared uniforms");
|
||||||
|
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||||
|
if (shading == null)
|
||||||
|
{
|
||||||
|
shading = DhApiRenderableBoxGroupShading.getUnshaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
shaderProgram.fillSharedDirectUniformData(renderEventParam, shading, boxGroup, camPos);
|
||||||
|
|
||||||
|
for (int i = 0; i < boxGroup.size(); i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DhApiRenderableBox box = boxGroup.get(i);
|
||||||
|
if (box != null)
|
||||||
|
{
|
||||||
|
profiler.popPush("direct uniforms");
|
||||||
|
shaderProgram.fillDirectUniformData(renderEventParam, boxGroup, box, camPos);
|
||||||
|
|
||||||
|
profiler.popPush("render");
|
||||||
|
GL32.glDrawElements(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IndexOutOfBoundsException e)
|
||||||
|
{
|
||||||
|
// Concurrency issue, the list was modified while rendering
|
||||||
|
// this can probably be ignored.
|
||||||
|
// However, if it does become a problem we can add locks to the box group.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
profiler.pop();
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// getters //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/** @throws IllegalStateException if {@link #init()} function hasn't been called yet */
|
||||||
|
public boolean getInstancedRenderingAvailable() throws IllegalStateException
|
||||||
|
{
|
||||||
|
if (!this.init)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("GL initialization hasn't been completed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.instancedRenderingAvailable;
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// F3 menu //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public String getVboRenderDebugMenuString()
|
||||||
|
{
|
||||||
|
// get counts
|
||||||
|
int totalGroupCount = this.boxGroupById.size();
|
||||||
|
int totalBoxCount = 0;
|
||||||
|
|
||||||
|
int activeGroupCount = 0;
|
||||||
|
int activeBoxCount = 0;
|
||||||
|
|
||||||
|
for (long key : this.boxGroupById.keySet())
|
||||||
|
{
|
||||||
|
RenderableBoxGroup renderGroup = this.boxGroupById.get(key);
|
||||||
|
if (renderGroup.active)
|
||||||
|
{
|
||||||
|
activeGroupCount++;
|
||||||
|
activeBoxCount += renderGroup.size();
|
||||||
|
}
|
||||||
|
totalBoxCount += renderGroup.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return "Generic Obj #: " + F3Screen.NUMBER_FORMAT.format(activeGroupCount) + "/" + F3Screen.NUMBER_FORMAT.format(totalGroupCount) + ", " +
|
||||||
|
"Cube #: " + F3Screen.NUMBER_FORMAT.format(activeBoxCount) + "/" + F3Screen.NUMBER_FORMAT.format(totalBoxCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+231
@@ -0,0 +1,231 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.generic;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
|
||||||
|
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.math.DhApiVec3i;
|
||||||
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||||
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.shader.GlShaderProgram;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.vertexAttribute.GlAbstractVertexAttribute;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.vertexAttribute.GlVertexPointer;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.misc.LightMapWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||||
|
|
||||||
|
public class GlGenericObjectShaderProgram extends GlShaderProgram implements IDhApiGenericObjectShaderProgram
|
||||||
|
{
|
||||||
|
public static final String VERTEX_SHADER_INSTANCED_PATH = "assets/distanthorizons/shaders/generic/gl/instanced/vert.vert";
|
||||||
|
public static final String VERTEX_SHADER_DIRECT_PATH = "assets/distanthorizons/shaders/generic/gl/direct/vert.vert";
|
||||||
|
public static final String FRAGMENT_SHADER_INSTANCED_PATH = "assets/distanthorizons/shaders/generic/gl/instanced/frag.frag";
|
||||||
|
public static final String FRAGMENT_SHADER_DIRECT_PATH = "assets/distanthorizons/shaders/generic/gl/direct/frag.frag";
|
||||||
|
|
||||||
|
public final GlAbstractVertexAttribute va;
|
||||||
|
|
||||||
|
|
||||||
|
// shader uniforms
|
||||||
|
private final int directShaderTransformUniform;
|
||||||
|
private final int directShaderColorUniform;
|
||||||
|
|
||||||
|
private final int instancedShaderOffsetChunkUniform;
|
||||||
|
private final int instancedShaderOffsetSubChunkUniform;
|
||||||
|
private final int instancedShaderCameraChunkPosUniform;
|
||||||
|
private final int instancedShaderCameraSubChunkPosUniform;
|
||||||
|
private final int instancedShaderProjectionModelViewMatrixUniform;
|
||||||
|
|
||||||
|
private final int lightMapUniform;
|
||||||
|
private final int skyLightUniform;
|
||||||
|
private final int blockLightUniform;
|
||||||
|
|
||||||
|
private final int northShadingUniform;
|
||||||
|
private final int southShadingUniform;
|
||||||
|
private final int eastShadingUniform;
|
||||||
|
private final int westShadingUniform;
|
||||||
|
private final int topShadingUniform;
|
||||||
|
private final int bottomShadingUniform;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
public GlGenericObjectShaderProgram(boolean useInstancedRendering)
|
||||||
|
{
|
||||||
|
super(
|
||||||
|
useInstancedRendering ? VERTEX_SHADER_INSTANCED_PATH : VERTEX_SHADER_DIRECT_PATH,
|
||||||
|
useInstancedRendering ? FRAGMENT_SHADER_INSTANCED_PATH : FRAGMENT_SHADER_DIRECT_PATH,
|
||||||
|
"vPosition"
|
||||||
|
);
|
||||||
|
|
||||||
|
this.va = GlAbstractVertexAttribute.create();
|
||||||
|
this.va.bind();
|
||||||
|
// Pos
|
||||||
|
this.va.setVertexAttribute(0, 0, GlVertexPointer.addVec3Pointer(false));
|
||||||
|
this.va.completeAndCheck(Float.BYTES * 3);
|
||||||
|
|
||||||
|
this.directShaderTransformUniform = this.tryGetUniformLocation("uTransform");
|
||||||
|
this.directShaderColorUniform = this.tryGetUniformLocation("uColor");
|
||||||
|
|
||||||
|
this.instancedShaderOffsetChunkUniform = this.tryGetUniformLocation("uOffsetChunk");
|
||||||
|
this.instancedShaderOffsetSubChunkUniform = this.tryGetUniformLocation("uOffsetSubChunk");
|
||||||
|
this.instancedShaderCameraChunkPosUniform = this.tryGetUniformLocation("uCameraPosChunk");
|
||||||
|
this.instancedShaderCameraSubChunkPosUniform = this.tryGetUniformLocation("uCameraPosSubChunk");
|
||||||
|
this.instancedShaderProjectionModelViewMatrixUniform = this.tryGetUniformLocation("uProjectionMvm");
|
||||||
|
|
||||||
|
this.lightMapUniform = this.getUniformLocation("uLightMap");
|
||||||
|
this.skyLightUniform = this.getUniformLocation("uSkyLight");
|
||||||
|
this.blockLightUniform = this.getUniformLocation("uBlockLight");
|
||||||
|
this.northShadingUniform = this.getUniformLocation("uNorthShading");
|
||||||
|
this.southShadingUniform = this.getUniformLocation("uSouthShading");
|
||||||
|
this.eastShadingUniform = this.getUniformLocation("uEastShading");
|
||||||
|
this.westShadingUniform = this.getUniformLocation("uWestShading");
|
||||||
|
this.topShadingUniform = this.getUniformLocation("uTopShading");
|
||||||
|
this.bottomShadingUniform = this.getUniformLocation("uBottomShading");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// methods //
|
||||||
|
//=========//
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bind(DhApiRenderParam renderEventParam)
|
||||||
|
{
|
||||||
|
super.bind();
|
||||||
|
this.va.bind();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void unbind()
|
||||||
|
{
|
||||||
|
super.unbind();
|
||||||
|
this.va.unbind();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void free()
|
||||||
|
{
|
||||||
|
this.va.free();
|
||||||
|
super.free();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bindVertexBuffer(int vbo) { this.va.bindBufferToAllBindingPoints(vbo); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillIndirectUniformData(
|
||||||
|
DhApiRenderParam renderParameters,
|
||||||
|
DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup,
|
||||||
|
DhApiVec3d camPos
|
||||||
|
)
|
||||||
|
{
|
||||||
|
Mat4f projectionMvmMatrix = new Mat4f(renderParameters.dhProjectionMatrix);
|
||||||
|
projectionMvmMatrix.multiply(renderParameters.dhModelViewMatrix);
|
||||||
|
|
||||||
|
super.bind();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.setUniform(this.instancedShaderOffsetChunkUniform,
|
||||||
|
new DhApiVec3i(
|
||||||
|
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||||
|
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||||
|
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||||
|
));
|
||||||
|
this.setUniform(this.instancedShaderOffsetSubChunkUniform,
|
||||||
|
new Vec3f(
|
||||||
|
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||||
|
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||||
|
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||||
|
));
|
||||||
|
|
||||||
|
this.setUniform(this.instancedShaderCameraChunkPosUniform,
|
||||||
|
new DhApiVec3i(
|
||||||
|
LodUtil.getChunkPosFromDouble(camPos.x),
|
||||||
|
LodUtil.getChunkPosFromDouble(camPos.y),
|
||||||
|
LodUtil.getChunkPosFromDouble(camPos.z)
|
||||||
|
));
|
||||||
|
this.setUniform(this.instancedShaderCameraSubChunkPosUniform,
|
||||||
|
new Vec3f(
|
||||||
|
LodUtil.getSubChunkPosFromDouble(camPos.x),
|
||||||
|
LodUtil.getSubChunkPosFromDouble(camPos.y),
|
||||||
|
LodUtil.getSubChunkPosFromDouble(camPos.z)
|
||||||
|
));
|
||||||
|
|
||||||
|
this.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, projectionMvmMatrix);
|
||||||
|
|
||||||
|
this.setUniform(this.lightMapUniform, LightMapWrapper.GL_BOUND_INDEX);
|
||||||
|
this.setUniform(this.skyLightUniform, boxGroup.getSkyLight());
|
||||||
|
this.setUniform(this.blockLightUniform, boxGroup.getBlockLight());
|
||||||
|
|
||||||
|
|
||||||
|
this.setUniform(this.northShadingUniform, shading.north);
|
||||||
|
this.setUniform(this.southShadingUniform, shading.south);
|
||||||
|
this.setUniform(this.eastShadingUniform, shading.east);
|
||||||
|
this.setUniform(this.westShadingUniform, shading.west);
|
||||||
|
this.setUniform(this.topShadingUniform, shading.top);
|
||||||
|
this.setUniform(this.bottomShadingUniform, shading.bottom);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void fillSharedDirectUniformData(
|
||||||
|
DhApiRenderParam renderParameters,
|
||||||
|
DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup,
|
||||||
|
DhApiVec3d camPos)
|
||||||
|
{
|
||||||
|
|
||||||
|
this.setUniform(this.lightMapUniform, LightMapWrapper.GL_BOUND_INDEX);
|
||||||
|
this.setUniform(this.skyLightUniform, boxGroup.getSkyLight());
|
||||||
|
this.setUniform(this.blockLightUniform, boxGroup.getBlockLight());
|
||||||
|
|
||||||
|
|
||||||
|
this.setUniform(this.northShadingUniform, shading.north);
|
||||||
|
this.setUniform(this.southShadingUniform, shading.south);
|
||||||
|
this.setUniform(this.eastShadingUniform, shading.east);
|
||||||
|
this.setUniform(this.westShadingUniform, shading.west);
|
||||||
|
this.setUniform(this.topShadingUniform, shading.top);
|
||||||
|
this.setUniform(this.bottomShadingUniform, shading.bottom);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fillDirectUniformData(
|
||||||
|
DhApiRenderParam renderParameters,
|
||||||
|
IDhApiRenderableBoxGroup boxGroup, DhApiRenderableBox box,
|
||||||
|
DhApiVec3d camPos)
|
||||||
|
{
|
||||||
|
Mat4f projectionMvmMatrix = new Mat4f(renderParameters.dhProjectionMatrix);
|
||||||
|
projectionMvmMatrix.multiply(renderParameters.dhModelViewMatrix);
|
||||||
|
|
||||||
|
Mat4f boxTransform = Mat4f.createTranslateMatrix(
|
||||||
|
(float) (box.minPos.x + boxGroup.getOriginBlockPos().x - camPos.x),
|
||||||
|
(float) (box.minPos.y + boxGroup.getOriginBlockPos().y - camPos.y),
|
||||||
|
(float) (box.minPos.z + boxGroup.getOriginBlockPos().z - camPos.z));
|
||||||
|
boxTransform.multiply(Mat4f.createScaleMatrix(
|
||||||
|
(float) (box.maxPos.x - box.minPos.x),
|
||||||
|
(float) (box.maxPos.y - box.minPos.y),
|
||||||
|
(float) (box.maxPos.z - box.minPos.z)));
|
||||||
|
projectionMvmMatrix.multiply(boxTransform);
|
||||||
|
this.setUniform(this.directShaderTransformUniform, projectionMvmMatrix);
|
||||||
|
|
||||||
|
this.setUniform(this.directShaderColorUniform, box.color);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() { return this.id; }
|
||||||
|
|
||||||
|
/** The base DH render program should always render */
|
||||||
|
@Override
|
||||||
|
public boolean overrideThisFrame() { return true; }
|
||||||
|
|
||||||
|
}
|
||||||
+177
@@ -0,0 +1,177 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.generic;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.renderer.RenderableBoxGroup;
|
||||||
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IDhGenericObjectVertexBufferContainer;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For use by {@link RenderableBoxGroup}
|
||||||
|
*
|
||||||
|
* @see RenderableBoxGroup
|
||||||
|
*/
|
||||||
|
public class GlGenericObjectVertexContainer implements IDhGenericObjectVertexBufferContainer
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public int chunkPos = 0;
|
||||||
|
public int subChunkPos = 0;
|
||||||
|
public int scale = 0;
|
||||||
|
public int color = 0;
|
||||||
|
public int material = 0;
|
||||||
|
|
||||||
|
public int[] chunkPosData = new int[0];
|
||||||
|
public float[] subChunkPosData = new float[0];
|
||||||
|
public float[] scalingData = new float[0];
|
||||||
|
public float[] colorData = new float[0];
|
||||||
|
public int[] materialData = new int[0];
|
||||||
|
|
||||||
|
public int uploadedBoxCount = 0;
|
||||||
|
|
||||||
|
private EState state = EState.NEW;
|
||||||
|
@Override
|
||||||
|
public EState getState() { return this.state; }
|
||||||
|
@Override
|
||||||
|
public void setState(EState state) { this.state = state; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===========================//
|
||||||
|
// render building/uploading //
|
||||||
|
//===========================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public void updateVertexData(List<DhApiRenderableBox> uploadBoxList)
|
||||||
|
{
|
||||||
|
int boxCount = uploadBoxList.size();
|
||||||
|
|
||||||
|
|
||||||
|
// recreate the data arrays if their size is different
|
||||||
|
if (this.uploadedBoxCount != boxCount)
|
||||||
|
{
|
||||||
|
this.uploadedBoxCount = boxCount;
|
||||||
|
|
||||||
|
this.chunkPosData = new int[boxCount * 3]; // 3 elements XYZ
|
||||||
|
this.subChunkPosData = new float[boxCount * 3]; // 3 elements XYZ
|
||||||
|
this.scalingData = new float[boxCount * 3]; // 3 elements XYZ
|
||||||
|
|
||||||
|
this.colorData = new float[boxCount * 4]; // 4 elements, RGBA
|
||||||
|
this.materialData = new int[boxCount];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// transformation / scaling //
|
||||||
|
for (int i = 0; i < boxCount; i++)
|
||||||
|
{
|
||||||
|
DhApiRenderableBox box = uploadBoxList.get(i);
|
||||||
|
|
||||||
|
int dataIndex = i * 3;
|
||||||
|
|
||||||
|
this.chunkPosData[dataIndex] = LodUtil.getChunkPosFromDouble(box.minPos.x);
|
||||||
|
this.chunkPosData[dataIndex + 1] = LodUtil.getChunkPosFromDouble(box.minPos.y);
|
||||||
|
this.chunkPosData[dataIndex + 2] = LodUtil.getChunkPosFromDouble(box.minPos.z);
|
||||||
|
|
||||||
|
this.subChunkPosData[dataIndex] = LodUtil.getSubChunkPosFromDouble(box.minPos.x);
|
||||||
|
this.subChunkPosData[dataIndex + 1] = LodUtil.getSubChunkPosFromDouble(box.minPos.y);
|
||||||
|
this.subChunkPosData[dataIndex + 2] = LodUtil.getSubChunkPosFromDouble(box.minPos.z);
|
||||||
|
|
||||||
|
this.scalingData[dataIndex] = (float) (box.maxPos.x - box.minPos.x);
|
||||||
|
this.scalingData[dataIndex + 1] = (float) (box.maxPos.y - box.minPos.y);
|
||||||
|
this.scalingData[dataIndex + 2] = (float) (box.maxPos.z - box.minPos.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// colors/materials //
|
||||||
|
for (int i = 0; i < boxCount; i++)
|
||||||
|
{
|
||||||
|
DhApiRenderableBox box = uploadBoxList.get(i);
|
||||||
|
Color color = box.color;
|
||||||
|
int colorIndex = i * 4;
|
||||||
|
this.colorData[colorIndex] = color.getRed() / 255.0f;
|
||||||
|
this.colorData[colorIndex + 1] = color.getGreen() / 255.0f;
|
||||||
|
this.colorData[colorIndex + 2] = color.getBlue() / 255.0f;
|
||||||
|
this.colorData[colorIndex + 3] = color.getAlpha() / 255.0f;
|
||||||
|
|
||||||
|
this.materialData[i] = box.material;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadDataToGpu()
|
||||||
|
{
|
||||||
|
this.tryCreateBuffers();
|
||||||
|
|
||||||
|
// Upload transformation matrices
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.chunkPos);
|
||||||
|
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.chunkPosData, GL32.GL_DYNAMIC_DRAW);
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.subChunkPos);
|
||||||
|
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.subChunkPosData, GL32.GL_DYNAMIC_DRAW);
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.scale);
|
||||||
|
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.scalingData, GL32.GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
// Upload colors
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.color);
|
||||||
|
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.colorData, GL32.GL_DYNAMIC_DRAW);
|
||||||
|
|
||||||
|
// Upload materials
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.material);
|
||||||
|
GL32.glBufferData(GL32.GL_ARRAY_BUFFER, this.materialData, GL32.GL_DYNAMIC_DRAW);
|
||||||
|
}
|
||||||
|
/** needs to be done on the render thread */
|
||||||
|
private void tryCreateBuffers()
|
||||||
|
{
|
||||||
|
if (this.chunkPos == 0)
|
||||||
|
{
|
||||||
|
this.chunkPos = GLMC.glGenBuffers();
|
||||||
|
this.subChunkPos = GLMC.glGenBuffers();
|
||||||
|
this.scale = GLMC.glGenBuffers();
|
||||||
|
this.color = GLMC.glGenBuffers();
|
||||||
|
this.material = GLMC.glGenBuffers();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
tryDeleteBuffer(this.chunkPos);
|
||||||
|
tryDeleteBuffer(this.subChunkPos);
|
||||||
|
tryDeleteBuffer(this.scale);
|
||||||
|
tryDeleteBuffer(this.color);
|
||||||
|
tryDeleteBuffer(this.material);
|
||||||
|
}
|
||||||
|
private static void tryDeleteBuffer(int bufferId)
|
||||||
|
{
|
||||||
|
// usually unnecessary, but just in case
|
||||||
|
if (bufferId != 0)
|
||||||
|
{
|
||||||
|
GLMC.glDeleteBuffers(bufferId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+338
@@ -0,0 +1,338 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiGLErrorHandlingMode;
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.util.objects.GLMessages.*;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
import org.lwjgl.opengl.GL;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
import org.lwjgl.opengl.GLCapabilities;
|
||||||
|
import org.lwjgl.opengl.GLUtil;
|
||||||
|
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A singleton that holds references to different openGL contexts
|
||||||
|
* and GPU capabilities.
|
||||||
|
*/
|
||||||
|
public class GLProxy
|
||||||
|
{
|
||||||
|
public static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logRendererGLEventToFile)
|
||||||
|
.chatLevelConfig(Config.Common.Logging.logRendererGLEventToChat)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final Set<String> LOGGED_GL_MESSAGES = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static GLProxy instance = null;
|
||||||
|
|
||||||
|
|
||||||
|
/** Minecraft's GL capabilities */
|
||||||
|
public final GLCapabilities glCapabilities;
|
||||||
|
|
||||||
|
public boolean namedObjectSupported = false; // ~OpenGL 4.5 (UNUSED CURRENTLY)
|
||||||
|
public boolean bufferStorageSupported = false; // ~OpenGL 4.4
|
||||||
|
public boolean vertexAttributeBufferBindingSupported = false; // ~OpenGL 4.3
|
||||||
|
public boolean instancedArraysSupported = false;
|
||||||
|
public boolean vertexAttribDivisorSupported = false; // OpenGL 3.3 or newer
|
||||||
|
|
||||||
|
private final EDhApiGpuUploadMethod preferredUploadMethod;
|
||||||
|
|
||||||
|
public final GLMessageBuilder vanillaDebugMessageBuilder =
|
||||||
|
new GLMessageBuilder(
|
||||||
|
(type) ->
|
||||||
|
{
|
||||||
|
if (type == EGLMessageType.POP_GROUP)
|
||||||
|
return false;
|
||||||
|
else if (type == EGLMessageType.PUSH_GROUP)
|
||||||
|
return false;
|
||||||
|
else if (type == EGLMessageType.MARKER)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
(severity) ->
|
||||||
|
{
|
||||||
|
// notifications can generally be ignored (if they are logged at all)
|
||||||
|
if (severity == EGLMessageSeverity.NOTIFICATION)
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private GLProxy() throws IllegalStateException
|
||||||
|
{
|
||||||
|
// this must be created on minecraft's render context to work correctly
|
||||||
|
if (GLFW.glfwGetCurrentContext() == 0L)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException(GLProxy.class.getSimpleName() + " was created outside the render thread!");
|
||||||
|
}
|
||||||
|
|
||||||
|
LOGGER.info("Creating " + GLProxy.class.getSimpleName() + "... If this is the last message you see there must have been an OpenGL error.");
|
||||||
|
LOGGER.info("Lod Render OpenGL version [" + GL32.glGetString(GL32.GL_VERSION) + "].");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============================//
|
||||||
|
// get Minecraft's GL context //
|
||||||
|
//============================//
|
||||||
|
|
||||||
|
// get Minecraft's capabilities
|
||||||
|
this.glCapabilities = GL.getCapabilities();
|
||||||
|
|
||||||
|
// crash the game if the GPU doesn't support OpenGL 3.2
|
||||||
|
if (!this.glCapabilities.OpenGL32)
|
||||||
|
{
|
||||||
|
String supportedVersionInfo = this.getFailedVersionInfo(this.glCapabilities);
|
||||||
|
|
||||||
|
// See full requirement at above.
|
||||||
|
String errorMessage = ModInfo.READABLE_NAME + " was initializing " + GLProxy.class.getSimpleName()
|
||||||
|
+ " and discovered this GPU doesn't meet the OpenGL requirements. Sorry I couldn't tell you sooner :(\n" +
|
||||||
|
"Additional info:\n" + supportedVersionInfo;
|
||||||
|
IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||||
|
MC.crashMinecraft(errorMessage, new UnsupportedOperationException("Distant Horizon OpenGL requirements not met"));
|
||||||
|
}
|
||||||
|
LOGGER.info("minecraftGlCapabilities:\n" + this.versionInfoToString(this.glCapabilities));
|
||||||
|
|
||||||
|
if (Config.Client.Advanced.Debugging.OpenGl.overrideVanillaGLLogger.get())
|
||||||
|
{
|
||||||
|
GLUtil.setupDebugMessageCallback(new PrintStream(new GLMessageOutputStream(GLProxy::logMessage, this.vanillaDebugMessageBuilder), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//======================//
|
||||||
|
// get GPU capabilities //
|
||||||
|
//======================//
|
||||||
|
|
||||||
|
// UNUSED currently
|
||||||
|
// Check if we can use the named version of all calls, which is available in GL4.5 or after
|
||||||
|
this.namedObjectSupported = this.glCapabilities.glNamedBufferData != 0L; //Nullptr
|
||||||
|
|
||||||
|
// Check if we can use the Buffer Storage, which is available in GL4.4 or after
|
||||||
|
this.bufferStorageSupported = this.glCapabilities.glBufferStorage != 0L; // Nullptr
|
||||||
|
if (!this.bufferStorageSupported)
|
||||||
|
{
|
||||||
|
LOGGER.info("This GPU doesn't support Buffer Storage (OpenGL 4.4), falling back to using other methods.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if we can use the make-over version of Vertex Attribute, which is available in GL4.3 or after
|
||||||
|
this.vertexAttributeBufferBindingSupported = this.glCapabilities.glBindVertexBuffer != 0L; // Nullptr
|
||||||
|
|
||||||
|
// used by instanced rendering
|
||||||
|
this.vertexAttribDivisorSupported = this.glCapabilities.OpenGL33;
|
||||||
|
// denotes if ARBInstancedArrays.glVertexAttribDivisorARB() is available or not
|
||||||
|
// can be used as a backup if MC didn't create a GL 3.3+ context
|
||||||
|
this.instancedArraysSupported = this.glCapabilities.GL_ARB_instanced_arrays;
|
||||||
|
|
||||||
|
// get the best automatic upload method
|
||||||
|
String vendor = GL32.glGetString(GL32.GL_VENDOR).toUpperCase(); // example return: "NVIDIA CORPORATION"
|
||||||
|
if (EPlatform.get() != EPlatform.MACOS)
|
||||||
|
{
|
||||||
|
if (vendor.contains("NVIDIA") || vendor.contains("GEFORCE"))
|
||||||
|
{
|
||||||
|
// NVIDIA card
|
||||||
|
this.preferredUploadMethod = this.bufferStorageSupported ? EDhApiGpuUploadMethod.BUFFER_STORAGE : EDhApiGpuUploadMethod.SUB_DATA;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// AMD or Intel card
|
||||||
|
this.preferredUploadMethod = this.bufferStorageSupported ? EDhApiGpuUploadMethod.BUFFER_STORAGE : EDhApiGpuUploadMethod.DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Mac may have an issue with Buffer Storage, so default to the most basic
|
||||||
|
// form of uploading
|
||||||
|
this.preferredUploadMethod = EDhApiGpuUploadMethod.DATA;
|
||||||
|
}
|
||||||
|
LOGGER.info("GPU Vendor [" + vendor + "] with OS [" + EPlatform.get().getName() + "], Preferred upload method is [" + this.preferredUploadMethod + "].");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========//
|
||||||
|
// clean up //
|
||||||
|
//==========//
|
||||||
|
|
||||||
|
// GLProxy creation success
|
||||||
|
LOGGER.info(GLProxy.class.getSimpleName() + " creation successful. OpenGL smiles upon you this day.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// getters //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public static boolean hasInstance() { return instance != null; }
|
||||||
|
/** @throws IllegalStateException if the Proxy hasn't been created yet and this is called outside the render thread */
|
||||||
|
public static GLProxy getInstance() throws IllegalStateException
|
||||||
|
{
|
||||||
|
if (instance == null)
|
||||||
|
{
|
||||||
|
instance = new GLProxy();
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public EDhApiGpuUploadMethod getGpuUploadMethod() { return this.preferredUploadMethod; }
|
||||||
|
|
||||||
|
public static boolean runningOnRenderThread()
|
||||||
|
{
|
||||||
|
long currentContext = GLFW.glfwGetCurrentContext();
|
||||||
|
return currentContext != 0L; // if the context isn't null, it's the MC context
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// logging //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/** this method is called on the render thread at the point of the GL Error */
|
||||||
|
private static void logMessage(GLMessage msg)
|
||||||
|
{
|
||||||
|
EDhApiGLErrorHandlingMode errorHandlingMode = Config.Client.Advanced.Debugging.OpenGl.glErrorHandlingMode.get();
|
||||||
|
if (errorHandlingMode == EDhApiGLErrorHandlingMode.IGNORE)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
boolean onlyLogOnce = Config.Client.Advanced.Debugging.OpenGl.onlyLogGlErrorsOnce.get();
|
||||||
|
String errorMessage = "GL ERROR [" + msg.id + "] from [" + msg.source + "]: [" + msg.message + "]"+(onlyLogOnce ? " this message will only be logged once" : "")+".";
|
||||||
|
if (onlyLogOnce
|
||||||
|
&& !LOGGED_GL_MESSAGES.add(errorMessage))
|
||||||
|
{
|
||||||
|
// this message has already been logged
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// create an exception so we get a stacktrace of where the message was triggered from
|
||||||
|
RuntimeException exception = new RuntimeException(errorMessage);
|
||||||
|
|
||||||
|
if (msg.type == EGLMessageType.ERROR || msg.type == EGLMessageType.UNDEFINED_BEHAVIOR)
|
||||||
|
{
|
||||||
|
// critical error
|
||||||
|
|
||||||
|
LOGGER.error(exception.getMessage(), exception);
|
||||||
|
|
||||||
|
if (errorHandlingMode == EDhApiGLErrorHandlingMode.LOG_THROW)
|
||||||
|
{
|
||||||
|
// will probably crash the game,
|
||||||
|
// good for quickly checking if there's a problem while preventing log spam
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// non-critical log
|
||||||
|
|
||||||
|
EGLMessageSeverity severity = msg.severity;
|
||||||
|
if (severity == null)
|
||||||
|
{
|
||||||
|
// just in case the message was malformed
|
||||||
|
severity = EGLMessageSeverity.LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (severity)
|
||||||
|
{
|
||||||
|
case HIGH:
|
||||||
|
LOGGER.error(exception.getMessage(), exception);
|
||||||
|
break;
|
||||||
|
case MEDIUM:
|
||||||
|
LOGGER.warn(exception.getMessage(), exception);
|
||||||
|
break;
|
||||||
|
case LOW:
|
||||||
|
LOGGER.info(exception.getMessage(), exception);
|
||||||
|
break;
|
||||||
|
case NOTIFICATION:
|
||||||
|
LOGGER.debug(exception.getMessage(), exception);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper methods //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private String getFailedVersionInfo(GLCapabilities c)
|
||||||
|
{
|
||||||
|
return "Your OpenGL support:\n" +
|
||||||
|
"openGL version 3.2+: [" + c.OpenGL32 + "] <- REQUIRED\n" +
|
||||||
|
"Vertex Attribute Buffer Binding: [" + (c.glVertexAttribBinding != 0) + "] <- optional improvement\n" +
|
||||||
|
"Buffer Storage: [" + (c.glBufferStorage != 0) + "] <- optional improvement\n" +
|
||||||
|
"If you noticed that your computer supports higher OpenGL versions"
|
||||||
|
+ " but not the required version, try running the game in compatibility mode."
|
||||||
|
+ " (How you turn that on, I have no clue~)";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String versionInfoToString(GLCapabilities c)
|
||||||
|
{
|
||||||
|
return "Your OpenGL support:\n" +
|
||||||
|
"openGL version 3.2+: [" + c.OpenGL32 + "] <- REQUIRED\n" +
|
||||||
|
"Vertex Attribute Buffer Binding: [" + (c.glVertexAttribBinding != 0) + "] <- optional improvement\n" +
|
||||||
|
"Buffer Storage: [" + (c.glBufferStorage != 0) + "] <- optional improvement\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+259
@@ -0,0 +1,259 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.enums.GLEnums;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
public class GLState implements AutoCloseable
|
||||||
|
{
|
||||||
|
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
public int program;
|
||||||
|
public int vao;
|
||||||
|
public int vbo;
|
||||||
|
public int ebo;
|
||||||
|
public int fbo;
|
||||||
|
public int texture2D;
|
||||||
|
/** IE: GL_TEXTURE0, GL_TEXTURE1, etc. */
|
||||||
|
public int activeTextureNumber;
|
||||||
|
public int texture0;
|
||||||
|
public int texture1;
|
||||||
|
public int texture2;
|
||||||
|
public int texture3;
|
||||||
|
public int frameBufferTexture0;
|
||||||
|
public int frameBufferTexture1;
|
||||||
|
public int frameBufferDepthTexture;
|
||||||
|
public boolean blend;
|
||||||
|
public boolean scissor;
|
||||||
|
public int blendEqRGB;
|
||||||
|
public int blendEqAlpha;
|
||||||
|
public int blendSrcColor;
|
||||||
|
public int blendSrcAlpha;
|
||||||
|
public int blendDstColor;
|
||||||
|
public int blendDstAlpha;
|
||||||
|
public boolean depth;
|
||||||
|
public boolean writeToDepthBuffer;
|
||||||
|
public int depthFunc;
|
||||||
|
public boolean stencil;
|
||||||
|
public int stencilFunc;
|
||||||
|
public int stencilRef;
|
||||||
|
public int stencilMask;
|
||||||
|
public int[] view;
|
||||||
|
public boolean cull;
|
||||||
|
public int cullMode;
|
||||||
|
public int polyMode;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public GLState() { this.saveState(); }
|
||||||
|
|
||||||
|
public void saveState()
|
||||||
|
{
|
||||||
|
this.program = GL32.glGetInteger(GL32.GL_CURRENT_PROGRAM);
|
||||||
|
this.vao = GL32.glGetInteger(GL32.GL_VERTEX_ARRAY_BINDING);
|
||||||
|
this.vbo = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING);
|
||||||
|
this.ebo = GL32.glGetInteger(GL32.GL_ELEMENT_ARRAY_BUFFER_BINDING);
|
||||||
|
|
||||||
|
this.fbo = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
|
||||||
|
|
||||||
|
this.texture2D = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||||
|
this.activeTextureNumber = GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE);
|
||||||
|
|
||||||
|
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||||
|
this.texture0 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||||
|
|
||||||
|
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
|
||||||
|
this.texture1 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||||
|
|
||||||
|
GLMC.glActiveTexture(GL32.GL_TEXTURE2); // problem with Iris
|
||||||
|
this.texture2 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||||
|
|
||||||
|
GLMC.glActiveTexture(GL32.GL_TEXTURE3);
|
||||||
|
this.texture3 = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
|
||||||
|
|
||||||
|
GLMC.glActiveTexture(this.activeTextureNumber);
|
||||||
|
|
||||||
|
if (this.fbo != 0)
|
||||||
|
{
|
||||||
|
this.frameBufferTexture0 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||||
|
this.frameBufferTexture1 = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||||
|
this.frameBufferDepthTexture = GL32.glGetFramebufferAttachmentParameteri(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// attempting to get values from the default framebuffer can throw errors on Linux
|
||||||
|
this.frameBufferTexture0 = 0;
|
||||||
|
this.frameBufferTexture1 = 0;
|
||||||
|
this.frameBufferDepthTexture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.blend = GL32.glIsEnabled(GL32.GL_BLEND);
|
||||||
|
this.scissor = GL32.glIsEnabled(GL32.GL_SCISSOR_TEST);
|
||||||
|
this.blendEqRGB = GL32.glGetInteger(GL32.GL_BLEND_EQUATION_RGB);
|
||||||
|
this.blendEqAlpha = GL32.glGetInteger(GL32.GL_BLEND_EQUATION_ALPHA);
|
||||||
|
this.blendSrcColor = GL32.glGetInteger(GL32.GL_BLEND_SRC_RGB);
|
||||||
|
this.blendSrcAlpha = GL32.glGetInteger(GL32.GL_BLEND_SRC_ALPHA);
|
||||||
|
this.blendDstColor = GL32.glGetInteger(GL32.GL_BLEND_DST_RGB);
|
||||||
|
this.blendDstAlpha = GL32.glGetInteger(GL32.GL_BLEND_DST_ALPHA);
|
||||||
|
this.depth = GL32.glIsEnabled(GL32.GL_DEPTH_TEST);
|
||||||
|
this.writeToDepthBuffer = GL32.glGetInteger(GL32.GL_DEPTH_WRITEMASK) == GL32.GL_TRUE;
|
||||||
|
this.depthFunc = GL32.glGetInteger(GL32.GL_DEPTH_FUNC);
|
||||||
|
this.stencil = GL32.glIsEnabled(GL32.GL_STENCIL_TEST);
|
||||||
|
this.stencilFunc = GL32.glGetInteger(GL32.GL_STENCIL_FUNC);
|
||||||
|
this.stencilRef = GL32.glGetInteger(GL32.GL_STENCIL_REF);
|
||||||
|
this.stencilMask = GL32.glGetInteger(GL32.GL_STENCIL_VALUE_MASK);
|
||||||
|
this.view = new int[4];
|
||||||
|
GL32.glGetIntegerv(GL32.GL_VIEWPORT, this.view);
|
||||||
|
this.cull = GL32.glIsEnabled(GL32.GL_CULL_FACE);
|
||||||
|
this.cullMode = GL32.glGetInteger(GL32.GL_CULL_FACE_MODE);
|
||||||
|
this.polyMode = GL32.glGetInteger(GL32.GL_POLYGON_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close()
|
||||||
|
{
|
||||||
|
// explicitly unbinding the frame buffer is necessary to prevent GL_CLEAR calls from hitting the wrong buffer
|
||||||
|
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, 0);
|
||||||
|
boolean frameBufferSet = false;
|
||||||
|
|
||||||
|
if (this.fbo != 0 && GL32.glIsFramebuffer(this.fbo))
|
||||||
|
{
|
||||||
|
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fbo);
|
||||||
|
frameBufferSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (this.blend)
|
||||||
|
{
|
||||||
|
GLMC.enableBlend();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLMC.disableBlend();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.scissor)
|
||||||
|
{
|
||||||
|
GLMC.enableScissorTest();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLMC.disableScissorTest();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLMC.glActiveTexture(GL32.GL_TEXTURE0);
|
||||||
|
GLMC.glBindTexture(GL32.glIsTexture(this.texture0) ? this.texture0 : 0);
|
||||||
|
|
||||||
|
GLMC.glActiveTexture(GL32.GL_TEXTURE1);
|
||||||
|
GLMC.glBindTexture(GL32.glIsTexture(this.texture1) ? this.texture1 : 0);
|
||||||
|
|
||||||
|
GLMC.glActiveTexture(GL32.GL_TEXTURE2);
|
||||||
|
GLMC.glBindTexture(GL32.glIsTexture(this.texture2) ? this.texture2 : 0);
|
||||||
|
|
||||||
|
GLMC.glActiveTexture(GL32.GL_TEXTURE3);
|
||||||
|
GLMC.glBindTexture(GL32.glIsTexture(this.texture3) ? this.texture3 : 0);
|
||||||
|
|
||||||
|
GLMC.glActiveTexture(this.activeTextureNumber);
|
||||||
|
GLMC.glBindTexture(GL32.glIsTexture(this.texture2D) ? this.texture2D : 0);
|
||||||
|
|
||||||
|
// attempting to set textures on the default frame buffer (ID 0) will throw errors
|
||||||
|
if (frameBufferSet)
|
||||||
|
{
|
||||||
|
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.frameBufferTexture0, 0);
|
||||||
|
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT1, GL32.GL_TEXTURE_2D, this.frameBufferTexture1, 0);
|
||||||
|
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_DEPTH_ATTACHMENT, GL32.GL_TEXTURE_2D, this.frameBufferDepthTexture, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
GL32.glBindVertexArray(GL32.glIsVertexArray(this.vao) ? this.vao : 0);
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, GL32.glIsBuffer(this.vbo) ? this.vbo : 0);
|
||||||
|
GL32.glBindBuffer(GL32.GL_ELEMENT_ARRAY_BUFFER, GL32.glIsBuffer(this.ebo) ? this.ebo: 0);
|
||||||
|
GL32.glUseProgram(GL32.glIsProgram(this.program) ? this.program : 0);
|
||||||
|
|
||||||
|
if (this.writeToDepthBuffer)
|
||||||
|
{
|
||||||
|
GLMC.enableDepthMask();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLMC.disableDepthMask();
|
||||||
|
}
|
||||||
|
|
||||||
|
GLMC.glBlendFunc(this.blendSrcColor, this.blendDstColor);
|
||||||
|
GL32.glBlendEquationSeparate(this.blendEqRGB, this.blendEqAlpha);
|
||||||
|
GLMC.glBlendFuncSeparate(this.blendSrcColor, this.blendDstColor, this.blendSrcAlpha, this.blendDstAlpha);
|
||||||
|
|
||||||
|
if (this.depth)
|
||||||
|
{
|
||||||
|
GLMC.enableDepthTest();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLMC.disableDepthTest();
|
||||||
|
}
|
||||||
|
GLMC.glDepthFunc(this.depthFunc);
|
||||||
|
|
||||||
|
if (this.stencil)
|
||||||
|
{
|
||||||
|
GL32.glEnable(GL32.GL_STENCIL_TEST);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GL32.glDisable(GL32.GL_STENCIL_TEST);
|
||||||
|
}
|
||||||
|
GL32.glStencilFunc(this.stencilFunc, this.stencilRef, this.stencilMask);
|
||||||
|
|
||||||
|
GL32.glViewport(this.view[0], this.view[1], this.view[2], this.view[3]);
|
||||||
|
if (this.cull)
|
||||||
|
{
|
||||||
|
GLMC.enableFaceCulling();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
GLMC.disableFaceCulling();
|
||||||
|
}
|
||||||
|
GL32.glCullFace(this.cullMode);
|
||||||
|
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, this.polyMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "GLState{" +
|
||||||
|
"program=" + this.program + ", vao=" + this.vao + ", vbo=" + this.vbo + ", ebo=" + this.ebo + ", fbo=" + this.fbo +
|
||||||
|
", text=" + GLEnums.getString(this.texture2D) + "@" + this.activeTextureNumber + ", text0=" + GLEnums.getString(this.texture0) +
|
||||||
|
", FB text0=" + this.frameBufferTexture0 +
|
||||||
|
", FB text1=" + this.frameBufferTexture1 +
|
||||||
|
", FB depth=" + this.frameBufferDepthTexture +
|
||||||
|
", blend=" + this.blend + ", scissor=" + this.scissor + ", blendMode=" + GLEnums.getString(this.blendSrcColor) + "," + GLEnums.getString(this.blendDstColor) +
|
||||||
|
", depth=" + this.depth +
|
||||||
|
", depthFunc=" + GLEnums.getString(this.depthFunc) + ", stencil=" + this.stencil +
|
||||||
|
", stencilFunc=" + GLEnums.getString(this.stencilFunc) + ", stencilRef=" + this.stencilRef + ", stencilMask=" + this.stencilMask +
|
||||||
|
", view={x:" + this.view[0] + ", y:" + this.view[1] +
|
||||||
|
", w:" + this.view[2] + ", h:" + this.view[3] + "}" + ", cull=" + this.cull +
|
||||||
|
", cullMode=" + GLEnums.getString(this.cullMode) + ", polyMode=" + GLEnums.getString(this.polyMode) +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+94
@@ -0,0 +1,94 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
public class GlDhFramebuffer implements IDhApiFramebuffer
|
||||||
|
{
|
||||||
|
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public GlDhFramebuffer() { this.id = GL32.glGenFramebuffers(); }
|
||||||
|
|
||||||
|
/** For internal use by Iris, do not remove. */
|
||||||
|
public GlDhFramebuffer(int id) { this.id = id; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// methods //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addDepthAttachment(int textureId, boolean isCombinedStencil)
|
||||||
|
{
|
||||||
|
this.bind();
|
||||||
|
|
||||||
|
int depthAttachment = isCombinedStencil ? GL32.GL_DEPTH_STENCIL_ATTACHMENT : GL32.GL_DEPTH_ATTACHMENT;
|
||||||
|
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, depthAttachment, GL32.GL_TEXTURE_2D, textureId, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addColorAttachment(int textureIndex, int textureId)
|
||||||
|
{
|
||||||
|
this.bind();
|
||||||
|
|
||||||
|
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0 + textureIndex, GL32.GL_TEXTURE_2D, textureId, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bind()
|
||||||
|
{
|
||||||
|
if (this.id == -1)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Framebuffer does not exist!");
|
||||||
|
}
|
||||||
|
GLMC.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
GL32.glDeleteFramebuffers(this.id);
|
||||||
|
this.id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getStatus()
|
||||||
|
{
|
||||||
|
this.bind();
|
||||||
|
int status = GL32.glCheckFramebufferStatus(GL32.GL_FRAMEBUFFER);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getId() { return this.id; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// API methods //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public boolean overrideThisFrame() { return true; }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+17
@@ -0,0 +1,17 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodBufferContainer;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.ILodContainerUniformBufferWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* With OpenGL all uniform data is uploaded during the rendering phase
|
||||||
|
* so nothing is needed here.
|
||||||
|
*/
|
||||||
|
public class GlDummyUniformData implements ILodContainerUniformBufferWrapper
|
||||||
|
{
|
||||||
|
@Override public void createUniformData(LodBufferContainer bufferContainer) { }
|
||||||
|
@Override public void tryUpload() { }
|
||||||
|
@Override public void upload() { }
|
||||||
|
@Override public void close() { }
|
||||||
|
|
||||||
|
}
|
||||||
+383
@@ -0,0 +1,383 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.buffer;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.GLState;
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||||
|
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||||
|
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
import org.lwjgl.opengl.GL44;
|
||||||
|
|
||||||
|
import java.lang.ref.PhantomReference;
|
||||||
|
import java.lang.ref.Reference;
|
||||||
|
import java.lang.ref.ReferenceQueue;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class GLBuffer implements AutoCloseable
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logRendererGLEventToFile)
|
||||||
|
.chatLevelConfig(Config.Common.Logging.logRendererGLEventToChat)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
public static final double BUFFER_EXPANSION_MULTIPLIER = 1.3;
|
||||||
|
public static final double BUFFER_SHRINK_TRIGGER = BUFFER_EXPANSION_MULTIPLIER * BUFFER_EXPANSION_MULTIPLIER;
|
||||||
|
/** the number of active buffers, can be used for debugging */
|
||||||
|
public static AtomicInteger bufferCount = new AtomicInteger(0);
|
||||||
|
|
||||||
|
private static final int PHANTOM_REF_CHECK_TIME_IN_MS = 5 * 1000;
|
||||||
|
private static final ConcurrentHashMap<PhantomReference<? extends GLBuffer>, Integer> PHANTOM_TO_BUFFER_ID = new ConcurrentHashMap<>();
|
||||||
|
private static final ConcurrentHashMap<Integer, PhantomReference<? extends GLBuffer>> BUFFER_ID_TO_PHANTOM = new ConcurrentHashMap<>();
|
||||||
|
private static final ReferenceQueue<GLBuffer> PHANTOM_REFERENCE_QUEUE = new ReferenceQueue<>();
|
||||||
|
private static final ThreadPoolExecutor CLEANUP_THREAD = ThreadUtil.makeSingleDaemonThreadPool("GLBuffer Cleanup");
|
||||||
|
|
||||||
|
|
||||||
|
protected int id;
|
||||||
|
public final int getId() { return this.id; }
|
||||||
|
protected int size = 0;
|
||||||
|
public int getSize() { return this.size; }
|
||||||
|
protected boolean bufferStorage;
|
||||||
|
public final boolean isBufferStorage() { return this.bufferStorage; }
|
||||||
|
protected boolean isMapped = false;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// constructors //
|
||||||
|
//==============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
static { CLEANUP_THREAD.execute(() -> runPhantomReferenceCleanupLoop()); }
|
||||||
|
|
||||||
|
public GLBuffer(boolean isBufferStorage) { this.destroyOldAndCreate(isBufferStorage); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// methods //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
// Should be override by subclasses
|
||||||
|
public int getBufferBindingTarget() { return GL32.GL_COPY_READ_BUFFER; }
|
||||||
|
|
||||||
|
public void bind() { GL32.glBindBuffer(this.getBufferBindingTarget(), this.id); }
|
||||||
|
public void unbind() { GL32.glBindBuffer(this.getBufferBindingTarget(), 0); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//====================//
|
||||||
|
// create and destroy //
|
||||||
|
//====================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
protected void destroyOldAndCreate(boolean asBufferStorage)
|
||||||
|
{
|
||||||
|
if (!GLProxy.runningOnRenderThread())
|
||||||
|
{
|
||||||
|
LodUtil.assertNotReach("Thread ["+Thread.currentThread()+"] tried to create a GLBuffer outside the MC render thread.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// destroy the old buffer if one is present
|
||||||
|
if (this.id != 0)
|
||||||
|
{
|
||||||
|
destroyBufferIdNow(this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.id = GLMC.glGenBuffers();
|
||||||
|
this.bufferStorage = asBufferStorage;
|
||||||
|
bufferCount.getAndIncrement();
|
||||||
|
|
||||||
|
PhantomReference<GLBuffer> phantom = new PhantomReference<>(this, PHANTOM_REFERENCE_QUEUE);
|
||||||
|
PHANTOM_TO_BUFFER_ID.put(phantom, this.id);
|
||||||
|
BUFFER_ID_TO_PHANTOM.put(this.id, phantom);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void destroyAsync()
|
||||||
|
{
|
||||||
|
if (this.id == 0)
|
||||||
|
{
|
||||||
|
// the buffer has already been closed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int idToDelete = this.id; // saving the ID to a separate variable is necessary so it can be captured by the lambda
|
||||||
|
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer destroyAsync", () -> { destroyBufferIdNow(idToDelete); });
|
||||||
|
|
||||||
|
this.id = 0;
|
||||||
|
this.size = 0;
|
||||||
|
}
|
||||||
|
private static void destroyBufferIdNow(int id)
|
||||||
|
{
|
||||||
|
// only delete valid buffers
|
||||||
|
if (id == 0)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Attempted to destroy a buffer with ID 0, VRAM memory leaks may occur.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove and clear the phantom reference if present
|
||||||
|
if (BUFFER_ID_TO_PHANTOM.containsKey(id))
|
||||||
|
{
|
||||||
|
Reference<? extends GLBuffer> phantom = BUFFER_ID_TO_PHANTOM.get(id);
|
||||||
|
|
||||||
|
// if we are manually closing this buffer, we don't want the phantom reference to accidentally close it again
|
||||||
|
// this can cause a race condition were we accidentally delete an in-use buffer and cause NVIDIA
|
||||||
|
// to throw an EXCEPTION_ACCESS_VIOLATION when we attempt to render it
|
||||||
|
phantom.clear();
|
||||||
|
|
||||||
|
PHANTOM_TO_BUFFER_ID.remove(phantom);
|
||||||
|
BUFFER_ID_TO_PHANTOM.remove(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bufferCount.decrementAndGet();
|
||||||
|
|
||||||
|
// destroy the buffer if it exists,
|
||||||
|
// the buffer may not exist if the destroy method is called twice
|
||||||
|
if (GL32.glIsBuffer(id))
|
||||||
|
{
|
||||||
|
GLMC.glDeleteBuffers(id);
|
||||||
|
|
||||||
|
if (Config.Client.Advanced.Debugging.logBufferGarbageCollection.get())
|
||||||
|
{
|
||||||
|
LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==================//
|
||||||
|
// buffer uploading //
|
||||||
|
//==================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Assumes the GL Context is already bound. <br>
|
||||||
|
* Will create the VBO if one exist.
|
||||||
|
*/
|
||||||
|
public void uploadBuffer(ByteBuffer bb, EDhApiGpuUploadMethod uploadMethod, int maxExpansionSize, int bufferHint)
|
||||||
|
{
|
||||||
|
LodUtil.assertTrue(!uploadMethod.useEarlyMapping, "UploadMethod signal that this should use Mapping instead of uploadBuffer!");
|
||||||
|
int bbSize = bb.limit() - bb.position();
|
||||||
|
if (bbSize > maxExpansionSize)
|
||||||
|
{
|
||||||
|
LodUtil.assertNotReach("maxExpansionSize is [" + maxExpansionSize + "] but buffer size is [" + bbSize + "]!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't upload an empty buffer
|
||||||
|
if (bbSize == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// re-binding the old VBO is necessary for old MC versions (IE 1.16.5 and older)
|
||||||
|
// otherwise the screen may be black when on the home menu
|
||||||
|
int previousBoundVbo = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// make sure the buffer is ready for uploading
|
||||||
|
this.createOrChangeBufferTypeForUpload(uploadMethod);
|
||||||
|
|
||||||
|
switch (uploadMethod)
|
||||||
|
{
|
||||||
|
case AUTO:
|
||||||
|
LodUtil.assertNotReach("GpuUploadMethod AUTO must be resolved before call to uploadBuffer()!");
|
||||||
|
case BUFFER_STORAGE:
|
||||||
|
this.uploadBufferStorage(bb);
|
||||||
|
break;
|
||||||
|
case DATA:
|
||||||
|
this.uploadBufferData(bb, bufferHint);
|
||||||
|
break;
|
||||||
|
case SUB_DATA:
|
||||||
|
this.uploadSubData(bb, maxExpansionSize, bufferHint);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
LodUtil.assertNotReach("Unknown GpuUploadMethod!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, GL32.glIsBuffer(previousBoundVbo) ? previousBoundVbo : 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** Requires the buffer to be bound */
|
||||||
|
protected void uploadBufferStorage(ByteBuffer bb)
|
||||||
|
{
|
||||||
|
LodUtil.assertTrue(this.bufferStorage, "Buffer is not bufferStorage but its trying to use bufferStorage upload method!");
|
||||||
|
|
||||||
|
int bbSize = bb.limit() - bb.position();
|
||||||
|
this.destroyOldAndCreate(true);
|
||||||
|
this.bind();
|
||||||
|
GL44.glBufferStorage(this.getBufferBindingTarget(), bb, 0);
|
||||||
|
this.size = bbSize;
|
||||||
|
}
|
||||||
|
/** Requires the buffer to be bound */
|
||||||
|
protected void uploadBufferData(ByteBuffer bb, int bufferDataHint)
|
||||||
|
{
|
||||||
|
LodUtil.assertTrue(!this.bufferStorage, "Buffer is bufferStorage but its trying to use bufferData upload method!");
|
||||||
|
|
||||||
|
int bbSize = bb.limit() - bb.position();
|
||||||
|
GL32.glBufferData(this.getBufferBindingTarget(), bb, bufferDataHint);
|
||||||
|
this.size = bbSize;
|
||||||
|
}
|
||||||
|
/** Requires the buffer to be bound */
|
||||||
|
protected void uploadSubData(ByteBuffer bb, int maxExpansionSize, int bufferDataHint)
|
||||||
|
{
|
||||||
|
LodUtil.assertTrue(!this.bufferStorage, "Buffer is bufferStorage but its trying to use subData upload method!");
|
||||||
|
|
||||||
|
int bbSize = bb.limit() - bb.position();
|
||||||
|
if (this.size < bbSize || this.size > bbSize * BUFFER_SHRINK_TRIGGER)
|
||||||
|
{
|
||||||
|
int newSize = (int) (bbSize * BUFFER_EXPANSION_MULTIPLIER);
|
||||||
|
if (newSize > maxExpansionSize) newSize = maxExpansionSize;
|
||||||
|
GL32.glBufferData(this.getBufferBindingTarget(), newSize, bufferDataHint);
|
||||||
|
this.size = newSize;
|
||||||
|
}
|
||||||
|
GL32.glBufferSubData(this.getBufferBindingTarget(), 0, bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() { this.destroyAsync(); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return (this.bufferStorage ? "" : "Static-") + this.getClass().getSimpleName() +
|
||||||
|
"[id:" + this.id + ",size:" + this.size + (this.isMapped ? ",MAPPED" : "") + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper methods //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Makes sure the buffer exists and is of the correct format
|
||||||
|
* before uploading.
|
||||||
|
*/
|
||||||
|
private void createOrChangeBufferTypeForUpload(EDhApiGpuUploadMethod uploadMethod)
|
||||||
|
{
|
||||||
|
// create/change the buffer type if necessary
|
||||||
|
if (uploadMethod.useBufferStorage != this.bufferStorage)
|
||||||
|
{
|
||||||
|
// recreate if the buffer storage type changed
|
||||||
|
this.bind();
|
||||||
|
destroyBufferIdNow(this.id);
|
||||||
|
this.destroyOldAndCreate(uploadMethod.useBufferStorage);
|
||||||
|
this.bind();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Prevent uploading to the null buffer (ID 0).
|
||||||
|
// This can happen if the buffer was deleted previously.
|
||||||
|
if (this.id == 0)
|
||||||
|
{
|
||||||
|
this.destroyOldAndCreate(this.bufferStorage);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bind();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// static cleanup //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
private static void runPhantomReferenceCleanupLoop()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Thread.sleep(PHANTOM_REF_CHECK_TIME_IN_MS);
|
||||||
|
}
|
||||||
|
catch (InterruptedException ignore) { }
|
||||||
|
|
||||||
|
|
||||||
|
Reference<? extends GLBuffer> phantomRef = PHANTOM_REFERENCE_QUEUE.poll();
|
||||||
|
while (phantomRef != null)
|
||||||
|
{
|
||||||
|
// destroy the buffer if it hasn't been cleared yet
|
||||||
|
if (PHANTOM_TO_BUFFER_ID.containsKey(phantomRef))
|
||||||
|
{
|
||||||
|
int id = PHANTOM_TO_BUFFER_ID.get(phantomRef);
|
||||||
|
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("GLBuffer phantom destroy", () -> { destroyBufferIdNow(id); });
|
||||||
|
//LOGGER.warn("Buffer Phantom collected, ID: ["+id+"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
phantomRef = PHANTOM_REFERENCE_QUEUE.poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
LOGGER.error("Unexpected error in buffer cleanup thread: [" + e.getMessage() + "].", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.buffer;
|
||||||
|
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AKA the GLElementBuffer
|
||||||
|
*
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 11-20-2021
|
||||||
|
*/
|
||||||
|
public class GLIndexBuffer extends GLBuffer
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* When uploading to a buffer that is too small, recreate it this many times
|
||||||
|
* bigger than the upload payload
|
||||||
|
*/
|
||||||
|
protected int indicesCount = 0;
|
||||||
|
protected int glType = GL32.GL_UNSIGNED_INT;
|
||||||
|
public int getGlType() { return this.glType; }
|
||||||
|
|
||||||
|
public GLIndexBuffer(boolean isBufferStorage)
|
||||||
|
{
|
||||||
|
super(isBufferStorage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void destroyAsync()
|
||||||
|
{
|
||||||
|
super.destroyAsync();
|
||||||
|
this.indicesCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBufferBindingTarget() { return GL32.GL_ELEMENT_ARRAY_BUFFER; }
|
||||||
|
|
||||||
|
}
|
||||||
+190
@@ -0,0 +1,190 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.buffer;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.GLProxy;
|
||||||
|
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.LodQuadBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||||
|
import com.seibel.distanthorizons.core.jar.EPlatform;
|
||||||
|
import com.seibel.distanthorizons.core.render.RenderThreadTaskHandler;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.AbstractDhRenderApiDefinition;
|
||||||
|
import com.seibel.distanthorizons.core.wrapperInterfaces.render.objects.IVertexBufferWrapper;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a container for a OpenGL
|
||||||
|
* VBO (Vertex Buffer Object).
|
||||||
|
*
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 11-20-2021
|
||||||
|
*/
|
||||||
|
public class GLVertexBuffer extends GLBuffer implements IVertexBufferWrapper
|
||||||
|
{
|
||||||
|
private static final AbstractDhRenderApiDefinition RENDER_DEF = SingletonInjector.INSTANCE.get(AbstractDhRenderApiDefinition.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When uploading to a buffer that is too small, recreate it this many times
|
||||||
|
* bigger than the upload payload
|
||||||
|
*/
|
||||||
|
protected int vertexCount = 0;
|
||||||
|
public int getVertexCount() { return this.vertexCount; }
|
||||||
|
|
||||||
|
|
||||||
|
private GlQuadIndexBuffer quadIBO = null;
|
||||||
|
private static GlQuadIndexBuffer GLOBAL_QUAD_IBO = null;
|
||||||
|
public GlQuadIndexBuffer getQuadIBO()
|
||||||
|
{
|
||||||
|
if (RENDER_DEF.useSingleIbo())
|
||||||
|
{
|
||||||
|
return GLOBAL_QUAD_IBO;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return this.quadIBO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
static
|
||||||
|
{
|
||||||
|
if (RENDER_DEF.useSingleIbo())
|
||||||
|
{
|
||||||
|
RenderThreadTaskHandler.INSTANCE.queueRunningOnRenderThread("Global IBO Creation", () ->
|
||||||
|
{
|
||||||
|
GLOBAL_QUAD_IBO = new GlQuadIndexBuffer();
|
||||||
|
|
||||||
|
int maxSize = LodQuadBuilder.getMaxBufferByteSize();
|
||||||
|
int maxVertexCount = maxSize / LodQuadBuilder.BYTES_PER_VERTEX;
|
||||||
|
int maxQuadCount = (maxVertexCount / 4);
|
||||||
|
GLOBAL_QUAD_IBO.upload(maxQuadCount);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public GLVertexBuffer() { this(GLProxy.getInstance().getGpuUploadMethod() == EDhApiGpuUploadMethod.BUFFER_STORAGE); }
|
||||||
|
public GLVertexBuffer(boolean isBufferStorage) { super(isBufferStorage); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//======================//
|
||||||
|
// uploading/destroying //
|
||||||
|
//======================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBufferBindingTarget() { return GL32.GL_ARRAY_BUFFER; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadVertexBuffer(ByteBuffer buffer, int vertexCount)
|
||||||
|
{
|
||||||
|
EDhApiGpuUploadMethod uploadMethod = GLProxy.getInstance().getGpuUploadMethod();
|
||||||
|
int maxBufferSize = LodQuadBuilder.getMaxBufferByteSize();
|
||||||
|
this.uploadBuffer(buffer, vertexCount, uploadMethod, maxBufferSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* bufferSize is the number of shared verticies. <br>
|
||||||
|
* This number will be higher when actually rendered since each box's face needs 2 triangles
|
||||||
|
* with 2 shared verticies.
|
||||||
|
*/
|
||||||
|
public void uploadBuffer(ByteBuffer byteBuffer, int vertexCount, EDhApiGpuUploadMethod uploadMethod, int maxExpansionSize)
|
||||||
|
{
|
||||||
|
if (vertexCount < 0)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("vertexCount is negative!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If size is zero, just ignore it.
|
||||||
|
if (byteBuffer.limit() - byteBuffer.position() != 0)
|
||||||
|
{
|
||||||
|
super.uploadBuffer(byteBuffer, uploadMethod, maxExpansionSize, uploadMethod.useBufferStorage ? 0 : GL32.GL_STATIC_DRAW);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.vertexCount = vertexCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void uploadIndexBuffer(ByteBuffer buffer, int vertexCount)
|
||||||
|
{
|
||||||
|
if (RENDER_DEF.useSingleIbo())
|
||||||
|
{
|
||||||
|
// ignore index uploading when running a single IBO
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If size is zero, just ignore it.
|
||||||
|
if (vertexCount == 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (this.quadIBO != null)
|
||||||
|
{
|
||||||
|
this.quadIBO.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.quadIBO = new GlQuadIndexBuffer();
|
||||||
|
|
||||||
|
int quadCount = (vertexCount / 4);
|
||||||
|
this.quadIBO.upload(quadCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// base overrides //
|
||||||
|
//================//
|
||||||
|
//region
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() { this.destroyAsync(); }
|
||||||
|
@Override
|
||||||
|
public void destroyAsync()
|
||||||
|
{
|
||||||
|
super.destroyAsync();
|
||||||
|
if (this.quadIBO != null)
|
||||||
|
{
|
||||||
|
this.quadIBO.destroyAsync();
|
||||||
|
}
|
||||||
|
this.vertexCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+89
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.buffer;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.enums.GLEnums;
|
||||||
|
import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.IndexBufferBuilder;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
/** aka GlQuadElementBuffer */
|
||||||
|
public class GlQuadIndexBuffer extends GLIndexBuffer
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public GlQuadIndexBuffer() { super(false); }
|
||||||
|
|
||||||
|
public void upload(int quadCount)
|
||||||
|
{
|
||||||
|
if (quadCount < 0)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("quadCount must be greater than 0");
|
||||||
|
}
|
||||||
|
if (quadCount == 0)
|
||||||
|
{
|
||||||
|
// shouldn't happen, but just in case
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.indicesCount = quadCount * 6; // 2 triangles per quad
|
||||||
|
if (this.indicesCount >= this.getCapacity()
|
||||||
|
&& this.indicesCount < this.getCapacity() * BUFFER_SHRINK_TRIGGER)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.glType = GL32.GL_UNSIGNED_INT;
|
||||||
|
ByteBuffer buffer = IndexBufferBuilder.createBuffer(quadCount);
|
||||||
|
this.bind();
|
||||||
|
super.uploadBuffer(buffer, EDhApiGpuUploadMethod.DATA,
|
||||||
|
this.indicesCount * GLEnums.getTypeSize(this.glType), GL32.GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
MemoryUtil.memFree(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// getters //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public int getCapacity() { return super.getSize() / GLEnums.getTypeSize(this.getGlType()); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+9
@@ -0,0 +1,9 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.enums;
|
||||||
|
|
||||||
|
public enum EGlVersion
|
||||||
|
{
|
||||||
|
GL_11,
|
||||||
|
GL_12,
|
||||||
|
GL_30,
|
||||||
|
GL_31
|
||||||
|
}
|
||||||
+261
@@ -0,0 +1,261 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.enums;
|
||||||
|
|
||||||
|
import static org.lwjgl.opengl.GL46.*;
|
||||||
|
|
||||||
|
// Turns GL int enums back to readable strings
|
||||||
|
public class GLEnums
|
||||||
|
{
|
||||||
|
|
||||||
|
public static String getString(int glEnum)
|
||||||
|
{
|
||||||
|
// blend stuff
|
||||||
|
switch (glEnum)
|
||||||
|
{
|
||||||
|
case GL_ZERO:
|
||||||
|
return "GL_ZERO";
|
||||||
|
case GL_ONE:
|
||||||
|
return "GL_ONE";
|
||||||
|
case GL_SRC_COLOR:
|
||||||
|
return "GL_SRC_COLOR";
|
||||||
|
case GL_ONE_MINUS_SRC_COLOR:
|
||||||
|
return "GL_ONE_MINUS_SRC_COLOR";
|
||||||
|
case GL_DST_COLOR:
|
||||||
|
return "GL_DST_COLOR";
|
||||||
|
case GL_ONE_MINUS_DST_COLOR:
|
||||||
|
return "GL_ONE_MINUS_DST_COLOR";
|
||||||
|
case GL_SRC_ALPHA:
|
||||||
|
return "GL_SRC_ALPHA";
|
||||||
|
case GL_ONE_MINUS_SRC_ALPHA:
|
||||||
|
return "GL_ONE_MINUS_SRC_ALPHA";
|
||||||
|
case GL_DST_ALPHA:
|
||||||
|
return "GL_DST_ALPHA";
|
||||||
|
case GL_ONE_MINUS_DST_ALPHA:
|
||||||
|
return "GL_ONE_MINUS_DST_ALPHA";
|
||||||
|
case GL_CONSTANT_COLOR:
|
||||||
|
return "GL_CONSTANT_COLOR";
|
||||||
|
case GL_ONE_MINUS_CONSTANT_COLOR:
|
||||||
|
return "GL_ONE_MINUS_CONSTANT_COLOR";
|
||||||
|
case GL_CONSTANT_ALPHA:
|
||||||
|
return "GL_CONSTANT_ALPHA";
|
||||||
|
case GL_ONE_MINUS_CONSTANT_ALPHA:
|
||||||
|
return "GL_ONE_MINUS_CONSTANT_ALPHA";
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// shader stuff
|
||||||
|
switch (glEnum)
|
||||||
|
{
|
||||||
|
case GL_VERTEX_SHADER:
|
||||||
|
return "GL_VERTEX_SHADER";
|
||||||
|
case GL_GEOMETRY_SHADER:
|
||||||
|
return "GL_GEOMETRY_SHADER";
|
||||||
|
case GL_FRAGMENT_SHADER:
|
||||||
|
return "GL_FRAGMENT_SHADER";
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// stencil stuff
|
||||||
|
switch (glEnum)
|
||||||
|
{
|
||||||
|
case GL_KEEP:
|
||||||
|
return "GL_KEEP";
|
||||||
|
case GL_ZERO:
|
||||||
|
return "GL_ZERO";
|
||||||
|
case GL_REPLACE:
|
||||||
|
return "GL_REPLACE";
|
||||||
|
case GL_INCR:
|
||||||
|
return "GL_INCR";
|
||||||
|
case GL_DECR:
|
||||||
|
return "GL_DECR";
|
||||||
|
case GL_INVERT:
|
||||||
|
return "GL_INVERT";
|
||||||
|
case GL_INCR_WRAP:
|
||||||
|
return "GL_INCR_WRAP";
|
||||||
|
case GL_DECR_WRAP:
|
||||||
|
return "GL_DECR_WRAP";
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// depth stuff
|
||||||
|
switch (glEnum)
|
||||||
|
{
|
||||||
|
case GL_NEVER:
|
||||||
|
return "GL_NEVER";
|
||||||
|
case GL_LESS:
|
||||||
|
return "GL_LESS";
|
||||||
|
case GL_EQUAL:
|
||||||
|
return "GL_EQUAL";
|
||||||
|
case GL_LEQUAL:
|
||||||
|
return "GL_LEQUAL";
|
||||||
|
case GL_GREATER:
|
||||||
|
return "GL_GREATER";
|
||||||
|
case GL_NOTEQUAL:
|
||||||
|
return "GL_NOTEQUAL";
|
||||||
|
case GL_GEQUAL:
|
||||||
|
return "GL_GEQUAL";
|
||||||
|
case GL_ALWAYS:
|
||||||
|
return "GL_ALWAYS";
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Texture binding points
|
||||||
|
switch (glEnum)
|
||||||
|
{
|
||||||
|
case GL_TEXTURE0:
|
||||||
|
return "GL_TEXTURE0";
|
||||||
|
case GL_TEXTURE1:
|
||||||
|
return "GL_TEXTURE1";
|
||||||
|
case GL_TEXTURE2:
|
||||||
|
return "GL_TEXTURE2";
|
||||||
|
case GL_TEXTURE3:
|
||||||
|
return "GL_TEXTURE3";
|
||||||
|
case GL_TEXTURE4:
|
||||||
|
return "GL_TEXTURE4";
|
||||||
|
case GL_TEXTURE5:
|
||||||
|
return "GL_TEXTURE5";
|
||||||
|
case GL_TEXTURE6:
|
||||||
|
return "GL_TEXTURE6";
|
||||||
|
case GL_TEXTURE7:
|
||||||
|
return "GL_TEXTURE7";
|
||||||
|
case GL_TEXTURE8:
|
||||||
|
return "GL_TEXTURE8";
|
||||||
|
case GL_TEXTURE9:
|
||||||
|
return "GL_TEXTURE9";
|
||||||
|
case GL_TEXTURE10:
|
||||||
|
return "GL_TEXTURE10";
|
||||||
|
case GL_TEXTURE11:
|
||||||
|
return "GL_TEXTURE11";
|
||||||
|
case GL_TEXTURE12:
|
||||||
|
return "GL_TEXTURE12";
|
||||||
|
case GL_TEXTURE13:
|
||||||
|
return "GL_TEXTURE13";
|
||||||
|
case GL_TEXTURE14:
|
||||||
|
return "GL_TEXTURE14";
|
||||||
|
case GL_TEXTURE15:
|
||||||
|
return "GL_TEXTURE15";
|
||||||
|
case GL_TEXTURE16:
|
||||||
|
return "GL_TEXTURE16";
|
||||||
|
case GL_TEXTURE17:
|
||||||
|
return "GL_TEXTURE17";
|
||||||
|
case GL_TEXTURE18:
|
||||||
|
return "GL_TEXTURE18";
|
||||||
|
case GL_TEXTURE19:
|
||||||
|
return "GL_TEXTURE19";
|
||||||
|
case GL_TEXTURE20:
|
||||||
|
return "GL_TEXTURE20";
|
||||||
|
case GL_TEXTURE21:
|
||||||
|
return "GL_TEXTURE21";
|
||||||
|
case GL_TEXTURE22:
|
||||||
|
return "GL_TEXTURE22";
|
||||||
|
case GL_TEXTURE23:
|
||||||
|
return "GL_TEXTURE23";
|
||||||
|
case GL_TEXTURE24:
|
||||||
|
return "GL_TEXTURE24";
|
||||||
|
case GL_TEXTURE25:
|
||||||
|
return "GL_TEXTURE25";
|
||||||
|
case GL_TEXTURE26:
|
||||||
|
return "GL_TEXTURE26";
|
||||||
|
case GL_TEXTURE27:
|
||||||
|
return "GL_TEXTURE27";
|
||||||
|
case GL_TEXTURE28:
|
||||||
|
return "GL_TEXTURE28";
|
||||||
|
case GL_TEXTURE29:
|
||||||
|
return "GL_TEXTURE29";
|
||||||
|
case GL_TEXTURE30:
|
||||||
|
return "GL_TEXTURE30";
|
||||||
|
case GL_TEXTURE31:
|
||||||
|
return "GL_TEXTURE31";
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Polygon modes
|
||||||
|
switch (glEnum)
|
||||||
|
{
|
||||||
|
case GL_POINT:
|
||||||
|
return "GL_POINT";
|
||||||
|
case GL_LINE:
|
||||||
|
return "GL_LINE";
|
||||||
|
case GL_FILL:
|
||||||
|
return "GL_FILL";
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Culling modes
|
||||||
|
switch (glEnum)
|
||||||
|
{
|
||||||
|
case GL_FRONT:
|
||||||
|
return "GL_FRONT";
|
||||||
|
case GL_BACK:
|
||||||
|
return "GL_BACK";
|
||||||
|
case GL_FRONT_AND_BACK:
|
||||||
|
return "GL_FRONT_AND_BACK";
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
// Types
|
||||||
|
switch (glEnum)
|
||||||
|
{
|
||||||
|
case GL_BYTE:
|
||||||
|
return "GL_BYTE";
|
||||||
|
case GL_UNSIGNED_BYTE:
|
||||||
|
return "GL_UNSIGNED_BYTE";
|
||||||
|
case GL_SHORT:
|
||||||
|
return "GL_SHORT";
|
||||||
|
case GL_UNSIGNED_SHORT:
|
||||||
|
return "GL_UNSIGNED_SHORT";
|
||||||
|
case GL_INT:
|
||||||
|
return "GL_INT";
|
||||||
|
case GL_UNSIGNED_INT:
|
||||||
|
return "GL_UNSIGNED_INT";
|
||||||
|
case GL_FLOAT:
|
||||||
|
return "GL_FLOAT";
|
||||||
|
case GL_DOUBLE:
|
||||||
|
return "GL_DOUBLE";
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
|
return "GL_UNKNOWN(" + glEnum + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getTypeSize(int glTypeEnum)
|
||||||
|
{
|
||||||
|
switch (glTypeEnum)
|
||||||
|
{
|
||||||
|
case GL_BYTE:
|
||||||
|
case GL_UNSIGNED_BYTE:
|
||||||
|
return 1;
|
||||||
|
case GL_SHORT:
|
||||||
|
case GL_UNSIGNED_SHORT:
|
||||||
|
return 2;
|
||||||
|
case GL_INT:
|
||||||
|
case GL_UNSIGNED_INT:
|
||||||
|
return 4;
|
||||||
|
case GL_FLOAT:
|
||||||
|
return 4;
|
||||||
|
case GL_DOUBLE:
|
||||||
|
return 8;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown type enum: " + getString(glTypeEnum));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+184
@@ -0,0 +1,184 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.shader;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.config.Config;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||||
|
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||||
|
import org.lwjgl.PointerBuffer;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
import org.lwjgl.opengl.GL32C;
|
||||||
|
import org.lwjgl.system.MemoryStack;
|
||||||
|
import org.lwjgl.system.MemoryUtil;
|
||||||
|
import org.lwjgl.system.NativeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This object holds a OpenGL reference to a shader
|
||||||
|
* and allows for reading in and compiling a shader file.
|
||||||
|
*/
|
||||||
|
public class GlShader
|
||||||
|
{
|
||||||
|
private static final DhLogger LOGGER = new DhLoggerBuilder()
|
||||||
|
.fileLevelConfig(Config.Common.Logging.logRendererGLEventToFile)
|
||||||
|
.chatLevelConfig(Config.Common.Logging.logRendererGLEventToChat)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
|
||||||
|
/** OpenGL shader ID */
|
||||||
|
public final int id;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// constructors //
|
||||||
|
//==============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a shader with specified type.
|
||||||
|
*
|
||||||
|
* @param type Either GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.
|
||||||
|
* @param sourceString File path of the shader
|
||||||
|
* @throws RuntimeException if the shader fails to compile
|
||||||
|
*/
|
||||||
|
public GlShader(int type, String sourceString)
|
||||||
|
{
|
||||||
|
LOGGER.info("Loading shader with type: ["+type+"]");
|
||||||
|
LOGGER.debug("Source: \n["+sourceString+"]");
|
||||||
|
if (sourceString == null || sourceString.isEmpty())
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("No shader source given.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create an empty shader object
|
||||||
|
this.id = GL32.glCreateShader(type);
|
||||||
|
if (this.id == 0)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Failed to create shader with type ["+type+"] and Source: \n["+sourceString+"].");
|
||||||
|
}
|
||||||
|
|
||||||
|
safeShaderSource(this.id, sourceString);
|
||||||
|
GL32.glCompileShader(this.id);
|
||||||
|
// check if the shader compiled
|
||||||
|
int status = GL32.glGetShaderi(this.id, GL32.GL_COMPILE_STATUS);
|
||||||
|
if (status != GL32.GL_TRUE)
|
||||||
|
{
|
||||||
|
|
||||||
|
String message = "Shader compiler error. Details: [" + GL32.glGetShaderInfoLog(this.id) + "]\n";
|
||||||
|
message += "Source: \n[" + sourceString + "]";
|
||||||
|
this.free(); // important!
|
||||||
|
throw new RuntimeException(message);
|
||||||
|
}
|
||||||
|
LOGGER.info("Shader loaded sucessfully.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// helpers //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Identical in function to {@link GL32C#glShaderSource(int, CharSequence)} but
|
||||||
|
* passes a null pointer for string length to force the driver to rely on the null
|
||||||
|
* terminator for string length. This is a workaround for an apparent flaw with some
|
||||||
|
* AMD drivers that don't receive or interpret the length correctly, resulting in
|
||||||
|
* an access violation when the driver tries to read past the string memory.
|
||||||
|
*
|
||||||
|
* <p>Hat tip to fewizz for the find and the fix.
|
||||||
|
*
|
||||||
|
* <p>Source: https://github.com/vram-guild/canvas/commit/820bf754092ccaf8d0c169620c2ff575722d7d96
|
||||||
|
*/
|
||||||
|
private static void safeShaderSource(@NativeType("GLuint") int glId, @NativeType("GLchar const **") CharSequence source)
|
||||||
|
{
|
||||||
|
final MemoryStack stack = MemoryStack.stackGet();
|
||||||
|
final int stackPointer = stack.getPointer();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
final ByteBuffer sourceBuffer = MemoryUtil.memUTF8(source, true);
|
||||||
|
final PointerBuffer pointers = stack.mallocPointer(1);
|
||||||
|
pointers.put(sourceBuffer);
|
||||||
|
|
||||||
|
GL32.nglShaderSource(glId, 1, pointers.address0(), 0);
|
||||||
|
org.lwjgl.system.APIUtil.apiArrayFree(pointers.address0(), 1);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
stack.setPointer(stackPointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void free() { GL32.glDeleteShader(this.id); }
|
||||||
|
|
||||||
|
public static String loadFile(String path, boolean absoluteFilePath)
|
||||||
|
{
|
||||||
|
StringBuilder stringBuilder = new StringBuilder();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// open the file
|
||||||
|
InputStream in;
|
||||||
|
if (absoluteFilePath)
|
||||||
|
{
|
||||||
|
// Throws FileNotFoundException
|
||||||
|
in = new FileInputStream(path); // Note: this should use OS path seperator
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
in = GlShader.class.getClassLoader().getResourceAsStream(path); // Note: path seperator should be '/'
|
||||||
|
if (in == null)
|
||||||
|
{
|
||||||
|
throw new FileNotFoundException("Shader file not found in resource: " + path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||||
|
|
||||||
|
// read in the file
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null)
|
||||||
|
{
|
||||||
|
stringBuilder.append(line).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Unable to load shader from file [" + path + "]. Error: " + e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return stringBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+225
@@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizons mod
|
||||||
|
* licensed under the GNU LGPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2020 James Seibel
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, version 3.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.shader;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.api.objects.math.DhApiVec3i;
|
||||||
|
import org.lwjgl.opengl.GL32;
|
||||||
|
import org.lwjgl.system.MemoryStack;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||||
|
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This object holds the reference to a OpenGL shader program
|
||||||
|
* and contains a few methods that can be used with OpenGL shader programs.
|
||||||
|
* The reason for many of these simple wrapper methods is as reminders of what
|
||||||
|
* can (and needs to be) done with a shader program.
|
||||||
|
*/
|
||||||
|
public class GlShaderProgram
|
||||||
|
{
|
||||||
|
/** Stores the handle of the program. */
|
||||||
|
public final int id;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public GlShaderProgram(String vertResourcePath, String fragResourcePath, String attribute) { this(vertResourcePath, fragResourcePath, new String[]{ attribute }); }
|
||||||
|
/**
|
||||||
|
* @param vertResourcePath the relative path the vertex shader should be found
|
||||||
|
* @param fragResourcePath the relative path the fragment shader should be found
|
||||||
|
*/
|
||||||
|
public GlShaderProgram(String vertResourcePath, String fragResourcePath, String[] attributes)
|
||||||
|
{
|
||||||
|
this.id = GL32.glCreateProgram();
|
||||||
|
|
||||||
|
{
|
||||||
|
String shaderString = GlShader.loadFile(vertResourcePath, false);
|
||||||
|
GlShader vertShader = new GlShader(GL32.GL_VERTEX_SHADER, shaderString);
|
||||||
|
GL32.glAttachShader(this.id, vertShader.id);
|
||||||
|
vertShader.free();
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
String shaderString = GlShader.loadFile(fragResourcePath, false);
|
||||||
|
GlShader fragShader = new GlShader(GL32.GL_FRAGMENT_SHADER, shaderString);
|
||||||
|
GL32.glAttachShader(this.id, fragShader.id);
|
||||||
|
fragShader.free();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < attributes.length; i++)
|
||||||
|
{
|
||||||
|
GL32.glBindAttribLocation(this.id, i, attributes[i]);
|
||||||
|
}
|
||||||
|
GL32.glLinkProgram(this.id);
|
||||||
|
|
||||||
|
int status = GL32.glGetProgrami(this.id, GL32.GL_LINK_STATUS);
|
||||||
|
if (status != GL32.GL_TRUE)
|
||||||
|
{
|
||||||
|
String message = "Shader Link Error. Details: " + GL32.glGetProgramInfoLog(this.id);
|
||||||
|
this.free(); // important!
|
||||||
|
throw new RuntimeException(message);
|
||||||
|
}
|
||||||
|
GL32.glUseProgram(this.id); // This HAVE to be a direct call to prevent calling the overloaded version
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// binding //
|
||||||
|
//=========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
public void bind() { GL32.glUseProgram(this.id); }
|
||||||
|
public void unbind() { GL32.glUseProgram(0); }
|
||||||
|
|
||||||
|
public void free() { GL32.glDeleteProgram(this.id); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============//
|
||||||
|
// attributes //
|
||||||
|
//============//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WARNING: Slow native call! Cache it if possible!
|
||||||
|
* Gets the location of an attribute variable with specified name.
|
||||||
|
* Calls GL20.glGetAttribLocation(id, name)
|
||||||
|
*
|
||||||
|
* @param name Attribute name
|
||||||
|
* @return Location of the attribute
|
||||||
|
* @throws RuntimeException if attribute not found
|
||||||
|
*/
|
||||||
|
public int getAttributeLocation(CharSequence name)
|
||||||
|
{
|
||||||
|
int i = GL32.glGetAttribLocation(id, name);
|
||||||
|
if (i == -1) throw new RuntimeException("Attribute name not found: " + name);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Same as above but without throwing errors. <br>
|
||||||
|
* Returns -1 if the attribute doesn't exist or has been optimized out.
|
||||||
|
*/
|
||||||
|
public int tryGetAttributeLocation(CharSequence name)
|
||||||
|
{ return GL32.glGetAttribLocation(this.id, name); }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==========//
|
||||||
|
// uniforms //
|
||||||
|
//==========//
|
||||||
|
//region
|
||||||
|
|
||||||
|
/**
|
||||||
|
* WARNING: Slow native call! Cache it if possible!
|
||||||
|
* Gets the location of a uniform variable with specified name.
|
||||||
|
* Calls GL20.glGetUniformLocation(id, name)
|
||||||
|
*
|
||||||
|
* @param name Uniform name
|
||||||
|
* @return Location of the Uniform
|
||||||
|
* @throws RuntimeException if uniform not found
|
||||||
|
*/
|
||||||
|
public int getUniformLocation(CharSequence name) throws RuntimeException
|
||||||
|
{
|
||||||
|
int i = GL32.glGetUniformLocation(id, name);
|
||||||
|
if (i == -1)
|
||||||
|
{
|
||||||
|
throw new RuntimeException("Uniform name not found: " + name);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Same as above but without throwing errors.
|
||||||
|
// Return -1 if uniform doesn't exist or has been optimized out
|
||||||
|
public int tryGetUniformLocation(CharSequence name)
|
||||||
|
{ return GL32.glGetUniformLocation(this.id, name); }
|
||||||
|
|
||||||
|
/** Requires a bound ShaderProgram. */
|
||||||
|
public void setUniform(int location, boolean value) { GL32.glUniform1i(location, value ? 1 : 0); }
|
||||||
|
/** @see GlShaderProgram#setUniform(int, boolean) */
|
||||||
|
public void trySetUniform(int location, boolean value) { if (location != -1) { this.setUniform(location, value); } }
|
||||||
|
|
||||||
|
/** Requires a bound ShaderProgram. */
|
||||||
|
public void setUniform(int location, int value) { GL32.glUniform1i(location, value); }
|
||||||
|
/** @see GlShaderProgram#setUniform(int, int) */
|
||||||
|
public void trySetUniform(int location, int value) { if (location != -1) { this.setUniform(location, value); } }
|
||||||
|
|
||||||
|
/** Requires a bound ShaderProgram. */
|
||||||
|
public void setUniform(int location, float value) { GL32.glUniform1f(location, value); }
|
||||||
|
/** @see GlShaderProgram#setUniform(int, float) */
|
||||||
|
public void trySetUniform(int location, float value) { if (location != -1) { this.setUniform(location, value); } }
|
||||||
|
|
||||||
|
/** Requires a bound ShaderProgram. */
|
||||||
|
public void setUniform(int location, Vec3f value) { GL32.glUniform3f(location, value.x, value.y, value.z); }
|
||||||
|
/** @see GlShaderProgram#setUniform(int, Vec3f) */
|
||||||
|
public void trySetUniform(int location, Vec3f value) { if (location != -1) { this.setUniform(location, value); } }
|
||||||
|
|
||||||
|
/** Requires a bound ShaderProgram. */
|
||||||
|
public void setUniform(int location, DhApiVec3i value) { GL32.glUniform3i(location, value.x, value.y, value.z); }
|
||||||
|
/** @see GlShaderProgram#setUniform(int, Mat4f) */
|
||||||
|
public void trySetUniform(int location, DhApiVec3i value) { if (location != -1) { this.setUniform(location, value); } }
|
||||||
|
|
||||||
|
/** Requires a bound ShaderProgram. */
|
||||||
|
public void setUniform(int location, Mat4f value)
|
||||||
|
{
|
||||||
|
try (MemoryStack stack = MemoryStack.stackPush())
|
||||||
|
{
|
||||||
|
FloatBuffer buffer = stack.mallocFloat(4 * 4);
|
||||||
|
value.store(buffer);
|
||||||
|
GL32.glUniformMatrix4fv(location, false, buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/** @see GlShaderProgram#setUniform(int, Mat4f) */
|
||||||
|
public void trySetUniform(int location, Mat4f value) { if (location != -1) { this.setUniform(location, value); } }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the color's RGBA values into values between 0 and 1. <br>
|
||||||
|
* Requires a bound ShaderProgram.
|
||||||
|
*/
|
||||||
|
public void setUniform(int location, Color value)
|
||||||
|
{
|
||||||
|
GL32.glUniform4f(location,
|
||||||
|
value.getRed() / 256.0f,
|
||||||
|
value.getGreen() / 256.0f,
|
||||||
|
value.getBlue() / 256.0f,
|
||||||
|
value.getAlpha() / 256.0f);
|
||||||
|
}
|
||||||
|
/** @see GlShaderProgram#setUniform(int, Color) */
|
||||||
|
public void trySetUniform(int location, Color value) { if (location != -1) { this.setUniform(location, value); } }
|
||||||
|
|
||||||
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+114
@@ -0,0 +1,114 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.texture;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.lwjgl.opengl.GL30C;
|
||||||
|
import org.lwjgl.opengl.GL43C;
|
||||||
|
|
||||||
|
public enum EGlDhDepthBufferFormat
|
||||||
|
{
|
||||||
|
DEPTH(false),
|
||||||
|
DEPTH16(false),
|
||||||
|
DEPTH24(false),
|
||||||
|
DEPTH32(false),
|
||||||
|
DEPTH32F(false),
|
||||||
|
DEPTH_STENCIL(true),
|
||||||
|
DEPTH24_STENCIL8(true),
|
||||||
|
DEPTH32F_STENCIL8(true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private final boolean combinedStencil;
|
||||||
|
|
||||||
|
EGlDhDepthBufferFormat(boolean combinedStencil) { this.combinedStencil = combinedStencil; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static EGlDhDepthBufferFormat fromGlEnum(int glenum)
|
||||||
|
{
|
||||||
|
switch (glenum)
|
||||||
|
{
|
||||||
|
case GL30C.GL_DEPTH_COMPONENT:
|
||||||
|
return EGlDhDepthBufferFormat.DEPTH;
|
||||||
|
case GL30C.GL_DEPTH_COMPONENT16:
|
||||||
|
return EGlDhDepthBufferFormat.DEPTH16;
|
||||||
|
case GL30C.GL_DEPTH_COMPONENT24:
|
||||||
|
return EGlDhDepthBufferFormat.DEPTH24;
|
||||||
|
case GL30C.GL_DEPTH_COMPONENT32:
|
||||||
|
return EGlDhDepthBufferFormat.DEPTH32;
|
||||||
|
case GL30C.GL_DEPTH_COMPONENT32F:
|
||||||
|
return EGlDhDepthBufferFormat.DEPTH32F;
|
||||||
|
case GL30C.GL_DEPTH_STENCIL:
|
||||||
|
return EGlDhDepthBufferFormat.DEPTH_STENCIL;
|
||||||
|
case GL30C.GL_DEPTH24_STENCIL8:
|
||||||
|
return EGlDhDepthBufferFormat.DEPTH24_STENCIL8;
|
||||||
|
case GL30C.GL_DEPTH32F_STENCIL8:
|
||||||
|
return EGlDhDepthBufferFormat.DEPTH32F_STENCIL8;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EGlDhDepthBufferFormat fromGlEnumOrDefault(int glenum)
|
||||||
|
{
|
||||||
|
EGlDhDepthBufferFormat format = fromGlEnum(glenum);
|
||||||
|
if (format == null)
|
||||||
|
{
|
||||||
|
// yolo, just assume it's GL_DEPTH_COMPONENT
|
||||||
|
return EGlDhDepthBufferFormat.DEPTH;
|
||||||
|
}
|
||||||
|
return format;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlInternalFormat()
|
||||||
|
{
|
||||||
|
switch (this)
|
||||||
|
{
|
||||||
|
case DEPTH:
|
||||||
|
return GL30C.GL_DEPTH_COMPONENT;
|
||||||
|
case DEPTH16:
|
||||||
|
return GL30C.GL_DEPTH_COMPONENT16;
|
||||||
|
case DEPTH24:
|
||||||
|
return GL30C.GL_DEPTH_COMPONENT24;
|
||||||
|
case DEPTH32:
|
||||||
|
return GL30C.GL_DEPTH_COMPONENT32;
|
||||||
|
case DEPTH32F:
|
||||||
|
return GL30C.GL_DEPTH_COMPONENT32F;
|
||||||
|
case DEPTH_STENCIL:
|
||||||
|
return GL30C.GL_DEPTH_STENCIL;
|
||||||
|
case DEPTH24_STENCIL8:
|
||||||
|
return GL30C.GL_DEPTH24_STENCIL8;
|
||||||
|
case DEPTH32F_STENCIL8:
|
||||||
|
return GL30C.GL_DEPTH32F_STENCIL8;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AssertionError("unreachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlType() { return isCombinedStencil() ? GL30C.GL_DEPTH_STENCIL : GL30C.GL_DEPTH_COMPONENT; }
|
||||||
|
|
||||||
|
public int getGlFormat()
|
||||||
|
{
|
||||||
|
switch (this)
|
||||||
|
{
|
||||||
|
case DEPTH:
|
||||||
|
case DEPTH16:
|
||||||
|
return GL43C.GL_UNSIGNED_SHORT;
|
||||||
|
case DEPTH24:
|
||||||
|
case DEPTH32:
|
||||||
|
return GL43C.GL_UNSIGNED_INT;
|
||||||
|
case DEPTH32F:
|
||||||
|
return GL30C.GL_FLOAT;
|
||||||
|
case DEPTH_STENCIL:
|
||||||
|
case DEPTH24_STENCIL8:
|
||||||
|
return GL30C.GL_UNSIGNED_INT_24_8;
|
||||||
|
case DEPTH32F_STENCIL8:
|
||||||
|
return GL30C.GL_FLOAT_32_UNSIGNED_INT_24_8_REV;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new AssertionError("unreachable");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCombinedStencil() { return combinedStencil; }
|
||||||
|
|
||||||
|
}
|
||||||
+131
@@ -0,0 +1,131 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.texture;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.enums.EGlVersion;
|
||||||
|
import org.lwjgl.opengl.GL11C;
|
||||||
|
import org.lwjgl.opengl.GL30C;
|
||||||
|
import org.lwjgl.opengl.GL31C;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public enum EGlDhInternalTextureFormat
|
||||||
|
{
|
||||||
|
RGBA(GL11C.GL_RGBA, EGlVersion.GL_11, EGlDhPixelFormat.RGBA),
|
||||||
|
|
||||||
|
// 8-bit normalized
|
||||||
|
R8(GL30C.GL_R8, EGlVersion.GL_30, EGlDhPixelFormat.RED),
|
||||||
|
RG8(GL30C.GL_RG8, EGlVersion.GL_30, EGlDhPixelFormat.RG),
|
||||||
|
RGB8(GL11C.GL_RGB8, EGlVersion.GL_11, EGlDhPixelFormat.RGB),
|
||||||
|
RGBA8(GL11C.GL_RGBA8, EGlVersion.GL_11, EGlDhPixelFormat.RGBA),
|
||||||
|
|
||||||
|
// 8-bit signed normalized
|
||||||
|
R8_SNORM(GL31C.GL_R8_SNORM, EGlVersion.GL_31, EGlDhPixelFormat.RED),
|
||||||
|
RG8_SNORM(GL31C.GL_RG8_SNORM, EGlVersion.GL_31, EGlDhPixelFormat.RG),
|
||||||
|
RGB8_SNORM(GL31C.GL_RGB8_SNORM, EGlVersion.GL_31, EGlDhPixelFormat.RGB),
|
||||||
|
RGBA8_SNORM(GL31C.GL_RGBA8_SNORM, EGlVersion.GL_31, EGlDhPixelFormat.RGBA),
|
||||||
|
|
||||||
|
// 16-bit normalized
|
||||||
|
R16(GL30C.GL_R16, EGlVersion.GL_30, EGlDhPixelFormat.RED),
|
||||||
|
RG16(GL30C.GL_RG16, EGlVersion.GL_30, EGlDhPixelFormat.RG),
|
||||||
|
RGB16(GL11C.GL_RGB16, EGlVersion.GL_11, EGlDhPixelFormat.RGB),
|
||||||
|
RGBA16(GL11C.GL_RGBA16, EGlVersion.GL_11, EGlDhPixelFormat.RGBA),
|
||||||
|
|
||||||
|
// 16-bit signed normalized
|
||||||
|
R16_SNORM(GL31C.GL_R16_SNORM, EGlVersion.GL_31, EGlDhPixelFormat.RED),
|
||||||
|
RG16_SNORM(GL31C.GL_RG16_SNORM, EGlVersion.GL_31, EGlDhPixelFormat.RG),
|
||||||
|
RGB16_SNORM(GL31C.GL_RGB16_SNORM, EGlVersion.GL_31, EGlDhPixelFormat.RGB),
|
||||||
|
RGBA16_SNORM(GL31C.GL_RGBA16_SNORM, EGlVersion.GL_31, EGlDhPixelFormat.RGBA),
|
||||||
|
|
||||||
|
// 16-bit float
|
||||||
|
R16F(GL30C.GL_R16F, EGlVersion.GL_30, EGlDhPixelFormat.RED),
|
||||||
|
RG16F(GL30C.GL_RG16F, EGlVersion.GL_30, EGlDhPixelFormat.RG),
|
||||||
|
RGB16F(GL30C.GL_RGB16F, EGlVersion.GL_30, EGlDhPixelFormat.RGB),
|
||||||
|
RGBA16F(GL30C.GL_RGBA16F, EGlVersion.GL_30, EGlDhPixelFormat.RGBA),
|
||||||
|
|
||||||
|
// 32-bit float
|
||||||
|
R32F(GL30C.GL_R32F, EGlVersion.GL_30, EGlDhPixelFormat.RED),
|
||||||
|
RG32F(GL30C.GL_RG32F, EGlVersion.GL_30, EGlDhPixelFormat.RG),
|
||||||
|
RGB32F(GL30C.GL_RGB32F, EGlVersion.GL_30, EGlDhPixelFormat.RGB),
|
||||||
|
RGBA32F(GL30C.GL_RGBA32F, EGlVersion.GL_30, EGlDhPixelFormat.RGBA),
|
||||||
|
|
||||||
|
// 8-bit integer
|
||||||
|
R8I(GL30C.GL_R8I, EGlVersion.GL_30, EGlDhPixelFormat.RED_INTEGER),
|
||||||
|
RG8I(GL30C.GL_RG8I, EGlVersion.GL_30, EGlDhPixelFormat.RG_INTEGER),
|
||||||
|
RGB8I(GL30C.GL_RGB8I, EGlVersion.GL_30, EGlDhPixelFormat.RGB_INTEGER),
|
||||||
|
RGBA8I(GL30C.GL_RGBA8I, EGlVersion.GL_30, EGlDhPixelFormat.RGBA_INTEGER),
|
||||||
|
|
||||||
|
// 8-bit unsigned integer
|
||||||
|
R8UI(GL30C.GL_R8UI, EGlVersion.GL_30, EGlDhPixelFormat.RED_INTEGER),
|
||||||
|
RG8UI(GL30C.GL_RG8UI, EGlVersion.GL_30, EGlDhPixelFormat.RG_INTEGER),
|
||||||
|
RGB8UI(GL30C.GL_RGB8UI, EGlVersion.GL_30, EGlDhPixelFormat.RGB_INTEGER),
|
||||||
|
RGBA8UI(GL30C.GL_RGBA8UI, EGlVersion.GL_30, EGlDhPixelFormat.RGBA_INTEGER),
|
||||||
|
|
||||||
|
// 16-bit integer
|
||||||
|
R16I(GL30C.GL_R16I, EGlVersion.GL_30, EGlDhPixelFormat.RED_INTEGER),
|
||||||
|
RG16I(GL30C.GL_RG16I, EGlVersion.GL_30, EGlDhPixelFormat.RG_INTEGER),
|
||||||
|
RGB16I(GL30C.GL_RGB16I, EGlVersion.GL_30, EGlDhPixelFormat.RGB_INTEGER),
|
||||||
|
RGBA16I(GL30C.GL_RGBA16I, EGlVersion.GL_30, EGlDhPixelFormat.RGBA_INTEGER),
|
||||||
|
|
||||||
|
// 16-bit unsigned integer
|
||||||
|
R16UI(GL30C.GL_R16UI, EGlVersion.GL_30, EGlDhPixelFormat.RED_INTEGER),
|
||||||
|
RG16UI(GL30C.GL_RG16UI, EGlVersion.GL_30, EGlDhPixelFormat.RG_INTEGER),
|
||||||
|
RGB16UI(GL30C.GL_RGB16UI, EGlVersion.GL_30, EGlDhPixelFormat.RGB_INTEGER),
|
||||||
|
RGBA16UI(GL30C.GL_RGBA16UI, EGlVersion.GL_30, EGlDhPixelFormat.RGBA_INTEGER),
|
||||||
|
|
||||||
|
// 32-bit integer
|
||||||
|
R32I(GL30C.GL_R32I, EGlVersion.GL_30, EGlDhPixelFormat.RED_INTEGER),
|
||||||
|
RG32I(GL30C.GL_RG32I, EGlVersion.GL_30, EGlDhPixelFormat.RG_INTEGER),
|
||||||
|
RGB32I(GL30C.GL_RGB32I, EGlVersion.GL_30, EGlDhPixelFormat.RGB_INTEGER),
|
||||||
|
RGBA32I(GL30C.GL_RGBA32I, EGlVersion.GL_30, EGlDhPixelFormat.RGBA_INTEGER),
|
||||||
|
|
||||||
|
// 32-bit unsigned integer
|
||||||
|
R32UI(GL30C.GL_R32UI, EGlVersion.GL_30, EGlDhPixelFormat.RED_INTEGER),
|
||||||
|
RG32UI(GL30C.GL_RG32UI, EGlVersion.GL_30, EGlDhPixelFormat.RG_INTEGER),
|
||||||
|
RGB32UI(GL30C.GL_RGB32UI, EGlVersion.GL_30, EGlDhPixelFormat.RGB_INTEGER),
|
||||||
|
RGBA32UI(GL30C.GL_RGBA32UI, EGlVersion.GL_30, EGlDhPixelFormat.RGBA_INTEGER),
|
||||||
|
|
||||||
|
// Mixed
|
||||||
|
R3_G3_B2(GL11C.GL_R3_G3_B2, EGlVersion.GL_11, EGlDhPixelFormat.RGB),
|
||||||
|
RGB5_A1(GL11C.GL_RGB5_A1, EGlVersion.GL_11, EGlDhPixelFormat.RGBA),
|
||||||
|
RGB10_A2(GL11C.GL_RGB10_A2, EGlVersion.GL_11, EGlDhPixelFormat.RGBA),
|
||||||
|
R11F_G11F_B10F(GL30C.GL_R11F_G11F_B10F, EGlVersion.GL_30, EGlDhPixelFormat.RGB),
|
||||||
|
RGB9_E5(GL30C.GL_RGB9_E5, EGlVersion.GL_30, EGlDhPixelFormat.RGB);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private final int glFormat;
|
||||||
|
private final EGlVersion minimumGlVersion;
|
||||||
|
private final EGlDhPixelFormat expectedPixelFormat;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EGlDhInternalTextureFormat(int glFormat, EGlVersion minimumGlVersion, EGlDhPixelFormat expectedPixelFormat)
|
||||||
|
{
|
||||||
|
this.glFormat = glFormat;
|
||||||
|
this.minimumGlVersion = minimumGlVersion;
|
||||||
|
this.expectedPixelFormat = expectedPixelFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Optional<EGlDhInternalTextureFormat> fromString(String name)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Optional.of(EGlDhInternalTextureFormat.valueOf(name.toUpperCase(Locale.US)));
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlFormat() { return this.glFormat; }
|
||||||
|
|
||||||
|
public EGlDhPixelFormat getPixelFormat() { return this.expectedPixelFormat; }
|
||||||
|
|
||||||
|
public EGlVersion getMinimumGlVersion() { return this.minimumGlVersion; }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+61
@@ -0,0 +1,61 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.texture;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.enums.EGlVersion;
|
||||||
|
import org.lwjgl.opengl.GL11C;
|
||||||
|
import org.lwjgl.opengl.GL12C;
|
||||||
|
import org.lwjgl.opengl.GL30C;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public enum EGlDhPixelFormat
|
||||||
|
{
|
||||||
|
RED(GL11C.GL_RED, EGlVersion.GL_11, false),
|
||||||
|
RG(GL30C.GL_RG, EGlVersion.GL_30, false),
|
||||||
|
RGB(GL11C.GL_RGB, EGlVersion.GL_11, false),
|
||||||
|
BGR(GL12C.GL_BGR, EGlVersion.GL_12, false),
|
||||||
|
RGBA(GL11C.GL_RGBA, EGlVersion.GL_11, false),
|
||||||
|
BGRA(GL12C.GL_BGRA, EGlVersion.GL_12, false),
|
||||||
|
RED_INTEGER(GL30C.GL_RED_INTEGER, EGlVersion.GL_30, true),
|
||||||
|
RG_INTEGER(GL30C.GL_RG_INTEGER, EGlVersion.GL_30, true),
|
||||||
|
RGB_INTEGER(GL30C.GL_RGB_INTEGER, EGlVersion.GL_30, true),
|
||||||
|
BGR_INTEGER(GL30C.GL_BGR_INTEGER, EGlVersion.GL_30, true),
|
||||||
|
RGBA_INTEGER(GL30C.GL_RGBA_INTEGER, EGlVersion.GL_30, true),
|
||||||
|
BGRA_INTEGER(GL30C.GL_BGRA_INTEGER, EGlVersion.GL_30, true);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private final int glFormat;
|
||||||
|
private final EGlVersion minimumGlVersion;
|
||||||
|
private final boolean isInteger;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EGlDhPixelFormat(int glFormat, EGlVersion minimumGlVersion, boolean isInteger)
|
||||||
|
{
|
||||||
|
this.glFormat = glFormat;
|
||||||
|
this.minimumGlVersion = minimumGlVersion;
|
||||||
|
this.isInteger = isInteger;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Optional<EGlDhPixelFormat> fromString(String name)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Optional.of(EGlDhPixelFormat.valueOf(name.toUpperCase(Locale.US)));
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlFormat() { return this.glFormat; }
|
||||||
|
|
||||||
|
public EGlVersion getMinimumGlVersion() { return this.minimumGlVersion; }
|
||||||
|
|
||||||
|
public boolean isInteger() { return this.isInteger; }
|
||||||
|
|
||||||
|
}
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.texture;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.render.openGl.glObject.enums.EGlVersion;
|
||||||
|
import org.lwjgl.opengl.GL11C;
|
||||||
|
import org.lwjgl.opengl.GL12C;
|
||||||
|
import org.lwjgl.opengl.GL30C;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public enum EGlDhPixelType
|
||||||
|
{
|
||||||
|
BYTE(GL11C.GL_BYTE, EGlVersion.GL_11),
|
||||||
|
SHORT(GL11C.GL_SHORT, EGlVersion.GL_11),
|
||||||
|
INT(GL11C.GL_INT, EGlVersion.GL_11),
|
||||||
|
HALF_FLOAT(GL30C.GL_HALF_FLOAT, EGlVersion.GL_30),
|
||||||
|
FLOAT(GL11C.GL_FLOAT, EGlVersion.GL_11),
|
||||||
|
UNSIGNED_BYTE(GL11C.GL_UNSIGNED_BYTE, EGlVersion.GL_11),
|
||||||
|
UNSIGNED_BYTE_3_3_2(GL12C.GL_UNSIGNED_BYTE_3_3_2, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_BYTE_2_3_3_REV(GL12C.GL_UNSIGNED_BYTE_2_3_3_REV, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_SHORT(GL11C.GL_UNSIGNED_SHORT, EGlVersion.GL_11),
|
||||||
|
UNSIGNED_SHORT_5_6_5(GL12C.GL_UNSIGNED_SHORT_5_6_5, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_SHORT_5_6_5_REV(GL12C.GL_UNSIGNED_SHORT_5_6_5_REV, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_SHORT_4_4_4_4(GL12C.GL_UNSIGNED_SHORT_4_4_4_4, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_SHORT_4_4_4_4_REV(GL12C.GL_UNSIGNED_SHORT_4_4_4_4_REV, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_SHORT_5_5_5_1(GL12C.GL_UNSIGNED_SHORT_5_5_5_1, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_SHORT_1_5_5_5_REV(GL12C.GL_UNSIGNED_SHORT_1_5_5_5_REV, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_INT(GL11C.GL_UNSIGNED_INT, EGlVersion.GL_11),
|
||||||
|
UNSIGNED_INT_8_8_8_8(GL12C.GL_UNSIGNED_INT_8_8_8_8, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_INT_8_8_8_8_REV(GL12C.GL_UNSIGNED_INT_8_8_8_8_REV, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_INT_10_10_10_2(GL12C.GL_UNSIGNED_INT_10_10_10_2, EGlVersion.GL_12),
|
||||||
|
UNSIGNED_INT_2_10_10_10_REV(GL12C.GL_UNSIGNED_INT_2_10_10_10_REV, EGlVersion.GL_12);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private final int glFormat;
|
||||||
|
private final EGlVersion minimumGlVersion;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
EGlDhPixelType(int glFormat, EGlVersion minimumGlVersion)
|
||||||
|
{
|
||||||
|
this.glFormat = glFormat;
|
||||||
|
this.minimumGlVersion = minimumGlVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static Optional<EGlDhPixelType> fromString(String name)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return Optional.of(EGlDhPixelType.valueOf(name.toUpperCase(Locale.US)));
|
||||||
|
}
|
||||||
|
catch (IllegalArgumentException e)
|
||||||
|
{
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getGlFormat() { return glFormat; }
|
||||||
|
|
||||||
|
public EGlVersion getMinimumGlVersion() { return minimumGlVersion; }
|
||||||
|
|
||||||
|
}
|
||||||
+183
@@ -0,0 +1,183 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.texture;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
|
import org.joml.Vector2i;
|
||||||
|
import org.lwjgl.opengl.GL11C;
|
||||||
|
import org.lwjgl.opengl.GL13C;
|
||||||
|
import org.lwjgl.opengl.GL43C;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class GlDhColorTexture
|
||||||
|
{
|
||||||
|
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
private final EGlDhInternalTextureFormat internalFormat;
|
||||||
|
private final EGlDhPixelFormat format;
|
||||||
|
private final EGlDhPixelType type;
|
||||||
|
private int width;
|
||||||
|
private int height;
|
||||||
|
|
||||||
|
private boolean isValid;
|
||||||
|
/** AKA, the OpenGL name of this texture */
|
||||||
|
private final int id;
|
||||||
|
|
||||||
|
private static final ByteBuffer NULL_BUFFER = null;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// constructor //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
public GlDhColorTexture(Builder builder)
|
||||||
|
{
|
||||||
|
this.isValid = true;
|
||||||
|
|
||||||
|
this.internalFormat = builder.internalFormat;
|
||||||
|
this.format = builder.format;
|
||||||
|
this.type = builder.type;
|
||||||
|
|
||||||
|
this.width = builder.width;
|
||||||
|
this.height = builder.height;
|
||||||
|
|
||||||
|
this.id = GL43C.glGenTextures();
|
||||||
|
|
||||||
|
boolean isPixelFormatInteger = builder.internalFormat.getPixelFormat().isInteger();
|
||||||
|
this.setupTexture(this.id, builder.width, builder.height, !isPixelFormatInteger); // this binds the texture
|
||||||
|
|
||||||
|
// Clean up after ourselves
|
||||||
|
// This is strictly defensive to ensure that other buggy code doesn't tamper with our textures
|
||||||
|
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=========//
|
||||||
|
// methods //
|
||||||
|
//=========//
|
||||||
|
|
||||||
|
private void setupTexture(int id, int width, int height, boolean allowsLinear)
|
||||||
|
{
|
||||||
|
this.resizeTexture(id, width, height);
|
||||||
|
|
||||||
|
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MIN_FILTER, allowsLinear ? GL11C.GL_LINEAR : GL11C.GL_NEAREST);
|
||||||
|
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MAG_FILTER, allowsLinear ? GL11C.GL_LINEAR : GL11C.GL_NEAREST);
|
||||||
|
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE);
|
||||||
|
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
// disable mip-mapping since DH is just going to draw straight to the screen
|
||||||
|
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resizeTexture(int texture, int width, int height)
|
||||||
|
{
|
||||||
|
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, texture);
|
||||||
|
GL43C.glTexImage2D(GL11C.GL_TEXTURE_2D, 0, this.internalFormat.getGlFormat(), width, height, 0, this.format.getGlFormat(), this.type.getGlFormat(), NULL_BUFFER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void resize(Vector2i textureScaleOverride) { this.resize(textureScaleOverride.x, textureScaleOverride.y); }
|
||||||
|
|
||||||
|
// Package private, call CompositeRenderTargets#resizeIfNeeded instead.
|
||||||
|
public void resize(int width, int height)
|
||||||
|
{
|
||||||
|
this.throwIfInvalid();
|
||||||
|
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
|
||||||
|
this.resizeTexture(this.id, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EGlDhInternalTextureFormat getInternalFormat() { return this.internalFormat; }
|
||||||
|
|
||||||
|
public int getTextureId()
|
||||||
|
{
|
||||||
|
this.throwIfInvalid();
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getWidth() { return this.width; }
|
||||||
|
|
||||||
|
public int getHeight() { return this.height; }
|
||||||
|
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
this.throwIfInvalid();
|
||||||
|
this.isValid = false;
|
||||||
|
|
||||||
|
GLMC.glDeleteTextures(this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @throws IllegalStateException if the texture isn't valid */
|
||||||
|
private void throwIfInvalid()
|
||||||
|
{
|
||||||
|
if (!this.isValid)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Attempted to use a deleted composite render target");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder builder() { return new Builder(); }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// helper classes //
|
||||||
|
//================//
|
||||||
|
|
||||||
|
public static class Builder
|
||||||
|
{
|
||||||
|
private EGlDhInternalTextureFormat internalFormat = EGlDhInternalTextureFormat.RGBA8;
|
||||||
|
private int width = 0;
|
||||||
|
private int height = 0;
|
||||||
|
private EGlDhPixelFormat format = EGlDhPixelFormat.RGBA;
|
||||||
|
private EGlDhPixelType type = EGlDhPixelType.UNSIGNED_BYTE;
|
||||||
|
|
||||||
|
private Builder()
|
||||||
|
{
|
||||||
|
// No-op
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setInternalFormat(EGlDhInternalTextureFormat format)
|
||||||
|
{
|
||||||
|
this.internalFormat = format;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setDimensions(int width, int height)
|
||||||
|
{
|
||||||
|
if (width <= 0)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Width must be greater than zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height <= 0)
|
||||||
|
{
|
||||||
|
throw new IllegalArgumentException("Height must be greater than zero");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.width = width;
|
||||||
|
this.height = height;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setPixelFormat(EGlDhPixelFormat pixelFormat)
|
||||||
|
{
|
||||||
|
this.format = pixelFormat;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder setPixelType(EGlDhPixelType pixelType)
|
||||||
|
{
|
||||||
|
this.type = pixelType;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GlDhColorTexture build() { return new GlDhColorTexture(this); }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
+62
@@ -0,0 +1,62 @@
|
|||||||
|
package com.seibel.distanthorizons.common.render.openGl.glObject.texture;
|
||||||
|
|
||||||
|
import com.seibel.distanthorizons.common.wrappers.minecraft.MinecraftGLWrapper;
|
||||||
|
import org.lwjgl.opengl.GL11C;
|
||||||
|
import org.lwjgl.opengl.GL13C;
|
||||||
|
import org.lwjgl.opengl.GL43C;
|
||||||
|
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
|
||||||
|
public class GlDhDepthTexture
|
||||||
|
{
|
||||||
|
private static final MinecraftGLWrapper GLMC = MinecraftGLWrapper.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
private int id;
|
||||||
|
public GlDhDepthTexture(int width, int height, EGlDhDepthBufferFormat format)
|
||||||
|
{
|
||||||
|
this.id = GL43C.glGenTextures();
|
||||||
|
|
||||||
|
this.resize(width, height, format);
|
||||||
|
|
||||||
|
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MIN_FILTER, GL11C.GL_NEAREST);
|
||||||
|
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_MAG_FILTER, GL11C.GL_NEAREST);
|
||||||
|
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_S, GL13C.GL_CLAMP_TO_EDGE);
|
||||||
|
GL43C.glTexParameteri(GL11C.GL_TEXTURE_2D, GL11C.GL_TEXTURE_WRAP_T, GL13C.GL_CLAMP_TO_EDGE);
|
||||||
|
|
||||||
|
// disable mip-mapping since DH is just going to draw straight to the screen
|
||||||
|
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_BASE_LEVEL, 0);
|
||||||
|
GL43C.glTexParameteri(GL43C.GL_TEXTURE_2D, GL43C.GL_TEXTURE_MAX_LEVEL, 0);
|
||||||
|
|
||||||
|
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For internal use by Iris for copying data. Do not use this in DH.
|
||||||
|
public GlDhDepthTexture(int id) { this.id = id; }
|
||||||
|
|
||||||
|
public void resize(int width, int height, EGlDhDepthBufferFormat format)
|
||||||
|
{
|
||||||
|
GL43C.glBindTexture(GL43C.GL_TEXTURE_2D, this.getTextureId());
|
||||||
|
GL43C.glTexImage2D(GL11C.GL_TEXTURE_2D, 0, format.getGlInternalFormat(), width, height, 0,
|
||||||
|
format.getGlType(), format.getGlFormat(), (ByteBuffer) null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTextureId()
|
||||||
|
{
|
||||||
|
if (this.id == -1)
|
||||||
|
{
|
||||||
|
throw new IllegalStateException("Depth texture does not exist!");
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void destroy()
|
||||||
|
{
|
||||||
|
GLMC.glDeleteTextures(this.getTextureId());
|
||||||
|
this.id = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user