Compare commits
1103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a7897e45f3 | |||
| 751ce4afef | |||
| 0b2373e830 | |||
| ddf9700804 | |||
| e93c53b1ec | |||
| 2852bd91f9 | |||
| d5740c5d7f | |||
| 816249acdb | |||
| 23d9cf10d3 | |||
| eeea070fd1 | |||
| e47cdaa2e4 | |||
| db074a6a5b | |||
| f2f0e291d8 | |||
| db123072bd | |||
| 6bbb99ff39 | |||
| 88c5fc8fde | |||
| a40417bbd6 | |||
| cf7373a303 | |||
| 49c0581b1d | |||
| 72d3b50077 | |||
| aaedc8e384 | |||
| b63f24c92e | |||
| 76154aada0 | |||
| 6b029da899 | |||
| 818c4243e0 | |||
| a41a4fe77f | |||
| 9a03a45cd7 | |||
| e2eaca7869 | |||
| 0bfef6b3d3 | |||
| 03345924f3 | |||
| 37f72980ee | |||
| 7fd43deaca | |||
| 05a3d4002f | |||
| 8a574074c5 | |||
| f801567301 | |||
| 632947c8ce | |||
| 5cb32d6181 | |||
| 505f48cebc | |||
| e2bdfcc2da | |||
| cd72edf9a6 | |||
| 5172fec97f | |||
| b1a39ce74b | |||
| 563fea608e | |||
| be6e52ded0 | |||
| 6d54edd74c | |||
| 492c634cc4 | |||
| d92cb6016f | |||
| 0250eba715 | |||
| cbf1bf698d | |||
| 2aed897b9b | |||
| 7402ad6be0 | |||
| d4556e7f84 | |||
| 7b910ba4fd | |||
| 5762c41f1a | |||
| dee9fa793d | |||
| 1962053a2f | |||
| bb16cfa4fe | |||
| 73ddbd66b5 | |||
| 8e727011de | |||
| 717e189107 | |||
| cff8326810 | |||
| fd0604c7e7 | |||
| f822aed285 | |||
| 26535ef81c | |||
| 2b0c0f89a2 | |||
| 51e7e318ac | |||
| e5ef7e7026 | |||
| 62794766c6 | |||
| e32addfd06 | |||
| 42678a27a4 | |||
| 1488747075 | |||
| a03ddf7339 | |||
| c537e0cf49 | |||
| 853c706b77 | |||
| 65c091bb63 | |||
| 9b389332be | |||
| 1093001841 | |||
| a3db8e50f5 | |||
| db15e8684c | |||
| 00ac368bba | |||
| f2face9782 | |||
| 923d57b377 | |||
| 447325e5a1 | |||
| bf712e893e | |||
| 27f9a527bc | |||
| bde14012d9 | |||
| 12a32b9fb4 | |||
| 4ad081e0c6 | |||
| 936a3a7ece | |||
| 98f36936d0 | |||
| f6f012c42c | |||
| a3e6c09268 | |||
| 10cb46c9f9 | |||
| 95aa9cb9ab | |||
| 638a0ddae1 | |||
| d321833335 | |||
| b8cba0dc4c | |||
| bd8ccb4a05 | |||
| 895895da04 | |||
| 09d5df2856 | |||
| 668f225528 | |||
| 1cd71a6b50 | |||
| f041f79ae3 | |||
| ef3ac96b2c | |||
| 59f527e6de | |||
| 16a082b17f | |||
| a24d28b0e2 | |||
| 910f11f688 | |||
| e00de99e31 | |||
| f80af39e0e | |||
| 5bba3cb3eb | |||
| d4261d4ccf | |||
| 8b854e3abd | |||
| 4064155567 | |||
| 6243201f2d | |||
| c5a2944d68 | |||
| 1405b7a433 | |||
| be00670b7e | |||
| 6f2c02d283 | |||
| 309526e7b9 | |||
| d5466e0fda | |||
| 7a0b95a105 | |||
| 7c59e33aee | |||
| 9907d2ddd5 | |||
| 1a838d4bd8 | |||
| dce3227bf1 | |||
| ea6f3e9881 | |||
| 2f57b67bdc | |||
| be024f524d | |||
| e0a176c0c4 | |||
| b00795a0ab | |||
| 8bfa8e70a1 | |||
| 2a0653419f | |||
| cc1b9ea28e | |||
| b32bdb3807 | |||
| 42bac2bd57 | |||
| 9bd89accd3 | |||
| 5493ef9033 | |||
| 7d1df26cc5 | |||
| 63f6d4cc56 | |||
| 6066a572d9 | |||
| ea679992e8 | |||
| fedce10917 | |||
| 80448ce990 | |||
| 89fac88b7e | |||
| 032b63208c | |||
| 9faed3a2c8 | |||
| 05800089cb | |||
| 8585511007 | |||
| 890de58c72 | |||
| 8def361f63 | |||
| 58d5a8beda | |||
| 443bb64df0 | |||
| 400e00f572 | |||
| 5c36a3df16 | |||
| 8578a833b4 | |||
| 974a9b4452 | |||
| d35fbb0bb3 | |||
| 0551fbb2d4 | |||
| fe8a847637 | |||
| b04eec91bc | |||
| 6eddef2fb0 | |||
| 10382342d8 | |||
| 9d80b81378 | |||
| 12abc4f018 | |||
| 21e774489c | |||
| f6f7f1043e | |||
| 30e9dd1aac | |||
| 219f3eba17 | |||
| d737500d95 | |||
| 2a402ef1d6 | |||
| 84c0fd994d | |||
| cf782c5b6f | |||
| 96c19620cb | |||
| d0f93a2c89 | |||
| 85157d0da0 | |||
| 33d150b090 | |||
| e6949dcd14 | |||
| b411f083e2 | |||
| d3cd714f48 | |||
| df0d1483c7 | |||
| 0e82afd6e1 | |||
| d80253546f | |||
| 441e4ff1f2 | |||
| cbdfabeaeb | |||
| bdf7fb3466 | |||
| 7595248406 | |||
| b5bcab36cd | |||
| 5ed1e6135b | |||
| 636d4129bd | |||
| a90dfb695d | |||
| 15c1a64cfd | |||
| c5f823c54e | |||
| a7c2e8a6ed | |||
| cb496208f5 | |||
| 4ff1815436 | |||
| 31ada4e5d2 | |||
| accf082309 | |||
| e1b1f26f37 | |||
| a0c14c86ca | |||
| a122015f6d | |||
| 164d407153 | |||
| 893bfa096f | |||
| 37995af19e | |||
| c637d23121 | |||
| d762508188 | |||
| f5437f00a2 | |||
| dec20962b2 | |||
| 30e796f5bf | |||
| 4ab4dc59e7 | |||
| 839a76c594 | |||
| 3fb4d16e41 | |||
| 002d86af9f | |||
| e1877f9149 | |||
| 4da1fcc118 | |||
| af123a8c80 | |||
| 94bc7fd011 | |||
| 905d8bddf3 | |||
| 5ee762cc78 | |||
| 7c07a88b45 | |||
| d8981af7aa | |||
| 9906eb75f4 | |||
| d94fedc61e | |||
| 3e3b979530 | |||
| 6ad94d3362 | |||
| 31f8cecc92 | |||
| b4106a8c3c | |||
| b6390c57ef | |||
| 5172c66b9b | |||
| 067fa92419 | |||
| 15e80ed063 | |||
| 2c6549e815 | |||
| 32423c07eb | |||
| 4a0640a219 | |||
| 5f9f20a064 | |||
| ef4ba7208e | |||
| 80edf19b33 | |||
| 4baa649972 | |||
| c7dbc28a9a | |||
| 707c55653a | |||
| 40cb7f4efc | |||
| df22a082a1 | |||
| 3a7f411aa4 | |||
| 11c419e503 | |||
| 30b82e8009 | |||
| 7df4a161dd | |||
| 56160db7ec | |||
| ac84c3707a | |||
| d16f571467 | |||
| d7bd0498a0 | |||
| 57a2b956dd | |||
| 51aadc8d39 | |||
| 70e2f7f3e6 | |||
| 0ef8615a98 | |||
| 4c6412d09f | |||
| 27b8cfea09 | |||
| b5ab06bfb6 | |||
| 732476b454 | |||
| 9d1a9eb9f3 | |||
| 6018449cbe | |||
| 8f43695a47 | |||
| 30913a0c29 | |||
| d8cee2b10c | |||
| 33a706f660 | |||
| 6c2b707c02 | |||
| ecb01c731e | |||
| 72737a56c1 | |||
| 1d1b5f6115 | |||
| b67ab59a89 | |||
| ca4597e3d9 | |||
| efd9a5a51b | |||
| 4c3d19a6c6 | |||
| 6c4faa9103 | |||
| 6066957584 | |||
| c3f8b0b677 | |||
| e2cdf1549a | |||
| fe9bc5e77e | |||
| ea0ef9e394 | |||
| 27d74958bf | |||
| dc8db97f33 | |||
| 3ec30d49be | |||
| 627327140e | |||
| 2ebbb6f591 | |||
| 126b581e97 | |||
| f625e714d4 | |||
| 5db7e349b9 | |||
| 272546af4d | |||
| c0a9e3061c | |||
| 5872dc3be5 | |||
| 8fe6eff36c | |||
| d89f2dc9b8 | |||
| e0ac03db6c | |||
| ee58f3d9dc | |||
| b02d58227c | |||
| 61cb27020c | |||
| 443da5eede | |||
| 78ab4b8598 | |||
| 028aed53f8 | |||
| 1ed36ba6c4 | |||
| 6deca8e235 | |||
| a6f3c2478e | |||
| a66554f2dd | |||
| 28cf2eb450 | |||
| e154f552c7 | |||
| 0c275e1495 | |||
| 2b15c089f4 | |||
| fca926bc8f | |||
| f6ea990ab0 | |||
| ee6c8d597c | |||
| 1e819bd555 | |||
| a0358dd298 | |||
| 90987fc389 | |||
| f72c846fe5 | |||
| 2ca8576ad7 | |||
| 0194cffaba | |||
| cc52815315 | |||
| 900b67920c | |||
| 9c1e5c33a5 | |||
| d7a1d330d9 | |||
| 3ac05c6a2b | |||
| eeff5437b5 | |||
| ee89d6f512 | |||
| a577851f6b | |||
| 536bff2fe7 | |||
| b1995445e2 | |||
| 5d4d483b16 | |||
| c13abc3b7d | |||
| 1cbb15045f | |||
| 48ea096ff1 | |||
| 2e08b61672 | |||
| b0bb01fde4 | |||
| cc666e917e | |||
| 9e0abd06fb | |||
| 0f56a98499 | |||
| 529c52b93f | |||
| 8020b298fb | |||
| 37db05d18f | |||
| 555e5a78b5 | |||
| 32d492f5f6 | |||
| d9ee9135d7 | |||
| d59f9dc4c6 | |||
| 8f329ac785 | |||
| 9865b23e5b | |||
| a987149aa3 | |||
| 22b7e46d39 | |||
| e5c1e67369 | |||
| 328792cf4e | |||
| 344901aad5 | |||
| 5f89bd8e7d | |||
| 7c5713fac2 | |||
| d222854717 | |||
| 6b9be10635 | |||
| 69a72312e4 | |||
| 948b58d8e9 | |||
| 86406fd12b | |||
| cc3e1d1b12 | |||
| 85a0110af6 | |||
| a76436b73d | |||
| 391c99fd21 | |||
| fb5aceb44d | |||
| 4c76a48e84 | |||
| d7a42d3a51 | |||
| e0a946673e | |||
| ad793fe17e | |||
| 209e2579c3 | |||
| 8627b87aa4 | |||
| 5f855dd573 | |||
| d6c918427b | |||
| a9bdbc4300 | |||
| 58a150f8de | |||
| 1a3e1dfa8c | |||
| 430a908829 | |||
| 0ca0cd9213 | |||
| 2f392375fe | |||
| ff43118976 | |||
| 3b4e28d74a | |||
| 13abed4eb8 | |||
| ccb2c601a6 | |||
| f6816d9974 | |||
| 5156ae8e63 | |||
| 55c0c95339 | |||
| 0b8503f1fa | |||
| 79d9ac5d56 | |||
| 6cf4e663fb | |||
| bf9c3ce567 | |||
| 5bbdd22b58 | |||
| 6c1c04bb5f | |||
| 66728cc1eb | |||
| d4739b9bed | |||
| a93bb63c44 | |||
| a2e18de9f3 | |||
| 6183152d99 | |||
| 5d9f36bb5f | |||
| d330083d7b | |||
| 6d489b498e | |||
| d36d836bb3 | |||
| 29d2d1cff1 | |||
| 0a9ea1dfce | |||
| b9424cbe9f | |||
| 593a014dfc | |||
| 83ac04dca4 | |||
| c9aed389ae | |||
| 00da0e0520 | |||
| 5124739348 | |||
| d65bfd408e | |||
| da413f594e | |||
| 1fcef4be96 | |||
| d7cddd9b39 | |||
| fb480c2695 | |||
| 265abb64b3 | |||
| 1cf4852788 | |||
| 90d0fbe45b | |||
| ea9eac89ec | |||
| 017cc201b1 | |||
| bda963036d | |||
| 46bdf5763f | |||
| 8228a3b7a6 | |||
| e3df6c99da | |||
| a4e9e22d2c | |||
| 435c5ee73a | |||
| c6b063a380 | |||
| 1f5c3f5bd8 | |||
| 688cb3f89a | |||
| af80ff5267 | |||
| 2bc5c43b19 | |||
| e7c4827d08 | |||
| 482dfb918e | |||
| 5aaf6e0185 | |||
| ab014af15d | |||
| 772de1b869 | |||
| cb42683774 | |||
| a00698ccab | |||
| 29ed26f023 | |||
| af3c4ab801 | |||
| 1156b7dd28 | |||
| 25fd29b97e | |||
| a11ff5b493 | |||
| 7655ae03b0 | |||
| 075e29c617 | |||
| e482bf02a5 | |||
| 0dab4a2274 | |||
| 001335ab47 | |||
| faedb85f41 | |||
| 01b9a3f3b0 | |||
| cfd9bd903d | |||
| 3e634c082a | |||
| 6e86a808a5 | |||
| e615674246 | |||
| 86b5fc48a2 | |||
| 2fab33fa78 | |||
| b56b581bb6 | |||
| 2ee5289881 | |||
| 3da4e4818c | |||
| 686062f39c | |||
| ae857dfeae | |||
| 686592effb | |||
| 34b92d1053 | |||
| 01a850eb9d | |||
| 7d6f7f35ff | |||
| 28764bc16c | |||
| ee1657a798 | |||
| c7bf60b4e0 | |||
| 031af5f25c | |||
| d8200422b2 | |||
| c89cd54429 | |||
| ca940d5a36 | |||
| 2241492bc5 | |||
| 7b807bcea2 | |||
| ebe2c22a28 | |||
| cffb17aeb1 | |||
| c67a5a5e29 | |||
| 1d687fd1d4 | |||
| 783d4086c6 | |||
| d5243b7d16 | |||
| 43f3854068 | |||
| 0025f43a2e | |||
| 07d792979c | |||
| a939d29357 | |||
| ba1d096a48 | |||
| 1c9c72cfe3 | |||
| aa95361866 | |||
| ff5139d403 | |||
| 16fc4914fb | |||
| c110524c11 | |||
| 400b263059 | |||
| dadda4bdc9 | |||
| 1888ac7adc | |||
| 5c59ba7a80 | |||
| f3dd99e792 | |||
| 103ec128ac | |||
| b4226ec9ec | |||
| 7c28dd70d3 | |||
| d8c9a41314 | |||
| 5a7f77479f | |||
| d200a5ac24 | |||
| 5099f85da6 | |||
| 6e150fe378 | |||
| fd67d1ac66 | |||
| 7161bd52de | |||
| 82cf25c341 | |||
| 68d279807f | |||
| 3530158def | |||
| 62223480e2 | |||
| 50ab424497 | |||
| 900467cef2 | |||
| fa1d950ff9 | |||
| 83571951be | |||
| c31b1f4039 | |||
| 8fcd428194 | |||
| 87c275f768 | |||
| 8df6e972cb | |||
| d7d88d61ee | |||
| 9b1c0a1125 | |||
| b008b70255 | |||
| b6c350f667 | |||
| e23bbfcd91 | |||
| 6bc14fbb2d | |||
| d911017112 | |||
| fc4546538f | |||
| a90b3e9d37 | |||
| b2aca27615 | |||
| 6bf9e187e0 | |||
| b5f32705e8 | |||
| 8bc72af63f | |||
| 0e4cf8e882 | |||
| 5ede5fa202 | |||
| cdeba2616c | |||
| 6dc94b0cc2 | |||
| 7f9c7d8722 | |||
| aebbeb6ade | |||
| a945eb4579 | |||
| f9cf27a2c7 | |||
| e03e09a243 | |||
| fe02813d17 | |||
| 145479267d | |||
| 77ccd9eec3 | |||
| 9b216fedad | |||
| e9798ace13 | |||
| 75e78d9000 | |||
| 34776074fd | |||
| 8822e2d8a1 | |||
| 32de70b4f0 | |||
| 76a7baeb32 | |||
| 95d9c17e49 | |||
| a6544d3bb6 | |||
| c3115caa8f | |||
| 4e1e5b24ee | |||
| 7b73445f4d | |||
| 5f1f5f0948 | |||
| bdcc4c7755 | |||
| 1395e32a50 | |||
| 99f7d70613 | |||
| 59bfd739f4 | |||
| 3f1cf6c305 | |||
| 5c05df0361 | |||
| feebc3564a | |||
| a9aa630aff | |||
| 6ec146ba60 | |||
| 21140593e2 | |||
| 878714dae3 | |||
| e876d7bec6 | |||
| 4f06395557 | |||
| aa3dbe8f32 | |||
| b1bcdb24f0 | |||
| cbd7f4300e | |||
| 4d8e30121e | |||
| fbe39542fc | |||
| 6a1f448b41 | |||
| e13b23832c | |||
| 4c9e0edf32 | |||
| 8664a06d3b | |||
| 18b8359f0d | |||
| 7de4c7c72a | |||
| b4bbabae42 | |||
| 40321d6e21 | |||
| cf1702bd0c | |||
| a9b50cdb32 | |||
| 7eed472029 | |||
| 0262e452c7 | |||
| 30287d5a7d | |||
| 83346fed1f | |||
| e897c3edba | |||
| bd9e2acaf6 | |||
| 1e15d372c4 | |||
| 849d563425 | |||
| aa5a8aa3b8 | |||
| b096cc53aa | |||
| 94d994e761 | |||
| f76fa17e25 | |||
| 53a66268cb | |||
| 139867d4b8 | |||
| 81cf05ba19 | |||
| 13a1e7ed56 | |||
| 42bd0fbde9 | |||
| ebe2bd97bc | |||
| a3ac3386d0 | |||
| 69ba83d34f | |||
| e048d277f8 | |||
| 0bca47a92b | |||
| ce84b30ddb | |||
| 1843f96526 | |||
| e46864431b | |||
| 152a3fa108 | |||
| 3420133bd3 | |||
| c79bf7c3f7 | |||
| 2219da4050 | |||
| a1aa90cccb | |||
| d19abaef7b | |||
| 77625c65c7 | |||
| 91ba48ad4a | |||
| 32e587d536 | |||
| e3dfe658f5 | |||
| 4e249e943a | |||
| 1360edb459 | |||
| 4c7ca395c6 | |||
| a1c720d588 | |||
| 7b09840d02 | |||
| e65579f346 | |||
| 78d6481a49 | |||
| 1428e72d46 | |||
| 2c2c6d6785 | |||
| d5d48f2448 | |||
| 536de1a22d | |||
| 193c579712 | |||
| cdba7b20f5 | |||
| 5467d007b8 | |||
| b24d691d8a | |||
| f68e6a9a13 | |||
| 2dcdc854e3 | |||
| 42da213ea9 | |||
| dfea2f561a | |||
| d8b4730ee0 | |||
| 74cbf794a1 | |||
| 812fa65054 | |||
| ba63b44288 | |||
| b19a80f411 | |||
| 450f15ad36 | |||
| a6ed4968f5 | |||
| 65dc629771 | |||
| 80aa49e28b | |||
| 2c3149ef30 | |||
| cd792d7045 | |||
| 3ade43651f | |||
| f4c3ad8bb5 | |||
| 13d2c7b421 | |||
| c54c2c6612 | |||
| 13878b7387 | |||
| 2f20fc6b77 | |||
| d4ada067c5 | |||
| 9277b3ad38 | |||
| c48d409015 | |||
| ccdebb4242 | |||
| 18c94cea46 | |||
| fe381fc207 | |||
| acc73af666 | |||
| 685284f131 | |||
| f803bd58af | |||
| 26fbdfc92c | |||
| e3e8ef705a | |||
| e1a425dbcc | |||
| d8bd4e2347 | |||
| 49cdd5702f | |||
| 32c19eab7f | |||
| a32b66aaab | |||
| 425f4948dc | |||
| d05908af32 | |||
| 822a088096 | |||
| 36079e1624 | |||
| 8db782a406 | |||
| dd018f90d3 | |||
| af4e30588f | |||
| 2630d50147 | |||
| db2410e7fe | |||
| 9990132db2 | |||
| 21069d6479 | |||
| b27afbb18c | |||
| 783c0c97a1 | |||
| 3dfa2d778a | |||
| b44a641d96 | |||
| 8139b83a01 | |||
| 456ba183da | |||
| 7525c1b257 | |||
| 5d4d634537 | |||
| e1149be7c1 | |||
| fc0aaac69f | |||
| 9786a12273 | |||
| c169cb6b7f | |||
| afcdce4667 | |||
| ab7ed9a4c5 | |||
| 120e8e5f6d | |||
| 65824a6fed | |||
| 114aaf9fe4 | |||
| 347b149037 | |||
| 70317a37cb | |||
| 74e4744ff7 | |||
| 98cbc30709 | |||
| b44900e3f0 | |||
| 1755a252b1 | |||
| afcedd0c6d | |||
| 525005bcb6 | |||
| 360294d37c | |||
| ea05e3f9e6 | |||
| 70a75f0543 | |||
| 488d520b8f | |||
| 30bb175ea0 | |||
| 500a68e0fc | |||
| 0cd9bfaef2 | |||
| a464176a25 | |||
| a0dcde48ae | |||
| 8ae81d3aac | |||
| c4f864f0e3 | |||
| cddd239fc5 | |||
| 189b0ec878 | |||
| bd305a0269 | |||
| bbf99ed145 | |||
| cac4807986 | |||
| 181539b83b | |||
| 4795ddd1ff | |||
| c1c6680d04 | |||
| 81cbc7a12b | |||
| 4c6185556f | |||
| b0ed460230 | |||
| 38e323a12f | |||
| 9840c594e6 | |||
| fdd8204a46 | |||
| fb188e4819 | |||
| 9b3d9cbba3 | |||
| a2aa1dd081 | |||
| cb889d7430 | |||
| 2a88b2e746 | |||
| 93dd441708 | |||
| a81ce6c28a | |||
| 967627c57e | |||
| 31cb684bec | |||
| d5112be385 | |||
| 547d54aab1 | |||
| 397573bc08 | |||
| b52d7e4f20 | |||
| a450f44aa7 | |||
| a4e8e9ef60 | |||
| 3c28ed5601 | |||
| c5ec41eb2d | |||
| d1bb96c2dc | |||
| d72ba5bb82 | |||
| baba54bdb8 | |||
| aa7ea85cde | |||
| a1f01bef78 | |||
| 1a7655e752 | |||
| e2a983e4ac | |||
| e2f0263643 | |||
| b280303f8f | |||
| ff3b2aee6b | |||
| 804f830a10 | |||
| 68b5978135 | |||
| 9ebb84bf9c | |||
| a08e08856a | |||
| 8d5c8bf7b8 | |||
| 168eb537cb | |||
| ca57c15d46 | |||
| 5aea9877e0 | |||
| c20ec4ef59 | |||
| 32fb349621 | |||
| c5b4e20787 | |||
| a246dd7561 | |||
| 615e29451a | |||
| bcac2bd7ba | |||
| a02c232f5f | |||
| d27dbbb64e | |||
| fdfbee108a | |||
| de54c37cf1 | |||
| d4580806d1 | |||
| 5a856c65fa | |||
| 75d6da98dc | |||
| 7654cac01d | |||
| cbe242cd2f | |||
| 7f69b11ae4 | |||
| 426c9edb05 | |||
| 88fb9b5b21 | |||
| 163f8ca979 | |||
| ee416a10ec | |||
| c5ef03aa0e | |||
| 25cb08f541 | |||
| fcd06bde87 | |||
| 00f50a2e60 | |||
| 550c0f1bf2 | |||
| 0f0179bd19 | |||
| 7885d14a91 | |||
| bd9c3bba3f | |||
| 04f8cd653a | |||
| 02bfc20ae6 | |||
| d65017366a | |||
| 05d17ba9fa | |||
| 967aab3b3b | |||
| 9f77bf4e61 | |||
| 6aa096de57 | |||
| d312d60cd9 | |||
| 65fde550cb | |||
| 736b5ba625 | |||
| b2227688bc | |||
| cbe8b647b1 | |||
| 0b0f0eab2f | |||
| ffb63ce8ef | |||
| 0e6f5d9805 | |||
| a0bd9648dc | |||
| aa1778cf82 | |||
| 10d66a4775 | |||
| 4082c97e0e | |||
| 665f979e82 | |||
| 911205ce0a | |||
| 51078fde5b | |||
| adde7e8d67 | |||
| 582e38eec5 | |||
| e987e679d0 | |||
| 6d776407a4 | |||
| 8a61a5f0e7 | |||
| 49a9ff8640 | |||
| 47ebdb4aee | |||
| 2b10a9d977 | |||
| 247b7d5633 | |||
| ae9eba0608 | |||
| 7983681b70 | |||
| 85d4106f28 | |||
| 22d329b8aa | |||
| 004d36ffa7 | |||
| 231340d979 | |||
| f55f5b881f | |||
| 03ac090e06 | |||
| 3b375e9c1b | |||
| e44157fae5 | |||
| 997513231c | |||
| 64c3ba297b | |||
| 3ae9c49de4 | |||
| 5692f9fa69 | |||
| 72ba9f5699 | |||
| 696be6f796 | |||
| 5198335948 | |||
| 8102063850 | |||
| 86bf551de8 | |||
| ec2933f23c | |||
| f6daf62c7d | |||
| 50988db28c | |||
| 047cef184d | |||
| ee5b8662d1 | |||
| 9470ee2507 | |||
| 8f63e755be | |||
| b0d62da7fe | |||
| 7a4347b288 | |||
| bbaa583a6d | |||
| c3709f726c | |||
| d1417069d9 | |||
| 412f1bead0 | |||
| 1095f63832 | |||
| 89d0317c7f | |||
| 4f489a5272 | |||
| 8c843ba4b5 | |||
| 77401cbfa0 | |||
| b983692fc1 | |||
| e1a40c6868 | |||
| 9c2add4e3b | |||
| 8cede4760e | |||
| bceab238d5 | |||
| 121676e661 | |||
| 9ec3be8a48 | |||
| bb61cdad70 | |||
| 2e32e4d768 | |||
| d4ee641362 | |||
| 953c2b2e92 | |||
| 2cc78c874b | |||
| f6f0ecb21b | |||
| 190fef934c | |||
| 52608a9f3f | |||
| 54e5fd30ab | |||
| 89115fd5d5 | |||
| 5631ae52be | |||
| 6520cdb184 | |||
| ce5f8708cd | |||
| 270a83ddbc | |||
| 64b8cb3556 | |||
| 7f7884c130 | |||
| 5a95613cee | |||
| 9a58800499 | |||
| d68e46a2d0 | |||
| 20d1ff6d49 | |||
| ed188448f2 | |||
| 87c803e4c6 | |||
| 58f51aae91 | |||
| 97a773176d | |||
| f6d92021ed | |||
| 026cbd5da3 | |||
| 3538e79a6b | |||
| d520fb8535 | |||
| d7dbf8b994 | |||
| 2d70e8ebe2 | |||
| 5eafe8f818 | |||
| e875c664fd | |||
| e313a03410 | |||
| 781aa339bc | |||
| 73e318ee38 | |||
| 337853cdfa | |||
| afe4e111c3 | |||
| 3675c5da46 | |||
| a4cc39dbac | |||
| e3787079b7 | |||
| b2f98e2d92 | |||
| e1edd01069 | |||
| eb3455452b | |||
| 34baf923b2 | |||
| 499308870d | |||
| f852a79a0e | |||
| fa98454151 | |||
| 286fc91db6 | |||
| 99209f920d | |||
| 19fd1aff98 | |||
| 9ebc5aeb32 | |||
| 7c890a4627 | |||
| ccc661225e | |||
| d7b13a2e0b | |||
| c53ce15f7d | |||
| 35ac6fc756 | |||
| 6bcf58959b | |||
| 5051508e42 | |||
| 196e02e61a | |||
| bc8188beb0 | |||
| 0fc4c5532b | |||
| 98586d6af9 | |||
| bdd1e2410a | |||
| c0240c71bf | |||
| 65ffc93e0f | |||
| 01183be383 | |||
| 359791ea58 | |||
| 5b3aa82817 | |||
| d77bb48da1 | |||
| 8b941cb95c | |||
| b9d991db63 | |||
| 1a8a7be494 | |||
| d054ac91b1 | |||
| e40ee20460 | |||
| 29b3e9fadc | |||
| 3cc78c62a0 | |||
| 2c719c41d9 | |||
| cd06b42b02 | |||
| e8b46a6fd2 | |||
| 814ac5df84 | |||
| 7854f659a3 | |||
| 6cb1d2f8f4 | |||
| f95d57ab6d | |||
| 55f9d142e6 | |||
| 58607ab1fc | |||
| 433ab4f92f | |||
| 8840973a1e | |||
| f91479829d | |||
| 829c9531fa | |||
| f9bb248eef | |||
| 03ce4d9c42 | |||
| f181d073a3 | |||
| 63b01f3ec7 | |||
| 14f1b6db54 | |||
| 604089cfa8 | |||
| 712d9db2fa | |||
| 2b5b023472 | |||
| 4a9bc7ca74 | |||
| 804f910584 | |||
| d5b2512e27 | |||
| 280d281604 | |||
| 95bcc71d23 | |||
| b623f1581f | |||
| 62b6d9ea30 | |||
| 6c8d0f98a6 | |||
| dc353cd029 | |||
| 86e4ab7e83 | |||
| c6a96ae710 | |||
| 9e24ee0ef7 | |||
| 4460789ab1 | |||
| a232f449ed | |||
| 1c5988fbfb | |||
| b386547616 | |||
| 03ea7ee460 | |||
| 752a2e4a69 | |||
| 3e3e30c4b1 | |||
| f5cc5c2846 | |||
| 609d471346 | |||
| 5f921ffcef | |||
| 4aebf36f02 | |||
| 0b1fdba6ea | |||
| 475324ed73 | |||
| d36f97d765 | |||
| ee5dc0a6b3 | |||
| 05ed61b0a1 | |||
| 2ef6c59dfc | |||
| fd90f761a1 | |||
| 72bcc87de7 | |||
| 7ec7d6bdc5 | |||
| f9ed9a472c | |||
| b542738097 | |||
| bceefb5717 | |||
| f977687ad6 | |||
| 31ef1d4959 | |||
| 86d07eb62b | |||
| 39c7ae8d17 | |||
| 5c369fd515 | |||
| 2b0926a097 | |||
| 9b6b67b178 | |||
| bb07e3db9a | |||
| 46e65704d7 | |||
| d5ec17551e | |||
| 8390cfc6fb | |||
| 2711fbf01a | |||
| e4f64df660 | |||
| a6c9d0df98 | |||
| 136dd5b47a | |||
| 277def2acc | |||
| e941b553e7 | |||
| 92e651c779 | |||
| 2b82eb88c8 | |||
| 13fecf9d1d | |||
| cdd1529a13 | |||
| 7915444713 | |||
| 2135ae769d | |||
| b98cfb9666 | |||
| a28da86d44 | |||
| 799b0e2481 | |||
| e380c7c069 | |||
| 5a3b8f5baa | |||
| a1c547b72e | |||
| bb5613e3fe | |||
| a29060bf4f | |||
| 79ee23e0b0 | |||
| d3231a480d | |||
| 3694dcba4c | |||
| bf6db89a4b | |||
| 38c644739a | |||
| a0fe977976 | |||
| 739d6d5856 | |||
| 84125735a1 | |||
| 884f6811a1 | |||
| 402abb0963 | |||
| 2f7f489e14 | |||
| 4de5c287fc | |||
| ccb58024a1 | |||
| 0381d56511 | |||
| 7bbd3fd815 | |||
| 4e243252e9 | |||
| b488d21a14 | |||
| 3e8dbf7ac7 | |||
| 695b73f9d3 | |||
| 6e37bce38a | |||
| 06232f65b2 | |||
| bebe4b7436 | |||
| 7d9f04d54c | |||
| 70336acc75 | |||
| e1ef08a783 | |||
| 648a70097a | |||
| 280892f5f4 | |||
| 3c57b124d5 | |||
| 04d6bae479 | |||
| 98096a5db7 | |||
| 7e4f3a3185 | |||
| 9fe6be10f6 | |||
| 76b356d38e | |||
| 811e24ee5e | |||
| 5002db15d6 | |||
| a3357c1193 | |||
| af36224a57 | |||
| 630ff361d3 | |||
| 34c6f29a18 | |||
| 909718e491 | |||
| 8a3d199247 | |||
| fa13c981b7 | |||
| 815b00c3ca | |||
| ae9144a6c4 | |||
| 359fde3b6b | |||
| 92fa904cc6 | |||
| 2583ae34d4 | |||
| e36b3394f4 | |||
| 7af38df92c | |||
| 51add24110 | |||
| 9e5aac3bf7 | |||
| 5738a5b7cd | |||
| e1216966a3 | |||
| 222c0de7f1 | |||
| b4f1fb6d28 | |||
| a32082ad20 | |||
| eeb5fb6c3c | |||
| cb50f24c86 | |||
| 5ca5764c0e | |||
| fccd1db045 | |||
| 6c515350bc | |||
| 50aee9dfb2 | |||
| 0649504770 | |||
| 29068f9550 | |||
| 18c08ccd88 | |||
| b71d6a5e3f | |||
| 8f619f3fa1 | |||
| eab16ff20a | |||
| d913ed9621 | |||
| a649cf179f | |||
| cf5de39250 | |||
| bab3cd9656 | |||
| cafd4f0c47 | |||
| e20833225f | |||
| 14a06c220b | |||
| e5a5ba327e | |||
| fedc8f7b66 |
@@ -20,6 +20,8 @@ build
|
||||
# other
|
||||
eclipse
|
||||
run
|
||||
**/src/generated/
|
||||
|
||||
# Files from Forge MDK
|
||||
logs
|
||||
forge*changelog.txt
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "core"]
|
||||
path = core
|
||||
url = https://gitlab.com/jeseibel/distant-horizons-core.git
|
||||
-65
@@ -1,65 +0,0 @@
|
||||
Minecraft Forge: Credits/Thank You
|
||||
|
||||
Forge is a set of tools and modifications to the Minecraft base game code to assist
|
||||
mod developers in creating new and exciting content. It has been in development for
|
||||
several years now, but I would like to take this time thank a few people who have
|
||||
helped it along it's way.
|
||||
|
||||
First, the people who originally created the Forge projects way back in Minecraft
|
||||
alpha. Eloraam of RedPower, and SpaceToad of Buildcraft, without their acceptiance
|
||||
of me taking over the project, who knows what Minecraft modding would be today.
|
||||
|
||||
Secondly, someone who has worked with me, and developed some of the core features
|
||||
that allow modding to be as functional, and as simple as it is, cpw. For developing
|
||||
FML, which stabelized the client and server modding ecosystem. As well as the base
|
||||
loading system that allows us to modify Minecraft's code as elegently as possible.
|
||||
|
||||
Mezz, who has stepped up as the issue and pull request manager. Helping to keep me
|
||||
sane as well as guiding the community into creating better additions to Forge.
|
||||
|
||||
Searge, Bspks, Fesh0r, ProfMobious, and all the rest over on the MCP team {of which
|
||||
I am a part}. For creating some of the core tools needed to make Minecraft modding
|
||||
both possible, and as stable as can be.
|
||||
On that note, here is some specific information of the MCP data we use:
|
||||
* Minecraft Coder Pack (MCP) *
|
||||
Forge Mod Loader and Minecraft Forge have permission to distribute and automatically
|
||||
download components of MCP and distribute MCP data files. This permission is not
|
||||
transitive and others wishing to redistribute the Minecraft Forge source independently
|
||||
should seek permission of MCP or remove the MCP data files and request their users
|
||||
to download MCP separately.
|
||||
|
||||
And lastly, the countless community members who have spent time submitting bug reports,
|
||||
pull requests, and just helping out the community in general. Thank you.
|
||||
|
||||
--LexManos
|
||||
|
||||
=========================================================================
|
||||
|
||||
This is Forge Mod Loader.
|
||||
|
||||
You can find the source code at all times at https://github.com/MinecraftForge/MinecraftForge/tree/1.12.x/src/main/java/net/minecraftforge/fml
|
||||
|
||||
This minecraft mod is a clean open source implementation of a mod loader for minecraft servers
|
||||
and minecraft clients.
|
||||
|
||||
The code is authored by cpw.
|
||||
|
||||
It began by partially implementing an API defined by the client side ModLoader, authored by Risugami.
|
||||
http://www.minecraftforum.net/topic/75440-
|
||||
This support has been dropped as of Minecraft release 1.7, as Risugami no longer maintains ModLoader.
|
||||
|
||||
It also contains suggestions and hints and generous helpings of code from LexManos, author of MinecraftForge.
|
||||
http://www.minecraftforge.net/
|
||||
|
||||
Additionally, it contains an implementation of topological sort based on that
|
||||
published at http://keithschwarz.com/interesting/code/?dir=topological-sort
|
||||
|
||||
It also contains code from the Maven project for performing versioned dependency
|
||||
resolution. http://maven.apache.org/
|
||||
|
||||
It also contains a partial repackaging of the javaxdelta library from http://sourceforge.net/projects/javaxdelta/
|
||||
with credit to it's authors.
|
||||
|
||||
Forge Mod Loader downloads components from the Minecraft Coder Pack
|
||||
(http://mcp.ocean-labs.de/index.php/Main_Page) with kind permission from the MCP team.
|
||||
|
||||
+555
-454
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,68 @@
|
||||
# Distant Horizons
|
||||
|
||||
This mod adds a Level Of Detail (LOD) system to Minecraft.\
|
||||
This implementation renders simplified chunks outside the normal render distance\
|
||||
allowing for an increased view distance without harming performance.
|
||||
|
||||
Or in other words: this mod lets you see farther without turning your game into a slide show.\
|
||||
If you want to see a quick demo, check out a video covering the mod here:
|
||||
|
||||
<a href="https://www.youtube.com/watch?v=H2tnvEVbO1c" target="_blank"></a>
|
||||
|
||||
|
||||
Forge version: 1.16.5-36.1.0
|
||||
|
||||
Notes:\
|
||||
This version has been confirmed to work in Eclipse and Retail Minecraft.\
|
||||
(Retail running forge version 1.16.5-36.1.0)
|
||||
|
||||
|
||||
## source code installation
|
||||
|
||||
See the Forge Documentation online for more detailed instructions:\
|
||||
http://mcforge.readthedocs.io/en/latest/gettingstarted/
|
||||
|
||||
1. Create a system variable called "JAVA_MC_HOME" with the location of the JDK 1.8.0_251 (This is needed for gradle to work correctly)
|
||||
2. replace JAVA_HOME with JAVA_MC_HOME in gradle.bat
|
||||
3. open a command line in the project folder
|
||||
|
||||
**If using Ecplise:**
|
||||
1. run the command: `./gradlew geneclipseruns`
|
||||
2. run the command: `./gradlew eclipse`
|
||||
3. Make sure eclipse has the JDK 1.8.0_251 installed. (This is needed so that eclipse can run minecraft)
|
||||
4. Import the project into eclipse
|
||||
|
||||
**If using IntelliJ:**
|
||||
1. open IDEA and import the build.gradle
|
||||
2. run the command: `./gradlew genIntellijRuns`
|
||||
3. refresh the Gradle project in IDEA if required
|
||||
|
||||
|
||||
## Compiling
|
||||
|
||||
1. open a command line in the project folder
|
||||
2. run the command: `./gradlew build`
|
||||
3. the compiled jar file will be in the folder `build\libs`
|
||||
|
||||
|
||||
## Other commands
|
||||
|
||||
`./gradlew --refresh-dependencies` to refresh local dependencies.
|
||||
|
||||
`./gradlew clean` to reset everything (this does not affect your code) and then start the process again.
|
||||
|
||||
|
||||
## Note to self
|
||||
|
||||
The Minecraft source code is NOT added to your workspace in an editable way. Minecraft is treated like a normal Library. Sources are there for documentation and research purposes only.
|
||||
|
||||
Source code uses Mojang mappings.
|
||||
|
||||
The source code can be 'created' with the `./eclipse` command and can be found in the following path:\
|
||||
`minecraft-lod-mod\build\fg_cache\mcp\ VERSION \joined\ RANDOM_STRING \patch\output.jar`
|
||||
|
||||
|
||||
## Open Source Acknowledgements
|
||||
|
||||
XZ for Java (data compression)\
|
||||
https://tukaani.org/xz/java.html
|
||||
-69
@@ -1,69 +0,0 @@
|
||||
This mod adds a Level Of Detail (LOD) system to Minecraft.
|
||||
This implementation renders simplified chunks outside the normal render distance
|
||||
allowing for an increased view distance without harming performance.
|
||||
|
||||
Or in other words: this mod let's you see farther without turning your game into a slide show.
|
||||
If you want to see a quick demo, check out the video I made here:
|
||||
https://youtu.be/v61iOYZQWCs
|
||||
|
||||
|
||||
Forge version: 1.16.4-35.1.4
|
||||
|
||||
Notes:
|
||||
This version has been confirmed to work in Eclipse and retail Minecraft.
|
||||
(retail running forge 1.16.4-35.1.37)
|
||||
That being said only singleplayer is currently supported; connecting
|
||||
to servers (local or otherwise) will cause no LODs to be drawn and
|
||||
may cause instibility.
|
||||
|
||||
|
||||
========================
|
||||
source code installation
|
||||
========================
|
||||
|
||||
See the Forge Documentation online for more detailed instructions:
|
||||
http://mcforge.readthedocs.io/en/latest/gettingstarted/
|
||||
|
||||
Step 1: Create a system variable called "JAVA_MC_HOME" with the location of the JDK 1.8.0_251 (This is needed for gradle to work correctly)
|
||||
|
||||
Step 2: replace JAVA_HOME with JAVA_MC_HOME in gradle.bat
|
||||
|
||||
Step 3: open a command line in the project folder
|
||||
|
||||
Step 4: run the command: "./gradlew geneclipseruns"
|
||||
|
||||
Step 5: run the command: "./gradlew eclipse"
|
||||
|
||||
Step 6: Make sure the eclipse has the JDK 1.8.0_251 installed. (This is needed so that eclipse can run minecraft)
|
||||
|
||||
Step 7: Import the project into eclipse
|
||||
|
||||
|
||||
|
||||
=========
|
||||
compiling
|
||||
=========
|
||||
|
||||
Step 1: open a command line in the project folder
|
||||
|
||||
Step 2: run the command: "./gradlew build"
|
||||
|
||||
Step 3: the compiled jar file will be in the folder "build\libs"
|
||||
|
||||
|
||||
|
||||
==============
|
||||
Other commands
|
||||
==============
|
||||
|
||||
"./gradlew --refresh-dependencies" to refresh local dependencies.
|
||||
"./gradlew clean" to reset everything (this does not affect your code) and then start the process again.
|
||||
|
||||
|
||||
|
||||
============
|
||||
Note to self
|
||||
============
|
||||
|
||||
The Minecraft source code is NOT added to your workspace in a editable way. Minecraft is treated like a normal Library. Sources are there for documentation and research purposes only.
|
||||
|
||||
+129
-19
@@ -1,24 +1,36 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
maven { url = 'https://files.minecraftforge.net/maven' }
|
||||
jcenter()
|
||||
maven { url = 'https://files.minecraftforge.net' }
|
||||
mavenCentral()
|
||||
maven { url='https://dist.creeper.host/Sponge/maven' }
|
||||
// potential replacement in case of problems: https://dist.creeper.host/Sponge/maven
|
||||
maven { url = 'https://repo.spongepowered.org/maven/' }
|
||||
// used to download and compile dependencies from git repos
|
||||
maven { url 'https://jitpack.io' }
|
||||
gradlePluginPortal()
|
||||
}
|
||||
dependencies {
|
||||
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
|
||||
// Note to self: Don't try to update ForgeGradle!
|
||||
// As of 11-27-2021 Mixins don't work on Gradle 7,
|
||||
// which the newer versions of ForgeGradle use
|
||||
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3+', changing: true
|
||||
classpath group: 'org.spongepowered', name: 'mixingradle', version: '0.7-SNAPSHOT'
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "com.github.johnrengelman.shadow" version "4.0.4"
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle'
|
||||
apply plugin: 'org.spongepowered.mixin'
|
||||
// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'maven-publish'
|
||||
|
||||
version = 'a1'
|
||||
group = 'com.backsun.lod'
|
||||
archivesBaseName = 'lod_1.16.4'
|
||||
version = 'a1.5.4'
|
||||
group = 'com.seibel.lod'
|
||||
archivesBaseName = 'Distant-Horizons_1.16.5'
|
||||
|
||||
|
||||
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
|
||||
|
||||
@@ -29,8 +41,8 @@ minecraft {
|
||||
// stable_# Stables are built at the discretion of the MCP team.
|
||||
// Use non-default mappings at your own risk. they may not always work.
|
||||
// Simply re-run your setup task after changing the mappings to update your workspace.
|
||||
mappings channel: 'snapshot', version: '20201028-1.16.3'
|
||||
|
||||
mappings channel: 'official', version: '1.16.5'
|
||||
|
||||
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
|
||||
|
||||
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
|
||||
@@ -43,9 +55,15 @@ minecraft {
|
||||
arg "-mixin.config=lod.mixins.json"
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
|
||||
// The markers can be changed as needed.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
mods {
|
||||
@@ -60,9 +78,15 @@ minecraft {
|
||||
arg "-mixin.config=lod.mixins.json"
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
|
||||
// The markers can be changed as needed.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
mods {
|
||||
@@ -76,9 +100,15 @@ minecraft {
|
||||
workingDirectory project.file('run')
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP'
|
||||
// The markers can be changed as needed.
|
||||
// "SCAN": For mods scan.
|
||||
// "REGISTRIES": For firing of registry events.
|
||||
// "REGISTRYDUMP": For getting the contents of all registries.
|
||||
property 'forge.logging.markers', 'REGISTRIES'
|
||||
|
||||
// Recommended logging level for the console
|
||||
// You can set various levels here.
|
||||
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
|
||||
property 'forge.logging.console.level', 'debug'
|
||||
|
||||
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
|
||||
@@ -93,14 +123,59 @@ minecraft {
|
||||
}
|
||||
}
|
||||
|
||||
// Include resources generated by data generators.
|
||||
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
// add Distant Horizon's Core source folders
|
||||
srcDirs("core/src/main/java");
|
||||
srcDirs("core/src/main/resources")
|
||||
}
|
||||
resources {
|
||||
// Include resources generated by data generators.
|
||||
srcDir("src/generated/resources")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// this is required so that we can use
|
||||
// jitpack in the dependencies section below
|
||||
repositories {
|
||||
mavenCentral()
|
||||
// used to download and compile dependencies from git repos
|
||||
maven { url 'https://jitpack.io' }
|
||||
}
|
||||
|
||||
configurations {
|
||||
shadowMe
|
||||
compileOnly.extendsFrom(embed)
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
|
||||
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
|
||||
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
|
||||
minecraft 'net.minecraftforge:forge:1.16.4-35.1.4'
|
||||
minecraft 'net.minecraftforge:forge:1.16.5-36.1.0'
|
||||
|
||||
// required to generate the mixin refmap
|
||||
annotationProcessor 'org.spongepowered:mixin:0.8:processor'
|
||||
|
||||
implementation 'org.tukaani:xz:1.9'
|
||||
shadowMe 'org.tukaani:xz:1.9'
|
||||
implementation 'org.apache.commons:commons-compress:1.21'
|
||||
shadowMe 'org.apache.commons:commons-compress:1.21'
|
||||
|
||||
// these were added to hopefully allow for cloning
|
||||
// configuredFeatures to allow for safe
|
||||
// multi threaded feature generation. Sadly I couldn't find
|
||||
// a way to duplicate lambda functions (which features use)
|
||||
// so for now I'm not sure what to do.
|
||||
//implementation 'io.github.kostaskougios:cloning:1.10.3'
|
||||
//
|
||||
//implementation ('com.esotericsoftware:kryo:5.1.1') {
|
||||
// exclude group: "org.objenesis"
|
||||
//}
|
||||
//implementation 'org.objenesis:objenesis:3.2'
|
||||
|
||||
|
||||
// You may put jars on which you depend on in ./libs or you may define them like so..
|
||||
// compile "some.group:artifact:version:classifier"
|
||||
@@ -119,26 +194,59 @@ dependencies {
|
||||
// For more info...
|
||||
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
|
||||
// http://www.gradle.org/docs/current/userguide/dependency_management.html
|
||||
}
|
||||
|
||||
task copyCoreResources(type: Copy) {
|
||||
from file("core/src/main/resources/shaders")
|
||||
into file("src/generated/resources/shaders")
|
||||
}
|
||||
|
||||
task copyCoreResourcesAtRuntime(type: Copy) {
|
||||
from file("core/src/main/resources/shaders")
|
||||
into file("build/resources/main/shaders")
|
||||
}
|
||||
|
||||
compileJava.dependsOn(copyCoreResources).dependsOn(copyCoreResourcesAtRuntime)
|
||||
|
||||
jar {
|
||||
classifier 'withoutDependencies'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
duplicatesStrategy = DuplicatesStrategy.INCLUDE
|
||||
configurations = [project.configurations.getByName("shadowMe")]
|
||||
relocate 'org.tukaani', 'shaded.tukaani'
|
||||
relocate 'org.apache.commons.compress', 'shaded.apache.commons.compress'
|
||||
classifier ''
|
||||
}
|
||||
|
||||
reobf {
|
||||
shadowJar {
|
||||
dependsOn tasks.createMcpToSrg
|
||||
mappings = tasks.createMcpToSrg.outputs.files.singleFile
|
||||
}
|
||||
}
|
||||
|
||||
artifacts {
|
||||
archives tasks.shadowJar
|
||||
}
|
||||
|
||||
// Example for how to get properties into the manifest for reading by the runtime..
|
||||
jar {
|
||||
manifest {
|
||||
attributes([
|
||||
"Specification-Title": "Levels of Detail",
|
||||
"Specification-Title": "LOD",
|
||||
"Specification-Version": "1", // We are version 1 of ourselves
|
||||
"Implementation-Title": project.name,
|
||||
"Implementation-Version": "1.0",
|
||||
"Implementation-Version": "1",
|
||||
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
|
||||
"MixinConfigs": "lod.mixins.json",
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
// Example configuration to allow publishing using the maven-publish task
|
||||
// This is the preferred method to reobfuscate your jar file
|
||||
jar.finalizedBy('reobfJar')
|
||||
jar.finalizedBy('reobfJar')
|
||||
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
|
||||
//publish.dependsOn('reobfJar')
|
||||
|
||||
@@ -157,4 +265,6 @@ publishing {
|
||||
|
||||
mixin {
|
||||
add sourceSets.main, "lod.refmap.json"
|
||||
config "lod.mixins.json"
|
||||
}
|
||||
|
||||
|
||||
-1664
File diff suppressed because it is too large
Load Diff
Submodule
+1
Submodule core added at f2fc669b37
+1
-1
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip
|
||||
|
||||
Binary file not shown.
@@ -1,65 +0,0 @@
|
||||
package com.backsun.lod;
|
||||
|
||||
import com.backsun.lod.proxy.ClientProxy;
|
||||
import com.backsun.lod.util.LodConfig;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
|
||||
/**
|
||||
* Initialize and setup the Mod.
|
||||
* <br>
|
||||
* If you are looking for the real start of the mod
|
||||
* check out the ClientProxy.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-07-2021
|
||||
*/
|
||||
@Mod(ModInfo.MODID)
|
||||
public class LodMain
|
||||
{
|
||||
public static LodMain instance;
|
||||
|
||||
public static ClientProxy client_proxy;
|
||||
|
||||
|
||||
private void init(final FMLCommonSetupEvent event)
|
||||
{
|
||||
Minecraft.getInstance().getFramebuffer().enableStencil();
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, LodConfig.clientSpec);
|
||||
}
|
||||
|
||||
|
||||
public LodMain()
|
||||
{
|
||||
// Register the methods
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::init);
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientStart);
|
||||
|
||||
// Register ourselves for server and other game events we are interested in
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
private void onClientStart(final FMLClientSetupEvent event)
|
||||
{
|
||||
client_proxy = new ClientProxy();
|
||||
MinecraftForge.EVENT_BUS.register(client_proxy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void onServerStarting(FMLServerStartingEvent event)
|
||||
{
|
||||
// this is called when the server starts
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
package com.backsun.lod;
|
||||
|
||||
/**
|
||||
* This file is similar to mcmod.info
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-17-2021
|
||||
*/
|
||||
public final class ModInfo
|
||||
{
|
||||
public static final String MODID = "lod";
|
||||
public static final String MODNAME = "Levels of Detail";
|
||||
public static final String MODAPI = "LodAPI";
|
||||
public static final String VERSION = "1.0";
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
package com.backsun.lod.builders;
|
||||
import java.awt.Color;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.backsun.lod.objects.NearFarBuffer;
|
||||
import com.backsun.lod.renderer.LodRenderer;
|
||||
import com.backsun.lod.util.enums.FogDistance;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
|
||||
/**
|
||||
* This object is used to create NearFarBuffer objects.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-27-2021
|
||||
*/
|
||||
public class LodBufferBuilder
|
||||
{
|
||||
public BufferBuilder nearBuffer;
|
||||
public BufferBuilder farBuffer;
|
||||
public FogDistance distanceMode;
|
||||
public AxisAlignedBB[][] lods;
|
||||
public Color[][] colors;
|
||||
|
||||
|
||||
|
||||
public LodBufferBuilder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public NearFarBuffer createBuffers(
|
||||
BufferBuilder newNearBufferBuilder, BufferBuilder newFarBufferBuilder,
|
||||
FogDistance newDistanceMode,
|
||||
AxisAlignedBB[][] newLods, Color[][] newColors)
|
||||
{
|
||||
nearBuffer = newNearBufferBuilder;
|
||||
farBuffer = newFarBufferBuilder;
|
||||
distanceMode = newDistanceMode;
|
||||
lods = newLods;
|
||||
colors = newColors;
|
||||
|
||||
|
||||
nearBuffer.begin(GL11.GL_QUADS, LodRenderer.LOD_VERTEX_FORMAT);
|
||||
farBuffer.begin(GL11.GL_QUADS, LodRenderer.LOD_VERTEX_FORMAT);
|
||||
|
||||
int numbChunksWide = lods.length;
|
||||
|
||||
BufferBuilder currentBuffer;
|
||||
AxisAlignedBB bb;
|
||||
int red;
|
||||
int green;
|
||||
int blue;
|
||||
int alpha;
|
||||
|
||||
|
||||
// x axis
|
||||
for (int i = 0; i < numbChunksWide; i++)
|
||||
{
|
||||
// z axis
|
||||
for (int j = 0; j < numbChunksWide; j++)
|
||||
{
|
||||
if (lods[i][j] == null || colors[i][j] == null)
|
||||
continue;
|
||||
|
||||
bb = lods[i][j];
|
||||
|
||||
// get the color of this LOD object
|
||||
red = colors[i][j].getRed();
|
||||
green = colors[i][j].getGreen();
|
||||
blue = colors[i][j].getBlue();
|
||||
alpha = colors[i][j].getAlpha();
|
||||
|
||||
|
||||
if (isCoordinateInNearFogArea(i, j, numbChunksWide / 2))
|
||||
currentBuffer = nearBuffer;
|
||||
else
|
||||
currentBuffer = farBuffer;
|
||||
|
||||
|
||||
if (bb.minY != bb.maxY)
|
||||
{
|
||||
// top (facing up)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
// bottom (facing down)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
|
||||
// south (facing -Z)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
// north (facing +Z)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
|
||||
// west (facing -X)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
// east (facing +X)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.maxY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
// render this LOD as one block thick
|
||||
|
||||
// top (facing up)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
// bottom (facing down)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
|
||||
// south (facing -Z)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
// north (facing +Z)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
|
||||
// west (facing -X)
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.minX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
// east (facing +X)
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.minZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY+1, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.maxZ, red, green, blue, alpha);
|
||||
addPosAndColor(currentBuffer, bb.maxX, bb.minY, bb.minZ, red, green, blue, alpha);
|
||||
}
|
||||
|
||||
} // z axis
|
||||
} // x axis
|
||||
|
||||
nearBuffer.finishDrawing();
|
||||
farBuffer.finishDrawing();
|
||||
|
||||
return new NearFarBuffer(nearBuffer, farBuffer);
|
||||
}
|
||||
|
||||
private void addPosAndColor(BufferBuilder buffer, double x, double y, double z, int red, int green, int blue, int alpha)
|
||||
{
|
||||
buffer.pos(x, y, z).color(red, green, blue, alpha).endVertex();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find the coordinates that are in the center half of the given
|
||||
* 2D matrix, starting at (0,0) and going to (2 * lodRadius, 2 * lodRadius).
|
||||
*/
|
||||
private static boolean isCoordinateInNearFogArea(int chunkX, int chunkZ, int lodRadius)
|
||||
{
|
||||
int halfRadius = lodRadius / 2;
|
||||
|
||||
return (chunkX >= lodRadius - halfRadius
|
||||
&& chunkX <= lodRadius + halfRadius)
|
||||
&&
|
||||
(chunkZ >= lodRadius - halfRadius
|
||||
&& chunkZ <= lodRadius + halfRadius);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,124 +0,0 @@
|
||||
package com.backsun.lod.builders;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.backsun.lod.handlers.LodDimensionFileHandler;
|
||||
import com.backsun.lod.objects.LodChunk;
|
||||
import com.backsun.lod.objects.LodDimension;
|
||||
import com.backsun.lod.objects.LodWorld;
|
||||
import com.backsun.lod.util.LodUtils;
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* This object is in charge of creating Lod
|
||||
* related objects.
|
||||
* (specifically: Lod World, Dimension, Region, and Chunk objects)
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2-22-2021
|
||||
*/
|
||||
public class LodBuilder
|
||||
{
|
||||
private ExecutorService lodGenThreadPool = Executors.newSingleThreadExecutor();
|
||||
public volatile LodWorld lodWorld;
|
||||
|
||||
/** Default size of any LOD regions we use */
|
||||
public int regionWidth = 5;
|
||||
|
||||
public LodBuilder()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns LodWorld so that it can be passed
|
||||
* to the LodRenderer.
|
||||
*/
|
||||
public LodWorld generateLodChunkAsync(Chunk chunk)
|
||||
{
|
||||
if (lodWorld != null)
|
||||
// is this chunk from the same world as the lodWorld?
|
||||
if (!lodWorld.worldName.equals(LodDimensionFileHandler.getCurrentWorldID()))
|
||||
// we are not in the same world anymore,
|
||||
// remove the old world so it can be recreated later
|
||||
lodWorld = null;
|
||||
|
||||
// don't try to create an LOD object
|
||||
// if for some reason we aren't
|
||||
// given a valid chunk object
|
||||
// (Minecraft often gives back empty
|
||||
// or null chunks in this method)
|
||||
if (chunk == null || !isValidChunk(chunk))
|
||||
return lodWorld;
|
||||
|
||||
|
||||
DimensionType dim = chunk.getWorld().getDimensionType();
|
||||
ServerWorld world = LodUtils.getServerWorldFromDimension(dim);
|
||||
|
||||
|
||||
if (world == null)
|
||||
return lodWorld;
|
||||
|
||||
Thread thread = new Thread(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
LodChunk lod = new LodChunk(chunk, world);
|
||||
LodDimension lodDim;
|
||||
|
||||
if (lodWorld == null)
|
||||
{
|
||||
lodWorld = new LodWorld(LodDimensionFileHandler.getCurrentWorldID());
|
||||
}
|
||||
|
||||
|
||||
if (lodWorld.getLodDimension(dim) == null)
|
||||
{
|
||||
lodDim = new LodDimension(dim, regionWidth);
|
||||
lodWorld.addLodDimension(lodDim);
|
||||
}
|
||||
else
|
||||
{
|
||||
lodDim = lodWorld.getLodDimension(dim);
|
||||
}
|
||||
|
||||
lodDim.addLod(lod);
|
||||
}
|
||||
catch(IllegalArgumentException | NullPointerException e)
|
||||
{
|
||||
// if the world changes while LODs are being generated
|
||||
// they will throw errors as they try to access things that no longer
|
||||
// exist.
|
||||
}
|
||||
});
|
||||
lodGenThreadPool.execute(thread);
|
||||
|
||||
return lodWorld;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given chunk
|
||||
* has any data in it.
|
||||
*/
|
||||
public boolean isValidChunk(Chunk chunk)
|
||||
{
|
||||
ChunkSection[] blockStorage = chunk.getSections();
|
||||
|
||||
for(ChunkSection section : blockStorage)
|
||||
{
|
||||
if(section != null && !section.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,289 +0,0 @@
|
||||
package com.backsun.lod.handlers;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import com.backsun.lod.objects.LodChunk;
|
||||
import com.backsun.lod.objects.LodDimension;
|
||||
import com.backsun.lod.objects.LodRegion;
|
||||
import com.backsun.lod.util.LodUtils;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* This object handles creating LodRegions
|
||||
* from files and saving LodRegion objects
|
||||
* to file.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 01-30-2021
|
||||
*/
|
||||
public class LodDimensionFileHandler
|
||||
{
|
||||
private LodDimension loadedDimension = null;
|
||||
public long regionLastWriteTime[][];
|
||||
|
||||
private File dimensionDataSaveFolder;
|
||||
|
||||
private final String FILE_NAME_PREFIX = "lod";
|
||||
private final String FILE_EXTENSION = ".txt";
|
||||
|
||||
private ExecutorService fileWritingThreadPool = Executors.newFixedThreadPool(1);
|
||||
|
||||
|
||||
public LodDimensionFileHandler(File newSaveFolder, LodDimension newLoadedDimension)
|
||||
{
|
||||
dimensionDataSaveFolder = newSaveFolder;
|
||||
|
||||
loadedDimension = newLoadedDimension;
|
||||
// these two variable are used in sync with the LodDimension
|
||||
regionLastWriteTime = new long[loadedDimension.getWidth()][loadedDimension.getWidth()];
|
||||
for(int i = 0; i < loadedDimension.getWidth(); i++)
|
||||
for(int j = 0; j < loadedDimension.getWidth(); j++)
|
||||
regionLastWriteTime[i][j] = -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// read from file //
|
||||
//================//
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the LodRegion at the given coordinates.
|
||||
* (null if the file doesn't exist)
|
||||
*/
|
||||
public LodRegion loadRegionFromFile(int regionX, int regionZ)
|
||||
{
|
||||
// we don't currently support reading or writing
|
||||
// files when connected to a server
|
||||
if (!Minecraft.getInstance().isIntegratedServerRunning())
|
||||
return null;
|
||||
|
||||
if (!readyToReadAndWrite())
|
||||
return null;
|
||||
|
||||
String fileName = getFileNameForRegion(regionX, regionZ);
|
||||
|
||||
File f = new File(fileName);
|
||||
|
||||
if (!f.exists())
|
||||
{
|
||||
// there wasn't a file, don't
|
||||
// return anything
|
||||
return null;
|
||||
}
|
||||
|
||||
LodRegion region = new LodRegion(regionX, regionZ);
|
||||
|
||||
try
|
||||
{
|
||||
BufferedReader br = new BufferedReader(new FileReader(f));
|
||||
String s = br.readLine();
|
||||
|
||||
while(s != null && !s.isEmpty())
|
||||
{
|
||||
try
|
||||
{
|
||||
// convert each line into an LOD object and add it to the region
|
||||
LodChunk lod = new LodChunk(s);
|
||||
|
||||
region.addLod(lod);
|
||||
}
|
||||
catch(IllegalArgumentException e)
|
||||
{
|
||||
// we were unable to create this chunk
|
||||
// for whatever reason.
|
||||
// skip to the next chunk
|
||||
}
|
||||
|
||||
s = br.readLine();
|
||||
}
|
||||
|
||||
br.close();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
// File not found
|
||||
|
||||
// or the buffered reader encountered a
|
||||
// problem reading the file
|
||||
return null;
|
||||
}
|
||||
|
||||
return region;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// Save to File //
|
||||
//==============//
|
||||
|
||||
/**
|
||||
* Save all dirty regions in this LodDimension to file.
|
||||
*/
|
||||
public synchronized void saveDirtyRegionsToFileAsync()
|
||||
{
|
||||
// we don't currently support reading or writing
|
||||
// files when connected to a server
|
||||
if (!Minecraft.getInstance().isIntegratedServerRunning())
|
||||
return;
|
||||
|
||||
if (!readyToReadAndWrite())
|
||||
// we aren't ready to read and write yet
|
||||
return;
|
||||
|
||||
fileWritingThreadPool.execute(saveDirtyRegionsThread);
|
||||
}
|
||||
private Thread saveDirtyRegionsThread = new Thread(() ->
|
||||
{
|
||||
for(int i = 0; i < loadedDimension.getWidth(); i++)
|
||||
{
|
||||
for(int j = 0; j < loadedDimension.getWidth(); j++)
|
||||
{
|
||||
if(loadedDimension.isRegionDirty[i][j])
|
||||
{
|
||||
saveRegionToDisk(loadedDimension.regions[i][j]);
|
||||
loadedDimension.isRegionDirty[i][j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* Save a specific region to disk.<br>
|
||||
* Note: it will save to the LodDimension that this
|
||||
* handler is associated with.
|
||||
*/
|
||||
private void saveRegionToDisk(LodRegion region)
|
||||
{
|
||||
if (!readyToReadAndWrite() || region == null)
|
||||
return;
|
||||
|
||||
// convert chunk coordinates to region
|
||||
// coordinates
|
||||
int x = region.x;
|
||||
int z = region.z;
|
||||
|
||||
File f = new File(getFileNameForRegion(x, z));
|
||||
|
||||
try
|
||||
{
|
||||
// make sure the file and folder exists
|
||||
if (!f.exists())
|
||||
if(!f.getParentFile().exists())
|
||||
f.getParentFile().mkdirs();
|
||||
f.createNewFile();
|
||||
|
||||
FileWriter fw = new FileWriter(f);
|
||||
|
||||
for(LodChunk[] chunkArray : region.getAllLods())
|
||||
for(LodChunk chunk : chunkArray)
|
||||
if(chunk != null)
|
||||
fw.write(chunk.toData() + "\n");
|
||||
|
||||
fw.close();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
System.err.println("LOD file write error: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
|
||||
|
||||
/**
|
||||
* Return the name of the file that should contain the
|
||||
* region at the given x and z. <br>
|
||||
* Returns null if this object isn't ready to read and write.
|
||||
*/
|
||||
private String getFileNameForRegion(int regionX, int regionZ)
|
||||
{
|
||||
if (!readyToReadAndWrite())
|
||||
return null;
|
||||
|
||||
try
|
||||
{
|
||||
// saveFolder is something like
|
||||
// ".\Super Flat\DIM-1\data"
|
||||
// or
|
||||
// ".\Super Flat\data"
|
||||
return dimensionDataSaveFolder.getCanonicalPath() + "\\lod\\" +
|
||||
FILE_NAME_PREFIX + "." + regionX + "." + regionZ + FILE_EXTENSION;
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns if this FileHandler is ready to read
|
||||
* and write files.
|
||||
* <br>
|
||||
* This returns true when the world save directory is known.
|
||||
*/
|
||||
public boolean readyToReadAndWrite()
|
||||
{
|
||||
return dimensionDataSaveFolder != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If on single player this will return the name of the user's
|
||||
* world, if in multiplayer it will return the server name
|
||||
* and game version.
|
||||
*/
|
||||
public static String getCurrentWorldID()
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
if(mc.isIntegratedServerRunning())
|
||||
{
|
||||
ServerWorld serverWorld = LodUtils.getFirstValidServerWorld();
|
||||
if (serverWorld == null)
|
||||
return "";
|
||||
|
||||
ServerChunkProvider provider = serverWorld.getChunkProvider();
|
||||
if(provider != null)
|
||||
return provider.getSavedData().folder.toString();
|
||||
|
||||
return "";
|
||||
}
|
||||
else
|
||||
{
|
||||
return mc.getCurrentServerData().serverName + "_version_" + mc.getCurrentServerData().gameVersion;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
package com.backsun.lod.handlers;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import com.backsun.lod.util.enums.FogQuality;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
/**
|
||||
* This object is used to get variables from methods
|
||||
* where they are private. Specifically the fog setting
|
||||
* in Optifine.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 09-21-2020
|
||||
*/
|
||||
public class ReflectionHandler
|
||||
{
|
||||
private Minecraft mc = Minecraft.getInstance();
|
||||
public Field ofFogField = null;
|
||||
|
||||
|
||||
public ReflectionHandler()
|
||||
{
|
||||
setupFogField();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Similar to setupFovMethod.
|
||||
*/
|
||||
private void setupFogField()
|
||||
{
|
||||
// get every variable from the entity renderer
|
||||
Field[] vars = mc.gameSettings.getClass().getDeclaredFields();
|
||||
|
||||
// try and find the ofFogType variable in gameSettings
|
||||
for(Field f : vars)
|
||||
{
|
||||
if(f.getName().equals("ofFogType"))
|
||||
{
|
||||
ofFogField = f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// we didn't find the field,
|
||||
// either optifine isn't installed, or
|
||||
// optifine changed the name of the variable
|
||||
ofFogField = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get what type of fog optifine is currently set to render.
|
||||
*/
|
||||
public FogQuality getFogQuality()
|
||||
{
|
||||
if (ofFogField == null)
|
||||
{
|
||||
// either optifine isn't installed,
|
||||
// the variable name was changed, or
|
||||
// the setup method wasn't called yet.
|
||||
return FogQuality.FANCY;
|
||||
}
|
||||
|
||||
int returnNum = 0;
|
||||
|
||||
try
|
||||
{
|
||||
returnNum = (int)ofFogField.get(mc.gameSettings);
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalAccessException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
switch (returnNum)
|
||||
{
|
||||
case 0:
|
||||
return FogQuality.FAST;
|
||||
case 1:
|
||||
return FogQuality.FAST;
|
||||
case 2:
|
||||
return FogQuality.FANCY;
|
||||
case 3:
|
||||
return FogQuality.OFF;
|
||||
|
||||
default:
|
||||
return FogQuality.FAST;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
package com.backsun.lod.mixin;
|
||||
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.backsun.lod.renderer.RenderGlobalHook;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
|
||||
@Mixin(WorldRenderer.class)
|
||||
public class MixinWorldRenderer
|
||||
{
|
||||
@Inject(at = @At("HEAD"), method = "renderBlockLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/matrix/MatrixStack;DDD)V", cancellable = false)
|
||||
private void renderBlockLayer(RenderType blockLayerIn, MatrixStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
|
||||
{
|
||||
RenderGlobalHook.startRenderingStencil(blockLayerIn);
|
||||
}
|
||||
}
|
||||
@@ -1,776 +0,0 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import com.backsun.lod.util.enums.ColorDirection;
|
||||
import com.backsun.lod.util.enums.LodCorner;
|
||||
import com.backsun.lod.util.enums.LodLocation;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.color.BlockColors;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
|
||||
/**
|
||||
* This object contains position
|
||||
* and color data for an LOD object.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-13-2021
|
||||
*/
|
||||
public class LodChunk
|
||||
{
|
||||
/** how many different pieces of data are in one line */
|
||||
private static final int DATA_DELIMITER_COUNT = 28;
|
||||
|
||||
/** This is what separates each piece of data in the toData method */
|
||||
public static final char DATA_DELIMITER = ',';
|
||||
|
||||
public static final int WIDTH = 16;
|
||||
|
||||
private static final int CHUNK_DATA_WIDTH = WIDTH;
|
||||
private static final int CHUNK_DATA_HEIGHT = WIDTH;
|
||||
|
||||
/**
|
||||
* This is how many blocks are
|
||||
* required at a specific y-value
|
||||
* to constitute a LOD point
|
||||
*/
|
||||
private final int LOD_BLOCK_REQ = 16;
|
||||
// the max number of blocks per layer = 64 (8*8)
|
||||
// since each layer is 1/4 the chunk
|
||||
|
||||
|
||||
/** The x coordinate of the chunk. */
|
||||
public int x;
|
||||
/** The z coordinate of the chunk. */
|
||||
public int z;
|
||||
|
||||
// each short is the height of
|
||||
// that 8th of the chunk.
|
||||
public short top[];
|
||||
public short bottom[];
|
||||
|
||||
/** The average color of each 6 cardinal directions */
|
||||
public Color colors[];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
/**
|
||||
* Create an empty invisible LodChunk at (0,0)
|
||||
*/
|
||||
public LodChunk()
|
||||
{
|
||||
x = 0;
|
||||
z = 0;
|
||||
|
||||
top = new short[4];
|
||||
bottom = new short[4];
|
||||
colors = new Color[6];
|
||||
|
||||
// by default have the colors invisible
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
{
|
||||
colors[dir.value] = new Color(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an LodChunk from the string
|
||||
* generated by the toData method.
|
||||
*
|
||||
* @throws IllegalArgumentException if the data isn't valid to create a LodChunk
|
||||
* @throws NumberFormatException if the data can't be converted into an int at any point
|
||||
*/
|
||||
public LodChunk(String data) throws IllegalArgumentException, NumberFormatException
|
||||
{
|
||||
/*
|
||||
* data format:
|
||||
* x, z, top data, bottom data, rgb color data
|
||||
*
|
||||
* example:
|
||||
* 5,8, 4,4,4,4, 0,0,0,0, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
|
||||
*/
|
||||
|
||||
// make sure there are the correct number of entries
|
||||
// in the data string (28)
|
||||
int count = 0;
|
||||
|
||||
for(int i = 0; i < data.length(); i++)
|
||||
{
|
||||
if(data.charAt(i) == DATA_DELIMITER)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if(count != DATA_DELIMITER_COUNT)
|
||||
{
|
||||
throw new IllegalArgumentException("LodChunk constructor givin an invalid string. The data given had " + count + " delimiters when it should have had " + DATA_DELIMITER_COUNT + ".");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// index we will use when going through the String
|
||||
int index = 0;
|
||||
int lastIndex = 0;
|
||||
|
||||
|
||||
|
||||
// x and z position
|
||||
index = data.indexOf(DATA_DELIMITER, 0);
|
||||
x = Integer.parseInt(data.substring(0,index));
|
||||
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
z = Integer.parseInt(data.substring(lastIndex+1,index));
|
||||
|
||||
|
||||
|
||||
// top
|
||||
top = new short[4];
|
||||
for(LodLocation loc : LodLocation.values())
|
||||
{
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
|
||||
top[loc.value] = Short.parseShort(data.substring(lastIndex+1,index));
|
||||
}
|
||||
|
||||
|
||||
// bottom
|
||||
bottom = new short[4];
|
||||
for(LodLocation loc : LodLocation.values())
|
||||
{
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
|
||||
bottom[loc.value] = Short.parseShort(data.substring(lastIndex+1,index));
|
||||
}
|
||||
|
||||
|
||||
// color
|
||||
colors = new Color[6];
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
{
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
|
||||
// get r,g,b
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
|
||||
String raw = "";
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
raw = data.substring(lastIndex+1,index);
|
||||
red = Short.parseShort(raw);
|
||||
break;
|
||||
case 1:
|
||||
raw = data.substring(lastIndex+1,index);
|
||||
green = Short.parseShort(raw);
|
||||
break;
|
||||
case 2:
|
||||
raw = data.substring(lastIndex+1,index);
|
||||
blue = Short.parseShort(raw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
colors[dir.value] = new Color(red, green, blue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a LodChunk for a chunk in the given world. <br>
|
||||
* Note: The world is required to determine each block's color
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* thrown if either the chunk or world is null.
|
||||
*/
|
||||
public LodChunk(Chunk chunk, World world) throws IllegalArgumentException
|
||||
{
|
||||
if(chunk == null)
|
||||
{
|
||||
throw new IllegalArgumentException("LodChunk constructor given a null chunk");
|
||||
}
|
||||
if(world == null)
|
||||
{
|
||||
throw new IllegalArgumentException("LodChunk constructor given a null world");
|
||||
}
|
||||
|
||||
|
||||
x = chunk.getPos().x;
|
||||
z = chunk.getPos().z;
|
||||
|
||||
top = new short[4];
|
||||
bottom = new short[4];
|
||||
colors = new Color[6];
|
||||
|
||||
// generate the top and bottom points of this LOD
|
||||
for(LodLocation loc : LodLocation.values())
|
||||
{
|
||||
top[loc.value] = generateLodCorner(chunk, SectionGenerationMode.GENERATE_TOP, loc);
|
||||
bottom[loc.value] = generateLodCorner(chunk, SectionGenerationMode.GENERATE_BOTTOM, loc);
|
||||
}
|
||||
|
||||
// determine the average color for each direction
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
{
|
||||
colors[dir.value] = generateLodColorForDirection(chunk, world, dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================//
|
||||
// constructor helpers //
|
||||
//=====================//
|
||||
|
||||
|
||||
/**
|
||||
* Generate the height for the given LodLocation, either the top or bottom.
|
||||
* <br><br>
|
||||
* If invalid/null/empty chunks are given
|
||||
* crashes may occur.
|
||||
*/
|
||||
public short generateLodCorner(Chunk chunk, SectionGenerationMode generationMode, LodLocation lodLoc)
|
||||
{
|
||||
// should have a length of 16
|
||||
// (each storage is 16x16x16 and the
|
||||
// world height is 256)
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
|
||||
|
||||
|
||||
int startX = 0;
|
||||
int endX = 0;
|
||||
|
||||
int startZ = 0;
|
||||
int endZ = 0;
|
||||
|
||||
// determine where we should look in this
|
||||
// chunk
|
||||
switch(lodLoc)
|
||||
{
|
||||
case NE:
|
||||
// -N
|
||||
startZ = 0;
|
||||
endZ = (CHUNK_DATA_WIDTH / 2) - 1;
|
||||
// +E
|
||||
startX = CHUNK_DATA_WIDTH / 2;
|
||||
endX = CHUNK_DATA_WIDTH - 1;
|
||||
break;
|
||||
|
||||
case SE:
|
||||
// +S
|
||||
startZ = CHUNK_DATA_WIDTH / 2;
|
||||
endZ = CHUNK_DATA_WIDTH;
|
||||
// +E
|
||||
startX = CHUNK_DATA_WIDTH / 2;
|
||||
endX = CHUNK_DATA_WIDTH;
|
||||
break;
|
||||
|
||||
case SW:
|
||||
// +S
|
||||
startZ = CHUNK_DATA_WIDTH / 2;
|
||||
endZ = CHUNK_DATA_WIDTH;
|
||||
// -W
|
||||
startX = 0;
|
||||
endX = (CHUNK_DATA_WIDTH / 2) - 1;
|
||||
break;
|
||||
|
||||
case NW:
|
||||
// -N
|
||||
startZ = 0;
|
||||
endZ = CHUNK_DATA_WIDTH / 2;
|
||||
// -W
|
||||
startX = 0;
|
||||
endX = CHUNK_DATA_WIDTH / 2;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if(generationMode == SectionGenerationMode.GENERATE_TOP)
|
||||
return determineTopPoint(chunkSections, startX, endX, startZ, endZ);
|
||||
else
|
||||
return determineBottomPoint(chunkSections, startX, endX, startZ, endZ);
|
||||
}
|
||||
/** GENERATE_TOP, GENERATE_BOTTOM */
|
||||
private enum SectionGenerationMode
|
||||
{
|
||||
GENERATE_TOP,
|
||||
GENERATE_BOTTOM;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the lowest valid point from the bottom.
|
||||
*/
|
||||
private short determineBottomPoint(ChunkSection[] chunkSections, int startX, int endX, int startZ, int endZ)
|
||||
{
|
||||
// search from the bottom up
|
||||
for(int i = 0; i < chunkSections.length; i++)
|
||||
{
|
||||
for(int y = 0; y < CHUNK_DATA_HEIGHT; y++)
|
||||
{
|
||||
|
||||
if(isLayerValidLodPoint(chunkSections, startX, endX, startZ, endZ, i, y))
|
||||
{
|
||||
// we found
|
||||
// enough blocks in this
|
||||
// layer to count as an
|
||||
// LOD point
|
||||
return (short) (y + (i * CHUNK_DATA_HEIGHT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we never found a valid LOD point
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the highest valid point from the Top
|
||||
*/
|
||||
private short determineTopPoint(ChunkSection[] chunkSections, int startX, int endX, int startZ, int endZ)
|
||||
{
|
||||
// search from the top down
|
||||
for(int i = chunkSections.length - 1; i >= 0; i--)
|
||||
{
|
||||
for(int y = CHUNK_DATA_WIDTH - 1; y >= 0; y--)
|
||||
{
|
||||
if(isLayerValidLodPoint(chunkSections, startX, endX, startZ, endZ, i, y))
|
||||
{
|
||||
// we found
|
||||
// enough blocks in this
|
||||
// layer to count as an
|
||||
// LOD point
|
||||
return (short) (y + (i * CHUNK_DATA_HEIGHT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we never found a valid LOD point
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the layer between the given X, Z, and dataIndex
|
||||
* values a valid LOD point?
|
||||
*/
|
||||
private boolean isLayerValidLodPoint(
|
||||
ChunkSection[] chunkSections,
|
||||
int startX, int endX,
|
||||
int startZ, int endZ,
|
||||
int sectionIndex, int y)
|
||||
{
|
||||
// search through this layer
|
||||
int layerBlocks = 0;
|
||||
|
||||
for(int x = startX; x < endX; x++)
|
||||
{
|
||||
for(int z = startZ; z < endZ; z++)
|
||||
{
|
||||
if(chunkSections[sectionIndex] == null)
|
||||
{
|
||||
// this section doesn't have any blocks,
|
||||
// it is not a valid section
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(chunkSections[sectionIndex].getBlockState(x, y, z) != null && chunkSections[sectionIndex].getBlockState(x, y, z).getBlock() != Blocks.AIR)
|
||||
{
|
||||
// we found a valid block in
|
||||
// in this layer
|
||||
layerBlocks++;
|
||||
|
||||
if(layerBlocks >= LOD_BLOCK_REQ)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // z
|
||||
} // x
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the color of the given ColorDirection at the given chunk
|
||||
* in the given world.
|
||||
*/
|
||||
private Color generateLodColorForDirection(Chunk chunk, World world, ColorDirection colorDir)
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
BlockColors bc = mc.getBlockColors();
|
||||
|
||||
switch (colorDir)
|
||||
{
|
||||
case TOP:
|
||||
return generateLodColorVertical(chunk, colorDir, world, bc);
|
||||
case BOTTOM:
|
||||
return generateLodColorVertical(chunk, colorDir, world, bc);
|
||||
|
||||
case N:
|
||||
return generateLodColorHorizontal(chunk, colorDir, world, bc);
|
||||
case S:
|
||||
return generateLodColorHorizontal(chunk, colorDir, world, bc);
|
||||
|
||||
case E:
|
||||
return generateLodColorHorizontal(chunk, colorDir, world, bc);
|
||||
case W:
|
||||
return generateLodColorHorizontal(chunk, colorDir, world, bc);
|
||||
}
|
||||
|
||||
return new Color(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the color of the top or bottom of a given chunk in the given world.
|
||||
*
|
||||
* @throws IllegalArgumentException if given a ColorDirection other than TOP or BOTTOM
|
||||
*/
|
||||
private Color generateLodColorVertical(Chunk chunk, ColorDirection colorDir, World world, BlockColors bc)
|
||||
{
|
||||
if(colorDir != ColorDirection.TOP && colorDir != ColorDirection.BOTTOM)
|
||||
{
|
||||
throw new IllegalArgumentException("generateLodColorVertical only accepts the ColorDirection TOP or BOTTOM");
|
||||
}
|
||||
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
|
||||
int numbOfBlocks = 0;
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
|
||||
boolean goTopDown = (colorDir == ColorDirection.TOP);
|
||||
|
||||
|
||||
// either go top down or bottom up
|
||||
int dataStart = goTopDown? chunkSections.length - 1 : 0;
|
||||
int dataMax = chunkSections.length;
|
||||
int dataMin = 0;
|
||||
int dataIncrement = goTopDown? -1 : 1;
|
||||
|
||||
int topStart = goTopDown? CHUNK_DATA_HEIGHT - 1 : 0;
|
||||
int topMax = CHUNK_DATA_HEIGHT;
|
||||
int topMin = 0;
|
||||
int topIncrement = goTopDown? -1 : 1;
|
||||
|
||||
for(int x = 0; x < CHUNK_DATA_WIDTH; x++)
|
||||
{
|
||||
for(int z = 0; z < CHUNK_DATA_WIDTH; z++)
|
||||
{
|
||||
boolean foundBlock = false;
|
||||
|
||||
for(int i = dataStart; !foundBlock && i >= dataMin && i < dataMax; i += dataIncrement)
|
||||
{
|
||||
if(!foundBlock && chunkSections[i] != null)
|
||||
{
|
||||
for(int y = topStart; !foundBlock && y >= topMin && y < topMax; y += topIncrement)
|
||||
{
|
||||
int ci;
|
||||
ci = chunkSections[i].getBlockState(x, y, z).materialColor.colorValue;
|
||||
|
||||
if(ci == 0)
|
||||
{
|
||||
// skip air or invisible blocks
|
||||
continue;
|
||||
}
|
||||
|
||||
Color c = intToColor(ci);
|
||||
|
||||
red += c.getRed();
|
||||
green += c.getGreen();
|
||||
blue += c.getBlue();
|
||||
|
||||
numbOfBlocks++;
|
||||
|
||||
|
||||
// we found a valid block, skip to the
|
||||
// next x and z
|
||||
foundBlock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(numbOfBlocks == 0)
|
||||
numbOfBlocks = 1;
|
||||
|
||||
red /= numbOfBlocks;
|
||||
green /= numbOfBlocks;
|
||||
blue /= numbOfBlocks;
|
||||
|
||||
return new Color(red, green, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the color of the side of a given chunk in the given world for the given ColorDirection.
|
||||
*
|
||||
* @throws IllegalArgumentException if given a ColorDirection other than N, S, W, E (North, South, East, West)
|
||||
*/
|
||||
private Color generateLodColorHorizontal(Chunk chunk, ColorDirection colorDir, World world, BlockColors bc)
|
||||
{
|
||||
if(colorDir != ColorDirection.N && colorDir != ColorDirection.S && colorDir != ColorDirection.E && colorDir != ColorDirection.W)
|
||||
{
|
||||
throw new IllegalArgumentException("generateLodColorHorizontal only accepts the ColorDirection N (North), S (South), E (East), or W (West)");
|
||||
}
|
||||
|
||||
ChunkSection[] chunkSections = chunk.getSections();
|
||||
|
||||
int numbOfBlocks = 0;
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
|
||||
|
||||
// these don't change since the over direction doesn't matter
|
||||
int overStart = 0;
|
||||
int overIncrement = 1;
|
||||
|
||||
// determine which direction is "in"
|
||||
int inStart = 0;
|
||||
int inIncrement = 1;
|
||||
switch (colorDir)
|
||||
{
|
||||
case N:
|
||||
inStart = 0;
|
||||
inIncrement = 1;
|
||||
break;
|
||||
case S:
|
||||
inStart = CHUNK_DATA_WIDTH - 1;
|
||||
inIncrement = -1;
|
||||
break;
|
||||
case E:
|
||||
inStart = 0;
|
||||
inIncrement = 1;
|
||||
break;
|
||||
case W:
|
||||
inStart = CHUNK_DATA_WIDTH - 1;
|
||||
inIncrement = -1;
|
||||
break;
|
||||
default:
|
||||
// we were given an invalid position, return invisible.
|
||||
// this shouldn't happen and is mostly here to make the
|
||||
// compiler happy
|
||||
return new Color(0,0,0,0);
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < chunkSections.length; i++)
|
||||
{
|
||||
if (chunkSections[i] != null)
|
||||
{
|
||||
for (int y = 0; y < CHUNK_DATA_HEIGHT; y++)
|
||||
{
|
||||
boolean foundBlock = false;
|
||||
|
||||
// over moves "over" the side of the chunk
|
||||
// in moves "into" the chunk until it finds a block
|
||||
|
||||
for (int over = overStart; !foundBlock && over >= 0 && over < CHUNK_DATA_WIDTH; over += overIncrement)
|
||||
{
|
||||
for (int in = inStart; !foundBlock && in >= 0 && in < CHUNK_DATA_WIDTH; in += inIncrement)
|
||||
{
|
||||
int x = -1;
|
||||
int z = -1;
|
||||
|
||||
// determine which should be X and Z
|
||||
switch(colorDir)
|
||||
{
|
||||
case N:
|
||||
x = over;
|
||||
z = in;
|
||||
break;
|
||||
case S:
|
||||
x = over;
|
||||
z = in;
|
||||
break;
|
||||
case E:
|
||||
x = in;
|
||||
z = over;
|
||||
break;
|
||||
case W:
|
||||
x = in;
|
||||
z = over;
|
||||
break;
|
||||
default:
|
||||
// this will never happen, it would have
|
||||
// been caught by the switch before the loops
|
||||
break;
|
||||
}
|
||||
|
||||
int ci;
|
||||
ci = chunkSections[i].getBlockState(x, y, z).getMaterial().getColor().colorValue;
|
||||
|
||||
if (ci == 0) {
|
||||
// skip air or invisible blocks
|
||||
continue;
|
||||
}
|
||||
|
||||
Color c = intToColor(ci);
|
||||
|
||||
red += c.getRed();
|
||||
green += c.getGreen();
|
||||
blue += c.getBlue();
|
||||
|
||||
numbOfBlocks++;
|
||||
|
||||
// we found a valid block, skip to the
|
||||
// next x and z
|
||||
foundBlock = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if(numbOfBlocks == 0)
|
||||
numbOfBlocks = 1;
|
||||
|
||||
red /= numbOfBlocks;
|
||||
green /= numbOfBlocks;
|
||||
blue /= numbOfBlocks;
|
||||
|
||||
return new Color(red, green, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a BlockColors int into a Color object.
|
||||
*/
|
||||
private Color intToColor(int num)
|
||||
{
|
||||
int filter = 0b11111111;
|
||||
|
||||
int red = (num >> 16 ) & filter;
|
||||
int green = (num >> 8 ) & filter;
|
||||
int blue = num & filter;
|
||||
|
||||
return new Color(red, green, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a Color into a BlockColors object.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
private int colorToInt(Color color)
|
||||
{
|
||||
return color.getRGB();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// misc functions //
|
||||
//================//
|
||||
|
||||
/**
|
||||
* If this LOD is either invisible from every
|
||||
* direction or doesn't have a valid height
|
||||
* it is empty.
|
||||
*/
|
||||
public boolean isLodEmpty()
|
||||
{
|
||||
for(LodCorner corner : LodCorner.values())
|
||||
if(top[corner.value] != -1 || bottom[corner.value] != -1)
|
||||
// at least one corner is valid
|
||||
return false;
|
||||
|
||||
Color invisible = new Color(0,0,0,0);
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
if(!colors[dir.value].equals(invisible))
|
||||
// at least one direction has a non-invisible color
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// output //
|
||||
//========//
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Outputs all data in csv format
|
||||
* with the given delimiter.
|
||||
* <br>
|
||||
* Exports data in the form:
|
||||
* <br>
|
||||
* x, z, top data, bottom data, rgb color data
|
||||
*
|
||||
* <br>
|
||||
* example output:
|
||||
* <br>
|
||||
* 5,8, 4,4,4,4, 0,0,0,0 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
|
||||
*/
|
||||
public String toData()
|
||||
{
|
||||
String s = "";
|
||||
|
||||
s += Integer.toString(x) + DATA_DELIMITER + Integer.toString(z) + DATA_DELIMITER;
|
||||
|
||||
for(int i = 0; i < top.length; i++)
|
||||
{
|
||||
s += Short.toString(top[i]) + DATA_DELIMITER;
|
||||
}
|
||||
|
||||
for(int i = 0; i < bottom.length; i++)
|
||||
{
|
||||
s += Short.toString(bottom[i]) + DATA_DELIMITER;
|
||||
}
|
||||
|
||||
for(int i = 0; i < colors.length; i++)
|
||||
{
|
||||
s += Integer.toString(colors[i].getRed()) + DATA_DELIMITER + Integer.toString(colors[i].getGreen()) + DATA_DELIMITER + Integer.toString(colors[i].getBlue()) + DATA_DELIMITER;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String s = "";
|
||||
|
||||
s += "x: " + x + " z: " + z + "\t";
|
||||
|
||||
s += "(" + colors[ColorDirection.TOP.value].getRed() + ", " + colors[ColorDirection.TOP.value].getGreen() + ", " + colors[ColorDirection.TOP.value].getBlue() + ")";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -1,351 +0,0 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import com.backsun.lod.handlers.LodDimensionFileHandler;
|
||||
import com.backsun.lod.util.LodUtils;
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
|
||||
/**
|
||||
* This object holds all loaded LOD regions
|
||||
* for a given dimension.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-23-2021
|
||||
*/
|
||||
public class LodDimension
|
||||
{
|
||||
public final DimensionType dimension;
|
||||
|
||||
private volatile int width;
|
||||
private volatile int halfWidth;
|
||||
|
||||
public LodRegion regions[][];
|
||||
public boolean isRegionDirty[][];
|
||||
|
||||
private int centerX;
|
||||
private int centerZ;
|
||||
|
||||
private LodDimensionFileHandler fileHandler;
|
||||
|
||||
|
||||
public LodDimension(DimensionType newDimension, int newMaxWidth)
|
||||
{
|
||||
dimension = newDimension;
|
||||
width = newMaxWidth;
|
||||
|
||||
ServerChunkProvider provider = LodUtils.getServerWorldFromDimension(newDimension).getChunkProvider();
|
||||
fileHandler = new LodDimensionFileHandler(provider.getSavedData().folder, this);
|
||||
|
||||
regions = new LodRegion[width][width];
|
||||
isRegionDirty = new boolean[width][width];
|
||||
|
||||
// populate isRegionDirty
|
||||
for(int i = 0; i < width; i++)
|
||||
for(int j = 0; j < width; j++)
|
||||
isRegionDirty[i][j] = false;
|
||||
|
||||
centerX = 0;
|
||||
centerZ = 0;
|
||||
|
||||
halfWidth = (int)Math.floor(width / 2);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Move the center of this LodDimension and move all owned
|
||||
* regions over by the given x and z offset.
|
||||
*/
|
||||
public void move(int xOffset, int zOffset)
|
||||
{
|
||||
// if the x or z offset is equal to or greater than
|
||||
// the total size, just delete the current data
|
||||
// and update the centerX and/or centerZ
|
||||
if (Math.abs(xOffset) >= width || Math.abs(zOffset) >= width)
|
||||
{
|
||||
for(int x = 0; x < width; x++)
|
||||
{
|
||||
for(int z = 0; z < width; z++)
|
||||
{
|
||||
regions[x][z] = null;
|
||||
}
|
||||
}
|
||||
|
||||
// update the new center
|
||||
centerX += xOffset;
|
||||
centerZ += zOffset;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// X
|
||||
if(xOffset > 0)
|
||||
{
|
||||
// move everything over to the left (as the center moves to the right)
|
||||
for(int x = 0; x < width; x++)
|
||||
{
|
||||
for(int z = 0; z < width; z++)
|
||||
{
|
||||
if(x + xOffset < width)
|
||||
regions[x][z] = regions[x + xOffset][z];
|
||||
else
|
||||
regions[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// move everything over to the right (as the center moves to the left)
|
||||
for(int x = width - 1; x >= 0; x--)
|
||||
{
|
||||
for(int z = 0; z < width; z++)
|
||||
{
|
||||
if(x + xOffset >= 0)
|
||||
regions[x][z] = regions[x + xOffset][z];
|
||||
else
|
||||
regions[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Z
|
||||
if(zOffset > 0)
|
||||
{
|
||||
// move everything up (as the center moves down)
|
||||
for(int x = 0; x < width; x++)
|
||||
{
|
||||
for(int z = 0; z < width; z++)
|
||||
{
|
||||
if(z + zOffset < width)
|
||||
regions[x][z] = regions[x][z + zOffset];
|
||||
else
|
||||
regions[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// move everything down (as the center moves up)
|
||||
for(int x = 0; x < width; x++)
|
||||
{
|
||||
for(int z = width - 1; z >= 0; z--)
|
||||
{
|
||||
if(z + zOffset >= 0)
|
||||
regions[x][z] = regions[x][z + zOffset];
|
||||
else
|
||||
regions[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// update the new center
|
||||
centerX += xOffset;
|
||||
centerZ += zOffset;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the region at the given X and Z
|
||||
* <br>
|
||||
* Returns null if the region doesn't exist
|
||||
* or is outside the loaded area.
|
||||
*/
|
||||
public LodRegion getRegion(int regionX, int regionZ)
|
||||
{
|
||||
int xIndex = (regionX - centerX) + halfWidth;
|
||||
int zIndex = (regionZ - centerZ) + halfWidth;
|
||||
|
||||
if (!regionIsInRange(regionX, regionZ))
|
||||
// out of range
|
||||
return null;
|
||||
|
||||
if (regions[xIndex][zIndex] == null)
|
||||
{
|
||||
regions[xIndex][zIndex] = getRegionFromFile(regionX, regionZ);
|
||||
if (regions[xIndex][zIndex] == null)
|
||||
{
|
||||
regions[xIndex][zIndex] = new LodRegion(regionX, regionZ);
|
||||
}
|
||||
}
|
||||
|
||||
return regions[xIndex][zIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrite the LodRegion at the location of newRegion with newRegion.
|
||||
* @throws ArrayIndexOutOfBoundsException if newRegion is outside what can be stored in this LodDimension.
|
||||
*/
|
||||
public void setRegion(LodRegion newRegion) throws ArrayIndexOutOfBoundsException
|
||||
{
|
||||
int xIndex = (newRegion.x - centerX) + halfWidth;
|
||||
int zIndex = (centerZ - newRegion.z) + halfWidth;
|
||||
|
||||
if (!regionIsInRange(newRegion.x, newRegion.z))
|
||||
// out of range
|
||||
throw new ArrayIndexOutOfBoundsException();
|
||||
|
||||
regions[xIndex][zIndex] = newRegion;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Add the given LOD to this dimension at the coordinate
|
||||
* stored in the LOD. If an LOD already exists at the given
|
||||
* coordinates it will be overwritten.
|
||||
*/
|
||||
public void addLod(LodChunk lod)
|
||||
{
|
||||
int regionX = lod.x / LodRegion.SIZE;
|
||||
int regionZ = lod.z / LodRegion.SIZE;
|
||||
|
||||
// prevent issues if X/Z is negative and less than 16
|
||||
if (lod.x < 0)
|
||||
{
|
||||
regionX = (Math.abs(regionX) * -1) - 1;
|
||||
}
|
||||
if (lod.z < 0)
|
||||
{
|
||||
regionZ = (Math.abs(regionZ) * -1) - 1;
|
||||
}
|
||||
|
||||
// don't continue if the region can't be saved
|
||||
if (!regionIsInRange(regionX, regionZ))
|
||||
return;
|
||||
|
||||
LodRegion region = getRegion(regionX, regionZ);
|
||||
|
||||
if (region == null)
|
||||
{
|
||||
// if no region exists, create it
|
||||
region = new LodRegion(regionX, regionZ);
|
||||
setRegion(region);
|
||||
}
|
||||
|
||||
region.addLod(lod);
|
||||
|
||||
// mark the region as dirty so it will be saved to disk
|
||||
int xIndex = (regionX - centerX) + halfWidth;
|
||||
int zIndex = (regionZ - centerZ) + halfWidth;
|
||||
isRegionDirty[xIndex][zIndex] = true;
|
||||
fileHandler.saveDirtyRegionsToFileAsync();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the LodChunk at the given X and Z coordinates
|
||||
* in this dimension.
|
||||
* <br>
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public LodChunk getLodFromCoordinates(int chunkX, int chunkZ)
|
||||
{
|
||||
int regionX = chunkX / LodRegion.SIZE;
|
||||
int regionZ = chunkZ / LodRegion.SIZE;
|
||||
|
||||
// prevent issues if chunkX/Z is negative and less than width
|
||||
if (chunkX < 0)
|
||||
{
|
||||
regionX = (Math.abs(regionX) * -1) - 1;
|
||||
}
|
||||
if (chunkZ < 0)
|
||||
{
|
||||
regionZ = (Math.abs(regionZ) * -1) - 1;
|
||||
}
|
||||
|
||||
LodRegion region = getRegion(regionX, regionZ);
|
||||
|
||||
if(region == null)
|
||||
return null;
|
||||
|
||||
return region.getLod(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the region at the given X and Z coordinates from the
|
||||
* RegionFileHandler.
|
||||
*/
|
||||
public LodRegion getRegionFromFile(int regionX, int regionZ)
|
||||
{
|
||||
return fileHandler.loadRegionFromFile(regionX, regionZ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether the region at the given X and Z coordinates
|
||||
* is within the loaded range.
|
||||
*/
|
||||
private boolean regionIsInRange(int regionX, int regionZ)
|
||||
{
|
||||
int xIndex = (regionX - centerX) + halfWidth;
|
||||
int zIndex = (regionZ - centerZ) + halfWidth;
|
||||
|
||||
return xIndex >= 0 && xIndex < width && zIndex >= 0 && zIndex < width;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public int getCenterX()
|
||||
{
|
||||
return centerX;
|
||||
}
|
||||
|
||||
public int getCenterZ()
|
||||
{
|
||||
return centerZ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public int getWidth()
|
||||
{
|
||||
return width;
|
||||
}
|
||||
|
||||
public void setRegionWidth(int newWidth)
|
||||
{
|
||||
width = newWidth;
|
||||
halfWidth = (int)Math.floor(width / 2);
|
||||
|
||||
regions = new LodRegion[width][width];
|
||||
isRegionDirty = new boolean[width][width];
|
||||
|
||||
// populate isRegionDirty
|
||||
for(int i = 0; i < width; i++)
|
||||
for(int j = 0; j < width; j++)
|
||||
isRegionDirty[i][j] = false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String s = "";
|
||||
|
||||
s += "dim: " + dimension.toString() + "\t";
|
||||
s += "(" + centerX + "," + centerZ + ")";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
/**
|
||||
* A LodRegion is the a 32x32
|
||||
* 2D array of LodChunk objects.
|
||||
* Each LodRegion corresponds to
|
||||
* one file in the file system.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 1-22-2021
|
||||
*/
|
||||
public class LodRegion
|
||||
{
|
||||
/** number of chunks wide */
|
||||
public static final int SIZE = 32;
|
||||
|
||||
/** X coordinate of this region */
|
||||
public final int x;
|
||||
/** Z coordinate of this region */
|
||||
public final int z;
|
||||
|
||||
private LodChunk chunks[][];
|
||||
|
||||
|
||||
public LodRegion(int regionX, int regionZ)
|
||||
{
|
||||
x = regionX;
|
||||
z = regionZ;
|
||||
|
||||
chunks = new LodChunk[SIZE][SIZE];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given LOD to this region at the coordinate
|
||||
* stored in the LOD. If an LOD already exists at the given
|
||||
* coordinates it will be overwritten.
|
||||
*/
|
||||
public void addLod(LodChunk lod)
|
||||
{
|
||||
// we use ABS since LODs can be negative, but if they are
|
||||
// the region will negative first, therefore we don't have to
|
||||
// store the LOD chunks at negative indexes since we search
|
||||
// LOD the region first
|
||||
int xIndex = Math.abs(lod.x % SIZE);
|
||||
int zIndex = Math.abs(lod.z % SIZE);
|
||||
|
||||
chunks[xIndex][zIndex] = lod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the LodChunk at the given X and Z coordinates
|
||||
* in this region.
|
||||
* <br>
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public LodChunk getLod(int chunkX, int chunkZ)
|
||||
{
|
||||
// since we add LOD's with ABS, we get them the same way
|
||||
int arrayX = Math.abs(chunkX % SIZE);
|
||||
int arrayZ = Math.abs(chunkZ % SIZE);
|
||||
|
||||
if(arrayX >= SIZE || arrayZ >= SIZE)
|
||||
return null;
|
||||
|
||||
return chunks[arrayX][arrayZ];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all LodChunks in this region
|
||||
*/
|
||||
public LodChunk[][] getAllLods()
|
||||
{
|
||||
return chunks;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String s = "";
|
||||
|
||||
s += "x: " + x + " z: " + z + "\t";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import java.util.Hashtable;
|
||||
import java.util.Map;
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
|
||||
/**
|
||||
* This stores all LODs for a given world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-22-2021
|
||||
*/
|
||||
public class LodWorld
|
||||
{
|
||||
public String worldName;
|
||||
|
||||
/**
|
||||
* Key = Dimension id (as an int)
|
||||
*/
|
||||
private Map<DimensionType, LodDimension> lodDimensions;
|
||||
|
||||
|
||||
public LodWorld(String newWorldName)
|
||||
{
|
||||
worldName = newWorldName;
|
||||
lodDimensions = new Hashtable<DimensionType, LodDimension>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void addLodDimension(LodDimension newStorage)
|
||||
{
|
||||
lodDimensions.put(newStorage.dimension, newStorage);
|
||||
}
|
||||
|
||||
public LodDimension getLodDimension(DimensionType dimension)
|
||||
{
|
||||
return lodDimensions.get(dimension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes the max width in regions that each LodDimension
|
||||
* should use.
|
||||
*/
|
||||
public void resizeDimensionRegionWidth(int newWidth)
|
||||
{
|
||||
for(DimensionType key : lodDimensions.keySet())
|
||||
lodDimensions.get(key).setRegionWidth(newWidth);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String s = "";
|
||||
|
||||
s += worldName + "\t - dimensions: ";
|
||||
for(DimensionType key : lodDimensions.keySet())
|
||||
s += lodDimensions.get(key).dimension.toString() + ", ";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
|
||||
/**
|
||||
* This object is just a replacement for an array
|
||||
* to make things easier to understand in the LodRenderer
|
||||
* and BuildBufferThread.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-21-2021
|
||||
*/
|
||||
public class NearFarBuffer
|
||||
{
|
||||
public BufferBuilder nearBuffer;
|
||||
|
||||
public BufferBuilder farBuffer;
|
||||
|
||||
|
||||
public NearFarBuffer(BufferBuilder newNearBuffer, BufferBuilder newFarBuffer)
|
||||
{
|
||||
nearBuffer = newNearBuffer;
|
||||
farBuffer = newFarBuffer;
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import com.backsun.lod.util.enums.FogDistance;
|
||||
|
||||
/**
|
||||
* This object is just a replacement for an array
|
||||
* to make things easier to understand in the LodRenderer.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-27-2021
|
||||
*/
|
||||
public class NearFarFogSetting
|
||||
{
|
||||
public FogDistance nearFogSetting = FogDistance.NEAR;
|
||||
public FogDistance farFogSetting = FogDistance.FAR;
|
||||
|
||||
|
||||
public NearFarFogSetting()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public NearFarFogSetting(FogDistance newNearFogSetting, FogDistance newFarFogSetting)
|
||||
{
|
||||
nearFogSetting = newNearFogSetting;
|
||||
farFogSetting = newFarFogSetting;
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
package com.backsun.lod.proxy;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.backsun.lod.builders.LodBuilder;
|
||||
import com.backsun.lod.handlers.LodDimensionFileHandler;
|
||||
import com.backsun.lod.objects.LodChunk;
|
||||
import com.backsun.lod.objects.LodDimension;
|
||||
import com.backsun.lod.objects.LodRegion;
|
||||
import com.backsun.lod.objects.LodWorld;
|
||||
import com.backsun.lod.renderer.LodRenderer;
|
||||
import com.backsun.lod.renderer.RenderGlobalHook;
|
||||
import com.backsun.lod.util.LodConfig;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
//TODO Find a way to replace getIntegratedServer so this mod could be used on non-local worlds.
|
||||
// Minecraft.getMinecraft().getIntegratedServer()
|
||||
|
||||
/**
|
||||
* This handles all events sent to the client,
|
||||
* and is the starting point for most of this program.
|
||||
*
|
||||
* @author James_Seibel
|
||||
* @version 02-23-2021
|
||||
*/
|
||||
public class ClientProxy
|
||||
{
|
||||
private LodRenderer renderer;
|
||||
private LodWorld lodWorld;
|
||||
private LodBuilder lodBuilder;
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
public ClientProxy()
|
||||
{
|
||||
lodBuilder = new LodBuilder();
|
||||
renderer = new LodRenderer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// render event //
|
||||
//==============//
|
||||
|
||||
@SubscribeEvent
|
||||
public void renderWorldLast(RenderWorldLastEvent event)
|
||||
{
|
||||
RenderGlobalHook.endRenderingStencil();
|
||||
GL11.glStencilFunc(GL11.GL_EQUAL, 0, 0xFF);
|
||||
|
||||
if (LodConfig.CLIENT.drawLODs.get())
|
||||
renderLods(event.getPartialTicks());
|
||||
|
||||
GL11.glDisable(GL11.GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
/**
|
||||
* Do any setup that is required to draw LODs
|
||||
* and then tell the LodRenderer to draw.
|
||||
*/
|
||||
public void renderLods(float partialTicks)
|
||||
{
|
||||
// update the
|
||||
int newWidth = Math.max(4, (mc.gameSettings.renderDistanceChunks * LodChunk.WIDTH * 2) / LodRegion.SIZE);
|
||||
if (lodWorld != null && lodBuilder.regionWidth != newWidth)
|
||||
{
|
||||
lodWorld.resizeDimensionRegionWidth(newWidth);
|
||||
lodBuilder.regionWidth = newWidth;
|
||||
|
||||
// skip this frame, hopefully the lodWorld
|
||||
// should have everything set up by then
|
||||
return;
|
||||
}
|
||||
|
||||
// are we still in the same world?
|
||||
if (!lodWorld.worldName.equals(LodDimensionFileHandler.getCurrentWorldID()))
|
||||
// no, don't render the wrong world
|
||||
return;
|
||||
|
||||
|
||||
if (mc == null || mc.player == null || lodWorld == null)
|
||||
return;
|
||||
|
||||
LodDimension lodDim = lodWorld.getLodDimension(mc.player.world.getDimensionType());
|
||||
if (lodDim == null)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
// offset the regions
|
||||
double playerX = mc.player.getPosX();
|
||||
double playerZ = mc.player.getPosZ();
|
||||
|
||||
int xOffset = ((int)playerX / (LodChunk.WIDTH * LodRegion.SIZE)) - lodDim.getCenterX();
|
||||
int zOffset = ((int)playerZ / (LodChunk.WIDTH * LodRegion.SIZE)) - lodDim.getCenterZ();
|
||||
|
||||
if (xOffset != 0 || zOffset != 0)
|
||||
{
|
||||
lodDim.move(xOffset, zOffset);
|
||||
}
|
||||
|
||||
|
||||
|
||||
renderer.drawLODs(lodDim, partialTicks, mc.getProfiler());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================//
|
||||
// lod creation events //
|
||||
//=====================//
|
||||
|
||||
@SubscribeEvent
|
||||
public void chunkLoadEvent(ChunkEvent.Load event)
|
||||
{
|
||||
if (event.getChunk().getClass() == Chunk.class)
|
||||
lodWorld = lodBuilder.generateLodChunkAsync((Chunk) event.getChunk());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,828 +0,0 @@
|
||||
package com.backsun.lod.renderer;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import com.backsun.lod.builders.LodBufferBuilder;
|
||||
import com.backsun.lod.handlers.ReflectionHandler;
|
||||
import com.backsun.lod.objects.LodChunk;
|
||||
import com.backsun.lod.objects.LodDimension;
|
||||
import com.backsun.lod.objects.NearFarBuffer;
|
||||
import com.backsun.lod.objects.NearFarFogSetting;
|
||||
import com.backsun.lod.util.LodConfig;
|
||||
import com.backsun.lod.util.enums.ColorDirection;
|
||||
import com.backsun.lod.util.enums.FogDistance;
|
||||
import com.backsun.lod.util.enums.FogQuality;
|
||||
import com.backsun.lod.util.enums.LodCorner;
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.renderer.vertex.VertexBuffer;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.potion.Effects;
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
|
||||
|
||||
/**
|
||||
* This is where all the magic happens.
|
||||
* This is where LODs are draw to the world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2-27-2021
|
||||
*/
|
||||
public class LodRenderer
|
||||
{
|
||||
/** this is the light used when rendering the LODs,
|
||||
* it should be something different than what is used by Minecraft */
|
||||
private static final int LOD_GL_LIGHT_NUMBER = GL11.GL_LIGHT2;
|
||||
|
||||
/** If true the LODs colors will be replaced with
|
||||
* a checkerboard, this can be used for debugging. */
|
||||
public boolean debugging = false;
|
||||
|
||||
private Minecraft mc;
|
||||
private GameRenderer gameRender;
|
||||
private IProfiler profiler;
|
||||
private float farPlaneDistance;
|
||||
/** this is the radius of the LODs */
|
||||
private static final int LOD_CHUNK_DISTANCE_RADIUS = 6;
|
||||
|
||||
private ReflectionHandler reflectionHandler;
|
||||
|
||||
public LodDimension lodDimension = null;
|
||||
|
||||
|
||||
/** This is used to generate the buildable buffers */
|
||||
private LodBufferBuilder lodBufferBuilder = null;
|
||||
|
||||
/** The buffers that are used to draw LODs using near fog */
|
||||
private volatile BufferBuilder drawableNearBuffer = null;
|
||||
/** The buffers that are used to draw LODs using far fog */
|
||||
private volatile BufferBuilder drawableFarBuffer = null;
|
||||
|
||||
/** The buffers that are used to create LODs using near fog */
|
||||
private volatile BufferBuilder buildableNearBuffer = null;
|
||||
/** The buffers that are used to create LODs using far fog */
|
||||
private volatile BufferBuilder buildableFarBuffer = null;
|
||||
|
||||
/** This is the VertexBuffer used to draw any LODs that use near fog */
|
||||
private volatile VertexBuffer nearVbo = null;
|
||||
/** This is the VertexBuffer used to draw any LODs that use far fog */
|
||||
private volatile VertexBuffer farVbo = null;
|
||||
public static final VertexFormat LOD_VERTEX_FORMAT = DefaultVertexFormats.POSITION_COLOR;
|
||||
|
||||
/** This holds the thread used to generate new LODs off the main thread. */
|
||||
private ExecutorService genThread = Executors.newSingleThreadExecutor();
|
||||
|
||||
/** This is used to determine if the LODs should be regenerated */
|
||||
private int previousChunkRenderDistance = 0;
|
||||
/** This is used to determine if the LODs should be regenerated */
|
||||
private int prevChunkX = 0;
|
||||
/** This is used to determine if the LODs should be regenerated */
|
||||
private int prevChunkZ = 0;
|
||||
/** This is used to determine if the LODs should be regenerated */
|
||||
private FogDistance prevFogDistance = FogDistance.NEAR_AND_FAR;
|
||||
|
||||
/** if this is true the LOD buffers should be regenerated,
|
||||
* provided they aren't already being regenerated. */
|
||||
private boolean regen = false;
|
||||
/** if this is true the LOD buffers are currently being
|
||||
* regenerated. */
|
||||
private volatile boolean regenerating = false;
|
||||
/** if this is true new LOD buffers have been generated
|
||||
* and are waiting to be swapped with the drawable buffers*/
|
||||
private volatile boolean switchBuffers = false;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public LodRenderer()
|
||||
{
|
||||
mc = Minecraft.getInstance();
|
||||
gameRender = mc.gameRenderer;
|
||||
|
||||
reflectionHandler = new ReflectionHandler();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Besides drawing the LODs this method also starts
|
||||
* the async process of generating the Buffers that hold those LODs.
|
||||
*
|
||||
* @param newDimension The dimension to draw, if null doesn't replace the current dimension.
|
||||
* @param partialTicks how far into the current tick this method was called.
|
||||
*/
|
||||
public void drawLODs(LodDimension newDimension, float partialTicks, IProfiler newProfiler)
|
||||
{
|
||||
if (lodDimension == null && newDimension == null)
|
||||
{
|
||||
// if there aren't any loaded LodChunks
|
||||
// don't try drawing anything
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// initial setup //
|
||||
//===============//
|
||||
|
||||
|
||||
// used for debugging and viewing how long different processes take
|
||||
profiler = newProfiler;
|
||||
profiler.endSection();
|
||||
profiler.startSection("LOD");
|
||||
profiler.startSection("LOD setup");
|
||||
|
||||
ClientPlayerEntity player = mc.player;
|
||||
|
||||
// should LODs be regenerated?
|
||||
if ((int)player.getPosX() / LodChunk.WIDTH != prevChunkX ||
|
||||
(int)player.getPosZ() / LodChunk.WIDTH != prevChunkZ ||
|
||||
previousChunkRenderDistance != mc.gameSettings.renderDistanceChunks ||
|
||||
prevFogDistance != LodConfig.CLIENT.fogDistance.get() ||
|
||||
lodDimension != newDimension)
|
||||
{
|
||||
// yes
|
||||
regen = true;
|
||||
|
||||
prevChunkX = (int)player.getPosX() / LodChunk.WIDTH;
|
||||
prevChunkZ = (int)player.getPosZ() / LodChunk.WIDTH;
|
||||
prevFogDistance = LodConfig.CLIENT.fogDistance.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
// nope, the player hasn't moved, the
|
||||
// render distance hasn't changed, and
|
||||
// the dimension is the same
|
||||
}
|
||||
|
||||
lodDimension = newDimension;
|
||||
if (lodDimension == null)
|
||||
{
|
||||
// if there aren't any loaded LodChunks
|
||||
// don't try drawing anything
|
||||
return;
|
||||
}
|
||||
|
||||
if (LodConfig.CLIENT.drawCheckerBoard.get())
|
||||
{
|
||||
if (debugging != LodConfig.CLIENT.drawCheckerBoard.get())
|
||||
regen = true;
|
||||
debugging = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debugging != LodConfig.CLIENT.drawCheckerBoard.get())
|
||||
regen = true;
|
||||
debugging = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// determine how far the game's render distance is currently set
|
||||
int renderDistWidth = mc.gameSettings.renderDistanceChunks;
|
||||
farPlaneDistance = renderDistWidth * LodChunk.WIDTH;
|
||||
|
||||
// set how big the LODs will be and how far they will go
|
||||
int totalLength = (int) farPlaneDistance * LOD_CHUNK_DISTANCE_RADIUS * 2;
|
||||
int numbChunksWide = (totalLength / LodChunk.WIDTH);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// create the LODs //
|
||||
//=================//
|
||||
|
||||
// only regenerate the LODs if:
|
||||
// 1. we want to regenerate LODs
|
||||
// 2. we aren't already regenerating the LODs
|
||||
// 3. we aren't waiting for the build and draw buffers to swap
|
||||
// (this is to prevent thread conflicts)
|
||||
if (regen && !regenerating && !switchBuffers)
|
||||
{
|
||||
regenerating = true;
|
||||
|
||||
if (lodBufferBuilder == null)
|
||||
lodBufferBuilder = new LodBufferBuilder();
|
||||
|
||||
// this will mainly happen when the view distance is changed
|
||||
if (drawableNearBuffer == null || drawableFarBuffer == null ||
|
||||
previousChunkRenderDistance != mc.gameSettings.renderDistanceChunks)
|
||||
setupBuffers(numbChunksWide);
|
||||
|
||||
// generate the LODs on a separate thread to prevent stuttering or freezing
|
||||
generateLodBuffersAsync(player.getPosX(), player.getPosZ(), numbChunksWide);
|
||||
|
||||
// the regen process has been started
|
||||
regen = false;
|
||||
}
|
||||
|
||||
// replace the buffers used to draw and build,
|
||||
// this is only done when the createLodBufferGenerationThread
|
||||
// has finished executing on a parallel thread.
|
||||
if (switchBuffers)
|
||||
{
|
||||
swapBuffers();
|
||||
switchBuffers = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===========================//
|
||||
// GL settings for rendering //
|
||||
//===========================//
|
||||
|
||||
// set the required open GL settings
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||
GL11.glEnable(GL11.GL_COLOR_MATERIAL);
|
||||
GL11.glEnable(GL11.GL_DEPTH_TEST);
|
||||
|
||||
Matrix4f modelViewMatrix = generateModelViewMatrix(partialTicks);
|
||||
|
||||
setupProjectionMatrix(partialTicks);
|
||||
setupLighting(partialTicks);
|
||||
|
||||
NearFarFogSetting fogSetting = determineFogSettings();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
|
||||
setupFog(fogSetting.nearFogSetting, reflectionHandler.getFogQuality());
|
||||
sendLodsToGpuAndDraw(nearVbo, modelViewMatrix);
|
||||
|
||||
setupFog(fogSetting.farFogSetting, reflectionHandler.getFogQuality());
|
||||
sendLodsToGpuAndDraw(farVbo, modelViewMatrix);
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// cleanup //
|
||||
//=========//
|
||||
|
||||
profiler.endStartSection("LOD cleanup");
|
||||
|
||||
// this must be done otherwise other parts of the screen may be drawn with a fog effect
|
||||
// IE the GUI
|
||||
FogRenderer.resetFog();
|
||||
RenderSystem.disableFog();
|
||||
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(LOD_GL_LIGHT_NUMBER);
|
||||
|
||||
// this can't be called until after the buffers are built
|
||||
// because otherwise the buffers may be set to the wrong size
|
||||
previousChunkRenderDistance = mc.gameSettings.renderDistanceChunks;
|
||||
|
||||
|
||||
// end of profiler tracking
|
||||
profiler.endSection();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create the model view matrix to move the LODs
|
||||
* from object space into world space.
|
||||
*/
|
||||
private Matrix4f generateModelViewMatrix(float partialTicks)
|
||||
{
|
||||
// get all relevant camera info
|
||||
ActiveRenderInfo renderInfo = mc.gameRenderer.getActiveRenderInfo();
|
||||
Vector3d projectedView = renderInfo.getProjectedView();
|
||||
|
||||
|
||||
// generate the model view matrix
|
||||
MatrixStack matrixStack = new MatrixStack();
|
||||
matrixStack.push();
|
||||
// translate and rotate to the current camera location
|
||||
matrixStack.rotate(Vector3f.XP.rotationDegrees(renderInfo.getPitch()));
|
||||
matrixStack.rotate(Vector3f.YP.rotationDegrees(renderInfo.getYaw() + 180));
|
||||
matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z);
|
||||
|
||||
return matrixStack.getLast().getMatrix();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This is where the actual drawing happens.
|
||||
*
|
||||
* @param buffers the buffers sent to the GPU to draw
|
||||
*/
|
||||
private void sendLodsToGpuAndDraw(VertexBuffer vbo, Matrix4f modelViewMatrix)
|
||||
{
|
||||
if (vbo == null)
|
||||
return;
|
||||
|
||||
profiler.endStartSection("LOD draw setup");
|
||||
vbo.bindBuffer();
|
||||
// 0L is the starting pointer, and the value doesn't appear to matter
|
||||
LOD_VERTEX_FORMAT.setupBufferState(0L);
|
||||
|
||||
profiler.endStartSection("LOD draw");
|
||||
vbo.draw(modelViewMatrix, GL11.GL_QUADS);
|
||||
|
||||
profiler.endStartSection("LOD draw cleanup");
|
||||
VertexBuffer.unbindBuffer();
|
||||
LOD_VERTEX_FORMAT.clearBufferState();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// Setup Functions //
|
||||
//=================//
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private void setupFog(FogDistance fogDistance, FogQuality fogQuality)
|
||||
{
|
||||
if(fogQuality == FogQuality.OFF)
|
||||
{
|
||||
FogRenderer.resetFog();
|
||||
RenderSystem.disableFog();
|
||||
return;
|
||||
}
|
||||
|
||||
if(fogDistance == FogDistance.NEAR_AND_FAR)
|
||||
{
|
||||
throw new IllegalArgumentException("setupFog doesn't accept the NEAR_AND_FAR fog distance.");
|
||||
}
|
||||
|
||||
// the multipliers are percentages
|
||||
// of the regular view distance.
|
||||
|
||||
if(fogDistance == FogDistance.NEAR)
|
||||
{
|
||||
// the reason that I wrote fogEnd then fogStart backwards
|
||||
// is because we are using fog backwards to how
|
||||
// it is normally used, with it hiding near objects
|
||||
// instead of far objects.
|
||||
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
{
|
||||
RenderSystem.fogEnd(farPlaneDistance * 0.3f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
RenderSystem.fogStart(farPlaneDistance * 0.35f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
}
|
||||
else if(fogQuality == FogQuality.FAST)
|
||||
{
|
||||
// for the far fog of the normal chunks
|
||||
// to start right where the LODs' end use:
|
||||
// end = 0.8f, start = 1.5f
|
||||
|
||||
RenderSystem.fogEnd(farPlaneDistance * 1.5f);
|
||||
RenderSystem.fogStart(farPlaneDistance * 2.0f);
|
||||
}
|
||||
}
|
||||
else if(fogDistance == FogDistance.FAR)
|
||||
{
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
{
|
||||
RenderSystem.fogStart(farPlaneDistance * 0.78f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
RenderSystem.fogEnd(farPlaneDistance * 1.0f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
}
|
||||
else if(fogQuality == FogQuality.FAST)
|
||||
{
|
||||
RenderSystem.fogStart(farPlaneDistance * 0.5f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
RenderSystem.fogEnd(farPlaneDistance * 0.75f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
}
|
||||
}
|
||||
|
||||
RenderSystem.fogMode(GlStateManager.FogMode.LINEAR);
|
||||
RenderSystem.enableFog();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* create a new projection matrix and send it over to the GPU
|
||||
* <br><br>
|
||||
* A lot of this code is copied from renderWorld (line 578)
|
||||
* in the GameRender class. The code copied is anything with
|
||||
* a matrixStack and is responsible for making sure the LOD
|
||||
* objects distort correctly relative to the rest of the world.
|
||||
* Distortions are caused by: standing in a nether portal,
|
||||
* nausea potion effect, walking bobbing.
|
||||
*
|
||||
* @param partialTicks how many ticks into the frame we are
|
||||
*/
|
||||
private void setupProjectionMatrix(float partialTicks)
|
||||
{
|
||||
// Note: if the LOD objects don't distort correctly
|
||||
// compared to regular minecraft terrain, make sure
|
||||
// all the transformations in renderWorld are here too
|
||||
|
||||
MatrixStack matrixStack = new MatrixStack();
|
||||
matrixStack.push();
|
||||
|
||||
gameRender.hurtCameraEffect(matrixStack, partialTicks);
|
||||
if (this.mc.gameSettings.viewBobbing) {
|
||||
gameRender.applyBobbing(matrixStack, partialTicks);
|
||||
}
|
||||
|
||||
// potion and nausea effects
|
||||
float f = MathHelper.lerp(partialTicks, mc.player.prevTimeInPortal, mc.player.timeInPortal) * mc.gameSettings.screenEffectScale * mc.gameSettings.screenEffectScale;
|
||||
if (f > 0.0F) {
|
||||
int i = this.mc.player.isPotionActive(Effects.NAUSEA) ? 7 : 20;
|
||||
float f1 = 5.0F / (f * f + 5.0F) - f * 0.04F;
|
||||
f1 = f1 * f1;
|
||||
Vector3f vector3f = new Vector3f(0.0F, MathHelper.SQRT_2 / 2.0F, MathHelper.SQRT_2 / 2.0F);
|
||||
matrixStack.rotate(vector3f.rotationDegrees((gameRender.rendererUpdateCount + partialTicks) * i));
|
||||
matrixStack.scale(1.0F / f1, 1.0F, 1.0F);
|
||||
float f2 = -(gameRender.rendererUpdateCount + partialTicks) * i;
|
||||
matrixStack.rotate(vector3f.rotationDegrees(f2));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// this projection matrix allows us to see past the normal
|
||||
// world render distance
|
||||
Matrix4f projectionMatrix =
|
||||
Matrix4f.perspective(
|
||||
getFov(partialTicks, true),
|
||||
(float)this.mc.getMainWindow().getFramebufferWidth() / (float)this.mc.getMainWindow().getFramebufferHeight(),
|
||||
0.5F,
|
||||
this.farPlaneDistance * LOD_CHUNK_DISTANCE_RADIUS * 2);
|
||||
|
||||
// add the screen space distortions
|
||||
projectionMatrix.mul(matrixStack.getLast().getMatrix());
|
||||
gameRender.resetProjectionMatrix(projectionMatrix);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* setup the lighting to be used for the LODs
|
||||
*/
|
||||
private void setupLighting(float partialTicks)
|
||||
{
|
||||
float sunBrightness = lodDimension.dimension.hasSkyLight() ? mc.world.getSunBrightness(partialTicks) : 0.2f;
|
||||
float gammaMultiplyer = (float)mc.gameSettings.gamma - 0.5f;
|
||||
float lightStrength = sunBrightness - 0.7f + (gammaMultiplyer * 0.2f);
|
||||
|
||||
float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f};
|
||||
|
||||
ByteBuffer temp = ByteBuffer.allocateDirect(16);
|
||||
temp.order(ByteOrder.nativeOrder());
|
||||
GL11.glLightfv(LOD_GL_LIGHT_NUMBER, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip());
|
||||
GL11.glEnable(LOD_GL_LIGHT_NUMBER); // Enable the above lighting
|
||||
|
||||
RenderSystem.enableLighting();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create all buffers that will be used.
|
||||
*/
|
||||
private void setupBuffers(int numbChunksWide)
|
||||
{
|
||||
// calculate the max amount of storage needed (in bytes)
|
||||
int bufferMaxCapacity = (numbChunksWide * numbChunksWide * (6 * 4 * (3 + 4)));
|
||||
// (numbChunksWide * numbChunksWide *
|
||||
// (sidesOnACube * pointsInASquare * (positionPoints + colorPoints)))
|
||||
|
||||
// TODO complain or do something when memory is too low
|
||||
// currently the VM will just crash and complain there is no more memory
|
||||
// issue #4
|
||||
drawableNearBuffer = new BufferBuilder(bufferMaxCapacity);
|
||||
drawableFarBuffer = new BufferBuilder(bufferMaxCapacity);
|
||||
|
||||
buildableNearBuffer = new BufferBuilder(bufferMaxCapacity);
|
||||
buildableFarBuffer = new BufferBuilder(bufferMaxCapacity);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//======================//
|
||||
// Other Misc Functions //
|
||||
//======================//
|
||||
|
||||
|
||||
/**
|
||||
* @Returns -1 if there are no valid points
|
||||
*/
|
||||
private int getValidHeightPoint(short[] heightPoints)
|
||||
{
|
||||
if (heightPoints[LodCorner.NE.value] != -1)
|
||||
return heightPoints[LodCorner.NE.value];
|
||||
if (heightPoints[LodCorner.NW.value] != -1)
|
||||
return heightPoints[LodCorner.NW.value];
|
||||
if (heightPoints[LodCorner.SE.value] != -1)
|
||||
return heightPoints[LodCorner.NE.value];
|
||||
return heightPoints[LodCorner.NE.value];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a thread to asynchronously generate LOD buffers
|
||||
* centered around the given camera X and Z.
|
||||
* <br>
|
||||
* This thread will write to the drawableNearBuffers and drawableFarBuffers.
|
||||
* <br>
|
||||
* After the buildable buffers have been generated they must be
|
||||
* swapped with the drawable buffers to be drawn.
|
||||
*/
|
||||
private void generateLodBuffersAsync(double playerX, double playerZ,
|
||||
int numbChunksWide)
|
||||
{
|
||||
// this is where we store the points for each LOD object
|
||||
AxisAlignedBB lodArray[][] = new AxisAlignedBB[numbChunksWide][numbChunksWide];
|
||||
// this is where we store the color for each LOD object
|
||||
Color colorArray[][] = new Color[numbChunksWide][numbChunksWide];
|
||||
|
||||
int alpha = 255; // 0 - 255
|
||||
Color red = new Color(255, 0, 0, alpha);
|
||||
Color black = new Color(0, 0, 0, alpha);
|
||||
Color white = new Color(255, 255, 255, alpha);
|
||||
@SuppressWarnings("unused")
|
||||
Color invisible = new Color(0,0,0,0);
|
||||
@SuppressWarnings("unused")
|
||||
Color error = new Color(255, 0, 225, alpha); // bright pink
|
||||
|
||||
// this seemingly useless math is required,
|
||||
// just using (int) camera doesn't work
|
||||
int playerXChunkOffset = ((int) playerX / LodChunk.WIDTH) * LodChunk.WIDTH;
|
||||
int playerZChunkOffset = ((int) playerZ / LodChunk.WIDTH) * LodChunk.WIDTH;
|
||||
// this is where we will start drawing squares
|
||||
// (exactly half the total width)
|
||||
int startX = (-LodChunk.WIDTH * (numbChunksWide / 2)) + playerXChunkOffset;
|
||||
int startZ = (-LodChunk.WIDTH * (numbChunksWide / 2)) + playerZChunkOffset;
|
||||
|
||||
Thread t = new Thread(()->
|
||||
{
|
||||
// x axis
|
||||
for (int i = 0; i < numbChunksWide; i++)
|
||||
{
|
||||
// z axis
|
||||
for (int j = 0; j < numbChunksWide; j++)
|
||||
{
|
||||
// skip the middle
|
||||
// (As the player moves some chunks will overlap or be missing,
|
||||
// this is just how chunk loading/unloading works. This can hopefully
|
||||
// be hidden with careful use of fog)
|
||||
int middle = (numbChunksWide / 2);
|
||||
if (isCoordInCenterArea(i, j, middle))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// set where this square will be drawn in the world
|
||||
double xOffset = (LodChunk.WIDTH * i) + // offset by the number of LOD blocks
|
||||
startX; // offset so the center LOD block is centered underneath the player
|
||||
double yOffset = 0;
|
||||
double zOffset = (LodChunk.WIDTH * j) + startZ;
|
||||
|
||||
int chunkX = i + (startX / LodChunk.WIDTH);
|
||||
int chunkZ = j + (startZ / LodChunk.WIDTH);
|
||||
|
||||
LodChunk lod = lodDimension.getLodFromCoordinates(chunkX, chunkZ);
|
||||
if (lod == null)
|
||||
{
|
||||
// note: for some reason if any color or lod objects are set here
|
||||
// it causes the game to use 100% gpu;
|
||||
// undefined in the debug menu
|
||||
// and drop to ~6 fps.
|
||||
colorArray[i][j] = null;
|
||||
lodArray[i][j] = null;
|
||||
|
||||
// This is something I would like to have done someday
|
||||
// but currently world generation is too slow to have it
|
||||
// here, maybe it could be put in a loop
|
||||
// that happens every tick for a specific number of chunks?
|
||||
// LodChunk tmpLod = new LodChunk();
|
||||
// tmpLod.x = chunkX;
|
||||
// tmpLod.z = chunkZ;
|
||||
// lodDimension.addLod(tmpLod);
|
||||
//
|
||||
// world.getChunkProvider().getChunk(chunkX, chunkZ, true);
|
||||
// System.out.println(chunkX + "," + chunkZ);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
Color c = new Color(
|
||||
(lod.colors[ColorDirection.TOP.value].getRed()),
|
||||
(lod.colors[ColorDirection.TOP.value].getGreen()),
|
||||
(lod.colors[ColorDirection.TOP.value].getBlue()),
|
||||
lod.colors[ColorDirection.TOP.value].getAlpha());
|
||||
|
||||
if (!debugging)
|
||||
{
|
||||
// add the color to the array
|
||||
colorArray[i][j] = c;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if debugging draw the squares as a black and white checker board
|
||||
if ((chunkX + chunkZ) % 2 == 0)
|
||||
c = white;
|
||||
else
|
||||
c = black;
|
||||
// draw the first square as red
|
||||
if (i == 0 && j == 0)
|
||||
c = red;
|
||||
|
||||
colorArray[i][j] = c;
|
||||
}
|
||||
|
||||
|
||||
// add the new box to the array
|
||||
int topPoint = getValidHeightPoint(lod.top);
|
||||
int bottomPoint = getValidHeightPoint(lod.bottom);
|
||||
|
||||
// don't draw an LOD if it is empty
|
||||
if (topPoint == -1 && bottomPoint == -1)
|
||||
continue;
|
||||
|
||||
lodArray[i][j] = new AxisAlignedBB(0, bottomPoint, 0, LodChunk.WIDTH, topPoint, LodChunk.WIDTH).offset(xOffset, yOffset, zOffset);
|
||||
}
|
||||
}
|
||||
|
||||
// generate our new buildable buffers
|
||||
NearFarBuffer nearFarBuffers = lodBufferBuilder.createBuffers(
|
||||
buildableNearBuffer, buildableFarBuffer,
|
||||
LodConfig.CLIENT.fogDistance.get(), lodArray, colorArray);
|
||||
|
||||
// update our buffers
|
||||
buildableNearBuffer = nearFarBuffers.nearBuffer;
|
||||
buildableFarBuffer = nearFarBuffers.farBuffer;
|
||||
|
||||
// mark the buildable buffers as ready to swap
|
||||
regenerating = false;
|
||||
switchBuffers = true;
|
||||
});
|
||||
|
||||
genThread.execute(t);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Swap buildable and drawable buffers.
|
||||
*/
|
||||
private void swapBuffers()
|
||||
{
|
||||
// swap the BufferBuilders
|
||||
BufferBuilder tmp = buildableNearBuffer;
|
||||
buildableNearBuffer = drawableNearBuffer;
|
||||
drawableNearBuffer = tmp;
|
||||
|
||||
tmp = buildableFarBuffer;
|
||||
buildableFarBuffer = drawableFarBuffer;
|
||||
drawableFarBuffer = tmp;
|
||||
|
||||
|
||||
// bind the buffers with their respective VBOs
|
||||
if (nearVbo != null)
|
||||
nearVbo.close();
|
||||
|
||||
nearVbo = new VertexBuffer(LOD_VERTEX_FORMAT);
|
||||
nearVbo.upload(drawableNearBuffer);
|
||||
|
||||
|
||||
if (farVbo != null)
|
||||
farVbo.close();
|
||||
|
||||
farVbo = new VertexBuffer(LOD_VERTEX_FORMAT);
|
||||
farVbo.upload(drawableFarBuffer);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns if the given coordinate is in the loaded area of the world.
|
||||
* @param centerCoordinate the center of the loaded world
|
||||
*/
|
||||
private boolean isCoordInCenterArea(int i, int j, int centerCoordinate)
|
||||
{
|
||||
return (i >= centerCoordinate - mc.gameSettings.renderDistanceChunks
|
||||
&& i <= centerCoordinate + mc.gameSettings.renderDistanceChunks)
|
||||
&&
|
||||
(j >= centerCoordinate - mc.gameSettings.renderDistanceChunks
|
||||
&& j <= centerCoordinate + mc.gameSettings.renderDistanceChunks);
|
||||
}
|
||||
|
||||
|
||||
public double getFov(float partialTicks, boolean useFovSetting)
|
||||
{
|
||||
return mc.gameRenderer.getFOVModifier(mc.gameRenderer.getActiveRenderInfo(), partialTicks, useFovSetting);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Based on the fogDistance setting and
|
||||
* optifine's fogQuality setting return what fog
|
||||
* settings should be used when rendering.
|
||||
*/
|
||||
private NearFarFogSetting determineFogSettings()
|
||||
{
|
||||
NearFarFogSetting fogSetting = new NearFarFogSetting();
|
||||
|
||||
LodConfig.CLIENT.fogDistance.get();
|
||||
switch(reflectionHandler.getFogQuality())
|
||||
{
|
||||
case FANCY:
|
||||
|
||||
switch(LodConfig.CLIENT.fogDistance.get())
|
||||
{
|
||||
case NEAR_AND_FAR:
|
||||
fogSetting.nearFogSetting = FogDistance.NEAR;
|
||||
fogSetting.farFogSetting = FogDistance.FAR;
|
||||
break;
|
||||
|
||||
case NEAR:
|
||||
fogSetting.nearFogSetting = FogDistance.NEAR;
|
||||
fogSetting.farFogSetting = FogDistance.NEAR;
|
||||
break;
|
||||
|
||||
case FAR:
|
||||
fogSetting.nearFogSetting = FogDistance.FAR;
|
||||
fogSetting.farFogSetting = FogDistance.FAR;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case FAST:
|
||||
// fast fog setting should only have one type of
|
||||
// fog, since the LODs are separated into a near
|
||||
// and far portion; and fast fog is rendered from the
|
||||
// frustrum's perspective instead of the camera
|
||||
|
||||
switch(LodConfig.CLIENT.fogDistance.get())
|
||||
{
|
||||
case NEAR_AND_FAR:
|
||||
fogSetting.nearFogSetting = FogDistance.NEAR;
|
||||
fogSetting.farFogSetting = FogDistance.NEAR;
|
||||
break;
|
||||
|
||||
case NEAR:
|
||||
fogSetting.nearFogSetting = FogDistance.NEAR;
|
||||
fogSetting.farFogSetting = FogDistance.NEAR;
|
||||
break;
|
||||
|
||||
case FAR:
|
||||
fogSetting.nearFogSetting = FogDistance.FAR;
|
||||
fogSetting.farFogSetting = FogDistance.FAR;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case OFF:
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return fogSetting;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package com.backsun.lod.renderer;
|
||||
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
|
||||
/**
|
||||
* This code is used for drawing
|
||||
* to the stencil buffer.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-17-2021
|
||||
*/
|
||||
public class RenderGlobalHook
|
||||
{
|
||||
/**
|
||||
* this variable should be the same as the method name below.
|
||||
* It is used when transforming the RenderGlobal class'
|
||||
* renderBlockLayer method.
|
||||
*/
|
||||
public static final String START_STENCIL_METHOD_NAME = "startRenderingStencil";
|
||||
|
||||
/**
|
||||
* This method tells OpenGL to start drawing everything to the stencil.
|
||||
* This is done to prevent LODs from being rendered on top of the world.
|
||||
* <br><br>
|
||||
* Called in the order (as of minecraft 1.16.4): <br>
|
||||
* RenderType.getSolid() <br>
|
||||
* RenderType.getCutoutMipped() <br>
|
||||
* RenderType.getCutout() <br>
|
||||
* RenderType.getTranslucent() <br>
|
||||
* RenderType.getTripwire() <br>
|
||||
*/
|
||||
public static void startRenderingStencil(RenderType blockLayerIn)
|
||||
{
|
||||
// we only enable drawing to the stencil once since
|
||||
// we want to skip the rendering of the out of world fog
|
||||
// but catch everything else
|
||||
if (blockLayerIn == RenderType.getSolid())
|
||||
{
|
||||
// solid is the first layer rendered
|
||||
// clear the buffer so we can start fresh.
|
||||
// if this isn't cleared first we will have overlap with the fog
|
||||
// outside the world
|
||||
GL11.glClearStencil(0);
|
||||
GL11.glStencilMask(0x11111111);
|
||||
GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
GL11.glEnable(GL11.GL_STENCIL_TEST);
|
||||
GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0x11111111);
|
||||
GL11.glStencilMask(0b11111111);
|
||||
GL11.glStencilOp(GL11.GL_KEEP, // this doesn't mater since GL_ALWAYS is being used
|
||||
GL11.GL_KEEP, // stencil test passes
|
||||
GL11.GL_REPLACE); // stencil + depth pass
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* this variable should be the same as the method name below.
|
||||
* It is used when transforming the RenderGlobal class'
|
||||
* renderBlockLayer method.
|
||||
*/
|
||||
public static final String END_STENCIL_METHOD_NAME = "endRenderingStencil";
|
||||
|
||||
/**
|
||||
* Currently this method isn't used in any transformations since we end
|
||||
* the stencil drawing in the ClientProxy right before we draw the LODs.
|
||||
*/
|
||||
public static void endRenderingStencil(RenderType blockLayerIn)
|
||||
{
|
||||
GL11.glStencilOp(GL11.GL_KEEP, // this doesn't mater since GL_ALWAYS is being used
|
||||
GL11.GL_KEEP, // stencil test passes
|
||||
GL11.GL_KEEP); // stencil + depth pass
|
||||
}
|
||||
|
||||
public static void endRenderingStencil()
|
||||
{
|
||||
endRenderingStencil(null);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
package com.backsun.lod.renderer;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
/**
|
||||
* This holds miscellaneous helper code
|
||||
* to be used in the rendering process.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2-13-2021
|
||||
*/
|
||||
public class RenderUtil
|
||||
{
|
||||
/**
|
||||
* Returns if the given coordinate is in the loaded area of the world.
|
||||
* @param centerCoordinate the center of the loaded world
|
||||
*/
|
||||
public static boolean isCoordinateInLoadedArea(int i, int j, int centerCoordinate)
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
return (i >= centerCoordinate - mc.gameSettings.renderDistanceChunks
|
||||
&& i <= centerCoordinate + mc.gameSettings.renderDistanceChunks)
|
||||
&&
|
||||
(j >= centerCoordinate - mc.gameSettings.renderDistanceChunks
|
||||
&& j <= centerCoordinate + mc.gameSettings.renderDistanceChunks);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the coordinates that are in the center half of the given
|
||||
* 2D matrix, starting at (0,0) and going to (2 * lodRadius, 2 * lodRadius).
|
||||
*/
|
||||
public static boolean isCoordinateInNearFogArea(int i, int j, int lodRadius)
|
||||
{
|
||||
int halfRadius = lodRadius / 2;
|
||||
|
||||
return (i >= lodRadius - halfRadius
|
||||
&& i <= lodRadius + halfRadius)
|
||||
&&
|
||||
(j >= lodRadius - halfRadius
|
||||
&& j <= lodRadius + halfRadius);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
package com.backsun.lod.util;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import com.backsun.lod.ModInfo;
|
||||
import com.backsun.lod.util.enums.FogDistance;
|
||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||
import com.electronwill.nightconfig.core.io.WritingMode;
|
||||
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-27-2021
|
||||
*/
|
||||
@Mod.EventBusSubscriber
|
||||
public class LodConfig
|
||||
{
|
||||
public static class Client
|
||||
{
|
||||
public ForgeConfigSpec.BooleanValue drawLODs;
|
||||
|
||||
public ForgeConfigSpec.EnumValue<FogDistance> fogDistance;
|
||||
|
||||
public ForgeConfigSpec.BooleanValue drawCheckerBoard;
|
||||
|
||||
|
||||
Client(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(ModInfo.MODNAME + " configuration settings").push("client");
|
||||
|
||||
drawLODs = builder
|
||||
.comment("If false LODs will not be drawn, \n"
|
||||
+ "however they will still be generated \n"
|
||||
+ "and saved to file for later use.")
|
||||
.define("drawLODs", true);
|
||||
|
||||
fogDistance = builder
|
||||
.comment("\n"
|
||||
+ "At what distance should Fog be drawn on the LODs? \n"
|
||||
+ "If fog cuts off ubruptly or you are using Optifine's \"fast\" \n"
|
||||
+ "fog option set this to " + FogDistance.NEAR.toString() + " or " + FogDistance.FAR.toString() + ".")
|
||||
.defineEnum("fogDistance", FogDistance.NEAR_AND_FAR);
|
||||
|
||||
drawCheckerBoard = builder
|
||||
.comment("\n"
|
||||
+ "If false the LODs will draw with their normal world colors. \n"
|
||||
+ "If true they will draw as a black and white checkerboard. \n"
|
||||
+ "This can be used for debugging or imagining you are playing a \n"
|
||||
+ "giant game of chess ;)")
|
||||
.define("drawCheckerBoard", false);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* {@link Path} to the configuration file of this mod
|
||||
*/
|
||||
private static final Path CONFIG_PATH =
|
||||
Paths.get("config", ModInfo.MODID + ".toml");
|
||||
|
||||
public static final ForgeConfigSpec clientSpec;
|
||||
public static final Client CLIENT;
|
||||
static {
|
||||
final Pair<Client, ForgeConfigSpec> specPair = new ForgeConfigSpec.Builder().configure(Client::new);
|
||||
clientSpec = specPair.getRight();
|
||||
CLIENT = specPair.getLeft();
|
||||
|
||||
// setup the config file
|
||||
CommentedFileConfig config = CommentedFileConfig.builder(CONFIG_PATH)
|
||||
.writingMode(WritingMode.REPLACE)
|
||||
.build();
|
||||
config.load();
|
||||
config.save();
|
||||
clientSpec.setConfig(config);
|
||||
}
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLoad(final ModConfig.Loading configEvent)
|
||||
{
|
||||
LogManager.getLogger().debug(ModInfo.MODNAME, "Loaded forge config file {}", configEvent.getConfig().getFileName());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onFileChange(final ModConfig.Reloading configEvent)
|
||||
{
|
||||
LogManager.getLogger().debug(ModInfo.MODNAME, "Forge config just got changed on the file system!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package com.backsun.lod.util;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* This class holds methods that may be used in multiple places.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-26-2021
|
||||
*/
|
||||
public class LodUtils
|
||||
{
|
||||
private static Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Gets the first valid ServerWorld.
|
||||
*
|
||||
* @return null if there are no ServerWorlds
|
||||
*/
|
||||
public static ServerWorld getFirstValidServerWorld()
|
||||
{
|
||||
if (mc.getIntegratedServer() == null)
|
||||
return null;
|
||||
|
||||
Iterable<ServerWorld> worlds = mc.getIntegratedServer().getWorlds();
|
||||
|
||||
for (ServerWorld world : worlds)
|
||||
return world;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ServerWorld for the relevant dimension.
|
||||
*
|
||||
* @return null if there is no ServerWorld for the given dimension
|
||||
*/
|
||||
public static ServerWorld getServerWorldFromDimension(DimensionType dimension)
|
||||
{
|
||||
IntegratedServer server = mc.getIntegratedServer();
|
||||
if (server == null)
|
||||
return null;
|
||||
|
||||
Iterable<ServerWorld> worlds = server.getWorlds();
|
||||
ServerWorld returnWorld = null;
|
||||
|
||||
for (ServerWorld world : worlds)
|
||||
{
|
||||
if(world.getDimensionType() == dimension)
|
||||
{
|
||||
returnWorld = world;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return returnWorld;
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
package com.backsun.lod.util;
|
||||
|
||||
/**
|
||||
* This holds meta information about the mod.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 04-16-2020
|
||||
*/
|
||||
public class Reference
|
||||
{
|
||||
/** the mod's identifier */
|
||||
public static final String MOD_ID = "lod";
|
||||
/** the mod's name */
|
||||
public static final String NAME = "LOD Mod";
|
||||
/** the mod's version */
|
||||
public static final String VERSION = "1.0";
|
||||
/** the version of minecraft this mod is built for */
|
||||
public static final String ACCEPTED_VERSIONS = "[1.16.4]";
|
||||
|
||||
/** where the client proxy class is */
|
||||
public static final String CLIENT_PROXY_CLASS = "com.backsun.lod.proxy.ClientProxy";
|
||||
/** where the common proxy class is*/
|
||||
public static final String COMMON_PROXY_CLASS = "com.backsun.lod.proxy.CommonProxy";
|
||||
|
||||
|
||||
}
|
||||
@@ -1,96 +0,0 @@
|
||||
package com.backsun.lod.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import com.backsun.lod.util.enums.FogQuality;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
/**
|
||||
* This object is used to get variables from methods
|
||||
* where they are private.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-18-2021
|
||||
*/
|
||||
public class ReflectionHandler
|
||||
{
|
||||
private Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
public Field ofFogField = null;
|
||||
|
||||
|
||||
public ReflectionHandler()
|
||||
{
|
||||
setupFogField();
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to setupFovMethod.
|
||||
*/
|
||||
private void setupFogField()
|
||||
{
|
||||
// get every variable from the entity renderer
|
||||
Field[] vars = mc.gameSettings.getClass().getDeclaredFields();
|
||||
|
||||
// try and find the ofFogType variable in gameSettings
|
||||
for(Field f : vars)
|
||||
{
|
||||
if(f.getName().equals("ofFogType"))
|
||||
{
|
||||
ofFogField = f;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// we didn't find the field,
|
||||
// either optifine isn't installed, or
|
||||
// optifine changed the name of the variable
|
||||
ofFogField = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get what type of fog optifine is currently set to render.
|
||||
*/
|
||||
public FogQuality getFogQuality()
|
||||
{
|
||||
if (ofFogField == null)
|
||||
{
|
||||
// either optifine isn't installed,
|
||||
// the variable name was changed, or
|
||||
// the setup method wasn't called yet.
|
||||
return FogQuality.OFF;
|
||||
}
|
||||
|
||||
int returnNum = 0;
|
||||
|
||||
try
|
||||
{
|
||||
returnNum = (int)ofFogField.get(mc.gameSettings);
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalAccessException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
switch (returnNum)
|
||||
{
|
||||
case 0:
|
||||
return FogQuality.FAST;
|
||||
case 1:
|
||||
return FogQuality.FAST;
|
||||
case 2:
|
||||
return FogQuality.FANCY;
|
||||
case 3:
|
||||
return FogQuality.OFF;
|
||||
|
||||
default:
|
||||
return FogQuality.FAST;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.backsun.lod.util.enums;
|
||||
|
||||
/**
|
||||
* TOP, N, S, E, W, BOTTOM
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 10-17-2020
|
||||
*/
|
||||
public enum ColorDirection
|
||||
{
|
||||
// used for colors
|
||||
/** +Y */
|
||||
TOP(0),
|
||||
|
||||
/** -Z */
|
||||
N(1),
|
||||
/** +Z */
|
||||
S(2),
|
||||
|
||||
/** +X */
|
||||
E(3),
|
||||
/** -X */
|
||||
W(4),
|
||||
|
||||
/** -Y */
|
||||
BOTTOM(5);
|
||||
|
||||
public final int value;
|
||||
|
||||
private ColorDirection(int newValue)
|
||||
{
|
||||
value = newValue;
|
||||
}
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package com.backsun.lod.util.enums;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 1-23-2021
|
||||
*/
|
||||
public enum DrawMode
|
||||
{
|
||||
/** Draw the LOD objects in groups.
|
||||
* <br>
|
||||
* <br>
|
||||
* Fancy fog: render the center and outside LOD
|
||||
* objects in 2 different groups.
|
||||
* <br>
|
||||
* Fast fog: render all LOD objects at one time.
|
||||
*/
|
||||
BATCH(0),
|
||||
|
||||
/** Draw each LOD objects separately.
|
||||
* <br>
|
||||
* <br>
|
||||
* Not suggested normally since draw calls are GPU expensive.
|
||||
*/
|
||||
INDIVIDUAL(5);
|
||||
|
||||
public final int value;
|
||||
|
||||
private DrawMode(int newValue)
|
||||
{
|
||||
value = newValue;
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package com.backsun.lod.util.enums;
|
||||
|
||||
/**
|
||||
* Near, far, or NEAR_AND_FAR.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-14-2021
|
||||
*/
|
||||
public enum FogDistance
|
||||
{
|
||||
/** good for fast or fancy fog qualities. */
|
||||
NEAR,
|
||||
/** good for fast or fancy fog qualities. */
|
||||
FAR,
|
||||
/** only looks good if the fog quality is set to Fancy. */
|
||||
NEAR_AND_FAR;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package com.backsun.lod.util.enums;
|
||||
|
||||
/**
|
||||
* fast, fancy, or off
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-14-2021
|
||||
*/
|
||||
public enum FogQuality
|
||||
{
|
||||
FAST,
|
||||
FANCY,
|
||||
OFF;
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package com.backsun.lod.util.enums;
|
||||
|
||||
/**
|
||||
* NE, SE, SW, NW
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 1-20-2020
|
||||
*/
|
||||
public enum LodCorner
|
||||
{
|
||||
// used for position
|
||||
|
||||
/** -Z, +X */
|
||||
NE(0),
|
||||
/** +Z, +X */
|
||||
SE(1),
|
||||
/** +Z, -X */
|
||||
SW(2),
|
||||
/** -Z, -X */
|
||||
NW(3);
|
||||
|
||||
public final int value;
|
||||
|
||||
private LodCorner(int newValue)
|
||||
{
|
||||
value = newValue;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package com.backsun.lod.util.enums;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 1-20-2020
|
||||
*
|
||||
* NE, SE, SW, NW
|
||||
*/
|
||||
public enum LodLocation
|
||||
{
|
||||
// used for position
|
||||
|
||||
/** -Z, +X */
|
||||
NE(0),
|
||||
/** +Z, +X */
|
||||
SE(1),
|
||||
/** +Z, -X */
|
||||
SW(2),
|
||||
/** -Z, -X */
|
||||
NW(3);
|
||||
|
||||
public final int value;
|
||||
|
||||
private LodLocation(int newValue)
|
||||
{
|
||||
value = newValue;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge;
|
||||
|
||||
import com.seibel.lod.core.api.EventApi;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.DimensionTypeWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
|
||||
|
||||
import net.minecraftforge.client.event.InputEvent;
|
||||
import net.minecraftforge.event.TickEvent;
|
||||
import net.minecraftforge.event.world.BlockEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.event.world.WorldEvent;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
|
||||
/**
|
||||
* This handles all events sent to the client,
|
||||
* and is the starting point for most of the mod.
|
||||
*
|
||||
* @author James_Seibel
|
||||
* @version 11-12-2021
|
||||
*/
|
||||
public class ForgeClientProxy
|
||||
{
|
||||
private final EventApi eventApi = EventApi.INSTANCE;
|
||||
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void serverTickEvent(TickEvent.ServerTickEvent event)
|
||||
{
|
||||
eventApi.serverTickEvent();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void chunkLoadEvent(ChunkEvent.Load event)
|
||||
{
|
||||
eventApi.chunkLoadEvent(new ChunkWrapper(event.getChunk()), DimensionTypeWrapper.getDimensionTypeWrapper(event.getWorld().dimensionType()));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void worldSaveEvent(WorldEvent.Save event)
|
||||
{
|
||||
eventApi.worldSaveEvent();
|
||||
}
|
||||
|
||||
/** This is also called when a new dimension loads */
|
||||
@SubscribeEvent
|
||||
public void worldLoadEvent(WorldEvent.Load event)
|
||||
{
|
||||
eventApi.worldLoadEvent(WorldWrapper.getWorldWrapper(event.getWorld()));
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void worldUnloadEvent(WorldEvent.Unload event)
|
||||
{
|
||||
eventApi.worldUnloadEvent();
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void blockChangeEvent(BlockEvent event)
|
||||
{
|
||||
// we only care about certain block events
|
||||
if (event.getClass() == BlockEvent.BreakEvent.class ||
|
||||
event.getClass() == BlockEvent.EntityPlaceEvent.class ||
|
||||
event.getClass() == BlockEvent.EntityMultiPlaceEvent.class ||
|
||||
event.getClass() == BlockEvent.FluidPlaceBlockEvent.class ||
|
||||
event.getClass() == BlockEvent.PortalSpawnEvent.class)
|
||||
{
|
||||
IChunkWrapper chunk = new ChunkWrapper(event.getWorld().getChunk(event.getPos()));
|
||||
DimensionTypeWrapper dimType = DimensionTypeWrapper.getDimensionTypeWrapper(event.getWorld().dimensionType());
|
||||
|
||||
// recreate the LOD where the blocks were changed
|
||||
eventApi.blockChangeEvent(chunk, dimType);
|
||||
}
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public void onKeyInput(InputEvent.KeyInputEvent event)
|
||||
{
|
||||
eventApi.onKeyInput(event.getKey(), event.getAction());
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,453 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
|
||||
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||
import com.electronwill.nightconfig.core.io.WritingMode;
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.enums.config.BlocksToAvoid;
|
||||
import com.seibel.lod.core.enums.config.BufferRebuildTimes;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.GenerationPriority;
|
||||
import com.seibel.lod.core.enums.config.GpuUploadMethod;
|
||||
import com.seibel.lod.core.enums.config.HorizontalQuality;
|
||||
import com.seibel.lod.core.enums.config.HorizontalResolution;
|
||||
import com.seibel.lod.core.enums.config.HorizontalScale;
|
||||
import com.seibel.lod.core.enums.config.LodTemplate;
|
||||
import com.seibel.lod.core.enums.config.VanillaOverdraw;
|
||||
import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogColorMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawMode;
|
||||
import com.seibel.lod.core.objects.MinDefaultMax;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IBuffers;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IDebugging;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.IThreading;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IAdvancedGraphics;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IFogQuality;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IQuality;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IWorldGenerator;
|
||||
|
||||
import net.minecraftforge.common.ForgeConfigSpec;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
|
||||
/**
|
||||
* This handles any configuration the user has access to.
|
||||
* @author Leonardo Amato
|
||||
* @author James Seibel
|
||||
* @version 12-1-2021
|
||||
*/
|
||||
@Mod.EventBusSubscriber
|
||||
public class ForgeConfig
|
||||
{
|
||||
// CONFIG STRUCTURE
|
||||
// -> Client
|
||||
// |
|
||||
// |-> Graphics
|
||||
// | |-> Quality
|
||||
// | |-> FogQuality
|
||||
// | |-> AdvancedGraphics
|
||||
// |
|
||||
// |-> World Generation
|
||||
// |
|
||||
// |-> Advanced
|
||||
// |-> Threads
|
||||
// |-> Buffers
|
||||
// |-> Debugging
|
||||
|
||||
|
||||
|
||||
public static class Client
|
||||
{
|
||||
public final Graphics graphics;
|
||||
public final WorldGenerator worldGenerator;
|
||||
public final Advanced advanced;
|
||||
|
||||
|
||||
//================//
|
||||
// Client Configs //
|
||||
//================//
|
||||
public Client(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.push(this.getClass().getSimpleName());
|
||||
{
|
||||
graphics = new Graphics(builder);
|
||||
worldGenerator = new WorldGenerator(builder);
|
||||
advanced = new Advanced(builder);
|
||||
}
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
|
||||
//==================//
|
||||
// Graphics Configs //
|
||||
//==================//
|
||||
public static class Graphics
|
||||
{
|
||||
public final Quality quality;
|
||||
public final FogQuality fogQuality;
|
||||
public final AdvancedGraphics advancedGraphics;
|
||||
|
||||
Graphics(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IGraphics.DESC).push("Graphics");
|
||||
{
|
||||
quality = new Quality(builder);
|
||||
advancedGraphics = new AdvancedGraphics(builder);
|
||||
fogQuality = new FogQuality(builder);
|
||||
}
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
|
||||
public static class Quality
|
||||
{
|
||||
public final ForgeConfigSpec.EnumValue<HorizontalResolution> drawResolution;
|
||||
public final ForgeConfigSpec.IntValue lodChunkRenderDistance;
|
||||
public final ForgeConfigSpec.EnumValue<VerticalQuality> verticalQuality;
|
||||
public final ForgeConfigSpec.EnumValue<HorizontalScale> horizontalScale;
|
||||
public final ForgeConfigSpec.EnumValue<HorizontalQuality> horizontalQuality;
|
||||
|
||||
Quality(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IQuality.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
verticalQuality = builder
|
||||
.comment("\n\n"
|
||||
+ IQuality.VERTICAL_QUALITY_DESC)
|
||||
.defineEnum("Vertical Quality", IQuality.VERTICAL_QUALITY_DEFAULT);
|
||||
|
||||
horizontalScale = builder
|
||||
.comment("\n\n"
|
||||
+ IQuality.HORIZONTAL_SCALE_DESC)
|
||||
.defineEnum("Horizontal Scale", IQuality.HORIZONTAL_SCALE_DEFAULT);
|
||||
|
||||
horizontalQuality = builder
|
||||
.comment("\n\n"
|
||||
+ IQuality.HORIZONTAL_QUALITY_DESC)
|
||||
.defineEnum("Horizontal Quality", IQuality.HORIZONTAL_QUALITY_DEFAULT);
|
||||
|
||||
drawResolution = builder
|
||||
.comment("\n\n"
|
||||
+ IQuality.DRAW_RESOLUTION_DESC)
|
||||
.defineEnum("Block size", IQuality.DRAW_RESOLUTION_DEFAULT);
|
||||
|
||||
MinDefaultMax<Integer> minDefaultMax = IQuality.LOD_CHUNK_RENDER_DISTANCE_MIN_DEFAULT_MAX;
|
||||
lodChunkRenderDistance = builder
|
||||
.comment("\n\n"
|
||||
+ IQuality.LOD_CHUNK_RENDER_DISTANCE_DESC)
|
||||
.defineInRange("Lod Render Distance", minDefaultMax.defaultValue, minDefaultMax.minValue, minDefaultMax.maxValue);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class FogQuality
|
||||
{
|
||||
public final ForgeConfigSpec.EnumValue<FogDistance> fogDistance;
|
||||
public final ForgeConfigSpec.EnumValue<FogDrawMode> fogDrawMode;
|
||||
public final ForgeConfigSpec.EnumValue<FogColorMode> fogColorMode;
|
||||
public final ForgeConfigSpec.BooleanValue disableVanillaFog;
|
||||
|
||||
FogQuality(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IFogQuality.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
fogDistance = builder
|
||||
.comment("\n\n"
|
||||
+ IFogQuality.FOG_DISTANCE_DESC)
|
||||
.defineEnum("Fog Distance", IFogQuality.FOG_DISTANCE_DEFAULT);
|
||||
|
||||
fogDrawMode = builder
|
||||
.comment("\n\n"
|
||||
+ IFogQuality.FOG_DRAW_MODE_DESC)
|
||||
.defineEnum("Fog Draw Mode", IFogQuality.FOG_DRAW_MODE_DEFAULT);
|
||||
|
||||
fogColorMode = builder
|
||||
.comment("\n\n"
|
||||
+ IFogQuality.FOG_COLOR_MODE_DESC)
|
||||
.defineEnum("Fog Color Mode", IFogQuality.FOG_COLOR_MODE_DEFAULT);
|
||||
|
||||
disableVanillaFog = builder
|
||||
.comment("\n\n"
|
||||
+ IFogQuality.DISABLE_VANILLA_FOG_DESC)
|
||||
.define("Experimental Disable Vanilla Fog", IFogQuality.DISABLE_VANILLA_FOG_DEFAULT);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AdvancedGraphics
|
||||
{
|
||||
public final ForgeConfigSpec.EnumValue<LodTemplate> lodTemplate;
|
||||
public final ForgeConfigSpec.BooleanValue disableDirectionalCulling;
|
||||
public final ForgeConfigSpec.BooleanValue alwaysDrawAtMaxQuality;
|
||||
public final ForgeConfigSpec.EnumValue<VanillaOverdraw> vanillaOverdraw;
|
||||
public final ForgeConfigSpec.BooleanValue useExtendedNearClipPlane;
|
||||
|
||||
AdvancedGraphics(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IAdvancedGraphics.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
lodTemplate = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.LOD_TEMPLATE_DESC)
|
||||
.defineEnum("LOD Template", IAdvancedGraphics.LOD_TEMPLATE_DEFAULT);
|
||||
|
||||
disableDirectionalCulling = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DESC)
|
||||
.define("Disable Directional Culling", IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DEFAULT);
|
||||
|
||||
alwaysDrawAtMaxQuality = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.ALWAYS_DRAW_AT_MAD_QUALITY_DESC)
|
||||
.define("Always Use Max Quality", IAdvancedGraphics.ALWAYS_DRAW_AT_MAD_QUALITY_DEFAULT);
|
||||
|
||||
vanillaOverdraw = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.VANILLA_OVERDRAW_DESC)
|
||||
.defineEnum("Vanilla Overdraw", IAdvancedGraphics.VANILLA_OVERDRAW_DEFAULT);
|
||||
|
||||
// This is a temporary fix (like vanilla overdraw)
|
||||
// hopefully we can remove both once we get individual chunk rendering figured out
|
||||
useExtendedNearClipPlane = builder
|
||||
.comment("\n\n"
|
||||
+ IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DESC)
|
||||
.define("Use Extended Near Clip Plane", IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DEFAULT);
|
||||
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//========================//
|
||||
// WorldGenerator Configs //
|
||||
//========================//
|
||||
public static class WorldGenerator
|
||||
{
|
||||
public final ForgeConfigSpec.EnumValue<GenerationPriority> generationPriority;
|
||||
public final ForgeConfigSpec.EnumValue<DistanceGenerationMode> distanceGenerationMode;
|
||||
public final ForgeConfigSpec.BooleanValue allowUnstableFeatureGeneration;
|
||||
public final ForgeConfigSpec.EnumValue<BlocksToAvoid> blocksToAvoid;
|
||||
//public final ForgeConfigSpec.BooleanValue useExperimentalPreGenLoading;
|
||||
|
||||
WorldGenerator(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IWorldGenerator.DESC).push("Generation");
|
||||
|
||||
generationPriority = builder
|
||||
.comment("\n\n"
|
||||
+ IWorldGenerator.GENERATION_PRIORITY_DESC)
|
||||
.defineEnum("Generation Priority", IWorldGenerator.GENERATION_PRIORITY_DEFAULT);
|
||||
|
||||
distanceGenerationMode = builder
|
||||
.comment("\n\n"
|
||||
+ IWorldGenerator.DISTANCE_GENERATION_MODE_DESC)
|
||||
.defineEnum("Distance Generation Mode", IWorldGenerator.DISTANCE_GENERATION_MODE_DEFAULT);
|
||||
|
||||
allowUnstableFeatureGeneration = builder
|
||||
.comment("\n\n"
|
||||
+ IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DESC)
|
||||
.define("Allow Unstable Feature Generation", IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT);
|
||||
|
||||
blocksToAvoid = builder
|
||||
.comment("\n\n"
|
||||
+ IWorldGenerator.BLOCKS_TO_AVOID_DESC)
|
||||
.defineEnum("Blocks to avoid", IWorldGenerator.BLOCKS_TO_AVOID_DEFAULT);
|
||||
|
||||
/*useExperimentalPreGenLoading = builder
|
||||
.comment("\n\n"
|
||||
+ " if a chunk has been pre-generated, then the mod would use the real chunk for the \n"
|
||||
+ "fake chunk creation. May require a deletion of the lod file to see the result. \n")
|
||||
.define("Use pre-generated chunks", false);*/
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// Advanced Configs //
|
||||
//==================//
|
||||
public static class Advanced
|
||||
{
|
||||
public final Threading threading;
|
||||
public final Debugging debugging;
|
||||
public final Buffers buffers;
|
||||
|
||||
public Advanced(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IAdvanced.DESC).push(this.getClass().getSimpleName());
|
||||
{
|
||||
threading = new Threading(builder);
|
||||
debugging = new Debugging(builder);
|
||||
buffers = new Buffers(builder);
|
||||
}
|
||||
builder.pop();
|
||||
}
|
||||
|
||||
public static class Threading
|
||||
{
|
||||
public final ForgeConfigSpec.IntValue numberOfWorldGenerationThreads;
|
||||
public final ForgeConfigSpec.IntValue numberOfBufferBuilderThreads;
|
||||
|
||||
Threading(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IThreading.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
MinDefaultMax<Integer> minDefaultMax = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DEFAULT;
|
||||
numberOfWorldGenerationThreads = builder
|
||||
.comment("\n\n"
|
||||
+ IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DESC)
|
||||
.defineInRange("numberOfWorldGenerationThreads", minDefaultMax.defaultValue, minDefaultMax.minValue, minDefaultMax.maxValue);
|
||||
|
||||
|
||||
minDefaultMax = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX;
|
||||
numberOfBufferBuilderThreads = builder
|
||||
.comment("\n\n"
|
||||
+ IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX)
|
||||
.defineInRange("numberOfBufferBuilderThreads", minDefaultMax.defaultValue, minDefaultMax.minValue, minDefaultMax.maxValue);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// Debug Options //
|
||||
//===============//
|
||||
public static class Debugging
|
||||
{
|
||||
public final ForgeConfigSpec.BooleanValue drawLods;
|
||||
public final ForgeConfigSpec.EnumValue<DebugMode> debugMode;
|
||||
public final ForgeConfigSpec.BooleanValue enableDebugKeybindings;
|
||||
|
||||
Debugging(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IDebugging.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
drawLods = builder
|
||||
.comment("\n\n"
|
||||
+ IDebugging.DRAW_LODS_DESC)
|
||||
.define("Enable Rendering", IDebugging.DRAW_LODS_DEFAULT);
|
||||
|
||||
debugMode = builder
|
||||
.comment("\n\n"
|
||||
+ IDebugging.DEBUG_MODE_DESC)
|
||||
.defineEnum("Debug Mode", IDebugging.DEBUG_MODE_DEFAULT);
|
||||
|
||||
enableDebugKeybindings = builder
|
||||
.comment("\n\n"
|
||||
+ IDebugging.DEBUG_KEYBINDINGS_ENABLED_DESC)
|
||||
.define("Enable Debug Keybinding", IDebugging.DEBUG_KEYBINDINGS_ENABLED_DEFAULT);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Buffers
|
||||
{
|
||||
|
||||
public final ForgeConfigSpec.EnumValue<GpuUploadMethod> gpuUploadMethod;
|
||||
public final ForgeConfigSpec.IntValue gpuUploadTimeoutInMilleseconds;
|
||||
public final ForgeConfigSpec.EnumValue<BufferRebuildTimes> rebuildTimes;
|
||||
|
||||
Buffers(ForgeConfigSpec.Builder builder)
|
||||
{
|
||||
builder.comment(IBuffers.DESC).push(this.getClass().getSimpleName());
|
||||
|
||||
gpuUploadMethod = builder
|
||||
.comment("\n\n"
|
||||
+ IBuffers.GPU_UPLOAD_METHOD_DESC)
|
||||
.defineEnum("GPU Upload Method", IBuffers.GPU_UPLOAD_METHOD_DEFAULT);
|
||||
|
||||
MinDefaultMax<Integer> minDefaultMax = IBuffers.GPU_UPLOAD_TIMEOUT_IN_MILLISECONDS_DEFAULT;
|
||||
gpuUploadTimeoutInMilleseconds = builder
|
||||
.comment("\n\n"
|
||||
+ IBuffers.GPU_UPLOAD_TIMEOUT_IN_MILLISECONDS_DESC)
|
||||
.defineInRange("GPU Upload Timeout in Milleseconds", minDefaultMax.defaultValue, minDefaultMax.minValue, minDefaultMax.maxValue);
|
||||
|
||||
|
||||
rebuildTimes = builder
|
||||
.comment("\n\n"
|
||||
+ IBuffers.REBUILD_TIMES_DESC)
|
||||
.defineEnum("rebuildFrequency", IBuffers.REBUILD_TIMES_DEFAULT);
|
||||
|
||||
builder.pop();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** {@link Path} to the configuration file of this mod */
|
||||
private static final Path CONFIG_PATH = Paths.get("config", ModInfo.NAME + ".toml");
|
||||
|
||||
public static final ForgeConfigSpec CLIENT_SPEC;
|
||||
public static final Client CLIENT;
|
||||
|
||||
static
|
||||
{
|
||||
final Pair<Client, ForgeConfigSpec> specPair = new ForgeConfigSpec.Builder().configure(Client::new);
|
||||
CLIENT_SPEC = specPair.getRight();
|
||||
CLIENT = specPair.getLeft();
|
||||
CommentedFileConfig clientConfig = CommentedFileConfig.builder(CONFIG_PATH)
|
||||
.writingMode(WritingMode.REPLACE)
|
||||
.build();
|
||||
clientConfig.load();
|
||||
clientConfig.save();
|
||||
CLIENT_SPEC.setConfig(clientConfig);
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onLoad(final ModConfig.Loading configEvent)
|
||||
{
|
||||
LogManager.getLogger().debug(ModInfo.NAME, "Loaded forge config file {}", configEvent.getConfig().getFileName());
|
||||
}
|
||||
|
||||
@SubscribeEvent
|
||||
public static void onFileChange(final ModConfig.Reloading configEvent)
|
||||
{
|
||||
LogManager.getLogger().debug(ModInfo.NAME, "Forge config just got changed on the file system!");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge;
|
||||
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.forge.wrappers.ForgeDependencySetup;
|
||||
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.ModLoadingContext;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.config.ModConfig;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
|
||||
/**
|
||||
* Initialize and setup the Mod. <br>
|
||||
* If you are looking for the real start of the mod
|
||||
* check out the ClientProxy.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-16-2021
|
||||
*/
|
||||
@Mod(ModInfo.ID)
|
||||
public class ForgeMain
|
||||
{
|
||||
public static ForgeClientProxy forgeClientProxy;
|
||||
|
||||
private void init(final FMLCommonSetupEvent event)
|
||||
{
|
||||
// make sure the dependencies are set up before the mod needs them
|
||||
ForgeDependencySetup.createInitialBindings();
|
||||
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ForgeConfig.CLIENT_SPEC);
|
||||
}
|
||||
|
||||
|
||||
public ForgeMain()
|
||||
{
|
||||
// Register the methods
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::init);
|
||||
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientStart);
|
||||
|
||||
// Register ourselves for server and other game events we are interested in
|
||||
MinecraftForge.EVENT_BUS.register(this);
|
||||
}
|
||||
|
||||
private void onClientStart(final FMLClientSetupEvent event)
|
||||
{
|
||||
forgeClientProxy = new ForgeClientProxy();
|
||||
MinecraftForge.EVENT_BUS.register(forgeClientProxy);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SubscribeEvent
|
||||
public void onServerStarting(FMLServerStartingEvent event)
|
||||
{
|
||||
// this is called when the server starts
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.mixins;
|
||||
|
||||
import org.lwjgl.opengl.GL15;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import com.mojang.blaze3d.matrix.MatrixStack;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import com.seibel.lod.forge.wrappers.McObjectConverter;
|
||||
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
|
||||
/**
|
||||
* This class is used to mix in my rendering code
|
||||
* before Minecraft starts rendering blocks.
|
||||
* If this wasn't done, and we used Forge's
|
||||
* render last event, the LODs would render on top
|
||||
* of the normal terrain.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 9-19-2021
|
||||
*/
|
||||
@Mixin(WorldRenderer.class)
|
||||
public class MixinWorldRenderer
|
||||
{
|
||||
private static float previousPartialTicks = 0;
|
||||
|
||||
@Inject(at = @At("RETURN"), method = "renderSky(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V")
|
||||
private void renderSky(MatrixStack matrixStackIn, float partialTicks, CallbackInfo callback)
|
||||
{
|
||||
// get the partial ticks since renderBlockLayer doesn't
|
||||
// have access to them
|
||||
previousPartialTicks = partialTicks;
|
||||
}
|
||||
|
||||
@Inject(at = @At("HEAD"), method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/matrix/MatrixStack;DDD)V")
|
||||
private void renderChunkLayer(RenderType renderType, MatrixStack matrixStackIn, double xIn, double yIn, double zIn, CallbackInfo callback)
|
||||
{
|
||||
// only render before solid blocks
|
||||
if (renderType.equals(RenderType.solid()))
|
||||
{
|
||||
// get MC's current projection matrix
|
||||
float[] mcProjMatrixRaw = new float[16];
|
||||
GL15.glGetFloatv(GL15.GL_PROJECTION_MATRIX, mcProjMatrixRaw);
|
||||
Mat4f mcProjectionMatrix = new Mat4f(mcProjMatrixRaw);
|
||||
// OpenGl outputs their matrices in col,row form instead of row,col
|
||||
// (or maybe vice versa I have no idea :P)
|
||||
mcProjectionMatrix.transpose();
|
||||
|
||||
|
||||
Mat4f mcModelViewMatrix = McObjectConverter.Convert(matrixStackIn.last().pose());
|
||||
|
||||
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.seibel.lod.forge.wrappers;
|
||||
|
||||
import com.seibel.lod.core.handlers.IReflectionHandler;
|
||||
import com.seibel.lod.core.handlers.ReflectionHandler;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockColorSingletonWrapper;
|
||||
import com.seibel.lod.forge.wrappers.config.LodConfigWrapperSingleton;
|
||||
import com.seibel.lod.forge.wrappers.minecraft.MinecraftRenderWrapper;
|
||||
import com.seibel.lod.forge.wrappers.minecraft.MinecraftWrapper;
|
||||
|
||||
/**
|
||||
* Binds all necessary dependencies, so we
|
||||
* can access them in Core. <br>
|
||||
* This needs to be called before any Core classes
|
||||
* are loaded.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class ForgeDependencySetup
|
||||
{
|
||||
public static void createInitialBindings()
|
||||
{
|
||||
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);
|
||||
SingletonHandler.bind(IBlockColorSingletonWrapper.class, BlockColorSingletonWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IMinecraftWrapper.class, MinecraftWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
|
||||
SingletonHandler.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
|
||||
|
||||
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftWrapper.INSTANCE.getOptions()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.vector.Matrix4f;
|
||||
|
||||
/**
|
||||
* This class converts to and from Minecraft objects (Ex: Matrix4f)
|
||||
* and objects we created (Ex: Mat4f).
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class McObjectConverter
|
||||
{
|
||||
/** 4x4 float matrix converter */
|
||||
public static Mat4f Convert(Matrix4f mcMatrix)
|
||||
{
|
||||
FloatBuffer buffer = FloatBuffer.allocate(16);
|
||||
mcMatrix.store(buffer);
|
||||
Mat4f matrix = new Mat4f(buffer);
|
||||
matrix.transpose();
|
||||
return matrix;
|
||||
}
|
||||
|
||||
|
||||
public static Direction Convert(LodDirection lodDirection)
|
||||
{
|
||||
return Direction.byName(lodDirection.name());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers;
|
||||
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.worldGeneration.WorldGeneratorWrapper;
|
||||
|
||||
/**
|
||||
* This handles creating abstract wrapper objects.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class WrapperFactory implements IWrapperFactory
|
||||
{
|
||||
public static final WrapperFactory INSTANCE = new WrapperFactory();
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper createBlockPos()
|
||||
{
|
||||
return new BlockPosWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper createBlockPos(int x, int y, int z)
|
||||
{
|
||||
return new BlockPosWrapper(x,y,z);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos()
|
||||
{
|
||||
return new ChunkPosWrapper();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(int x, int z)
|
||||
{
|
||||
return new ChunkPosWrapper(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractChunkPosWrapper newChunkPos)
|
||||
{
|
||||
return new ChunkPosWrapper(newChunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractChunkPosWrapper createChunkPos(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return new ChunkPosWrapper(blockPos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractWorldGeneratorWrapper createWorldGenerator(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
|
||||
{
|
||||
return new WorldGeneratorWrapper(newLodBuilder, newLodDimension, worldWrapper);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers;
|
||||
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
|
||||
/**
|
||||
* Stores any variables or code that
|
||||
* may be shared between wrapper objects.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class WrapperUtil
|
||||
{
|
||||
/** If we ever need to use a heightmap for any reason, use this one. */
|
||||
public static final Heightmap.Type DEFAULT_HEIGHTMAP = Heightmap.Type.WORLD_SURFACE_WG;
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers.block;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorSingletonWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
|
||||
|
||||
/**
|
||||
* Contains methods that would have been static in BlockColorWrapper.
|
||||
* Since interfaces can't create/implement static methods we have
|
||||
* to split the object up in two.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-17-2021
|
||||
*/
|
||||
public class BlockColorSingletonWrapper implements IBlockColorSingletonWrapper
|
||||
{
|
||||
public static final BlockColorSingletonWrapper INSTANCE = new BlockColorSingletonWrapper();
|
||||
|
||||
@Override
|
||||
public IBlockColorWrapper getWaterColor()
|
||||
{
|
||||
return BlockColorWrapper.getBlockColorWrapper(Blocks.WATER);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers.block;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
|
||||
import com.seibel.lod.forge.wrappers.minecraft.MinecraftWrapper;
|
||||
|
||||
import net.minecraft.block.AbstractPlantBlock;
|
||||
import net.minecraft.block.AbstractTopPlantBlock;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.BushBlock;
|
||||
import net.minecraft.block.FlowerBlock;
|
||||
import net.minecraft.block.GrassBlock;
|
||||
import net.minecraft.block.IGrowable;
|
||||
import net.minecraft.block.LeavesBlock;
|
||||
import net.minecraft.block.TallGrassBlock;
|
||||
import net.minecraft.client.renderer.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||
|
||||
|
||||
/**
|
||||
* @author ??
|
||||
* @version 11-17-2021
|
||||
*/
|
||||
public class BlockColorWrapper implements IBlockColorWrapper
|
||||
{
|
||||
//set of block which require tint
|
||||
public static final ConcurrentMap<Block, BlockColorWrapper> blockColorWrapperMap = new ConcurrentHashMap<>();
|
||||
public static final ModelDataMap dataMap = new ModelDataMap.Builder().build();
|
||||
public static final BlockPos blockPos = new BlockPos(0, 0, 0);
|
||||
public static final Random random = new Random(0);
|
||||
//public static BlockColourWrapper WATER_COLOR = getBlockColorWrapper(Blocks.WATER);
|
||||
public static final Direction[] directions = new Direction[] { Direction.UP, Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.NORTH, Direction.DOWN };
|
||||
|
||||
private final Block block;
|
||||
private int color;
|
||||
private boolean isColored;
|
||||
private boolean toTint;
|
||||
private boolean foliageTint;
|
||||
private boolean grassTint;
|
||||
private boolean waterTint;
|
||||
|
||||
|
||||
/**Constructor only require for the block instance we are wrapping**/
|
||||
public BlockColorWrapper(Block block)
|
||||
{
|
||||
this.block = block;
|
||||
this.color = 0;
|
||||
this.isColored = true;
|
||||
this.toTint = false;
|
||||
this.foliageTint = false;
|
||||
this.grassTint = false;
|
||||
this.waterTint = false;
|
||||
setupColorAndTint();
|
||||
/*StringBuilder s = new StringBuilder();
|
||||
s.append(block + "\n"
|
||||
+ Integer.toHexString(
|
||||
Minecraft.getInstance().getBlockColors().createDefault().getColor(
|
||||
block.defaultBlockState(),
|
||||
(World) MinecraftWrapper.INSTANCE.getWrappedServerLevel().getLevel(),
|
||||
blockPosWrapper.getBlockPos())) + "\n"
|
||||
);
|
||||
for(Property x : Minecraft.getInstance().getBlockColors().getColoringProperties(block))
|
||||
s.append(x.getName() + " " + x.getPossibleValues() + '\n');
|
||||
System.out.println(s);*/
|
||||
//System.out.println(block + " color " + Integer.toHexString(color) + " to tint " + toTint + " folliageTint " + folliageTint + " grassTint " + grassTint + " waterTint " + waterTint);
|
||||
}
|
||||
|
||||
/**
|
||||
* this return a wrapper of the block in input
|
||||
* @param block object of the block to wrap
|
||||
*/
|
||||
public static IBlockColorWrapper getBlockColorWrapper(Block block)
|
||||
{
|
||||
//first we check if the block has already been wrapped
|
||||
if (blockColorWrapperMap.containsKey(block) && blockColorWrapperMap.get(block) != null)
|
||||
return blockColorWrapperMap.get(block);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
BlockColorWrapper blockWrapper = new BlockColorWrapper(block);
|
||||
blockColorWrapperMap.put(block, blockWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return blockWrapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the color of the given block from its texture
|
||||
* and store it for later use.
|
||||
*/
|
||||
private void setupColorAndTint()
|
||||
{
|
||||
BlockState blockState = block.defaultBlockState();
|
||||
BlockPosWrapper blockPosWrapper = new BlockPosWrapper();
|
||||
MinecraftWrapper mc = MinecraftWrapper.INSTANCE;
|
||||
TextureAtlasSprite texture;
|
||||
List<BakedQuad> quads = null;
|
||||
|
||||
boolean isTinted = false;
|
||||
int listSize = 0;
|
||||
|
||||
// first step is to check if this block has a tinted face
|
||||
for (Direction direction : directions)
|
||||
{
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
|
||||
listSize = Math.max(listSize, quads.size());
|
||||
for (BakedQuad bakedQuad : quads)
|
||||
{
|
||||
isTinted |= bakedQuad.isTinted();
|
||||
}
|
||||
}
|
||||
|
||||
//if it contains a tinted face then we store this block in the toTint set
|
||||
if (isTinted)
|
||||
this.toTint = true;
|
||||
|
||||
//now we get the first non-empty face
|
||||
for (Direction direction : directions)
|
||||
{
|
||||
quads = mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
|
||||
if (!quads.isEmpty())
|
||||
break;
|
||||
}
|
||||
|
||||
//the quads list is not empty we extract the first one
|
||||
if (!quads.isEmpty())
|
||||
{
|
||||
isColored = true;
|
||||
texture = quads.get(0).getSprite();
|
||||
}
|
||||
else
|
||||
{
|
||||
isColored = true;
|
||||
texture = mc.getModelManager().getBlockModelShaper().getTexture(block.defaultBlockState(), mc.getClientWorld(), blockPosWrapper.getBlockPos());
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int alpha = 0;
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
int numberOfGreyPixel = 0;
|
||||
int tempColor;
|
||||
int colorMultiplier;
|
||||
|
||||
// generate the block's color
|
||||
for (int frameIndex = 0; frameIndex < texture.getFrameCount(); frameIndex++)
|
||||
{
|
||||
// textures normally use u and v instead of x and y
|
||||
for (int u = 0; u < texture.getWidth(); u++)
|
||||
{
|
||||
for (int v = 0; v < texture.getHeight(); v++)
|
||||
{
|
||||
|
||||
tempColor = texture.getPixelRGBA(frameIndex, u, v);
|
||||
|
||||
if (ColorUtil.getAlpha(texture.getPixelRGBA(frameIndex, u, v)) == 0)
|
||||
continue;
|
||||
|
||||
// determine if this pixel is gray
|
||||
int colorMax = Math.max(Math.max(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
|
||||
int colorMin = 4 + Math.min(Math.min(ColorUtil.getBlue(tempColor), ColorUtil.getGreen(tempColor)), ColorUtil.getRed(tempColor));
|
||||
boolean isGray = colorMax < colorMin;
|
||||
if (isGray)
|
||||
numberOfGreyPixel++;
|
||||
|
||||
|
||||
// for flowers, weight their non-green color higher
|
||||
if (block instanceof FlowerBlock && (!(ColorUtil.getGreen(tempColor) > (ColorUtil.getBlue(tempColor) + 30)) || !(ColorUtil.getGreen(tempColor) > (ColorUtil.getRed(tempColor) + 30))))
|
||||
colorMultiplier = 5;
|
||||
else
|
||||
colorMultiplier = 1;
|
||||
|
||||
|
||||
// add to the running averages
|
||||
count += colorMultiplier;
|
||||
alpha += ColorUtil.getAlpha(tempColor) * colorMultiplier;
|
||||
red += ColorUtil.getBlue(tempColor) * colorMultiplier;
|
||||
green += ColorUtil.getGreen(tempColor) * colorMultiplier;
|
||||
blue += ColorUtil.getRed(tempColor) * colorMultiplier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (count == 0)
|
||||
// this block is entirely transparent
|
||||
tempColor = 0;
|
||||
else
|
||||
{
|
||||
// determine the average color
|
||||
alpha /= count;
|
||||
red /= count;
|
||||
green /= count;
|
||||
blue /= count;
|
||||
tempColor = ColorUtil.rgbToInt(alpha, red, green, blue);
|
||||
}
|
||||
|
||||
// determine if this block should use the biome color tint
|
||||
if ((grassInstance() || leavesInstance() || waterIstance()) && (float) numberOfGreyPixel / count > 0.75f)
|
||||
this.toTint = true;
|
||||
|
||||
// we check which kind of tint we need to apply
|
||||
this.grassTint = grassInstance() && toTint;
|
||||
|
||||
this.foliageTint = leavesInstance() && toTint;
|
||||
|
||||
this.waterTint = waterIstance() && toTint;
|
||||
|
||||
color = tempColor;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's grass color */
|
||||
private boolean grassInstance()
|
||||
{
|
||||
return block instanceof GrassBlock
|
||||
|| block instanceof BushBlock
|
||||
|| block instanceof IGrowable
|
||||
|| block instanceof AbstractPlantBlock
|
||||
|| block instanceof AbstractTopPlantBlock
|
||||
|| block instanceof TallGrassBlock;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's foliage color */
|
||||
private boolean leavesInstance()
|
||||
{
|
||||
return block instanceof LeavesBlock
|
||||
|| block == Blocks.VINE
|
||||
|| block == Blocks.SUGAR_CANE;
|
||||
}
|
||||
|
||||
/** determine if the given block should use the biome's foliage color */
|
||||
private boolean waterIstance()
|
||||
{
|
||||
return block == Blocks.WATER;
|
||||
}
|
||||
|
||||
//--------------//
|
||||
//Colors getters//
|
||||
//--------------//
|
||||
|
||||
@Override
|
||||
public boolean hasColor()
|
||||
{
|
||||
return isColored;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getColor()
|
||||
{
|
||||
return color;
|
||||
}
|
||||
|
||||
//------------//
|
||||
//Tint getters//
|
||||
//------------//
|
||||
|
||||
|
||||
@Override
|
||||
public boolean hasTint()
|
||||
{
|
||||
return toTint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasGrassTint()
|
||||
{
|
||||
return grassTint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFolliageTint()
|
||||
{
|
||||
return foliageTint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasWaterTint()
|
||||
{
|
||||
return waterTint;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof BlockColorWrapper))
|
||||
return false;
|
||||
BlockColorWrapper that = (BlockColorWrapper) o;
|
||||
return Objects.equals(block, that.block);
|
||||
}
|
||||
|
||||
@Override public int hashCode()
|
||||
{
|
||||
return Objects.hash(block);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers.block;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class BlockPosWrapper extends AbstractBlockPosWrapper
|
||||
{
|
||||
private final BlockPos.Mutable blockPos;
|
||||
|
||||
|
||||
public BlockPosWrapper()
|
||||
{
|
||||
this.blockPos = new BlockPos.Mutable(0, 0, 0);
|
||||
}
|
||||
|
||||
public BlockPosWrapper(int x, int y, int z)
|
||||
{
|
||||
this.blockPos = new BlockPos.Mutable(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(int x, int y, int z)
|
||||
{
|
||||
blockPos.set(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getX()
|
||||
{
|
||||
return blockPos.getX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getY()
|
||||
{
|
||||
return blockPos.getY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ()
|
||||
{
|
||||
return blockPos.getZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int get(LodDirection.Axis axis)
|
||||
{
|
||||
return axis.choose(getX(), getY(), getZ());
|
||||
}
|
||||
|
||||
public BlockPos.Mutable getBlockPos()
|
||||
{
|
||||
return blockPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
return blockPos.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(blockPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosWrapper offset(int x, int y, int z)
|
||||
{
|
||||
blockPos.set(blockPos.getX() + x, blockPos.getY() + y, blockPos.getZ() + z);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers.block;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkWrapper;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.block.SixWayBlock;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.IBlockReader;
|
||||
|
||||
|
||||
/**
|
||||
* @author ??
|
||||
* @version 11-18-2021
|
||||
*/
|
||||
public class BlockShapeWrapper implements IBlockShapeWrapper
|
||||
{
|
||||
//set of block which require tint
|
||||
public static final ConcurrentMap<Block, BlockShapeWrapper> blockShapeWrapperMap = new ConcurrentHashMap<>();
|
||||
public static BlockShapeWrapper WATER_SHAPE = new BlockShapeWrapper();
|
||||
|
||||
private final Block block;
|
||||
private final boolean toAvoid;
|
||||
private boolean nonFull;
|
||||
private boolean noCollision;
|
||||
|
||||
/**Constructor only require for the block instance we are wrapping**/
|
||||
public BlockShapeWrapper(Block block, IChunkWrapper chunkWrapper, AbstractBlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
this.block = block;
|
||||
this.nonFull = false;
|
||||
this.noCollision = false;
|
||||
this.toAvoid = ofBlockToAvoid();
|
||||
setupShapes((ChunkWrapper) chunkWrapper, (BlockPosWrapper) blockPosWrapper);
|
||||
//System.out.println(block + " non full " + nonFull + " no collision " + noCollision + " to avoid " + toAvoid);
|
||||
}
|
||||
|
||||
private BlockShapeWrapper()
|
||||
{
|
||||
this.block = Blocks.WATER;
|
||||
this.nonFull = false;
|
||||
this.noCollision = false;
|
||||
this.toAvoid = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* this return a wrapper of the block in input
|
||||
* @param block Block object to wrap
|
||||
*/
|
||||
static public BlockShapeWrapper getBlockShapeWrapper(Block block, IChunkWrapper chunkWrapper, AbstractBlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
//first we check if the block has already been wrapped
|
||||
if (blockShapeWrapperMap.containsKey(block) && blockShapeWrapperMap.get(block) != null)
|
||||
return blockShapeWrapperMap.get(block);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
BlockShapeWrapper blockWrapper = new BlockShapeWrapper(block, chunkWrapper, blockPosWrapper);
|
||||
blockShapeWrapperMap.put(block, blockWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return blockWrapper;
|
||||
}
|
||||
|
||||
private void setupShapes(ChunkWrapper chunkWrapper, BlockPosWrapper blockPosWrapper)
|
||||
{
|
||||
IBlockReader chunk = chunkWrapper.getChunk();
|
||||
BlockPos blockPos = blockPosWrapper.getBlockPos();
|
||||
boolean noCollisionSetted = false;
|
||||
boolean nonFullSetted = false;
|
||||
if (!block.defaultBlockState().getFluidState().isEmpty() || block instanceof SixWayBlock)
|
||||
{
|
||||
noCollisionSetted = true;
|
||||
nonFullSetted = true;
|
||||
noCollision = false;
|
||||
nonFull = false;
|
||||
}
|
||||
if (!nonFullSetted)
|
||||
{
|
||||
VoxelShape voxelShape = block.defaultBlockState().getShape(chunk, blockPos);
|
||||
|
||||
if (!voxelShape.isEmpty())
|
||||
{
|
||||
AxisAlignedBB bbox = voxelShape.bounds();
|
||||
double xWidth = (bbox.maxX - bbox.minX);
|
||||
double yWidth = (bbox.maxY - bbox.minY);
|
||||
double zWidth = (bbox.maxZ - bbox.minZ);
|
||||
nonFull = xWidth < 1 && zWidth < 1 && yWidth < 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nonFull = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!noCollisionSetted)
|
||||
{
|
||||
VoxelShape collisionShape = block.defaultBlockState().getCollisionShape(chunk, blockPos);
|
||||
noCollision = collisionShape.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean ofBlockToAvoid()
|
||||
{
|
||||
return block.equals(Blocks.AIR)
|
||||
|| block.equals(Blocks.CAVE_AIR)
|
||||
|| block.equals(Blocks.BARRIER)
|
||||
|| block.equals(Blocks.VOID_AIR);
|
||||
}
|
||||
//-----------------//
|
||||
//Avoidance getters//
|
||||
//-----------------//
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isNonFull()
|
||||
{
|
||||
return nonFull;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNoCollision()
|
||||
{
|
||||
return noCollision;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isToAvoid()
|
||||
{
|
||||
return toAvoid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof BlockShapeWrapper))
|
||||
return false;
|
||||
BlockShapeWrapper that = (BlockShapeWrapper) o;
|
||||
return Objects.equals(block, that.block);
|
||||
}
|
||||
|
||||
@Override public int hashCode()
|
||||
{
|
||||
return Objects.hash(block);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers.chunk;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-18-2021
|
||||
*/
|
||||
public class ChunkPosWrapper extends AbstractChunkPosWrapper
|
||||
{
|
||||
private final ChunkPos chunkPos;
|
||||
|
||||
public ChunkPosWrapper(ChunkPos newChunkPos)
|
||||
{
|
||||
this.chunkPos = newChunkPos;
|
||||
}
|
||||
|
||||
public ChunkPosWrapper(BlockPos blockPos)
|
||||
{
|
||||
this.chunkPos = new ChunkPos(blockPos);
|
||||
}
|
||||
|
||||
|
||||
public ChunkPosWrapper(AbstractChunkPosWrapper newChunkPos)
|
||||
{
|
||||
this.chunkPos = ((ChunkPosWrapper) newChunkPos).chunkPos;
|
||||
}
|
||||
|
||||
public ChunkPosWrapper(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
this.chunkPos = new ChunkPos(((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
|
||||
public ChunkPosWrapper(int chunkX, int chunkZ)
|
||||
{
|
||||
this.chunkPos = new ChunkPos(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
public ChunkPosWrapper()
|
||||
{
|
||||
this.chunkPos = new ChunkPos(0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getX()
|
||||
{
|
||||
return chunkPos.x;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getZ()
|
||||
{
|
||||
return chunkPos.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinBlockX()
|
||||
{
|
||||
return chunkPos.getMinBlockX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinBlockZ()
|
||||
{
|
||||
return chunkPos.getMinBlockZ();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRegionX()
|
||||
{
|
||||
return chunkPos.getRegionX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRegionZ()
|
||||
{
|
||||
return chunkPos.getRegionZ();
|
||||
}
|
||||
|
||||
public ChunkPos getChunkPos()
|
||||
{
|
||||
return chunkPos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o)
|
||||
{
|
||||
return chunkPos.equals(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
return Objects.hash(chunkPos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosWrapper getWorldPosition()
|
||||
{
|
||||
BlockPos blockPos = chunkPos.getWorldPosition();
|
||||
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers.chunk;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockColorWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockShapeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.lod.forge.wrappers.WrapperUtil;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockColorWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockShapeWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.BiomeWrapper;
|
||||
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.ILiquidContainer;
|
||||
import net.minecraft.block.IWaterLoggable;
|
||||
import net.minecraft.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
|
||||
/**
|
||||
* @author ??
|
||||
* @version 11-17-2021
|
||||
*/
|
||||
public class ChunkWrapper implements IChunkWrapper
|
||||
{
|
||||
private final IChunk chunk;
|
||||
private final ChunkPosWrapper chunkPos;
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return chunk.getMaxBuildHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPositionInWater(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
BlockState blockState = chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos());
|
||||
|
||||
//This type of block is always in water
|
||||
return ((blockState.getBlock() instanceof ILiquidContainer) && !(blockState.getBlock() instanceof IWaterLoggable))
|
||||
|| (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeightMapValue(int xRel, int zRel)
|
||||
{
|
||||
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeWrapper getBiome(int xRel, int yAbs, int zRel)
|
||||
{
|
||||
return BiomeWrapper.getBiomeWrapper(chunk.getBiomes().getNoiseBiome(xRel >> 2, yAbs >> 2, zRel >> 2));
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockColorWrapper getBlockColorWrapper(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BlockColorWrapper.getBlockColorWrapper(chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos()).getBlock());
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockShapeWrapper getBlockShapeWrapper(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BlockShapeWrapper.getBlockShapeWrapper(chunk.getBlockState(((BlockPosWrapper) blockPos).getBlockPos()).getBlock(), this, blockPos);
|
||||
}
|
||||
|
||||
public ChunkWrapper(IChunk chunk)
|
||||
{
|
||||
this.chunk = chunk;
|
||||
this.chunkPos = new ChunkPosWrapper(chunk.getPos());
|
||||
}
|
||||
|
||||
public IChunk getChunk()
|
||||
{
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkPosWrapper getPos()
|
||||
{
|
||||
return chunkPos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isLightCorrect()
|
||||
{
|
||||
return chunk.isLightCorrect();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isWaterLogged(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
BlockState blockState = chunk.getBlockState(((BlockPosWrapper)blockPos).getBlockPos());
|
||||
|
||||
//This type of block is always in water
|
||||
return ((blockState.getBlock() instanceof ILiquidContainer) && !(blockState.getBlock() instanceof IWaterLoggable))
|
||||
|| (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEmittedBrightness(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return chunk.getLightEmission(((BlockPosWrapper)blockPos).getBlockPos());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,516 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers.config;
|
||||
|
||||
import com.seibel.lod.core.enums.config.BlocksToAvoid;
|
||||
import com.seibel.lod.core.enums.config.BufferRebuildTimes;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.GenerationPriority;
|
||||
import com.seibel.lod.core.enums.config.GpuUploadMethod;
|
||||
import com.seibel.lod.core.enums.config.HorizontalQuality;
|
||||
import com.seibel.lod.core.enums.config.HorizontalResolution;
|
||||
import com.seibel.lod.core.enums.config.HorizontalScale;
|
||||
import com.seibel.lod.core.enums.config.LodTemplate;
|
||||
import com.seibel.lod.core.enums.config.VanillaOverdraw;
|
||||
import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogColorMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawMode;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.forge.ForgeConfig;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-29-2021
|
||||
*/
|
||||
public class LodConfigWrapperSingleton implements ILodConfigWrapperSingleton
|
||||
{
|
||||
public static final LodConfigWrapperSingleton INSTANCE = new LodConfigWrapperSingleton();
|
||||
|
||||
|
||||
private static final Client client = new Client();
|
||||
@Override
|
||||
public IClient client()
|
||||
{
|
||||
return client;
|
||||
}
|
||||
|
||||
public static class Client implements IClient
|
||||
{
|
||||
public final IGraphics graphics;
|
||||
public final IWorldGenerator worldGenerator;
|
||||
public final IAdvanced advanced;
|
||||
|
||||
|
||||
@Override
|
||||
public IGraphics graphics()
|
||||
{
|
||||
return graphics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorldGenerator worldGenerator()
|
||||
{
|
||||
return worldGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAdvanced advanced()
|
||||
{
|
||||
return advanced;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// Client Configs //
|
||||
//================//
|
||||
public Client()
|
||||
{
|
||||
graphics = new Graphics();
|
||||
worldGenerator = new WorldGenerator();
|
||||
advanced = new Advanced();
|
||||
}
|
||||
|
||||
|
||||
//==================//
|
||||
// Graphics Configs //
|
||||
//==================//
|
||||
public static class Graphics implements IGraphics
|
||||
{
|
||||
public final IQuality quality;
|
||||
public final IFogQuality fogQuality;
|
||||
public final IAdvancedGraphics advancedGraphics;
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public IQuality quality()
|
||||
{
|
||||
return quality;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IFogQuality fogQuality()
|
||||
{
|
||||
return fogQuality;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAdvancedGraphics advancedGraphics()
|
||||
{
|
||||
return advancedGraphics;
|
||||
}
|
||||
|
||||
|
||||
Graphics()
|
||||
{
|
||||
quality = new Quality();
|
||||
advancedGraphics = new AdvancedGraphics();
|
||||
fogQuality = new FogQuality();
|
||||
}
|
||||
|
||||
|
||||
public static class Quality implements IQuality
|
||||
{
|
||||
@Override
|
||||
public HorizontalResolution getDrawResolution()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.quality.drawResolution.get();
|
||||
}
|
||||
@Override
|
||||
public void setDrawResolution(HorizontalResolution newHorizontalResolution)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.quality.drawResolution.set(newHorizontalResolution);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getLodChunkRenderDistance()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.quality.lodChunkRenderDistance.get();
|
||||
}
|
||||
@Override
|
||||
public void setLodChunkRenderDistance(int newLodChunkRenderDistance)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.quality.lodChunkRenderDistance.set(newLodChunkRenderDistance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public VerticalQuality getVerticalQuality()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.quality.verticalQuality.get();
|
||||
}
|
||||
@Override
|
||||
public void setVerticalQuality(VerticalQuality newVerticalQuality)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.quality.verticalQuality.set(newVerticalQuality);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HorizontalScale getHorizontalScale()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.quality.horizontalScale.get();
|
||||
}
|
||||
@Override
|
||||
public void setHorizontalScale(HorizontalScale newHorizontalScale)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.quality.horizontalScale.set(newHorizontalScale);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public HorizontalQuality getHorizontalQuality()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.quality.horizontalQuality.get();
|
||||
}
|
||||
@Override
|
||||
public void setHorizontalQuality(HorizontalQuality newHorizontalQuality)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.quality.horizontalQuality.set(newHorizontalQuality);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class FogQuality implements IFogQuality
|
||||
{
|
||||
@Override
|
||||
public FogDistance getFogDistance()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.fogQuality.fogDistance.get();
|
||||
}
|
||||
@Override
|
||||
public void setFogDistance(FogDistance newFogDistance)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.fogQuality.fogDistance.set(newFogDistance);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FogDrawMode getFogDrawMode()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.fogQuality.fogDrawMode.get();
|
||||
}
|
||||
@Override
|
||||
public void setFogDrawMode(FogDrawMode newFogDrawMode)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.fogQuality.fogDrawMode.set(newFogDrawMode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public FogColorMode getFogColorMode()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.fogQuality.fogColorMode.get();
|
||||
}
|
||||
@Override
|
||||
public void setFogColorMode(FogColorMode newFogColorMode)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.fogQuality.fogColorMode.set(newFogColorMode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getDisableVanillaFog()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.fogQuality.disableVanillaFog.get();
|
||||
}
|
||||
@Override
|
||||
public void setDisableVanillaFog(boolean newDisableVanillaFog)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.fogQuality.disableVanillaFog.set(newDisableVanillaFog);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class AdvancedGraphics implements IAdvancedGraphics
|
||||
{
|
||||
@Override
|
||||
public LodTemplate getLodTemplate()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphics.lodTemplate.get();
|
||||
}
|
||||
@Override
|
||||
public void setLodTemplate(LodTemplate newLodTemplate)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphics.lodTemplate.set(newLodTemplate);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getDisableDirectionalCulling()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphics.disableDirectionalCulling.get();
|
||||
}
|
||||
@Override
|
||||
public void setDisableDirectionalCulling(boolean newDisableDirectionalCulling)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphics.disableDirectionalCulling.set(newDisableDirectionalCulling);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getAlwaysDrawAtMaxQuality()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphics.alwaysDrawAtMaxQuality.get();
|
||||
}
|
||||
@Override
|
||||
public void setAlwaysDrawAtMaxQuality(boolean newAlwaysDrawAtMaxQuality)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphics.alwaysDrawAtMaxQuality.set(newAlwaysDrawAtMaxQuality);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public VanillaOverdraw getVanillaOverdraw()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphics.vanillaOverdraw.get();
|
||||
}
|
||||
@Override
|
||||
public void setVanillaOverdraw(VanillaOverdraw newVanillaOverdraw)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphics.vanillaOverdraw.set(newVanillaOverdraw);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getUseExtendedNearClipPlane()
|
||||
{
|
||||
return ForgeConfig.CLIENT.graphics.advancedGraphics.useExtendedNearClipPlane.get();
|
||||
}
|
||||
@Override
|
||||
public void setUseExtendedNearClipPlane(boolean newUseExtendedNearClipPlane)
|
||||
{
|
||||
ForgeConfig.CLIENT.graphics.advancedGraphics.useExtendedNearClipPlane.set(newUseExtendedNearClipPlane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//========================//
|
||||
// WorldGenerator Configs //
|
||||
//========================//
|
||||
public static class WorldGenerator implements IWorldGenerator
|
||||
{
|
||||
@Override
|
||||
public GenerationPriority getGenerationPriority()
|
||||
{
|
||||
return ForgeConfig.CLIENT.worldGenerator.generationPriority.get();
|
||||
}
|
||||
@Override
|
||||
public void setGenerationPriority(GenerationPriority newGenerationPriority)
|
||||
{
|
||||
ForgeConfig.CLIENT.worldGenerator.generationPriority.set(newGenerationPriority);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DistanceGenerationMode getDistanceGenerationMode()
|
||||
{
|
||||
return ForgeConfig.CLIENT.worldGenerator.distanceGenerationMode.get();
|
||||
}
|
||||
@Override
|
||||
public void setDistanceGenerationMode(DistanceGenerationMode newDistanceGenerationMode)
|
||||
{
|
||||
ForgeConfig.CLIENT.worldGenerator.distanceGenerationMode.set(newDistanceGenerationMode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getAllowUnstableFeatureGeneration()
|
||||
{
|
||||
return ForgeConfig.CLIENT.worldGenerator.allowUnstableFeatureGeneration.get();
|
||||
}
|
||||
@Override
|
||||
public void setAllowUnstableFeatureGeneration(boolean newAllowUnstableFeatureGeneration)
|
||||
{
|
||||
ForgeConfig.CLIENT.worldGenerator.allowUnstableFeatureGeneration.set(newAllowUnstableFeatureGeneration);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BlocksToAvoid getBlocksToAvoid()
|
||||
{
|
||||
return ForgeConfig.CLIENT.worldGenerator.blocksToAvoid.get();
|
||||
}
|
||||
@Override
|
||||
public void setBlockToAvoid(BlocksToAvoid newBlockToAvoid)
|
||||
{
|
||||
ForgeConfig.CLIENT.worldGenerator.blocksToAvoid.set(newBlockToAvoid);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//============================//
|
||||
// AdvancedModOptions Configs //
|
||||
//============================//
|
||||
public static class Advanced implements IAdvanced
|
||||
{
|
||||
public final IThreading threading;
|
||||
public final IDebugging debugging;
|
||||
public final IBuffers buffers;
|
||||
|
||||
|
||||
@Override
|
||||
public IThreading threading()
|
||||
{
|
||||
return threading;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IDebugging debugging()
|
||||
{
|
||||
return debugging;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IBuffers buffers()
|
||||
{
|
||||
return buffers;
|
||||
}
|
||||
|
||||
|
||||
public Advanced()
|
||||
{
|
||||
threading = new Threading();
|
||||
debugging = new Debugging();
|
||||
buffers = new Buffers();
|
||||
}
|
||||
|
||||
public static class Threading implements IThreading
|
||||
{
|
||||
@Override
|
||||
public int getNumberOfWorldGenerationThreads()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advanced.threading.numberOfWorldGenerationThreads.get();
|
||||
}
|
||||
@Override
|
||||
public void setNumberOfWorldGenerationThreads(int newNumberOfWorldGenerationThreads)
|
||||
{
|
||||
ForgeConfig.CLIENT.advanced.threading.numberOfWorldGenerationThreads.set(newNumberOfWorldGenerationThreads);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getNumberOfBufferBuilderThreads()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advanced.threading.numberOfBufferBuilderThreads.get();
|
||||
}
|
||||
@Override
|
||||
public void setNumberOfBufferBuilderThreads(int newNumberOfWorldBuilderThreads)
|
||||
{
|
||||
ForgeConfig.CLIENT.advanced.threading.numberOfBufferBuilderThreads.set(newNumberOfWorldBuilderThreads);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// Debug Options //
|
||||
//===============//
|
||||
public static class Debugging implements IDebugging
|
||||
{
|
||||
@Override
|
||||
public boolean getDrawLods()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advanced.debugging.drawLods.get();
|
||||
}
|
||||
@Override
|
||||
public void setDrawLods(boolean newDrawLods)
|
||||
{
|
||||
ForgeConfig.CLIENT.advanced.debugging.drawLods.set(newDrawLods);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DebugMode getDebugMode()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advanced.debugging.debugMode.get();
|
||||
}
|
||||
@Override
|
||||
public void setDebugMode(DebugMode newDebugMode)
|
||||
{
|
||||
ForgeConfig.CLIENT.advanced.debugging.debugMode.set(newDebugMode);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean getDebugKeybindingsEnabled()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advanced.debugging.enableDebugKeybindings.get();
|
||||
}
|
||||
@Override
|
||||
public void setDebugKeybindingsEnabled(boolean newEnableDebugKeybindings)
|
||||
{
|
||||
ForgeConfig.CLIENT.advanced.debugging.enableDebugKeybindings.set(newEnableDebugKeybindings);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class Buffers implements IBuffers
|
||||
{
|
||||
@Override
|
||||
public GpuUploadMethod getGpuUploadMethod()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advanced.buffers.gpuUploadMethod.get();
|
||||
}
|
||||
@Override
|
||||
public void setGpuUploadMethod(GpuUploadMethod newDisableVanillaFog)
|
||||
{
|
||||
ForgeConfig.CLIENT.advanced.buffers.gpuUploadMethod.set(newDisableVanillaFog);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getGpuUploadTimeoutInMilliseconds()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advanced.buffers.gpuUploadTimeoutInMilleseconds.get();
|
||||
}
|
||||
@Override
|
||||
public void setGpuUploadTimeoutInMilliseconds(int newTimeoutInMilliseconds)
|
||||
{
|
||||
ForgeConfig.CLIENT.advanced.buffers.gpuUploadTimeoutInMilleseconds.set(newTimeoutInMilliseconds);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BufferRebuildTimes getRebuildTimes()
|
||||
{
|
||||
return ForgeConfig.CLIENT.advanced.buffers.rebuildTimes.get();
|
||||
}
|
||||
@Override
|
||||
public void setRebuildTimes(BufferRebuildTimes newBufferRebuildTimes)
|
||||
{
|
||||
ForgeConfig.CLIENT.advanced.buffers.rebuildTimes.set(newBufferRebuildTimes);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package com.seibel.lod.forge.wrappers.minecraft;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.util.HashSet;
|
||||
|
||||
import org.lwjgl.opengl.GL15;
|
||||
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import com.seibel.lod.core.objects.math.Vec3d;
|
||||
import com.seibel.lod.core.objects.math.Vec3f;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.lod.forge.wrappers.McObjectConverter;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.ActiveRenderInfo;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.renderer.chunk.ChunkRenderDispatcher.CompiledChunk;
|
||||
import net.minecraft.potion.Effects;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.vector.Vector3d;
|
||||
import net.minecraft.util.math.vector.Vector3f;
|
||||
|
||||
/**
|
||||
* A singleton that contains everything
|
||||
* related to rendering in Minecraft.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-26-2021
|
||||
*/
|
||||
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||
{
|
||||
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
||||
|
||||
private final GameRenderer gameRenderer = Minecraft.getInstance().gameRenderer;
|
||||
private final static Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public Vec3f getLookAtVector()
|
||||
{
|
||||
ActiveRenderInfo camera = gameRenderer.getMainCamera();
|
||||
Vector3f cameraDir = camera.getLookVector();
|
||||
return new Vec3f(cameraDir.x(), cameraDir.y(), cameraDir.z());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbstractBlockPosWrapper getCameraBlockPosition()
|
||||
{
|
||||
ActiveRenderInfo camera = gameRenderer.getMainCamera();
|
||||
BlockPos blockPos = camera.getBlockPosition();
|
||||
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerHasBlindnessEffect()
|
||||
{
|
||||
return mc.player.getActiveEffectsMap().get(Effects.BLINDNESS) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Vec3d getCameraExactPosition()
|
||||
{
|
||||
ActiveRenderInfo camera = gameRenderer.getMainCamera();
|
||||
Vector3d projectedView = camera.getPosition();
|
||||
|
||||
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mat4f getDefaultProjectionMatrix(float partialTicks)
|
||||
{
|
||||
return McObjectConverter.Convert(gameRenderer.getProjectionMatrix(gameRenderer.getMainCamera(), partialTicks, true));
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getGamma()
|
||||
{
|
||||
return mc.options.gamma;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getFogColor()
|
||||
{
|
||||
float[] colorValues = new float[4];
|
||||
GL15.glGetFloatv(GL15.GL_FOG_COLOR, colorValues);
|
||||
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Color getSkyColor()
|
||||
{
|
||||
if (mc.level.dimensionType().hasSkyLight())
|
||||
{
|
||||
Vector3d colorValues = mc.level.getSkyColor(mc.gameRenderer.getMainCamera().getBlockPosition(), mc.getFrameTime());
|
||||
return new Color((float) colorValues.x, (float) colorValues.y, (float) colorValues.z);
|
||||
}
|
||||
else
|
||||
{
|
||||
return new Color(0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getFov(float partialTicks)
|
||||
{
|
||||
return gameRenderer.getFov(gameRenderer.getMainCamera(), partialTicks, true);
|
||||
}
|
||||
|
||||
/** Measured in chunks */
|
||||
@Override
|
||||
public int getRenderDistance()
|
||||
{
|
||||
return mc.options.renderDistance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getScreenWidth()
|
||||
{
|
||||
return mc.getWindow().getWidth();
|
||||
}
|
||||
@Override
|
||||
public int getScreenHeight()
|
||||
{
|
||||
return mc.getWindow().getHeight();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns the ChunkPos of all chunks that Minecraft
|
||||
* is going to render this frame. <br><br>
|
||||
* <p>
|
||||
* Note: This isn't perfect. It will return some chunks that are outside
|
||||
* the clipping plane. (For example, if you are high above the ground some chunks
|
||||
* will be incorrectly added, even though they are outside render range).
|
||||
*/
|
||||
@Override
|
||||
public HashSet<AbstractChunkPosWrapper> getRenderedChunks()
|
||||
{
|
||||
HashSet<AbstractChunkPosWrapper> loadedPos = new HashSet<>();
|
||||
|
||||
// Wow, those are some long names!
|
||||
|
||||
// go through every RenderInfo to get the compiled chunks
|
||||
WorldRenderer renderer = mc.levelRenderer;
|
||||
for (WorldRenderer.LocalRenderInformationContainer worldRenderer$LocalRenderInformationContainer : renderer.renderChunks)
|
||||
{
|
||||
CompiledChunk compiledChunk = worldRenderer$LocalRenderInformationContainer.chunk.getCompiledChunk();
|
||||
if (!compiledChunk.hasNoRenderableLayers())
|
||||
{
|
||||
// add the ChunkPos for every rendered chunk
|
||||
BlockPos bpos = worldRenderer$LocalRenderInformationContainer.chunk.getOrigin();
|
||||
|
||||
loadedPos.add(new ChunkPosWrapper(bpos));
|
||||
}
|
||||
}
|
||||
|
||||
return loadedPos;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,394 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers.minecraft;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.seibel.lod.core.ModInfo;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.forge.wrappers.McObjectConverter;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.misc.LightMapWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.DimensionTypeWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
|
||||
|
||||
import net.minecraft.client.GameSettings;
|
||||
import net.minecraft.client.MainWindow;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.player.ClientPlayerEntity;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.client.network.play.ClientPlayNetHandler;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.WorldRenderer;
|
||||
import net.minecraft.client.renderer.model.ModelManager;
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.crash.CrashReport;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.text.StringTextComponent;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
/**
|
||||
* A singleton that wraps the Minecraft class
|
||||
* to allow for easier movement between Minecraft versions.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 9-16-2021
|
||||
*/
|
||||
public class MinecraftWrapper implements IMinecraftWrapper
|
||||
{
|
||||
public static final MinecraftWrapper INSTANCE = new MinecraftWrapper();
|
||||
|
||||
private final Minecraft mc = Minecraft.getInstance();
|
||||
|
||||
/**
|
||||
* The lightmap for the current:
|
||||
* Time, dimension, brightness setting, etc.
|
||||
*/
|
||||
private NativeImage lightMap = null;
|
||||
|
||||
private ProfilerWrapper profilerWrapper;
|
||||
|
||||
|
||||
private MinecraftWrapper()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
|
||||
/**
|
||||
* This should be called at the beginning of every frame to
|
||||
* clear any Minecraft data that becomes out of date after a frame. <br> <br>
|
||||
* <p>
|
||||
* LightMaps and other time sensitive objects fall in this category. <br> <br>
|
||||
* <p>
|
||||
* This doesn't affect OpenGL objects in any way.
|
||||
*/
|
||||
@Override
|
||||
public void clearFrameObjectCache()
|
||||
{
|
||||
lightMap = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// method wrappers //
|
||||
//=================//
|
||||
|
||||
@Override
|
||||
public float getShade(LodDirection lodDirection)
|
||||
{
|
||||
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
||||
return mc.level.getShade(mcDir, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSinglePlayerServer()
|
||||
{
|
||||
return mc.hasSingleplayerServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentServerName()
|
||||
{
|
||||
return mc.getCurrentServer().name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentServerIp()
|
||||
{
|
||||
return mc.getCurrentServer().ip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentServerVersion()
|
||||
{
|
||||
return mc.getCurrentServer().version.getString();
|
||||
}
|
||||
|
||||
/** Returns the dimension the player is currently in */
|
||||
@Override
|
||||
public IDimensionTypeWrapper getCurrentDimension()
|
||||
{
|
||||
return DimensionTypeWrapper.getDimensionTypeWrapper(mc.player.level.dimensionType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCurrentDimensionId()
|
||||
{
|
||||
return LodUtil.getDimensionIDFromWorld(WorldWrapper.getWorldWrapper(mc.level));
|
||||
}
|
||||
|
||||
/** This texture changes every frame */
|
||||
@Override
|
||||
public ILightMapWrapper getCurrentLightMap()
|
||||
{
|
||||
// get the current lightMap if the cache is empty
|
||||
if (lightMap == null)
|
||||
{
|
||||
LightTexture tex = mc.gameRenderer.lightTexture();
|
||||
lightMap = tex.lightPixels;
|
||||
}
|
||||
return new LightMapWrapper(lightMap);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the color int at the given pixel coordinates
|
||||
* from the current lightmap.
|
||||
* @param u x location in texture space
|
||||
* @param v z location in texture space
|
||||
*/
|
||||
@Override
|
||||
public int getColorIntFromLightMap(int u, int v)
|
||||
{
|
||||
if (lightMap == null)
|
||||
{
|
||||
// make sure the lightMap is up-to-date
|
||||
getCurrentLightMap();
|
||||
}
|
||||
|
||||
return lightMap.getPixelRGBA(u, v);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Color at the given pixel coordinates
|
||||
* from the current lightmap.
|
||||
* @param u x location in texture space
|
||||
* @param v z location in texture space
|
||||
*/
|
||||
@Override
|
||||
public Color getColorFromLightMap(int u, int v)
|
||||
{
|
||||
return LodUtil.intToColor(lightMap.getPixelRGBA(u, v));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// Simple gets //
|
||||
//=============//
|
||||
|
||||
public ClientPlayerEntity getPlayer()
|
||||
{
|
||||
return mc.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean playerExists()
|
||||
{
|
||||
return mc.player != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPosWrapper getPlayerBlockPos()
|
||||
{
|
||||
BlockPos playerPos = getPlayer().blockPosition();
|
||||
return new BlockPosWrapper(playerPos.getX(), playerPos.getY(), playerPos.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkPosWrapper getPlayerChunkPos()
|
||||
{
|
||||
return new ChunkPosWrapper(getPlayer().xChunk, getPlayer().zChunk);
|
||||
}
|
||||
|
||||
public GameSettings getOptions()
|
||||
{
|
||||
return mc.options;
|
||||
}
|
||||
|
||||
public ModelManager getModelManager()
|
||||
{
|
||||
return mc.getModelManager();
|
||||
}
|
||||
|
||||
public ClientWorld getClientWorld()
|
||||
{
|
||||
return mc.level;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to get the ServerWorld for the dimension
|
||||
* the user is currently in.
|
||||
* @returns null if no ServerWorld is available
|
||||
*/
|
||||
@Override
|
||||
public IWorldWrapper getWrappedServerWorld()
|
||||
{
|
||||
if (mc.level == null)
|
||||
return null;
|
||||
|
||||
DimensionType dimension = mc.level.dimensionType();
|
||||
IntegratedServer server = mc.getSingleplayerServer();
|
||||
|
||||
if (server == null)
|
||||
return null;
|
||||
|
||||
ServerWorld serverWorld = null;
|
||||
Iterable<ServerWorld> worlds = server.getAllLevels();
|
||||
for (ServerWorld world : worlds)
|
||||
{
|
||||
if (world.dimensionType() == dimension)
|
||||
{
|
||||
serverWorld = world;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return WorldWrapper.getWorldWrapper(serverWorld);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorldWrapper getWrappedClientWorld()
|
||||
{
|
||||
return WorldWrapper.getWorldWrapper(mc.level);
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getGameDirectory()
|
||||
{
|
||||
return mc.gameDirectory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IProfilerWrapper getProfiler()
|
||||
{
|
||||
if (profilerWrapper == null)
|
||||
profilerWrapper = new ProfilerWrapper(mc.getProfiler());
|
||||
else if (mc.getProfiler() != profilerWrapper.profiler)
|
||||
profilerWrapper.profiler = mc.getProfiler();
|
||||
|
||||
return profilerWrapper;
|
||||
}
|
||||
|
||||
public ClientPlayNetHandler getConnection()
|
||||
{
|
||||
return mc.getConnection();
|
||||
}
|
||||
|
||||
public GameRenderer getGameRenderer()
|
||||
{
|
||||
return mc.gameRenderer;
|
||||
}
|
||||
|
||||
public Entity getCameraEntity()
|
||||
{
|
||||
return mc.cameraEntity;
|
||||
}
|
||||
|
||||
public MainWindow getWindow()
|
||||
{
|
||||
return mc.getWindow();
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getSkyDarken(float partialTicks)
|
||||
{
|
||||
return mc.level.getSkyDarken(partialTicks);
|
||||
}
|
||||
|
||||
public IntegratedServer getSinglePlayerServer()
|
||||
{
|
||||
return mc.getSingleplayerServer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean connectedToServer()
|
||||
{
|
||||
return mc.getCurrentServer() != null;
|
||||
}
|
||||
|
||||
public ServerData getCurrentServer()
|
||||
{
|
||||
return mc.getCurrentServer();
|
||||
}
|
||||
|
||||
public WorldRenderer getLevelRenderer()
|
||||
{
|
||||
return mc.levelRenderer;
|
||||
}
|
||||
|
||||
/** Returns all worlds available to the server */
|
||||
@Override
|
||||
public ArrayList<IWorldWrapper> getAllServerWorlds()
|
||||
{
|
||||
ArrayList<IWorldWrapper> worlds = new ArrayList<IWorldWrapper>();
|
||||
|
||||
Iterable<ServerWorld> serverWorlds = mc.getSingleplayerServer().getAllLevels();
|
||||
for (ServerWorld world : serverWorlds)
|
||||
{
|
||||
worlds.add(WorldWrapper.getWorldWrapper(world));
|
||||
}
|
||||
|
||||
return worlds;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void sendChatMessage(String string)
|
||||
{
|
||||
getPlayer().sendMessage(new StringTextComponent(string), getPlayer().getUUID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Crashes Minecraft, displaying the given errorMessage <br> <br>
|
||||
* In the following format: <br>
|
||||
*
|
||||
* The game crashed whilst <strong>errorMessage</strong> <br>
|
||||
* Error: <strong>ExceptionClass: exceptionErrorMessage</strong> <br>
|
||||
* Exit Code: -1 <br>
|
||||
*/
|
||||
@Override
|
||||
public void crashMinecraft(String errorMessage, Throwable exception)
|
||||
{
|
||||
ClientApi.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
|
||||
CrashReport report = new CrashReport(errorMessage, exception);
|
||||
Minecraft.crash(report);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package com.seibel.lod.forge.wrappers.minecraft;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
|
||||
import net.minecraft.profiler.IProfiler;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class ProfilerWrapper implements IProfilerWrapper
|
||||
{
|
||||
public IProfiler profiler;
|
||||
|
||||
public ProfilerWrapper(IProfiler newProfiler)
|
||||
{
|
||||
profiler = newProfiler;
|
||||
}
|
||||
|
||||
|
||||
/** starts a new section inside the currently running section */
|
||||
@Override
|
||||
public void push(String newSection)
|
||||
{
|
||||
profiler.push(newSection);
|
||||
}
|
||||
|
||||
/** ends the currently running section and starts a new one */
|
||||
@Override
|
||||
public void popPush(String newSection)
|
||||
{
|
||||
profiler.popPush(newSection);
|
||||
}
|
||||
|
||||
/** ends the currently running section */
|
||||
@Override
|
||||
public void pop()
|
||||
{
|
||||
profiler.pop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package com.seibel.lod.forge.wrappers.misc;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||
|
||||
import net.minecraft.client.renderer.texture.NativeImage;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Leonardo Amato
|
||||
* @version 11-13-2021
|
||||
*/
|
||||
public class LightMapWrapper implements ILightMapWrapper
|
||||
{
|
||||
private NativeImage lightMap = null;
|
||||
|
||||
public LightMapWrapper(NativeImage newlightMap)
|
||||
{
|
||||
lightMap = newlightMap;
|
||||
}
|
||||
|
||||
public void setLightMap(NativeImage newlightMap)
|
||||
{
|
||||
lightMap = newlightMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLightValue(int skyLight, int blockLight)
|
||||
{
|
||||
return lightMap.getPixelRGBA(skyLight, blockLight);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers.world;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeColorWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
|
||||
import net.minecraft.world.biome.BiomeColors;
|
||||
|
||||
|
||||
/**
|
||||
* @author Cola?
|
||||
* @version 11-15-2021
|
||||
*/
|
||||
public class BiomeColorWrapperSingleton implements IBiomeColorWrapperSingleton
|
||||
{
|
||||
private static final BiomeColorWrapperSingleton instance = new BiomeColorWrapperSingleton();
|
||||
|
||||
@Override
|
||||
public IBiomeColorWrapperSingleton getInstance()
|
||||
{
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getGrassColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BiomeColors.getAverageGrassColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
@Override
|
||||
public int getWaterColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BiomeColors.getAverageWaterColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
@Override
|
||||
public int getFoliageColor(IWorldWrapper world, AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BiomeColors.getAverageFoliageColor(((WorldWrapper)world).getWorld(), ((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
package com.seibel.lod.forge.wrappers.world;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockColorSingletonWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockColorWrapper;
|
||||
|
||||
import net.minecraft.block.Blocks;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-15-2021
|
||||
*/
|
||||
public class BiomeWrapper implements IBiomeWrapper
|
||||
{
|
||||
public static final ConcurrentMap<Biome, BiomeWrapper> biomeWrapperMap = new ConcurrentHashMap<>();
|
||||
private final Biome biome;
|
||||
|
||||
public BiomeWrapper(Biome biome)
|
||||
{
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
static public BiomeWrapper getBiomeWrapper(Biome biome)
|
||||
{
|
||||
//first we check if the biome has already been wrapped
|
||||
if(biomeWrapperMap.containsKey(biome) && biomeWrapperMap.get(biome) != null)
|
||||
return biomeWrapperMap.get(biome);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
BiomeWrapper biomeWrapper = new BiomeWrapper(biome);
|
||||
biomeWrapperMap.put(biome, biomeWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return biomeWrapper;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Returns a color int for the given biome. */
|
||||
@Override
|
||||
public int getColorForBiome(int x, int z)
|
||||
{
|
||||
int colorInt;
|
||||
int tintValue = 0;
|
||||
|
||||
switch (biome.getBiomeCategory())
|
||||
{
|
||||
|
||||
case NETHER:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.NETHERRACK).getColor();
|
||||
break;
|
||||
|
||||
case THEEND:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.END_STONE).getColor();
|
||||
break;
|
||||
|
||||
case BEACH:
|
||||
case DESERT:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.SAND).getColor();
|
||||
break;
|
||||
|
||||
case EXTREME_HILLS:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.STONE).getColor();
|
||||
break;
|
||||
|
||||
case MUSHROOM:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.MYCELIUM).getColor();
|
||||
break;
|
||||
|
||||
case ICY:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.SNOW).getColor();
|
||||
break;
|
||||
|
||||
case MESA:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.RED_SAND).getColor();
|
||||
break;
|
||||
|
||||
case OCEAN:
|
||||
case RIVER:
|
||||
colorInt = BlockColorSingletonWrapper.INSTANCE.getWaterColor().getColor();
|
||||
tintValue = biome.getWaterColor();
|
||||
break;
|
||||
|
||||
case PLAINS:
|
||||
case SAVANNA:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.GRASS_BLOCK).getColor();
|
||||
tintValue = biome.getGrassColor(x, z);
|
||||
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
|
||||
break;
|
||||
|
||||
case TAIGA:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.SPRUCE_LEAVES).getColor();
|
||||
tintValue = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
|
||||
break;
|
||||
case JUNGLE:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.JUNGLE_LEAVES).getColor();
|
||||
tintValue = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
|
||||
break;
|
||||
|
||||
case NONE:
|
||||
default:
|
||||
case SWAMP:
|
||||
case FOREST:
|
||||
colorInt = BlockColorWrapper.getBlockColorWrapper(Blocks.OAK_LEAVES).getColor();
|
||||
tintValue = biome.getFoliageColor();
|
||||
colorInt = ColorUtil.multiplyRGBcolors(colorInt,tintValue);
|
||||
break;
|
||||
}
|
||||
|
||||
return colorInt;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getGrassTint(int x, int z)
|
||||
{
|
||||
return biome.getGrassColor(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getFolliageTint()
|
||||
{
|
||||
return biome.getFoliageColor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWaterTint()
|
||||
{
|
||||
return biome.getWaterColor();
|
||||
}
|
||||
|
||||
|
||||
@Override public boolean equals(Object o)
|
||||
{
|
||||
if (this == o)
|
||||
return true;
|
||||
if (!(o instanceof BiomeWrapper))
|
||||
return false;
|
||||
BiomeWrapper that = (BiomeWrapper) o;
|
||||
return Objects.equals(biome, that.biome);
|
||||
}
|
||||
|
||||
@Override public int hashCode()
|
||||
{
|
||||
return Objects.hash(biome);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
package com.seibel.lod.forge.wrappers.world;
|
||||
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||
|
||||
import net.minecraft.world.DimensionType;
|
||||
|
||||
/**
|
||||
* @author ??
|
||||
* @version 11-15-2021
|
||||
*/
|
||||
public class DimensionTypeWrapper implements IDimensionTypeWrapper
|
||||
{
|
||||
private static final ConcurrentMap<DimensionType, DimensionTypeWrapper> dimensionTypeWrapperMap = new ConcurrentHashMap<>();
|
||||
private final DimensionType dimensionType;
|
||||
|
||||
public DimensionTypeWrapper(DimensionType dimensionType)
|
||||
{
|
||||
this.dimensionType = dimensionType;
|
||||
}
|
||||
|
||||
public static DimensionTypeWrapper getDimensionTypeWrapper(DimensionType dimensionType)
|
||||
{
|
||||
//first we check if the biome has already been wrapped
|
||||
if(dimensionTypeWrapperMap.containsKey(dimensionType) && dimensionTypeWrapperMap.get(dimensionType) != null)
|
||||
return dimensionTypeWrapperMap.get(dimensionType);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
DimensionTypeWrapper dimensionTypeWrapper = new DimensionTypeWrapper(dimensionType);
|
||||
dimensionTypeWrapperMap.put(dimensionType, dimensionTypeWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return dimensionTypeWrapper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDimensionName()
|
||||
{
|
||||
return dimensionType.effectsLocation().getPath();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCeiling()
|
||||
{
|
||||
return dimensionType.hasCeiling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSkyLight()
|
||||
{
|
||||
return dimensionType.hasSkyLight();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
package com.seibel.lod.forge.wrappers.world;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.seibel.lod.core.enums.WorldType;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.forge.wrappers.block.BlockPosWrapper;
|
||||
|
||||
import net.minecraft.client.world.ClientWorld;
|
||||
import net.minecraft.world.IWorld;
|
||||
import net.minecraft.world.LightType;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @author ??
|
||||
* @version 11-20-2021
|
||||
*/
|
||||
public class WorldWrapper implements IWorldWrapper
|
||||
{
|
||||
private static final ConcurrentMap<IWorld, WorldWrapper> worldWrapperMap = new ConcurrentHashMap<>();
|
||||
private final IWorld world;
|
||||
public final WorldType worldType;
|
||||
|
||||
|
||||
public WorldWrapper(IWorld newWorld)
|
||||
{
|
||||
world = newWorld;
|
||||
|
||||
if (world.getClass() == ServerWorld.class)
|
||||
worldType = WorldType.ServerWorld;
|
||||
else if (world.getClass() == ClientWorld.class)
|
||||
worldType = WorldType.ClientWorld;
|
||||
else
|
||||
worldType = WorldType.Unknown;
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
public static WorldWrapper getWorldWrapper(IWorld world)
|
||||
{
|
||||
if (world == null) return null;
|
||||
//first we check if the biome has already been wrapped
|
||||
if(worldWrapperMap.containsKey(world) && worldWrapperMap.get(world) != null)
|
||||
return worldWrapperMap.get(world);
|
||||
|
||||
|
||||
//if it hasn't been created yet, we create it and save it in the map
|
||||
WorldWrapper worldWrapper = new WorldWrapper(world);
|
||||
worldWrapperMap.put(world, worldWrapper);
|
||||
|
||||
//we return the newly created wrapper
|
||||
return worldWrapper;
|
||||
}
|
||||
|
||||
public static void clearMap()
|
||||
{
|
||||
worldWrapperMap.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldType getWorldType()
|
||||
{
|
||||
return worldType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DimensionTypeWrapper getDimensionType()
|
||||
{
|
||||
return DimensionTypeWrapper.getDimensionTypeWrapper(world.dimensionType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBlockLight(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return world.getBrightness(LightType.BLOCK, ((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSkyLight(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return world.getBrightness(LightType.SKY, ((BlockPosWrapper) blockPos).getBlockPos());
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeWrapper getBiome(AbstractBlockPosWrapper blockPos)
|
||||
{
|
||||
return BiomeWrapper.getBiomeWrapper(world.getBiome(((BlockPosWrapper) blockPos).getBlockPos()));
|
||||
}
|
||||
|
||||
public IWorld getWorld()
|
||||
{
|
||||
return world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasCeiling()
|
||||
{
|
||||
return world.dimensionType().hasCeiling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasSkyLight()
|
||||
{
|
||||
return world.dimensionType().hasSkyLight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty()
|
||||
{
|
||||
return world == null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight()
|
||||
{
|
||||
return world.getHeight();
|
||||
}
|
||||
|
||||
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
|
||||
@Override
|
||||
public File getSaveFolder() throws UnsupportedOperationException
|
||||
{
|
||||
if (worldType != WorldType.ServerWorld)
|
||||
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
|
||||
|
||||
ServerChunkProvider chunkSource = ((ServerWorld) world).getChunkSource();
|
||||
return chunkSource.dataStorage.dataFolder;
|
||||
}
|
||||
|
||||
|
||||
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
|
||||
public ServerWorld getServerWorld() throws UnsupportedOperationException
|
||||
{
|
||||
if (worldType != WorldType.ServerWorld)
|
||||
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
|
||||
|
||||
return (ServerWorld) world;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel()
|
||||
{
|
||||
// TODO this is depreciated, what should we use instead?
|
||||
return world.getSeaLevel();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.forge.wrappers.worldGeneration;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.forge.wrappers.WrapperUtil;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.particles.IParticleData;
|
||||
import net.minecraft.tileentity.TileEntity;
|
||||
import net.minecraft.util.Direction;
|
||||
import net.minecraft.util.SoundCategory;
|
||||
import net.minecraft.util.SoundEvent;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.SectionPos;
|
||||
import net.minecraft.util.registry.DynamicRegistries;
|
||||
import net.minecraft.world.DifficultyInstance;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.EmptyTickList;
|
||||
import net.minecraft.world.ISeedReader;
|
||||
import net.minecraft.world.ITickList;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.biome.BiomeManager;
|
||||
import net.minecraft.world.border.WorldBorder;
|
||||
import net.minecraft.world.chunk.AbstractChunkProvider;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
import net.minecraft.world.gen.feature.structure.Structure;
|
||||
import net.minecraft.world.gen.feature.structure.StructureStart;
|
||||
import net.minecraft.world.lighting.WorldLightManager;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraft.world.storage.IWorldInfo;
|
||||
|
||||
|
||||
/**
|
||||
* This is a fake ServerWorld used when generating features.
|
||||
* It allows us to keep each LodChunk generation independent
|
||||
* of the actual ServerWorld, allowing
|
||||
* multithread generation.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 7-26-2021
|
||||
*/
|
||||
public class LodServerWorld implements ISeedReader
|
||||
{
|
||||
|
||||
public HashMap<Heightmap.Type, Heightmap> heightmaps = new HashMap<>();
|
||||
|
||||
public final IChunk chunk;
|
||||
|
||||
public final ServerWorld serverWorld;
|
||||
|
||||
public LodServerWorld(ServerWorld newServerWorld, IChunk newChunk)
|
||||
{
|
||||
chunk = newChunk;
|
||||
serverWorld = newServerWorld;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getHeight(Heightmap.Type heightmapType, int x, int z)
|
||||
{
|
||||
// make sure the block position is set relative to the chunk
|
||||
x = x % LodUtil.CHUNK_WIDTH;
|
||||
x = (x < 0) ? x + 16 : x;
|
||||
|
||||
z = z % LodUtil.CHUNK_WIDTH;
|
||||
z = (z < 0) ? z + 16 : z;
|
||||
|
||||
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Biome getBiome(BlockPos pos)
|
||||
{
|
||||
return chunk.getBiomes().getNoiseBiome(pos.getX() >> 2, pos.getY() >> 2, pos.getZ() >> 2);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBlock(BlockPos pos, BlockState state, int flags, int recursionLeft)
|
||||
{
|
||||
return chunk.setBlockState(pos, state, false) == state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getBlockState(BlockPos pos)
|
||||
{
|
||||
return chunk.getBlockState(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FluidState getFluidState(BlockPos pos)
|
||||
{
|
||||
return chunk.getFluidState(pos);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isStateAtPosition(BlockPos pos, Predicate<BlockState> state)
|
||||
{
|
||||
return state.test(chunk.getBlockState(pos));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITickList<Block> getBlockTicks()
|
||||
{
|
||||
return EmptyTickList.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IChunk getChunk(int x, int z, ChunkStatus requiredStatus, boolean nonnull)
|
||||
{
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<? extends StructureStart<?>> startsForFeature(SectionPos p_241827_1_, Structure<?> p_241827_2_)
|
||||
{
|
||||
return serverWorld.startsForFeature(p_241827_1_, p_241827_2_);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITickList<Fluid> getLiquidTicks()
|
||||
{
|
||||
return EmptyTickList.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldLightManager getLightEngine()
|
||||
{
|
||||
return new WorldLightManager(null, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getSeed()
|
||||
{
|
||||
return serverWorld.getSeed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public DynamicRegistries registryAccess()
|
||||
{
|
||||
return serverWorld.registryAccess();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* All methods below shouldn't be needed
|
||||
* and thus have been left unimplemented.
|
||||
*/
|
||||
|
||||
|
||||
@Override
|
||||
public Random getRandom()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playSound(PlayerEntity player, BlockPos pos, SoundEvent soundIn, SoundCategory category, float volume,
|
||||
float pitch)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addParticle(IParticleData particleData, double x, double y, double z, double xSpeed, double ySpeed,
|
||||
double zSpeed)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiomeManager getBiomeManager()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSeaLevel()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getShade(Direction p_230487_1_, boolean p_230487_2_)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldBorder getWorldBorder()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeBlock(BlockPos pos, boolean isMoving)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean destroyBlock(BlockPos pos, boolean dropBlock, Entity entity, int recursionLeft)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ServerWorld getLevel()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public AbstractChunkProvider getChunkSource()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DifficultyInstance getCurrentDifficultyAt(BlockPos arg0)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public IWorldInfo getLevelData()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void levelEvent(PlayerEntity arg0, int arg1, BlockPos arg2, int arg3)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<Entity> getEntities(Entity arg0, AxisAlignedBB arg1, Predicate<? super Entity> arg2)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T extends Entity> List<T> getEntitiesOfClass(Class<? extends T> arg0, AxisAlignedBB arg1,
|
||||
Predicate<? super T> arg2)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public List<? extends PlayerEntity> players()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getSkyDarken()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Biome getUncachedNoiseBiome(int p_225604_1_, int p_225604_2_, int p_225604_3_)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isClientSide()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DimensionType dimensionType()
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public TileEntity getBlockEntity(BlockPos p_175625_1_)
|
||||
{
|
||||
throw new UnsupportedOperationException("Not Implemented");
|
||||
}
|
||||
|
||||
}
|
||||
+389
@@ -0,0 +1,389 @@
|
||||
package com.seibel.lod.forge.wrappers.worldGeneration;
|
||||
|
||||
import java.util.ConcurrentModificationException;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilderConfig;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractWorldGeneratorWrapper;
|
||||
import com.seibel.lod.forge.wrappers.WrapperUtil;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkPosWrapper;
|
||||
import com.seibel.lod.forge.wrappers.chunk.ChunkWrapper;
|
||||
import com.seibel.lod.forge.wrappers.world.WorldWrapper;
|
||||
|
||||
import net.minecraft.util.palette.UpgradeData;
|
||||
import net.minecraft.util.registry.Registry;
|
||||
import net.minecraft.world.biome.Biome;
|
||||
import net.minecraft.world.chunk.ChunkPrimer;
|
||||
import net.minecraft.world.chunk.ChunkStatus;
|
||||
import net.minecraft.world.chunk.IChunk;
|
||||
import net.minecraft.world.gen.ChunkGenerator;
|
||||
import net.minecraft.world.gen.Heightmap;
|
||||
import net.minecraft.world.gen.feature.ConfiguredFeature;
|
||||
import net.minecraft.world.gen.feature.IceAndSnowFeature;
|
||||
import net.minecraft.world.gen.feature.NoFeatureConfig;
|
||||
import net.minecraft.world.gen.feature.template.TemplateManager;
|
||||
import net.minecraft.world.server.ServerChunkProvider;
|
||||
import net.minecraft.world.server.ServerWorld;
|
||||
import net.minecraft.world.server.ServerWorldLightManager;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 11-13-2021
|
||||
*/
|
||||
public class WorldGeneratorWrapper extends AbstractWorldGeneratorWrapper
|
||||
{
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
|
||||
/**
|
||||
* If a configured feature fails for whatever reason,
|
||||
* add it to this list. This will hopefully remove any
|
||||
* features that could cause issues down the line.
|
||||
*/
|
||||
private static final ConcurrentHashMap<Integer, ConfiguredFeature<?, ?>> FEATURES_TO_AVOID = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
public final ServerWorld serverWorld;
|
||||
public final LodDimension lodDim;
|
||||
public final LodBuilder lodBuilder;
|
||||
|
||||
public WorldGeneratorWrapper(LodBuilder newLodBuilder, LodDimension newLodDimension, IWorldWrapper worldWrapper)
|
||||
{
|
||||
super(newLodBuilder, newLodDimension, worldWrapper);
|
||||
|
||||
lodBuilder = newLodBuilder;
|
||||
lodDim = newLodDimension;
|
||||
serverWorld = ((WorldWrapper) worldWrapper).getServerWorld();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** takes about 2-5 ms */
|
||||
@Override
|
||||
public void generateBiomesOnly(AbstractChunkPosWrapper pos, DistanceGenerationMode generationMode)
|
||||
{
|
||||
List<IChunk> chunkList = new LinkedList<>();
|
||||
ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
|
||||
chunkList.add(chunk);
|
||||
|
||||
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
|
||||
ChunkGenerator chunkGen = chunkSource.generator;
|
||||
|
||||
// generate the terrain (this is thread safe)
|
||||
ChunkStatus.EMPTY.generate(serverWorld, chunkGen, serverWorld.getStructureManager(), (ServerWorldLightManager) serverWorld.getLightEngine(), null, chunkList);
|
||||
// override the chunk status, so we can run the next generator stage
|
||||
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
|
||||
chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
|
||||
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
|
||||
|
||||
|
||||
|
||||
|
||||
// generate fake height data for this LOD
|
||||
int seaLevel = serverWorld.getSeaLevel();
|
||||
|
||||
boolean simulateHeight = generationMode == DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||
boolean inTheEnd = false;
|
||||
|
||||
// add fake heightmap data so our LODs aren't at height 0
|
||||
Heightmap heightmap = new Heightmap(chunk, WrapperUtil.DEFAULT_HEIGHTMAP);
|
||||
for (int x = 0; x < LodUtil.CHUNK_WIDTH && !inTheEnd; x++)
|
||||
{
|
||||
for (int z = 0; z < LodUtil.CHUNK_WIDTH && !inTheEnd; z++)
|
||||
{
|
||||
if (simulateHeight)
|
||||
{
|
||||
// these heights are of course aren't super accurate,
|
||||
// they are just to simulate height data where there isn't any
|
||||
switch (chunk.getBiomes().getNoiseBiome(x >> 2, seaLevel >> 2, z >> 2).getBiomeCategory())
|
||||
{
|
||||
case NETHER:
|
||||
heightmap.setHeight(x, z, serverWorld.getHeight() / 2);
|
||||
break;
|
||||
|
||||
case EXTREME_HILLS:
|
||||
heightmap.setHeight(x, z, seaLevel + 30);
|
||||
break;
|
||||
case MESA:
|
||||
case JUNGLE:
|
||||
heightmap.setHeight(x, z, seaLevel + 20);
|
||||
break;
|
||||
case BEACH:
|
||||
heightmap.setHeight(x, z, seaLevel + 5);
|
||||
break;
|
||||
case NONE:
|
||||
heightmap.setHeight(x, z, 0);
|
||||
break;
|
||||
|
||||
case OCEAN:
|
||||
case RIVER:
|
||||
heightmap.setHeight(x, z, seaLevel);
|
||||
break;
|
||||
|
||||
case THEEND:
|
||||
inTheEnd = true;
|
||||
break;
|
||||
|
||||
// DESERT
|
||||
// FOREST
|
||||
// ICY
|
||||
// MUSHROOM
|
||||
// SAVANNA
|
||||
// SWAMP
|
||||
// TAIGA
|
||||
// PLAINS
|
||||
default:
|
||||
heightmap.setHeight(x, z, seaLevel + 10);
|
||||
break;
|
||||
}// heightmap switch
|
||||
}
|
||||
else
|
||||
{
|
||||
// we aren't simulating height
|
||||
// always use sea level
|
||||
heightmap.setHeight(x, z, seaLevel);
|
||||
}
|
||||
}// z
|
||||
}// x
|
||||
|
||||
chunk.setHeightmap(WrapperUtil.DEFAULT_HEIGHTMAP, heightmap.getRawData());
|
||||
|
||||
|
||||
if (!inTheEnd)
|
||||
{
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(true, true, false));
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we are in the end, don't generate any chunks.
|
||||
// Since we don't know where the islands are, everything
|
||||
// generates the same, and it looks awful.
|
||||
//TODO it appears that 'if' can be collapsed, but comment says that it should not be a case
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(true, true, false));
|
||||
}
|
||||
|
||||
|
||||
// long startTime = System.currentTimeMillis();
|
||||
// long endTime = System.currentTimeMillis();
|
||||
// System.out.println(endTime - startTime);
|
||||
}
|
||||
|
||||
|
||||
/** takes about 10 - 20 ms */
|
||||
@Override
|
||||
public void generateSurface(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
List<IChunk> chunkList = new LinkedList<>();
|
||||
ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
|
||||
chunkList.add(chunk);
|
||||
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
|
||||
|
||||
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
|
||||
ServerWorldLightManager lightEngine = (ServerWorldLightManager) serverWorld.getLightEngine();
|
||||
TemplateManager templateManager = serverWorld.getStructureManager();
|
||||
ChunkGenerator chunkGen = chunkSource.generator;
|
||||
|
||||
|
||||
// generate the terrain (this is thread safe)
|
||||
ChunkStatus.EMPTY.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
// override the chunk status, so we can run the next generator stage
|
||||
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
|
||||
chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
|
||||
ChunkStatus.NOISE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
ChunkStatus.SURFACE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
|
||||
// this feature has been proven to be thread safe,
|
||||
// so we will add it
|
||||
IceAndSnowFeature snowFeature = new IceAndSnowFeature(NoFeatureConfig.CODEC);
|
||||
snowFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition(), null);
|
||||
|
||||
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(DistanceGenerationMode.SURFACE));
|
||||
|
||||
/*TODO if we want to use Biome utils and terrain utils for overworld
|
||||
* lodBuilder.generateLodNodeFromChunk(lodDim, pos ,detailLevel, serverWorld.getSeed());*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* takes about 15 - 20 ms
|
||||
* <p>
|
||||
* Causes concurrentModification Exceptions,
|
||||
* which could cause instability or world generation bugs
|
||||
*/
|
||||
@Override
|
||||
public void generateFeatures(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
List<IChunk> chunkList = new LinkedList<>();
|
||||
ChunkPrimer chunk = new ChunkPrimer(((ChunkPosWrapper) pos).getChunkPos(), UpgradeData.EMPTY);
|
||||
chunkList.add(chunk);
|
||||
LodServerWorld lodServerWorld = new LodServerWorld(serverWorld, chunk);
|
||||
|
||||
ServerChunkProvider chunkSource = serverWorld.getChunkSource();
|
||||
ServerWorldLightManager lightEngine = (ServerWorldLightManager) serverWorld.getLightEngine();
|
||||
TemplateManager templateManager = serverWorld.getStructureManager();
|
||||
ChunkGenerator chunkGen = chunkSource.generator;
|
||||
|
||||
|
||||
// generate the terrain (this is thread safe)
|
||||
ChunkStatus.EMPTY.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
// override the chunk status, so we can run the next generator stage
|
||||
chunk.setStatus(ChunkStatus.STRUCTURE_REFERENCES);
|
||||
chunkGen.createBiomes(serverWorld.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), chunk);
|
||||
ChunkStatus.NOISE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
ChunkStatus.SURFACE.generate(serverWorld, chunkGen, templateManager, lightEngine, null, chunkList);
|
||||
|
||||
|
||||
// get all the biomes in the chunk
|
||||
HashSet<Biome> biomes = new HashSet<>();
|
||||
for (int x = 0; x < LodUtil.CHUNK_WIDTH; x++)
|
||||
{
|
||||
for (int z = 0; z < LodUtil.CHUNK_WIDTH; z++)
|
||||
{
|
||||
Biome biome = chunk.getBiomes().getNoiseBiome(x >> 2, serverWorld.getSeaLevel() >> 2, z >> 2);
|
||||
|
||||
// Issue #35
|
||||
// For some reason Jungle biomes cause incredible lag
|
||||
// the features here must be interacting with each other
|
||||
// in unpredictable ways (specifically tree feature generation).
|
||||
// When generating Features my CPU usage generally hovers around 30 - 40%
|
||||
// when generating Jungles it spikes to 100%.
|
||||
if (biome.getBiomeCategory() != Biome.Category.JUNGLE)
|
||||
{
|
||||
// should probably use the heightmap here instead of seaLevel,
|
||||
// but this seems to get the job done well enough
|
||||
biomes.add(biome);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean allowUnstableFeatures = CONFIG.client().worldGenerator().getAllowUnstableFeatureGeneration();
|
||||
|
||||
// generate all the features related to this chunk.
|
||||
// this may or may not be thread safe
|
||||
for (Biome biome : biomes)
|
||||
{
|
||||
List<List<Supplier<ConfiguredFeature<?, ?>>>> featuresForState = biome.generationSettings.features();
|
||||
|
||||
for (List<Supplier<ConfiguredFeature<?, ?>>> suppliers : featuresForState)
|
||||
{
|
||||
for (Supplier<ConfiguredFeature<?, ?>> featureSupplier : suppliers)
|
||||
{
|
||||
ConfiguredFeature<?, ?> configuredFeature = featureSupplier.get();
|
||||
|
||||
if (!allowUnstableFeatures &&
|
||||
FEATURES_TO_AVOID.containsKey(configuredFeature.hashCode()))
|
||||
continue;
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
configuredFeature.place(lodServerWorld, chunkGen, serverWorld.random, chunk.getPos().getWorldPosition());
|
||||
}
|
||||
catch (ConcurrentModificationException | UnsupportedOperationException e)
|
||||
{
|
||||
// This will happen. I'm not sure what to do about it
|
||||
// except pray that it doesn't affect the normal world generation
|
||||
// in any harmful way.
|
||||
// Update: this can cause crashes and high CPU usage.
|
||||
|
||||
// Issue #35
|
||||
// I tried cloning the config for each feature, but that
|
||||
// path was blocked since I can't clone lambda methods.
|
||||
// I tried using a deep cloning library and discovered
|
||||
// the problem there.
|
||||
// ( https://github.com/kostaskougios/cloning
|
||||
// and
|
||||
// https://github.com/EsotericSoftware/kryo )
|
||||
|
||||
if (!allowUnstableFeatures)
|
||||
FEATURES_TO_AVOID.put(configuredFeature.hashCode(), configuredFeature);
|
||||
// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
|
||||
}
|
||||
// This will happen when the LodServerWorld
|
||||
// isn't able to return something that a feature
|
||||
// generator needs
|
||||
catch (Exception e)
|
||||
{
|
||||
// I'm not sure what happened, print to the log
|
||||
|
||||
e.printStackTrace();
|
||||
|
||||
if (!allowUnstableFeatures)
|
||||
FEATURES_TO_AVOID.put(configuredFeature.hashCode(), configuredFeature);
|
||||
// ClientProxy.LOGGER.info(configuredFeaturesToAvoid.mappingCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generate a Lod like normal
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(chunk), new LodBuilderConfig(DistanceGenerationMode.FEATURES));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates using MC's ServerWorld.
|
||||
* <p>
|
||||
* on pre generated chunks 0 - 1 ms <br>
|
||||
* on un generated chunks 0 - 50 ms <br>
|
||||
* with the median seeming to hover around 15 - 30 ms <br>
|
||||
* and outliers in the 100 - 200 ms range <br>
|
||||
* <p>
|
||||
* Note this should not be multithreaded and does cause server/simulation lag
|
||||
* (Higher lag for generating than loading)
|
||||
*/
|
||||
@Override
|
||||
public void generateFull(AbstractChunkPosWrapper pos)
|
||||
{
|
||||
lodBuilder.generateLodNodeFromChunk(lodDim, new ChunkWrapper(serverWorld.getChunk(pos.getX(), pos.getZ(), ChunkStatus.FEATURES)), new LodBuilderConfig(DistanceGenerationMode.FULL));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* performance/generation tests related to
|
||||
* serverWorld.getChunk(x, z, ChunkStatus. *** )
|
||||
|
||||
true/false is whether they generated blocks or not
|
||||
the time is how long it took to generate
|
||||
|
||||
ChunkStatus.EMPTY 0 - 1 ms false (empty, what did you expect? :P)
|
||||
ChunkStatus.STRUCTURE_REFERENCES 1 - 2 ms false (no height, only generates some chunks)
|
||||
ChunkStatus.BIOMES 1 - 10 ms false (no height)
|
||||
ChunkStatus.NOISE 4 - 15 ms true (all blocks are stone)
|
||||
ChunkStatus.LIQUID_CARVERS 6 - 12 ms true (no snow/trees, just grass)
|
||||
ChunkStatus.SURFACE 5 - 15 ms true (no snow/trees, just grass)
|
||||
ChunkStatus.CARVERS 5 - 30 ms true (no snow/trees, just grass)
|
||||
ChunkStatus.FEATURES 7 - 25 ms true
|
||||
ChunkStatus.HEIGHTMAPS 20 - 40 ms true
|
||||
ChunkStatus.LIGHT 20 - 40 ms true
|
||||
ChunkStatus.FULL 30 - 50 ms true
|
||||
ChunkStatus.SPAWN 50 - 80 ms true
|
||||
|
||||
|
||||
At this point I would suggest using FEATURES, as it generates snow and trees
|
||||
(and any other object that are needed to make biomes distinct)
|
||||
|
||||
Otherwise, if snow/trees aren't necessary SURFACE is the next fastest (although not by much)
|
||||
*/
|
||||
}
|
||||
@@ -16,6 +16,41 @@ public net.minecraft.world.storage.DimensionSavedDataManager field_215759_d # fo
|
||||
# used when generating LodChunks
|
||||
public net.minecraft.block.AbstractBlock$AbstractBlockState field_235704_h_ # materialColor
|
||||
|
||||
# used when determining which chunks Vanilla Minecraft is going to render
|
||||
public net.minecraft.client.renderer.WorldRenderer$LocalRenderInformationContainer
|
||||
public net.minecraft.client.renderer.WorldRenderer field_72755_R # renderInfos
|
||||
public net.minecraft.client.renderer.WorldRenderer$LocalRenderInformationContainer field_178036_a # renderChunk
|
||||
|
||||
# used in world generation
|
||||
public net.minecraft.world.server.ServerWorld field_241106_P_ # structuremanager
|
||||
public net.minecraft.world.gen.Heightmap func_202267_b(II)I # getDataArrayIndex
|
||||
public net.minecraft.world.gen.Heightmap func_202272_a(III)V # set
|
||||
public net.minecraft.world.chunk.Chunk field_76634_f # heightMap
|
||||
public net.minecraft.world.chunk.Chunk field_76652_q # sections
|
||||
public net.minecraft.world.chunk.ChunkPrimer field_201661_i # sections
|
||||
public net.minecraft.world.server.ChunkManager field_219269_w # templateManager
|
||||
public net.minecraft.world.server.ChunkManager field_219256_j # lightManager
|
||||
public net.minecraft.world.gen.feature.template.TemplateManager field_186240_a # templates
|
||||
public net.minecraft.world.biome.Biome field_242424_k # biomeGenerationSettings
|
||||
public net.minecraft.world.gen.blockstateprovider.WeightedBlockStateProvider field_227406_b_ # weightedStates
|
||||
public net.minecraft.world.gen.placement.ConfiguredPlacement field_215096_a # decorator
|
||||
public net.minecraft.world.gen.placement.ConfiguredPlacement field_215097_b # config
|
||||
public net.minecraft.util.WeightedList field_220658_a # weightedEntries
|
||||
public net.minecraft.world.gen.feature.FeatureSpread field_242250_b # base
|
||||
public net.minecraft.world.gen.feature.FeatureSpread field_242251_c # spread
|
||||
public net.minecraft.world.gen.feature.ConfiguredFeature func_242765_a(Lnet/minecraft/world/ISeedReader;Lnet/minecraft/world/gen/ChunkGenerator;Ljava/util/Random;Lnet/minecraft/util/math/BlockPos;)Z # place
|
||||
public net.minecraft.world.server.ServerChunkProvider field_217244_j # dataStorage
|
||||
public net.minecraft.world.lighting.WorldLightManager field_215576_a # blockEngine
|
||||
public net.minecraft.world.lighting.WorldLightManager field_215577_b # skyEngine
|
||||
public net.minecraft.world.gen.feature.Feature field_236290_a_ # configuredCodec
|
||||
|
||||
# used for uploading vertex buffers off the render thread
|
||||
public net.minecraft.client.renderer.vertex.VertexBuffer field_177365_a # id
|
||||
public net.minecraft.client.renderer.vertex.VertexBuffer field_177363_b # format
|
||||
public net.minecraft.client.renderer.vertex.VertexBuffer field_177364_c # vertexCount
|
||||
|
||||
# used for accessing the lightmap
|
||||
public net.minecraft.client.renderer.LightTexture field_205111_b # lightPixels
|
||||
|
||||
|
||||
#=====================#
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
modLoader="javafml" #mandatory
|
||||
|
||||
#// A version range to match for said mod loader - for regular FML @Mod it will be the forge version
|
||||
loaderVersion="[35,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
|
||||
loaderVersion="[36,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
|
||||
|
||||
#// The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties.
|
||||
#// Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here.
|
||||
license="All rights reserved"
|
||||
license="GNU GPLv3"
|
||||
|
||||
#// A URL to refer people to when problems occur with this mod
|
||||
#//issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional
|
||||
issueTrackerURL="https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues" #optional
|
||||
#// A list of mods - how many allowed here is determined by the individual mod loader
|
||||
[[mods]] #mandatory
|
||||
|
||||
@@ -24,27 +24,28 @@ modId="lod" #mandatory
|
||||
#// The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
|
||||
#//${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata
|
||||
#// see the associated build.gradle script for how to populate this completely automatically during a build
|
||||
version="a1" #mandatory
|
||||
version="a1.5.4" #mandatory
|
||||
|
||||
#// A display name for the mod
|
||||
displayName="Levels of Detail" #mandatory
|
||||
displayName="Distant Horizons" #mandatory
|
||||
|
||||
#// A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/
|
||||
#//updateJSONURL="https://change.me.example.invalid/updates.json" #optional
|
||||
|
||||
#// A URL for the "homepage" for this mod, displayed in the mod UI
|
||||
#//displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional
|
||||
displayURL="https://www.curseforge.com/minecraft/mc-mods/lod-level-of-detail" #optional
|
||||
|
||||
#// A file name (in the root of the mod JAR) containing a logo for display
|
||||
#//logoFile="examplemod.png" #optional
|
||||
logoFile="logo.png" #optional
|
||||
|
||||
#// A file name (in the root of the mod JAR) containing a icon for display by catalogue
|
||||
catalogueImageIcon="icon.png"
|
||||
|
||||
#// A text field displayed in the mod UI
|
||||
credits="TechnoVision, Vike, and Darkhax for their modding tutorials." #optional
|
||||
|
||||
#// A text field displayed in the mod UI
|
||||
authors="James Seibel" #optional
|
||||
authors="James Seibel, Leonardo Amato, and Cola" #optional
|
||||
|
||||
#// The description text for the mod (multi line!) (#mandatory)
|
||||
description='''
|
||||
This mod generates and renders simplified chunks beyond the normal view distance, at a low performance cost.
|
||||
'''
|
||||
description='''This mod generates and renders simplified terrain beyond the normal view distance, at a low performance cost.'''
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 11 KiB |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "com.backsun.lod.mixin",
|
||||
"package": "com.seibel.lod.forge.mixins",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"refmap": "lod.refmap.json",
|
||||
"mixins": [
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 191 KiB |
@@ -1,16 +0,0 @@
|
||||
[
|
||||
{
|
||||
"modid": "lod",
|
||||
"name": "Level Of Details",
|
||||
"description": "Generates and renders simplified chunks beyond the normal view distance, at a low performance cost.",
|
||||
"version": "a1",
|
||||
"mcversion": "1.16.4",
|
||||
"url": "",
|
||||
"updateUrl": "",
|
||||
"authorList": ["James Seibel"],
|
||||
"credits": "TechnoVision, Vike, and Darkhax for their modding tutorials.",
|
||||
"logoFile": "",
|
||||
"screenshots": [],
|
||||
"dependencies": []
|
||||
}
|
||||
]
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "examplemod resources",
|
||||
"description": "",
|
||||
"pack_format": 6,
|
||||
"_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods."
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user