Compare commits
1153 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 | |||
| 7a3497d44c | |||
| 873034f7e4 | |||
| a151054b48 | |||
| 14c69971f6 | |||
| edc3858699 | |||
| bdaf33b80b | |||
| e1e63d4981 | |||
| 12f4a2d159 | |||
| fa2f12e4e0 | |||
| 520e2e99d9 | |||
| 759d6a0a94 | |||
| 7983f59ff1 | |||
| cd33b4c33e | |||
| 49bbc56941 | |||
| bf6813b6a5 | |||
| f96a6dcecd | |||
| 306f575edd | |||
| 8babc5aa65 | |||
| 6abbf328fb | |||
| 6bedfa5136 | |||
| e02156b1a4 | |||
| 673474cd64 | |||
| 807818e078 | |||
| 22840bd4e3 | |||
| 4c71c9aad5 | |||
| cc1683f573 | |||
| 62dc86d64e | |||
| ef65f87777 | |||
| 055f64e7c6 | |||
| a0fc9835b6 | |||
| b127ad0538 | |||
| e1cf190a7f | |||
| 27caab932c | |||
| d06415bd3e | |||
| 14e0fca1ed | |||
| 3d6ba0fad9 | |||
| 84bdd3dd90 | |||
| e81cd17ecf | |||
| 58b0eafe29 | |||
| 336cfb0749 | |||
| 0f5990e2f8 | |||
| 7acad77eda | |||
| fb0ff2a00c | |||
| ab7157476b | |||
| 40bc930d34 | |||
| 9500805243 | |||
| f637e5fd44 | |||
| cfda8c9655 | |||
| cb04b2df09 | |||
| f754467450 |
@@ -0,0 +1,5 @@
|
||||
# Disable autocrlf on generated files, they always generate with LF
|
||||
# Add any extra files or paths here to make git stop saying they
|
||||
# are changed when only line endings change.
|
||||
src/generated/**/.cache/cache text eol=lf
|
||||
src/generated/**/*.json text eol=lf
|
||||
+5
-4
@@ -19,8 +19,9 @@ build
|
||||
|
||||
# other
|
||||
eclipse
|
||||
run
|
||||
**/src/generated/
|
||||
|
||||
# minecraft run folder,
|
||||
# ignore everything but the mods folder
|
||||
run/*
|
||||
!run/mods
|
||||
# Files from Forge MDK
|
||||
logs
|
||||
forge*changelog.txt
|
||||
|
||||
+3
-4
@@ -1,4 +1,3 @@
|
||||
[submodule "ASMHelper"]
|
||||
path = ASMHelper
|
||||
url = https://github.com/squeek502/ASMHelper.git
|
||||
branch = 1.12.x
|
||||
[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 he 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.
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
IBXM is copyright (c) 2007, Martin Cameron, and is licensed under the BSD License.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
Neither the name of mumart nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
SoundSystem CodecIBXM Class License:
|
||||
|
||||
You are free to use this class for any purpose, commercial or otherwise.
|
||||
You may modify this class or source code, and distribute it any way you
|
||||
like, provided the following conditions are met:
|
||||
|
||||
1) You may not falsely claim to be the author of this class or any
|
||||
unmodified portion of it.
|
||||
2) You may not copyright this class or a modified version of it and then
|
||||
sue me for copyright infringement.
|
||||
3) If you modify the source code, you must clearly document the changes
|
||||
made before redistributing the modified source code, so other users know
|
||||
it is not the original code.
|
||||
4) You are not required to give me credit for this class in any derived
|
||||
work, but if you do, you must also mention my website:
|
||||
http://www.paulscode.com
|
||||
5) I the author will not be responsible for any damages (physical,
|
||||
financial, or otherwise) caused by the use if this class or any
|
||||
portion of it.
|
||||
6) I the author do not guarantee, warrant, or make any representations,
|
||||
either expressed or implied, regarding the use of this class or any
|
||||
portion of it.
|
||||
|
||||
Author: Paul Lamb
|
||||
http://www.paulscode.com
|
||||
|
||||
|
||||
This software is based on or using the IBXM library available from
|
||||
http://www.geocities.com/sunet2000/
|
||||
|
||||
|
||||
IBXM is copyright (c) 2007, Martin Cameron, and is licensed under the BSD License.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
Neither the name of mumart nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+555
-460
File diff suppressed because it is too large
Load Diff
Binary file not shown.
@@ -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
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
This program is an attempt to create Level Of Details (LODs) in Minecraft.
|
||||
The purpose is to increase the maximum view distance in game
|
||||
|
||||
Used in congunction with:
|
||||
https://gitlab.com/jeseibel/minecraft-lod-core-mod
|
||||
|
||||
|
||||
========================
|
||||
source code installation
|
||||
========================
|
||||
|
||||
See the Forge Documentation online for more detailed instructions:
|
||||
http://mcforge.readthedocs.io/en/latest/gettingstarted/
|
||||
|
||||
Step 1: open a command line in the project folder
|
||||
|
||||
Step 2: run the command: "./gradlew setupDecompWorkspace"
|
||||
|
||||
Step 3: run the command: "./gradlew eclipse"
|
||||
|
||||
Step 4: Import project
|
||||
|
||||
Step 5: 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)
|
||||
And make sure it is used in the build.gradle file.
|
||||
|
||||
Step 6: Import the lodcore and lodcore_source jar files into the referenced libraries.
|
||||
|
||||
Step 6: Make sure the eclipse has the JDK 1.8.0_251 installed. (This is needed so that eclipse can run minecraft)
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
|
||||
Tip:
|
||||
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.
|
||||
|
||||
Current location of mcp-srg.srg:
|
||||
"C:/Users/James Seibel/.gradle/caches/minecraft/de/oceanlabs/mcp/mcp_snapshot/20171003/1.12.2/srgs/"
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 23 KiB |
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
these are tools needed for looking at obfuscated minecraft code.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
these are tools needed for deobfuscating and looking at the code of optifine.
|
||||
@@ -1,3 +0,0 @@
|
||||
java -jar ./simpledeobf-0.6.jar --input ./OptiFine_1.12.2_HD_U_F5.jar --output ./OptiFine_1.12.2_HD_U_F5_dev.jar --mapFile C:/Users/James_Seibel/.gradle/caches/minecraft/de/oceanlabs/mcp/mcp_snapshot/20171003/1.12.2/srgs/notch-mcp.srg --ref C:/Users/James_Seibel/.gradle/caches/minecraft/net/minecraft/minecraft/1.12.2/minecraft-1.12.2.jar
|
||||
|
||||
pause
|
||||
Binary file not shown.
+244
-51
@@ -1,77 +1,270 @@
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven { url = "https://files.minecraftforge.net/maven" }
|
||||
maven { url = 'https://files.minecraftforge.net' }
|
||||
mavenCentral()
|
||||
// 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 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
|
||||
// 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'
|
||||
}
|
||||
}
|
||||
apply plugin: 'net.minecraftforge.gradle.forge'
|
||||
//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
|
||||
|
||||
|
||||
version = "1.0"
|
||||
group = "com.backsun.lod" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
archivesBaseName = "lod"
|
||||
|
||||
sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
|
||||
compileJava {
|
||||
sourceCompatibility = targetCompatibility = '1.8'
|
||||
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.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.
|
||||
|
||||
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
|
||||
minecraft {
|
||||
version = "1.12.2-14.23.5.2847"
|
||||
runDir = "run"
|
||||
|
||||
// the mappings can be changed at any time, and must be in the following format.
|
||||
// snapshot_YYYYMMDD snapshot are built nightly.
|
||||
// stable_# stables are built at the discretion of the MCP team.
|
||||
// The mappings can be changed at any time, and must be in the following format.
|
||||
// snapshot_YYYYMMDD Snapshot are built nightly.
|
||||
// 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 = "snapshot_20171003"
|
||||
// Simply re-run your setup task after changing the mappings to update your workspace.
|
||||
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')
|
||||
|
||||
// Default run configurations.
|
||||
// These can be tweaked, removed, or duplicated as needed.
|
||||
runs {
|
||||
client {
|
||||
workingDirectory project.file('run')
|
||||
arg "-mixin.config=lod.mixins.json"
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
// 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 {
|
||||
examplemod {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
workingDirectory project.file('run')
|
||||
arg "-mixin.config=lod.mixins.json"
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
// 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 {
|
||||
examplemod {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data {
|
||||
workingDirectory project.file('run')
|
||||
|
||||
// Recommended logging data for a userdev environment
|
||||
// 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.
|
||||
args '--mod', 'lod', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
|
||||
|
||||
mods {
|
||||
examplemod {
|
||||
source sourceSets.main
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
// you may put jars on which you depend on in ./libs
|
||||
// or you may define them like so..
|
||||
//compile "some.group:artifact:version:classifier"
|
||||
//compile "some.group:artifact:version"
|
||||
// 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.5-36.1.0'
|
||||
|
||||
// real examples
|
||||
//compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
|
||||
//compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
|
||||
// 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'
|
||||
|
||||
// the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
|
||||
//provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
|
||||
// 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'
|
||||
|
||||
// the deobf configurations: 'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided,
|
||||
// except that these dependencies get remapped to your current MCP mappings
|
||||
//deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev'
|
||||
//deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
|
||||
|
||||
// for more info...
|
||||
// You may put jars on which you depend on in ./libs or you may define them like so..
|
||||
// compile "some.group:artifact:version:classifier"
|
||||
// compile "some.group:artifact:version"
|
||||
|
||||
// Real examples
|
||||
// compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
|
||||
// compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
|
||||
|
||||
// The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
|
||||
// provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
|
||||
|
||||
// These dependencies get remapped to your current MCP mappings
|
||||
// deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev'
|
||||
|
||||
// For more info...
|
||||
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
|
||||
// http://www.gradle.org/docs/current/userguide/dependency_management.html
|
||||
|
||||
}
|
||||
|
||||
processResources {
|
||||
// this will ensure that this task is redone when the versions change.
|
||||
inputs.property "version", project.version
|
||||
inputs.property "mcversion", project.minecraft.version
|
||||
task copyCoreResources(type: Copy) {
|
||||
from file("core/src/main/resources/shaders")
|
||||
into file("src/generated/resources/shaders")
|
||||
}
|
||||
|
||||
// replace stuff in mcmod.info, nothing else
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
include 'mcmod.info'
|
||||
|
||||
// replace version and mcversion
|
||||
expand 'version':project.version, 'mcversion':project.minecraft.version
|
||||
}
|
||||
|
||||
// copy everything else except the mcmod.info
|
||||
from(sourceSets.main.resources.srcDirs) {
|
||||
exclude 'mcmod.info'
|
||||
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": "LOD",
|
||||
"Specification-Version": "1", // We are version 1 of ourselves
|
||||
"Implementation-Title": project.name,
|
||||
"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')
|
||||
// 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')
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
mavenJava(MavenPublication) {
|
||||
artifact jar
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
maven {
|
||||
url "file:///${project.projectDir}/mcmodsrepo"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mixin {
|
||||
add sourceSets.main, "lod.refmap.json"
|
||||
config "lod.mixins.json"
|
||||
}
|
||||
|
||||
|
||||
-467
@@ -1,467 +0,0 @@
|
||||
=========
|
||||
Build: 1.12.2-14.23.5.2846 - Tue Sep 03 21:22:46 GMT 2019
|
||||
ichttt:
|
||||
Fix CME when removing ticket managers (#5861)
|
||||
|
||||
=========
|
||||
Build: 1.12.2-14.23.5.2844 - Thu Aug 29 02:33:00 GMT 2019
|
||||
Barteks2x:
|
||||
Fix client sometimes generating biomes, causing incorrect biome
|
||||
generation on integrated server (#5720)
|
||||
|
||||
bs2609:
|
||||
Add checks for tile entities in now-unloaded chunks (#5724)
|
||||
|
||||
=========
|
||||
Build: 1.12.2-14.23.5.2843 - Thu Aug 29 02:23:04 GMT 2019
|
||||
bs2609:
|
||||
Fix invalid placeholder entity attributes (MC-150405) (#5718)
|
||||
|
||||
=========
|
||||
Build: 1.12.2-14.23.5.2842 - Thu Aug 29 02:08:57 GMT 2019
|
||||
bs2609:
|
||||
Allow conditional loading of advancements (#5255)
|
||||
|
||||
=========
|
||||
Build: 1.12.2-14.23.5.2841 - Thu Aug 29 01:58:50 GMT 2019
|
||||
bs2609:
|
||||
Improve performance of persistent chunk checks (#5706)
|
||||
|
||||
jensen.derik:
|
||||
Fix lightning not triggering EntityJoinWorldEvent (#5290)
|
||||
|
||||
=========
|
||||
Build: 1.12.2-14.23.5.2840 - Thu Aug 29 01:19:55 GMT 2019
|
||||
lex:
|
||||
Fix copy paste derp
|
||||
|
||||
|
||||
Build 2838:
|
||||
bs2609: Fix vanilla handling of options file (MC-117449, MC-151173) (#5725)
|
||||
|
||||
Build 2837:
|
||||
clienthax: Update EnumHelper to be compatible with Eclipse's OpenJ9 JVM. (#5712)
|
||||
|
||||
Build 2836:
|
||||
tterrag:
|
||||
Revert "Invalidate tile entities that are queued for removal (#5512)"
|
||||
This reverts commit 75788f63eea6c33ccef7e5cbcab27ad9ad2c2a04.
|
||||
This solution is invalid as TEs are free to modify the world
|
||||
tileEntities list, usually indirectly via chunkloading, from inside
|
||||
invalidate().
|
||||
This happens in vanilla, in TileEntityChest#invalidate, where it calls
|
||||
checkForAdjacentChests(), which has the potential to load neighboring
|
||||
chunks and cause a CME.
|
||||
A more sophisticated solution is needed.
|
||||
|
||||
Build 2835:
|
||||
bs2609: Fix some vertex format changes not being handled correctly (#5368)
|
||||
|
||||
Build 2834:
|
||||
bs2609:
|
||||
Transform vertex normals as well as positions when generating quads
|
||||
(#5242)
|
||||
|
||||
Build 2833:
|
||||
rseifert.phone: Fix for SidedInvWrapper isItemValid using wrong slot (#5642)
|
||||
|
||||
Build 2832:
|
||||
bs2609: Invalidate tile entities that are queued for removal (#5512)
|
||||
|
||||
Build 2831:
|
||||
lclc98: Added Wool to OreDictionary (#5414)
|
||||
|
||||
Build 2830:
|
||||
CreativeMD: Fixed boat not taking care of block-liquid hooks (#5086)
|
||||
|
||||
Build 2829:
|
||||
bs2609: Add Forge dimension-changing hooks to spectator handling code (#5212)
|
||||
|
||||
Build 2828:
|
||||
ichttt:
|
||||
Minor performace improvement when building chunks and rendering blocks
|
||||
(#5286)
|
||||
|
||||
Build 2827:
|
||||
bs2609: Catch json parsing errors from constants/factories files (#5258)
|
||||
|
||||
Build 2826:
|
||||
bs2609: Allow custom DataSerializers to be registered safely (#5245)
|
||||
|
||||
Build 2825:
|
||||
cpw:
|
||||
Try and make 1.13 mods more obviously wrong in 1.12..
|
||||
Signed-off-by: cpw <cpw+github@weeksfamily.ca>
|
||||
|
||||
Build 2824:
|
||||
tterrag: Fix #5651 Re-add canPlaceBlockOnSide check in World#mayPlace
|
||||
|
||||
Build 2823:
|
||||
Pokechu022:
|
||||
Fail fast when null is used with setTag instead of crashing in
|
||||
writeEntry (#5257)
|
||||
|
||||
Build 2822:
|
||||
tterrag: Fix block placement not checking for player collision
|
||||
|
||||
Build 2821:
|
||||
wynprice999: Added more Constants (#5323)
|
||||
|
||||
Build 2820:
|
||||
python0429: [1.12.2] Add a few events pertaining to villages (#5302)
|
||||
|
||||
Build 2819:
|
||||
Tyler Hancock: [1.12] Fix special spawn event not firing in many cases. (#5389)
|
||||
|
||||
Build 2818:
|
||||
bs2609: Only prompt for missing registries on local worlds (#5348)
|
||||
|
||||
Build 2817:
|
||||
ckrier.3000: Add EntityPlaceEvent (#5057)
|
||||
|
||||
Build 2816:
|
||||
bs2609: Generalise EnumRarity to an interface (#5182)
|
||||
|
||||
Build 2815:
|
||||
bs2609: Apply access-level changes to inner class attributes (#5468)
|
||||
|
||||
Build 2814:
|
||||
bs2609: Fix small logic error in ItemTextureQuadConverter (#5463)
|
||||
|
||||
Build 2813:
|
||||
bs2609: Better support for custom bows (#5209)
|
||||
|
||||
Build 2812:
|
||||
CovertJaguar: Remove FluidStack amount from hashcode calculation (#5272)
|
||||
molecularphylo:
|
||||
Fixed incorrect string representation of string list config property
|
||||
default values in their comments.
|
||||
bs2609:
|
||||
Improve tracking of used dimension IDs (#5249)
|
||||
Closes #5378 Large dimension IDs bloat level.data
|
||||
|
||||
Build 2811:
|
||||
bs2609:
|
||||
Fix up torch placement logic to handle more vanilla special-casing
|
||||
(#5426)
|
||||
|
||||
Build 2810:
|
||||
LexManos: Written size does not include int bytes.
|
||||
|
||||
Build 2809:
|
||||
LexManos:
|
||||
Extend Region files to support >1MB per chunk. If the 'sector count' is
|
||||
255, ask the compressed data header for the proper length.
|
||||
|
||||
Build 2808:
|
||||
tterrag1098: Add default impl to IConfigElement#getValidValuesDisplay
|
||||
|
||||
Build 2807:
|
||||
tterrag: Simplify custom item rendering by removing GL emissivity hacks
|
||||
|
||||
Build 2806:
|
||||
tterrag: Support diffuse lighting flag in item rendering
|
||||
|
||||
Build 2805:
|
||||
bs2609:
|
||||
Add a hook to allow continuously using items through stack changes
|
||||
(#4834)
|
||||
* Add a hook to allow continuously using items through stack changes
|
||||
|
||||
* Update licences
|
||||
|
||||
Build 2804:
|
||||
oOMitchOo:
|
||||
Added an additional constructor to every implementation of IFluidBlock.
|
||||
It is now possible to create a fluid block with a Fluid, Material and
|
||||
MapColor, so that the Material's MapColor isn't used for the blocks
|
||||
MapColor. (#5293)
|
||||
|
||||
Build 2803:
|
||||
bs2609: Add redirects to PotionEffect to respect registry replacement (#5213)
|
||||
|
||||
Build 2802:
|
||||
alexiy.ov:
|
||||
Add an annotation for @Config elements which will automatically create a
|
||||
slider control (#5026)
|
||||
|
||||
Build 2801:
|
||||
bs2609: Fix small logic error in emissive item rendering code (#5320)
|
||||
|
||||
Build 2800:
|
||||
molecularphylo:
|
||||
Allow config GUI cycling button elements generated from enums to display
|
||||
toString return values, rather than actual values. (#5125)
|
||||
|
||||
Build 2799:
|
||||
bs2609: Fix incorrect indexing in mipmap generation code (#5201)
|
||||
|
||||
Build 2798:
|
||||
bs2609:
|
||||
Ensure slave maps are cleaned up when handling registry overrides
|
||||
(#5250)
|
||||
|
||||
Build 2797:
|
||||
d_scalzi: Fix issue with --modListFile. (#5316)
|
||||
|
||||
Build 2796:
|
||||
LexManos:
|
||||
Fix potential issues with the Minecraft FakePlayer lingering around
|
||||
after world unloads.
|
||||
|
||||
Build 2795:
|
||||
tterrag: Fix potion remove event not always firing, add expiry event
|
||||
|
||||
Build 2794:
|
||||
tterrag: Clean up CraftingHelper constants loading API
|
||||
|
||||
Build 2793:
|
||||
tterrag: Fix crash from CraftingHelper due to FileSystem being closed early
|
||||
|
||||
Build 2792:
|
||||
tterrag:
|
||||
added PotionHooks, closes #3867, #4375 (#4614)
|
||||
* solved merge confilct
|
||||
|
||||
* improved var names & removed tabs
|
||||
|
||||
* Added spaces around !=
|
||||
|
||||
* fixed typo
|
||||
|
||||
Build 2791:
|
||||
tterrag:
|
||||
Add a hook for farmland watering (#4891)
|
||||
* Add a FarmlandWaterCheckEvent to allow mods to override when Farmland
|
||||
is watered or not
|
||||
|
||||
* revert 1.12.2 json
|
||||
|
||||
* Move the farmland patch to a ticket based instead of a event based
|
||||
system
|
||||
|
||||
* Minor changes
|
||||
|
||||
* Faster isValid checks, faster validation/invalidation if the state did
|
||||
not change, expand test mod to include a test for the validation system
|
||||
|
||||
* remove isValid boolean flag, we can express it with the tick counter
|
||||
|
||||
* Fix test mod resource warnings
|
||||
|
||||
* Remove tick timeout, add a javadoc note to invalidate on chunk unload,
|
||||
cleaned up test mod
|
||||
|
||||
* Allow mods to provide custom handling to determine if a pos is valid
|
||||
or not
|
||||
|
||||
* Make SimpleTicket more simple, make register public so custom tickets
|
||||
can be registered
|
||||
|
||||
* Fixes for review
|
||||
|
||||
* Add missing license headers
|
||||
|
||||
* Use a weak hash set
|
||||
|
||||
* Split up the map into smaller chunk based maps
|
||||
|
||||
* Add missing license headers
|
||||
|
||||
* Make MultiTicketManager more universal for custom implementations,
|
||||
cleanup imports
|
||||
|
||||
Build 2790:
|
||||
tterrag:
|
||||
Add methods to allow loading json constants outside of _constants
|
||||
(#4975)
|
||||
* add interface methods for loading json constants from an arbitary file
|
||||
|
||||
|
||||
* use try-with-resources
|
||||
|
||||
* don't make modders create jsoncontext, clean up resource use
|
||||
|
||||
* very minor cleanup
|
||||
|
||||
Build 2789:
|
||||
tterrag:
|
||||
Compute ASMDataTable submaps parallel, speeds up contructing mods
|
||||
(#5246)
|
||||
* Compute submaps parallel, speeds up contructing mods by a lot
|
||||
|
||||
* Use stream API better
|
||||
|
||||
Build 2788:
|
||||
mezz: Add logging for data manager key registration errors (#5129)
|
||||
|
||||
Build 2787:
|
||||
mezz: Improve support for custom block path types (#5203)
|
||||
|
||||
Build 2786:
|
||||
mezz: Fix missing comments in configs created with annotations (#5189)
|
||||
|
||||
Build 2785:
|
||||
mezz: Allow items to control the rate of repair from mending (#5102)
|
||||
|
||||
Build 2784:
|
||||
mezz: Improve exception handling from server starting events (#5226)
|
||||
|
||||
Build 2783:
|
||||
mezz: Improve context provided by potion icon rendering hooks (#5111)
|
||||
|
||||
Build 2782:
|
||||
mezz: Fix an ObjectHolderRef internal error message (#5214)
|
||||
|
||||
Build 2781:
|
||||
mezz: Implement rendering for item models with emissive quads (#5047)
|
||||
|
||||
Build 2780:
|
||||
mezz: Clean up logged mod states (#5227)
|
||||
mezz: Fix minor issue in getFilledPercentage for Fluid rendering (#5206)
|
||||
|
||||
Build 2779:
|
||||
mezz: Improve reflection helper methods (#4853)
|
||||
mezz: Fix inaccurate main thread name shown in client log (#5078)
|
||||
|
||||
Build 2778:
|
||||
mezz: Fix Baked Item models with transformations (#5241)
|
||||
|
||||
Build 2777:
|
||||
mezz:
|
||||
Re-add some missing villager profession patches (#5200)
|
||||
* Fix zombie villagers only spawning with vanilla professions
|
||||
* Fix spawning modded villagers that do not have their own building
|
||||
mezz: Fix missing string parameters in some log messages (#5210)
|
||||
mezz: Stop firing LivingSetAttackTargetEvent for setRevengeTarget (#5217)
|
||||
mezz: Prevent RecipeBook from crashing on empty modded ingredients (#5234)
|
||||
|
||||
Build 2776:
|
||||
mezz: Fix the bed position given to the SleepingTimeCheck event (#5107)
|
||||
|
||||
Build 2775:
|
||||
LexManos: Fix some null returns from defaulted registries (#5235)
|
||||
|
||||
Build 2774:
|
||||
LexManos:
|
||||
Only remove synthetic lambda methods referenced in body of SideOnly
|
||||
methods (#5127)
|
||||
|
||||
Build 2773:
|
||||
LexManos:
|
||||
A different approach to my changes in
|
||||
https://github.com/MinecraftForge/MinecraftForge/commit/8ace535995522bec0557d4217e0d98b3dc76cf1e
|
||||
to fix #5207
|
||||
LexManos: Fix patches from #5160 setting rotation as well as position (#5233)
|
||||
LexManos: Use HTTPS for files website.
|
||||
|
||||
Build 2772:
|
||||
tterrag: Make Forge-provided default transforms accessible to custom models
|
||||
tterrag:
|
||||
Make Forge blockstate variants correctly inherit AO setting from vanilla
|
||||
models (#5190)
|
||||
* Make Forge blockstate variants correctly inherit AO setting
|
||||
|
||||
* Move variant format checks into variant, check for added properties
|
||||
|
||||
* Small code cleanup
|
||||
tterrag: fixed visual bug with guislider
|
||||
tterrag:
|
||||
Allow IModel to express itself as a vanilla parent (#5195)
|
||||
* Fix errors caused by fancy missing model being non-vanilla parent
|
||||
|
||||
* Switch instanceof checks to a default IModel method
|
||||
|
||||
* Small code tweaks
|
||||
|
||||
Build 2771:
|
||||
tterrag: Add CreativeTabs#getLabelColor
|
||||
|
||||
Build 2770:
|
||||
tterrag:
|
||||
Allow providing a BufferedImage for banner render generation (#5041)
|
||||
* Adds an Event to allow providing a BufferedImage for the banner render
|
||||
generation (cached)
|
||||
textures, since banners don't use an atlas.
|
||||
implementation.
|
||||
|
||||
* Missed some copyright; might as well absolut text match, I guess
|
||||
|
||||
* Remove unneeded patch change
|
||||
|
||||
* Fix event variable access convention
|
||||
|
||||
* Formatting fix
|
||||
|
||||
* Improve event handling registration
|
||||
|
||||
* Import cleanup
|
||||
|
||||
* Replace event approach with Supplier approach
|
||||
|
||||
* Better name for test mod (now that it's no longer an event); adds
|
||||
ENABLE flag
|
||||
|
||||
* Moves MC code into
|
||||
net.minecraftforge.client.MinecraftForgeClient.getImageLayer to simplify
|
||||
patch
|
||||
|
||||
* Generalize naming
|
||||
|
||||
Build 2769:
|
||||
mezz: Fix Mesa biome entry tags in the BiomeDictionary (#5177)
|
||||
|
||||
Build 2768:
|
||||
LexManos: Bump version number for RB.
|
||||
|
||||
Build 2767:
|
||||
LexManos:
|
||||
Change biome spawn list entries to use factory method where possible
|
||||
(#5075)
|
||||
LexManos: Prevent some texture loading errors from crashing the game (#5121)
|
||||
LexManos: Patch PotionHelper to use registry delegates (#5142)
|
||||
LexManos: Add a notification event for handling game rule changes (#5152)
|
||||
|
||||
Build 2766:
|
||||
LexManos:
|
||||
Change universal bucket support to use fluid names instead of instances
|
||||
(#5031)
|
||||
|
||||
Build 2765:
|
||||
LexManos: Fix NPE on clientside entities constructed with null world (#5170)
|
||||
|
||||
Build 2764:
|
||||
tterrag: Fix patches from #5160 running on the client and causing stutter
|
||||
|
||||
Build 2763:
|
||||
LexManos:
|
||||
Class transformer optimizations (#5159)
|
||||
* Filter packages for deobf transformation
|
||||
* Only serialize transformed class with TerminalTransformer if bytecode
|
||||
changed
|
||||
|
||||
Build 2762:
|
||||
github: Update github stale so issues can be Assigned
|
||||
|
||||
Build 2761:
|
||||
LexManos:
|
||||
Fix MC-136995 - Chunk loading and unloading issue with entities placed
|
||||
in exact positions. (#5160)
|
||||
Scatter gun patches to improve entity tracking and position tracking.
|
||||
Provided by Aikar through the Paper project, this commit of patches
|
||||
combines the following patches:
|
||||
|
||||
https://github.com/PaperMC/Paper/blob/fd1bd5223a461b6d98280bb8f2d67280a30dd24a/Spigot-Server-Patches/0306-Mark-chunk-dirty-anytime-entities-change-to-guarante.patch
|
||||
|
||||
https://github.com/PaperMC/Paper/blob/fd1bd5223a461b6d98280bb8f2d67280a30dd24a/Spigot-Server-Patches/0315-Always-process-chunk-registration-after-moving.patch
|
||||
|
||||
https://github.com/PaperMC/Paper/blob/fd1bd5223a461b6d98280bb8f2d67280a30dd24a/Spigot-Server-Patches/0335-Ensure-chunks-are-always-loaded-on-hard-position-set.patch
|
||||
|
||||
https://github.com/PaperMC/Paper/blob/fd1bd5223a461b6d98280bb8f2d67280a30dd24a/Spigot-Server-Patches/0378-Sync-Player-Position-to-Vehicles.patch
|
||||
|
||||
Build 2760:
|
||||
LexManos: Fix --mods and --modListFile arguments not making it past LaunchWrapper.
|
||||
|
||||
Build 2759:
|
||||
LexManos: Remove BlamingTransformer (#5115)
|
||||
|
||||
Submodule
+1
Submodule core added at f2fc669b37
@@ -1,3 +1,4 @@
|
||||
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
|
||||
# This is required to provide enough memory for the Minecraft decompilation process.
|
||||
org.gradle.jvmargs=-Xmx3G
|
||||
org.gradle.daemon=false
|
||||
Vendored
BIN
Binary file not shown.
+1
-2
@@ -1,6 +1,5 @@
|
||||
#Mon Sep 14 12:28:28 PDT 2015
|
||||
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-2.14-bin.zip
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
#!/usr/bin/env sh
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
@@ -6,47 +6,6 @@
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn ( ) {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die ( ) {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
@@ -61,9 +20,49 @@ while [ -h "$PRG" ] ; do
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
@@ -90,7 +89,7 @@ location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
@@ -114,6 +113,7 @@ fi
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
@@ -154,11 +154,19 @@ if $cygwin ; then
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
Vendored
+4
-10
@@ -8,14 +8,14 @@
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_MC_HOME goto findJavaFromJavaHome
|
||||
|
||||
@@ -46,10 +46,9 @@ echo location of your Java installation.
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
@@ -60,11 +59,6 @@ set _SKIP=2
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1 +0,0 @@
|
||||
include ":ASMHelper"
|
||||
@@ -1,53 +0,0 @@
|
||||
package com.backsun.lod;
|
||||
|
||||
import com.backsun.lod.proxy.ClientProxy;
|
||||
import com.backsun.lod.proxy.CommonProxy;
|
||||
import com.backsun.lod.util.Reference;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.Mod.EventHandler;
|
||||
import net.minecraftforge.fml.common.Mod.Instance;
|
||||
import net.minecraftforge.fml.common.SidedProxy;
|
||||
import net.minecraftforge.fml.common.event.FMLInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
|
||||
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
|
||||
import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-07-2021
|
||||
*/
|
||||
@IFMLLoadingPlugin.MCVersion("1.12.2")
|
||||
@IFMLLoadingPlugin.TransformerExclusions({"com.backsun.lod.asm"})
|
||||
@Mod(modid = Reference.MOD_ID, name = Reference.NAME, version = Reference.VERSION, dependencies = "required-after:lodcore@[1.0,)")
|
||||
public class LodMain
|
||||
{
|
||||
@Instance
|
||||
public static LodMain instance;
|
||||
|
||||
@SidedProxy(clientSide = Reference.CLIENT_PROXY_CLASS, serverSide = Reference.COMMON_PROXY_CLASS)
|
||||
public static CommonProxy common_proxy;
|
||||
public static ClientProxy client_proxy;
|
||||
|
||||
@EventHandler
|
||||
public static void PreInit(FMLPreInitializationEvent event)
|
||||
{
|
||||
Minecraft.getMinecraft().getFramebuffer().enableStencil();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void Init(FMLInitializationEvent event)
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.register(common_proxy);
|
||||
client_proxy = new ClientProxy();
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public static void PostInit(FMLPostInitializationEvent event)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,755 +0,0 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import com.backsun.lod.util.enums.ColorDirection;
|
||||
import com.backsun.lod.util.enums.LodLocation;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.color.BlockColors;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
|
||||
private final int airBlockId = Block.getIdFromBlock(Block.getBlockFromName("air"));
|
||||
private final int waterBlockId = Block.getIdFromBlock(Block.getBlockFromName("water"));
|
||||
private final int waterColor = colorToInt(new Color(36, 50, 171));
|
||||
|
||||
/**
|
||||
* 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 LodChunk
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Illegal argument is thrown if either the
|
||||
* chunk or world is null. The reason the world
|
||||
* can't be null is because it's required to determine
|
||||
* a block's color.
|
||||
* @throws IllegalArgumentException
|
||||
*/
|
||||
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.x;
|
||||
z = chunk.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] = generateLodSection(chunk, true, loc);
|
||||
bottom[loc.value] = generateLodSection(chunk, false, loc);
|
||||
}
|
||||
|
||||
// determine the average color for each direction
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
{
|
||||
colors[dir.value] = generateLodColorSection(chunk, world, dir);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=====================//
|
||||
// constructor helpers //
|
||||
//=====================//
|
||||
|
||||
|
||||
/**
|
||||
* If invalid/null/empty chunks are given
|
||||
* crashes may occur.
|
||||
*/
|
||||
public short generateLodSection(Chunk chunk, boolean getTopSection, LodLocation lodLoc)
|
||||
{
|
||||
// should have a length of 16
|
||||
// (each storage is 16x16x16 and the
|
||||
// world height is 256)
|
||||
ExtendedBlockStorage[] data = chunk.getBlockStorageArray();
|
||||
|
||||
|
||||
|
||||
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(getTopSection)
|
||||
return determineTopPoint(data, startX, endX, startZ, endZ);
|
||||
else
|
||||
return determineBottomPoint(data, startX, endX, startZ, endZ);
|
||||
}
|
||||
|
||||
private short determineBottomPoint(ExtendedBlockStorage[] data, int startX, int endX, int startZ, int endZ)
|
||||
{
|
||||
// search from the bottom up
|
||||
for(int i = 0; i < data.length; i++)
|
||||
{
|
||||
for(int y = 0; y < CHUNK_DATA_HEIGHT; y++)
|
||||
{
|
||||
|
||||
if(isLayerValidLodPoint(data, 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));
|
||||
}
|
||||
|
||||
} // y
|
||||
} // data
|
||||
|
||||
|
||||
// we never found a valid LOD point
|
||||
return -1;
|
||||
}
|
||||
|
||||
private short determineTopPoint(ExtendedBlockStorage[] data, int startX, int endX, int startZ, int endZ)
|
||||
{
|
||||
// search from the top down
|
||||
for(int i = data.length - 1; i >= 0; i--)
|
||||
{
|
||||
for(int y = CHUNK_DATA_WIDTH - 1; y >= 0; y--)
|
||||
{
|
||||
if(isLayerValidLodPoint(data, 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));
|
||||
}
|
||||
} // y
|
||||
} // data
|
||||
|
||||
|
||||
|
||||
// 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(
|
||||
ExtendedBlockStorage[] data,
|
||||
int startX, int endX,
|
||||
int startZ, int endZ,
|
||||
int dataIndex, int y)
|
||||
{
|
||||
// search through this layer
|
||||
int layerBlocks = 0;
|
||||
|
||||
for(int x = startX; x < endX; x++)
|
||||
{
|
||||
for(int z = startZ; z < endZ; z++)
|
||||
{
|
||||
if(data[dataIndex] == null)
|
||||
{
|
||||
// this section doesn't have any blocks,
|
||||
// it is not a valid section
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(data[dataIndex].get(x, y, z) != null && Block.getIdFromBlock(data[dataIndex].get(x, y, z).getBlock()) != airBlockId)
|
||||
{
|
||||
// we found a valid block in
|
||||
// in this layer
|
||||
layerBlocks++;
|
||||
|
||||
if(layerBlocks >= LOD_BLOCK_REQ)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // z
|
||||
} // x
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private Color generateLodColorSection(Chunk chunk, World world, ColorDirection colorDir)
|
||||
{
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only accepts TOP and BOTTOM as ColorPositions
|
||||
*/
|
||||
private Color generateLodColorVertical(Chunk chunk, ColorDirection colorDir, World world, BlockColors bc)
|
||||
{
|
||||
ExtendedBlockStorage[] data = chunk.getBlockStorageArray();
|
||||
|
||||
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? data.length - 1 : 0;
|
||||
int dataMax = data.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 di = dataStart; !foundBlock && di >= dataMin && di < dataMax; di += dataIncrement)
|
||||
{
|
||||
if(!foundBlock && data[di] != null)
|
||||
{
|
||||
for(int y = topStart; !foundBlock && y >= topMin && y < topMax; y += topIncrement)
|
||||
{
|
||||
int ci;
|
||||
if(Block.getIdFromBlock(data[di].get(x, y, z).getBlock()) == waterBlockId)
|
||||
// this is a special case since getColor on water generally returns white
|
||||
ci = waterColor;
|
||||
else
|
||||
ci = bc.getColor(data[di].get(x, y, z), world, new BlockPos(x,y,z));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
private Color generateLodColorHorizontal(Chunk chunk, ColorDirection colorDir, World world, BlockColors bc)
|
||||
{
|
||||
ExtendedBlockStorage[] data = chunk.getBlockStorageArray();
|
||||
|
||||
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 di = 0; di < data.length; di++)
|
||||
{
|
||||
if (data[di] != 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;
|
||||
if(Block.getIdFromBlock(data[di].get(x, y, z).getBlock()) == waterBlockId)
|
||||
// this is a special case since getColor on water generally returns white
|
||||
ci = waterColor;
|
||||
else
|
||||
ci = bc.getColor(data[di].get(x, y, z), world, new BlockPos(x,y,z));
|
||||
|
||||
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.
|
||||
*/
|
||||
private int colorToInt(Color color)
|
||||
{
|
||||
return color.getRGB();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// 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 += "top: ";
|
||||
// for(int i = 0; i < top.length; i++)
|
||||
// {
|
||||
// s += top[i] + " ";
|
||||
// }
|
||||
// s += "\t";
|
||||
|
||||
// s += "bottom: ";
|
||||
// for(int i = 0; i < bottom.length; i++)
|
||||
// {
|
||||
// s += bottom[i] + " ";
|
||||
// }
|
||||
// s += "\t";
|
||||
|
||||
// s += "colors ";
|
||||
// for(int i = 0; i < colors.length; i++)
|
||||
// {
|
||||
// if(colors[i] != null)
|
||||
// s += "(" + colors[i].getRed() + ", " + colors[i].getGreen() + ", " + colors[i].getBlue() + "), ";
|
||||
// }
|
||||
|
||||
s += "(" + colors[ColorDirection.TOP.value].getRed() + ", " + colors[ColorDirection.TOP.value].getGreen() + ", " + colors[ColorDirection.TOP.value].getBlue() + "), ";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -1,319 +0,0 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import com.backsun.lod.util.LodFileHandler;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.DimensionType;
|
||||
|
||||
/**
|
||||
* This object holds all loaded LOD regions
|
||||
* for a given dimension.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 01-31-2021
|
||||
*/
|
||||
public class LodDimension
|
||||
{
|
||||
public final DimensionType dimension;
|
||||
|
||||
private volatile int width; // if this ever changes make sure to update the halfWidth too
|
||||
private volatile int halfWidth;
|
||||
|
||||
public LodRegion regions[][];
|
||||
public boolean isRegionDirty[][];
|
||||
|
||||
private int centerX;
|
||||
private int centerZ;
|
||||
|
||||
private LodFileHandler rfHandler;
|
||||
|
||||
public LodDimension(DimensionType newDimension, int newMaxWidth)
|
||||
{
|
||||
dimension = newDimension;
|
||||
width = newMaxWidth;
|
||||
|
||||
// dimension 0 works here since we are just looking for the save handler anyway
|
||||
rfHandler = new LodFileHandler(Minecraft.getMinecraft().getIntegratedServer().getWorld(0).getSaveHandler(), 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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
public int getCenterX()
|
||||
{
|
||||
return centerX;
|
||||
}
|
||||
|
||||
public int getCenterZ()
|
||||
{
|
||||
return centerZ;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public void addLod(LodChunk lod)
|
||||
{
|
||||
int regionX = (lod.x + centerX) / LodRegion.SIZE;
|
||||
int regionZ = (lod.z + centerZ) / 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;
|
||||
|
||||
|
||||
|
||||
rfHandler.saveDirtyRegionsToFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns null if the LodChunk isn't loaded
|
||||
*/
|
||||
public LodChunk getLodFromCoordinates(int chunkX, int chunkZ)
|
||||
{
|
||||
// (chunkX + centerX) % width
|
||||
int regionX = (chunkX + centerX) / LodRegion.SIZE;
|
||||
int regionZ = (chunkZ + centerZ) / 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);
|
||||
|
||||
// TODO fix small render distances sometimes not having all regions loaded
|
||||
if(region == null)
|
||||
return null;
|
||||
|
||||
return region.getLod(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public LodRegion getRegionFromFile(int regionX, int regionZ)
|
||||
{
|
||||
return rfHandler.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 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,76 +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-20-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];
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
|
||||
public LodChunk[][] getAllLods()
|
||||
{
|
||||
return chunks;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String s = "";
|
||||
|
||||
s += "x: " + x + " z: " + z + "\t";
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
package com.backsun.lod.objects;
|
||||
|
||||
import java.util.Dictionary;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Hashtable;
|
||||
|
||||
/**
|
||||
* This stores all LODs for a given world.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 01-31-2021
|
||||
*/
|
||||
public class LodWorld
|
||||
{
|
||||
public String worldName;
|
||||
|
||||
/**
|
||||
* Key = Dimension id (as an int)
|
||||
*/
|
||||
private Dictionary<Integer, LodDimension> lodDimensions;
|
||||
|
||||
|
||||
public LodWorld(String newWorldName)
|
||||
{
|
||||
worldName = newWorldName;
|
||||
lodDimensions = new Hashtable<Integer, LodDimension>();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void addLodDimension(LodDimension newStorage)
|
||||
{
|
||||
lodDimensions.put(newStorage.dimension.getId(), newStorage);
|
||||
}
|
||||
|
||||
public LodDimension getLodDimension(int dimensionId)
|
||||
{
|
||||
return lodDimensions.get(dimensionId);
|
||||
}
|
||||
|
||||
|
||||
public void resizeDimensionRegionWidth(int newWidth)
|
||||
{
|
||||
Enumeration<Integer> keys = lodDimensions.keys();
|
||||
|
||||
while(keys.hasMoreElements())
|
||||
lodDimensions.get(keys.nextElement()).setRegionWidth(newWidth);
|
||||
}
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
package com.backsun.lod.proxy;
|
||||
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
|
||||
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.util.LodConfig;
|
||||
import com.backsun.lod.util.LodFileHandler;
|
||||
import com.backsun.lodCore.util.RenderGlobalHook;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.world.DimensionType;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraftforge.client.event.RenderWorldLastEvent;
|
||||
import net.minecraftforge.event.terraingen.PopulateChunkEvent;
|
||||
import net.minecraftforge.event.world.ChunkEvent;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
//TODO Find a way to replace getIntegratedServer so this mod could be used on non-local worlds.
|
||||
// Minecraft.getMinecraft().getIntegratedServer()
|
||||
|
||||
/**
|
||||
* This is used by the client.
|
||||
*
|
||||
* @author James_Seibel
|
||||
* @version 01-31-2021
|
||||
*/
|
||||
public class ClientProxy extends CommonProxy
|
||||
{
|
||||
private LodRenderer renderer;
|
||||
private LodWorld lodWorld;
|
||||
private ExecutorService lodGenThreadPool = Executors.newFixedThreadPool(1);
|
||||
|
||||
/** Default size of any LOD regions we use */
|
||||
private int regionWidth = 5;
|
||||
|
||||
public ClientProxy()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// render event //
|
||||
//==============//
|
||||
|
||||
@SubscribeEvent
|
||||
public void renderWorldLast(RenderWorldLastEvent event)
|
||||
{
|
||||
RenderGlobalHook.endRenderingStencil();
|
||||
GL11.glStencilFunc(GL11.GL_EQUAL, 0, 0xFF);
|
||||
|
||||
if (LodConfig.drawLODs)
|
||||
renderLods(event.getPartialTicks());
|
||||
|
||||
GL11.glDisable(GL11.GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
public void renderLods(float partialTicks)
|
||||
{
|
||||
int newWidth = Math.max(4, (Minecraft.getMinecraft().gameSettings.renderDistanceChunks * LodChunk.WIDTH * 2) / LodRegion.SIZE);
|
||||
if (lodWorld != null && regionWidth != newWidth)
|
||||
{
|
||||
lodWorld.resizeDimensionRegionWidth(newWidth);
|
||||
regionWidth = newWidth;
|
||||
|
||||
// skip this frame, hopefully the lodWorld
|
||||
// should have everything set up by then
|
||||
return;
|
||||
}
|
||||
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (mc == null || mc.player == null || lodWorld == null)
|
||||
return;
|
||||
|
||||
int dimId = mc.player.dimension;
|
||||
LodDimension lodDim = lodWorld.getLodDimension(dimId);
|
||||
if (lodDim == null)
|
||||
return;
|
||||
|
||||
|
||||
double playerX = mc.player.posX;
|
||||
double playerZ = mc.player.posZ;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
// we wait to create the renderer until the first frame
|
||||
// to make sure that the EntityRenderer has
|
||||
// been created, that way we can get the fovModifer
|
||||
// method from it through reflection.
|
||||
if (renderer == null)
|
||||
{
|
||||
renderer = new LodRenderer();
|
||||
}
|
||||
else
|
||||
{
|
||||
renderer.drawLODs(lodDim, partialTicks);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// update events //
|
||||
//===============//
|
||||
|
||||
@SubscribeEvent
|
||||
public void chunkLoadEvent(ChunkEvent event)
|
||||
{
|
||||
generateLodChunk(event.getChunk());
|
||||
}
|
||||
|
||||
/**
|
||||
* this event is called whenever a chunk is created for the first time.
|
||||
*/
|
||||
@SubscribeEvent
|
||||
public void onChunkPopulate(PopulateChunkEvent event)
|
||||
{
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
if (mc != null && event != null)
|
||||
{
|
||||
WorldClient world = mc.world;
|
||||
|
||||
if(world != null)
|
||||
{
|
||||
generateLodChunk(world.getChunkFromChunkCoords(event.getChunkX(), event.getChunkZ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
Use this for generating chunks and maybe determining if they are loaded at all?
|
||||
|
||||
Could I create my own chunk generator and multithread it? It wouldn't save to the world, but could I save it for LODs?
|
||||
|
||||
chunk = Minecraft.getMinecraft().getIntegratedServer().getWorld(0).getChunkProvider().chunkGenerator.generateChunk(chunk.x, chunk.z);
|
||||
|
||||
System.out.println(chunk.x + " " + chunk.z + "\tloaded: " + chunk.isLoaded() + "\tpop: " + chunk.isPopulated() + "\tter pop: " + chunk.isTerrainPopulated());
|
||||
*/
|
||||
|
||||
private void generateLodChunk(Chunk chunk)
|
||||
{
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
// 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;
|
||||
|
||||
int dimId = chunk.getWorld().provider.getDimension();
|
||||
World world = mc.getIntegratedServer().getWorld(dimId);
|
||||
|
||||
if (world == null)
|
||||
return;
|
||||
|
||||
Thread thread = new Thread(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
LodChunk lod = new LodChunk(chunk, world);
|
||||
LodDimension lodDim;
|
||||
|
||||
if (lodWorld == null)
|
||||
{
|
||||
lodWorld = new LodWorld(LodFileHandler.getWorldName());
|
||||
}
|
||||
else
|
||||
{
|
||||
// if we have a lodWorld make sure
|
||||
// it is for this minecraft world
|
||||
if (!lodWorld.worldName.equals(LodFileHandler.getWorldName()))
|
||||
{
|
||||
// this lodWorld isn't for this minecraft world
|
||||
// delete it so we can get a new one
|
||||
lodWorld = null;
|
||||
|
||||
// skip this frame
|
||||
// we'll get this set up next time
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (lodWorld.getLodDimension(dimId) == null)
|
||||
{
|
||||
DimensionType dim = DimensionType.getById(dimId);
|
||||
lodDim = new LodDimension(dim, regionWidth);
|
||||
lodWorld.addLodDimension(lodDim);
|
||||
}
|
||||
else
|
||||
{
|
||||
lodDim = lodWorld.getLodDimension(dimId);
|
||||
}
|
||||
|
||||
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 whether the given chunk
|
||||
* has any data in it.
|
||||
*/
|
||||
private boolean isValidChunk(Chunk chunk)
|
||||
{
|
||||
ExtendedBlockStorage[] data = chunk.getBlockStorageArray();
|
||||
|
||||
for(ExtendedBlockStorage e : data)
|
||||
{
|
||||
if(e != null && !e.isEmpty())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package com.backsun.lod.proxy;
|
||||
|
||||
/**
|
||||
* This is used by the server.
|
||||
*
|
||||
* @author James_Seibel
|
||||
* @version 08-31-2020
|
||||
*/
|
||||
public class CommonProxy
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,333 +0,0 @@
|
||||
package com.backsun.lod.renderer;
|
||||
import java.awt.Color;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
import com.backsun.lod.util.enums.FogDistance;
|
||||
|
||||
import net.minecraft.client.renderer.GLAllocation;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormat;
|
||||
import net.minecraft.client.renderer.vertex.VertexFormatElement;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-13-2021
|
||||
*/
|
||||
public class BuildBufferThread implements Callable<NearFarBuffer>
|
||||
{
|
||||
public ByteBuffer nearBuffer;
|
||||
public ByteBuffer farBuffer;
|
||||
public FogDistance distanceMode;
|
||||
public AxisAlignedBB[][] lods;
|
||||
public Color[][] colors;
|
||||
|
||||
private int start = 0;
|
||||
private int end = -1;
|
||||
|
||||
private int vertexCount = 0;
|
||||
private VertexFormat vertexFormat = null;
|
||||
private int vertexFormatIndex = 0;
|
||||
private VertexFormatElement vertexFormatElement = null;
|
||||
|
||||
|
||||
|
||||
BuildBufferThread()
|
||||
{
|
||||
vertexCount = 0;
|
||||
vertexFormat = DefaultVertexFormats.POSITION_COLOR;
|
||||
vertexFormatIndex = 0;
|
||||
vertexFormatElement = vertexFormat.getElement(vertexFormatIndex);
|
||||
}
|
||||
|
||||
BuildBufferThread(ByteBuffer newNearByteBuffer, ByteBuffer newFarByteBuffer, AxisAlignedBB[][] newLods, Color[][] newColors, FogDistance newDistanceMode, int threadNumber, int totalThreads)
|
||||
{
|
||||
setNewData(newNearByteBuffer, newFarByteBuffer, distanceMode, newLods, newColors, threadNumber, totalThreads);
|
||||
|
||||
vertexCount = 0;
|
||||
vertexFormat = DefaultVertexFormats.POSITION_COLOR;
|
||||
vertexFormatIndex = 0;
|
||||
vertexFormatElement = vertexFormat.getElement(vertexFormatIndex);
|
||||
}
|
||||
|
||||
public void setNewData(ByteBuffer newNearByteBuffer, ByteBuffer newFarByteBuffer, FogDistance newDistanceMode, AxisAlignedBB[][] newLods, Color[][] newColors, int threadNumber, int totalThreads)
|
||||
{
|
||||
vertexCount = 0;
|
||||
vertexFormatIndex = 0;
|
||||
|
||||
nearBuffer = newNearByteBuffer;
|
||||
farBuffer = newFarByteBuffer;
|
||||
distanceMode = newDistanceMode;
|
||||
lods = newLods;
|
||||
colors = newColors;
|
||||
|
||||
int numbChunksWide = lods.length;
|
||||
int rowsToRender = numbChunksWide / totalThreads;
|
||||
start = threadNumber * rowsToRender;
|
||||
end = (threadNumber + 1) * rowsToRender;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NearFarBuffer call()
|
||||
{
|
||||
int numbChunksWide = lods.length;
|
||||
|
||||
ByteBuffer currentBuffer;
|
||||
AxisAlignedBB bb;
|
||||
int red;
|
||||
int green;
|
||||
int blue;
|
||||
int alpha;
|
||||
|
||||
if (distanceMode == FogDistance.NEAR)
|
||||
{
|
||||
currentBuffer = nearBuffer;
|
||||
}
|
||||
else // if (distanceMode == FogDistance.FAR)
|
||||
{
|
||||
currentBuffer = farBuffer;
|
||||
}
|
||||
|
||||
|
||||
// x axis
|
||||
for (int i = start; i < end; 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();
|
||||
|
||||
// choose which buffer to add these LODs too
|
||||
if (distanceMode == FogDistance.NEAR_AND_FAR)
|
||||
{
|
||||
if (RenderUtil.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
|
||||
|
||||
return new NearFarBuffer(nearBuffer, farBuffer);
|
||||
}
|
||||
|
||||
private void addPosAndColor(ByteBuffer buffer, double x, double y, double z, int red, int green, int blue, int alpha)
|
||||
{
|
||||
addPos(buffer, x, y, z);
|
||||
addColor(buffer, red, green, blue, alpha);
|
||||
endVertex();
|
||||
}
|
||||
|
||||
private void addPos(ByteBuffer byteBuffer, double x, double y, double z)
|
||||
{
|
||||
int i = this.vertexCount * this.vertexFormat.getNextOffset() + this.vertexFormat.getOffset(this.vertexFormatIndex);
|
||||
|
||||
switch (this.vertexFormatElement.getType())
|
||||
{
|
||||
case FLOAT: // This is the one currently used
|
||||
byteBuffer.putFloat(i, (float)(x));
|
||||
byteBuffer.putFloat(i + 4, (float)(y));
|
||||
byteBuffer.putFloat(i + 8, (float)(z));
|
||||
break;
|
||||
case UINT:
|
||||
case INT:
|
||||
byteBuffer.putInt(i, Float.floatToRawIntBits((float)(x)));
|
||||
byteBuffer.putInt(i + 4, Float.floatToRawIntBits((float)(y)));
|
||||
byteBuffer.putInt(i + 8, Float.floatToRawIntBits((float)(z)));
|
||||
break;
|
||||
case USHORT:
|
||||
case SHORT:
|
||||
byteBuffer.putShort(i, (short)((int)(x)));
|
||||
byteBuffer.putShort(i + 2, (short)((int)(y)));
|
||||
byteBuffer.putShort(i + 4, (short)((int)(z)));
|
||||
break;
|
||||
case UBYTE:
|
||||
case BYTE:
|
||||
byteBuffer.put(i, (byte)((int)(x)));
|
||||
byteBuffer.put(i + 1, (byte)((int)(y)));
|
||||
byteBuffer.put(i + 2, (byte)((int)(z)));
|
||||
}
|
||||
|
||||
nextVertexFormatIndex();
|
||||
}
|
||||
|
||||
private void addColor(ByteBuffer byteBuffer, int red, int green, int blue, int alpha)
|
||||
{
|
||||
int i = this.vertexCount * this.vertexFormat.getNextOffset() + this.vertexFormat.getOffset(this.vertexFormatIndex);
|
||||
|
||||
switch (this.vertexFormatElement.getType())
|
||||
{
|
||||
case FLOAT:
|
||||
byteBuffer.putFloat(i, red / 255.0F);
|
||||
byteBuffer.putFloat(i + 4, green / 255.0F);
|
||||
byteBuffer.putFloat(i + 8, blue / 255.0F);
|
||||
byteBuffer.putFloat(i + 12, alpha / 255.0F);
|
||||
break;
|
||||
case UINT:
|
||||
case INT:
|
||||
byteBuffer.putFloat(i, red);
|
||||
byteBuffer.putFloat(i + 4, green);
|
||||
byteBuffer.putFloat(i + 8, blue);
|
||||
byteBuffer.putFloat(i + 12, alpha);
|
||||
break;
|
||||
case USHORT:
|
||||
case SHORT:
|
||||
byteBuffer.putShort(i, (short)red);
|
||||
byteBuffer.putShort(i + 2, (short)green);
|
||||
byteBuffer.putShort(i + 4, (short)blue);
|
||||
byteBuffer.putShort(i + 6, (short)alpha);
|
||||
break;
|
||||
case UBYTE:
|
||||
case BYTE:
|
||||
|
||||
if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN)
|
||||
{
|
||||
// this is the one used currently
|
||||
byteBuffer.put(i, (byte)red);
|
||||
byteBuffer.put(i + 1, (byte)green);
|
||||
byteBuffer.put(i + 2, (byte)blue);
|
||||
byteBuffer.put(i + 3, (byte)alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
byteBuffer.put(i, (byte)alpha);
|
||||
byteBuffer.put(i + 1, (byte)blue);
|
||||
byteBuffer.put(i + 2, (byte)green);
|
||||
byteBuffer.put(i + 3, (byte)red);
|
||||
}
|
||||
}
|
||||
|
||||
nextVertexFormatIndex();
|
||||
}
|
||||
|
||||
private void nextVertexFormatIndex()
|
||||
{
|
||||
++this.vertexFormatIndex;
|
||||
this.vertexFormatIndex %= this.vertexFormat.getElementCount();
|
||||
this.vertexFormatElement = this.vertexFormat.getElement(this.vertexFormatIndex);
|
||||
|
||||
if (this.vertexFormatElement.getUsage() == VertexFormatElement.EnumUsage.PADDING)
|
||||
{
|
||||
this.nextVertexFormatIndex();
|
||||
}
|
||||
}
|
||||
|
||||
private void endVertex()
|
||||
{
|
||||
++this.vertexCount;
|
||||
growBuffer(this.vertexFormat.getNextOffset());
|
||||
}
|
||||
|
||||
private void growBuffer(int p_181670_1_)
|
||||
{
|
||||
//if (MathHelper.roundUp(p_181670_1_, 4) / 4 > this.rawIntBuffer.remaining() || this.vertexCount * this.vertexFormat.getNextOffset() + p_181670_1_ > this.byteBuffer.capacity())
|
||||
if (this.vertexCount * this.vertexFormat.getNextOffset() + p_181670_1_ > nearBuffer.capacity())
|
||||
{
|
||||
int i = nearBuffer.capacity();
|
||||
int j = i + MathHelper.roundUp(p_181670_1_, 2097152);
|
||||
// int k = this.rawIntBuffer.position();
|
||||
ByteBuffer directBytebuffer = GLAllocation.createDirectByteBuffer(j);
|
||||
nearBuffer.position(0);
|
||||
directBytebuffer.put(nearBuffer);
|
||||
directBytebuffer.rewind();
|
||||
nearBuffer = directBytebuffer;
|
||||
// this.rawFloatBuffer = buffer.asFloatBuffer().asReadOnlyBuffer();
|
||||
// this.rawIntBuffer = buffer.asIntBuffer();
|
||||
// this.rawIntBuffer.position(k);
|
||||
// this.rawShortBuffer = buffer.asShortBuffer();
|
||||
// this.rawShortBuffer.position(k << 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,667 +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.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CancellationException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import org.lwjgl.opengl.GL11;
|
||||
import org.lwjgl.util.glu.Project;
|
||||
|
||||
import com.backsun.lod.objects.LodChunk;
|
||||
import com.backsun.lod.objects.LodDimension;
|
||||
import com.backsun.lod.util.LodConfig;
|
||||
import com.backsun.lod.util.ReflectionHandler;
|
||||
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.LodLocation;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 2-13-2021
|
||||
*/
|
||||
public class LodRenderer
|
||||
{
|
||||
/** 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 float farPlaneDistance;
|
||||
// make sure this is an even number, or else it won't align with the chunk grid
|
||||
/** this is the total width of the LODs (I.E the diameter, not the radius) */
|
||||
private static final int LOD_CHUNK_DISTANCE_RADIUS = 6;
|
||||
|
||||
private Tessellator tessellator;
|
||||
private BufferBuilder bufferBuilder;
|
||||
|
||||
/**
|
||||
* This is an array of 0's used to clear old
|
||||
* ByteBuffers when they need to be rebuilt.
|
||||
*/
|
||||
byte[] clearBytes;
|
||||
|
||||
private ReflectionHandler reflectionHandler;
|
||||
|
||||
public LodDimension lodDimension = null;
|
||||
|
||||
|
||||
|
||||
private int maxNumbThreads = Runtime.getRuntime().availableProcessors();
|
||||
/** How many threads should be used for building the render buffer. */
|
||||
private int numbBufferThreads = maxNumbThreads;
|
||||
private ArrayList<BuildBufferThread> bufferThreads = new ArrayList<BuildBufferThread>();
|
||||
private volatile ByteBuffer[] nearBuffers = new ByteBuffer[maxNumbThreads];
|
||||
private volatile ByteBuffer[] farBuffers = new ByteBuffer[maxNumbThreads];
|
||||
private ExecutorService bufferThreadPool = Executors.newFixedThreadPool(maxNumbThreads);
|
||||
/*
|
||||
* this is the maximum number of bytes a buffer
|
||||
* would ever have to hold at once (this prevents the buffer
|
||||
* from having to resize and thus save performance)
|
||||
*/
|
||||
private int bufferMaxCapacity = 0;
|
||||
|
||||
/** 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 LODs should be regenerated */
|
||||
private boolean regen = false;
|
||||
|
||||
|
||||
|
||||
|
||||
public LodRenderer()
|
||||
{
|
||||
mc = Minecraft.getMinecraft();
|
||||
|
||||
// for some reason "Tessellator.getInstance()" won't work here, we have to create a new one
|
||||
tessellator = new Tessellator(2097152);
|
||||
bufferBuilder = tessellator.getBuffer();
|
||||
|
||||
reflectionHandler = new ReflectionHandler();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void drawLODs(LodDimension newDimension, float partialTicks)
|
||||
{
|
||||
if (reflectionHandler.fovMethod == null)
|
||||
{
|
||||
// don't continue if we can't get the
|
||||
// user's FOV
|
||||
return;
|
||||
}
|
||||
|
||||
if (reflectionHandler.fovMethod == null)
|
||||
{
|
||||
// we aren't able to get the user's
|
||||
// FOV, don't render anything
|
||||
return;
|
||||
}
|
||||
|
||||
// should the LODs be regenerated?
|
||||
if ((int)Minecraft.getMinecraft().player.posX / LodChunk.WIDTH != prevChunkX ||
|
||||
(int)Minecraft.getMinecraft().player.posZ / LodChunk.WIDTH != prevChunkZ ||
|
||||
previousChunkRenderDistance != mc.gameSettings.renderDistanceChunks ||
|
||||
prevFogDistance != LodConfig.fogDistance ||
|
||||
lodDimension != newDimension)
|
||||
{
|
||||
regen = true;
|
||||
|
||||
prevChunkX = (int)Minecraft.getMinecraft().player.posX / LodChunk.WIDTH;
|
||||
prevChunkZ = (int)Minecraft.getMinecraft().player.posZ / LodChunk.WIDTH;
|
||||
prevFogDistance = LodConfig.fogDistance;
|
||||
}
|
||||
else
|
||||
{
|
||||
// nope, the player hasn't moved, the
|
||||
// render distance hasn't changed, and
|
||||
// the dimension is the same
|
||||
regen = false;
|
||||
}
|
||||
|
||||
lodDimension = newDimension;
|
||||
if (lodDimension == null)
|
||||
{
|
||||
// if there aren't any loaded LodChunks
|
||||
// don't try drawing anything
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// used for debugging and viewing how long different processes take
|
||||
mc.mcProfiler.endSection();
|
||||
mc.mcProfiler.startSection("LOD");
|
||||
mc.mcProfiler.startSection("LOD setup");
|
||||
@SuppressWarnings("unused")
|
||||
long startTime = System.nanoTime();
|
||||
if (LodConfig.drawCheckerBoard)
|
||||
{
|
||||
if (debugging != LodConfig.drawCheckerBoard)
|
||||
regen = true;
|
||||
debugging = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (debugging != LodConfig.drawCheckerBoard)
|
||||
regen = true;
|
||||
debugging = false;
|
||||
}
|
||||
|
||||
|
||||
// color setup
|
||||
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
|
||||
|
||||
|
||||
|
||||
// get the camera location
|
||||
Entity player = mc.player;
|
||||
double cameraX = player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTicks;
|
||||
double cameraY = player.lastTickPosY + (player.posY - player.lastTickPosY) * partialTicks;
|
||||
double cameraZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTicks;
|
||||
|
||||
|
||||
|
||||
|
||||
// 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);
|
||||
|
||||
// this seemingly useless math is required,
|
||||
// just using (int) camera doesn't work
|
||||
int playerXChunkOffset = ((int) cameraX / LodChunk.WIDTH) * LodChunk.WIDTH;
|
||||
int playerZChunkOffset = ((int) cameraZ / LodChunk.WIDTH) * LodChunk.WIDTH;
|
||||
// this 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;
|
||||
|
||||
|
||||
// this is where we store the LOD objects
|
||||
AxisAlignedBB lodArray[][] = new AxisAlignedBB[numbChunksWide][numbChunksWide];
|
||||
// this is where we store the color for each LOD object
|
||||
Color colorArray[][] = new Color[numbChunksWide][numbChunksWide];
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// create the LODs //
|
||||
//=================//
|
||||
|
||||
if (regen)
|
||||
{
|
||||
mc.mcProfiler.endStartSection("LOD generation");
|
||||
|
||||
// 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 (RenderUtil.isCoordinateInLoadedArea(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); // new LodChunk(); //
|
||||
if (lod == null)
|
||||
{
|
||||
// note: for some reason if any color or lod object are set here
|
||||
// it causes the game to use 100% gpu, all of it undefined in the debug menu
|
||||
// and drop to ~6 fps.
|
||||
// colorArray[i][j] = null;
|
||||
// lodArray[i][j] = null;
|
||||
|
||||
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 = getLodHeightPoint(lod.top);
|
||||
int bottomPoint = getLodHeightPoint(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//===========================//
|
||||
// GL settings for rendering //
|
||||
//===========================//
|
||||
|
||||
// set the required open GL settings
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
|
||||
GL11.glLineWidth(2.0f);
|
||||
GL11.glDisable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glEnable(GL11.GL_CULL_FACE);
|
||||
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
|
||||
GlStateManager.translate(-cameraX, -cameraY, -cameraZ);
|
||||
|
||||
setProjectionMatrix(partialTicks);
|
||||
setupLighting(partialTicks);
|
||||
setupBufferThreads(lodArray);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
|
||||
mc.mcProfiler.endStartSection("LOD build buffer");
|
||||
if (regen)
|
||||
generateLodBuffers(lodArray, colorArray, LodConfig.fogDistance);
|
||||
|
||||
switch(LodConfig.fogDistance)
|
||||
{
|
||||
case NEAR_AND_FAR:
|
||||
mc.mcProfiler.endStartSection("LOD draw setup");
|
||||
setupFog(FogDistance.NEAR, reflectionHandler.getFogQuality());
|
||||
sendLodsToGpuAndDraw(nearBuffers);
|
||||
|
||||
mc.mcProfiler.endStartSection("LOD draw setup");
|
||||
setupFog(FogDistance.FAR, reflectionHandler.getFogQuality());
|
||||
sendLodsToGpuAndDraw(farBuffers);
|
||||
break;
|
||||
case NEAR:
|
||||
mc.mcProfiler.endStartSection("LOD draw setup");
|
||||
setupFog(FogDistance.NEAR, reflectionHandler.getFogQuality());
|
||||
sendLodsToGpuAndDraw(nearBuffers);
|
||||
break;
|
||||
case FAR:
|
||||
mc.mcProfiler.endStartSection("LOD draw setup");
|
||||
setupFog(FogDistance.FAR, reflectionHandler.getFogQuality());
|
||||
sendLodsToGpuAndDraw(farBuffers);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// cleanup //
|
||||
//=========//
|
||||
|
||||
mc.mcProfiler.endStartSection("LOD cleanup");
|
||||
|
||||
|
||||
// this must be done otherwise other parts of the screen may be drawn with a fog effect
|
||||
// IE the GUI
|
||||
GlStateManager.disableFog();
|
||||
|
||||
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_FILL);
|
||||
GL11.glEnable(GL11.GL_TEXTURE_2D);
|
||||
GL11.glDisable(GL11.GL_LIGHT1);
|
||||
GL11.glDisable(GL11.GL_COLOR_MATERIAL);
|
||||
|
||||
// change the perspective matrix back to prevent incompatibilities
|
||||
// with other mods that may render during forgeRenderLast
|
||||
Project.gluPerspective(reflectionHandler.getFov(mc, partialTicks, true), (float) this.mc.displayWidth / (float) this.mc.displayHeight, 0.05F, this.farPlaneDistance * MathHelper.SQRT_2);
|
||||
|
||||
// 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;
|
||||
|
||||
|
||||
|
||||
// This is about how long this whole process should take
|
||||
// 16 ms = 60 hz
|
||||
@SuppressWarnings("unused")
|
||||
long endTime = System.nanoTime();
|
||||
|
||||
// end of profiler tracking
|
||||
mc.mcProfiler.endSection();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* draw an array of cubes (or squares) with the given colors.
|
||||
* @param lods bounding boxes to draw
|
||||
* @param colors color of each box to draw
|
||||
*/
|
||||
private void generateLodBuffers(AxisAlignedBB[][] lods, Color[][] colors, FogDistance fogDistance)
|
||||
{
|
||||
List<Future<NearFarBuffer>> bufferFutures = new ArrayList<>();
|
||||
// TODO this should change based on whether we are using near/far or both fog settings
|
||||
bufferMaxCapacity = (lods.length * lods.length * (6 * 4 * ((3 * 4) + (4 * 4)))) / numbBufferThreads;
|
||||
|
||||
for(int i = 0; i < numbBufferThreads; i++)
|
||||
{
|
||||
if (nearBuffers[i] == null || previousChunkRenderDistance != mc.gameSettings.renderDistanceChunks)
|
||||
{
|
||||
nearBuffers[i] = ByteBuffer.allocateDirect(bufferMaxCapacity);
|
||||
nearBuffers[i].order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
farBuffers[i] = ByteBuffer.allocateDirect(bufferMaxCapacity);
|
||||
farBuffers[i].order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
clearBytes = new byte[bufferMaxCapacity];
|
||||
}
|
||||
|
||||
if (regen)
|
||||
{
|
||||
// this is the best way I could find to
|
||||
// overwrite the old data
|
||||
// (which needs to be done otherwise old
|
||||
// LODs may be drawn)
|
||||
nearBuffers[i].clear();
|
||||
nearBuffers[i].put(clearBytes);
|
||||
nearBuffers[i].clear();
|
||||
|
||||
farBuffers[i].clear();
|
||||
farBuffers[i].put(clearBytes);
|
||||
farBuffers[i].clear();
|
||||
}
|
||||
|
||||
int pos = bufferBuilder.getByteBuffer().position();
|
||||
nearBuffers[i].position(pos);
|
||||
farBuffers[i].position(pos);
|
||||
|
||||
bufferThreads.get(i).setNewData(nearBuffers[i], farBuffers[i], fogDistance, lods, colors, i, numbBufferThreads);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
bufferFutures = bufferThreadPool.invokeAll(bufferThreads);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{
|
||||
// this should never happen, but just in case
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
for(int i = 0; i < numbBufferThreads; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
nearBuffers[i] = bufferFutures.get(i).get().nearBuffer;
|
||||
farBuffers[i] = bufferFutures.get(i).get().farBuffer;
|
||||
}
|
||||
catch(CancellationException | ExecutionException| InterruptedException e)
|
||||
{
|
||||
// this should never happen, but just in case
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void sendLodsToGpuAndDraw(ByteBuffer[] buffers)
|
||||
{
|
||||
for(int i = 0; i < numbBufferThreads; i++)
|
||||
{
|
||||
int pos = bufferBuilder.getByteBuffer().position();
|
||||
buffers[i].position(pos);
|
||||
|
||||
bufferBuilder.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
|
||||
bufferBuilder.getByteBuffer().clear();
|
||||
bufferBuilder.putBulkData(buffers[i]);
|
||||
|
||||
mc.mcProfiler.endStartSection("LOD draw");
|
||||
tessellator.draw();
|
||||
mc.mcProfiler.endStartSection("LOD draw setup");
|
||||
|
||||
bufferBuilder.getByteBuffer().clear(); // this is required otherwise nothing is drawn
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// Setup Functions //
|
||||
//=================//
|
||||
|
||||
private void setupFog(FogDistance fogDistance, FogQuality fogQuality)
|
||||
{
|
||||
if(fogQuality == FogQuality.OFF)
|
||||
{
|
||||
GlStateManager.disableFog();
|
||||
return;
|
||||
}
|
||||
|
||||
if(fogDistance == FogDistance.NEAR_AND_FAR)
|
||||
{
|
||||
throw new IllegalArgumentException("setupFog only accepts NEAR or FAR fog distances.");
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
GlStateManager.setFogEnd(farPlaneDistance * 0.3f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
GlStateManager.setFogStart(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
|
||||
|
||||
GlStateManager.setFogEnd(farPlaneDistance * 1.5f);
|
||||
GlStateManager.setFogStart(farPlaneDistance * 2.0f);
|
||||
}
|
||||
}
|
||||
else if(fogDistance == FogDistance.FAR)
|
||||
{
|
||||
if (fogQuality == FogQuality.FANCY)
|
||||
{
|
||||
GlStateManager.setFogStart(farPlaneDistance * 0.78f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
GlStateManager.setFogEnd(farPlaneDistance * 1.0f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
}
|
||||
else if(fogQuality == FogQuality.FAST)
|
||||
{
|
||||
GlStateManager.setFogStart(farPlaneDistance * 0.5f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
GlStateManager.setFogEnd(farPlaneDistance * 0.75f * LOD_CHUNK_DISTANCE_RADIUS);
|
||||
}
|
||||
}
|
||||
|
||||
GlStateManager.setFogDensity(0.1f);
|
||||
GlStateManager.enableFog();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* create a new projection matrix and send it over to the GPU
|
||||
* @param partialTicks how many ticks into the frame we are
|
||||
* @return true if the matrix was successfully created and sent to the GPU, false otherwise
|
||||
*/
|
||||
private void setProjectionMatrix(float partialTicks)
|
||||
{
|
||||
// create a new view frustum so that the squares can be drawn outside the normal view distance
|
||||
GlStateManager.matrixMode(GL11.GL_PROJECTION);
|
||||
GlStateManager.loadIdentity();
|
||||
|
||||
// only continue if we can get the FOV
|
||||
if (reflectionHandler.fovMethod != null)
|
||||
{
|
||||
Project.gluPerspective(reflectionHandler.getFov(mc, partialTicks, true), (float) mc.displayWidth / (float) mc.displayHeight, 0.5F, farPlaneDistance * 12);
|
||||
}
|
||||
|
||||
// we weren't able to set up the projection matrix
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* setup the lighting to be used for the LODs
|
||||
*/
|
||||
private void setupLighting(float partialTicks)
|
||||
{
|
||||
GL11.glEnable(GL11.GL_COLOR_MATERIAL); // set the color to be used as the material (this allows lighting to be enabled)
|
||||
|
||||
// this isn't perfect right now, but it looks pretty good at 50% brightness
|
||||
float sunBrightness = mc.world.getSunBrightness(partialTicks) * mc.world.provider.getSunBrightnessFactor(partialTicks);
|
||||
float skyHasLight = mc.world.provider.hasSkyLight()? 1.0f : 0.15f;
|
||||
float gammaMultiplyer = (mc.gameSettings.gammaSetting * 0.5f + 0.5f);
|
||||
float lightStrength = sunBrightness * skyHasLight * gammaMultiplyer;
|
||||
float lightAmbient[] = {lightStrength, lightStrength, lightStrength, 1.0f};
|
||||
|
||||
ByteBuffer temp = ByteBuffer.allocateDirect(16);
|
||||
temp.order(ByteOrder.nativeOrder());
|
||||
GL11.glLight(GL11.GL_LIGHT1, GL11.GL_AMBIENT, (FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip());
|
||||
GL11.glEnable(GL11.GL_LIGHT1); // Enable the above lighting
|
||||
|
||||
GlStateManager.enableLighting();
|
||||
}
|
||||
|
||||
|
||||
private void setupBufferThreads(AxisAlignedBB[][] lods)
|
||||
{
|
||||
if (numbBufferThreads != bufferThreads.size())
|
||||
{
|
||||
bufferMaxCapacity = (lods.length * lods.length * (6 * 4 * ((3 * 4) + (4 * 4)))) / numbBufferThreads;
|
||||
clearBytes = new byte[bufferMaxCapacity];
|
||||
|
||||
bufferThreads.clear();
|
||||
for(int i = 0; i < numbBufferThreads; i++)
|
||||
bufferThreads.add(new BuildBufferThread());
|
||||
regen = true;
|
||||
|
||||
for(int i = 0; i < maxNumbThreads; i++)
|
||||
{
|
||||
nearBuffers[i] = ByteBuffer.allocateDirect(bufferMaxCapacity);
|
||||
nearBuffers[i].order(ByteOrder.LITTLE_ENDIAN);
|
||||
|
||||
farBuffers[i] = ByteBuffer.allocateDirect(bufferMaxCapacity);
|
||||
farBuffers[i].order(ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns -1 if there are no valid points
|
||||
*/
|
||||
private int getLodHeightPoint(short[] heightPoints)
|
||||
{
|
||||
if (heightPoints[LodLocation.NE.value] != -1)
|
||||
return heightPoints[LodLocation.NE.value];
|
||||
if (heightPoints[LodLocation.NW.value] != -1)
|
||||
return heightPoints[LodLocation.NW.value];
|
||||
if (heightPoints[LodLocation.SE.value] != -1)
|
||||
return heightPoints[LodLocation.NE.value];
|
||||
return heightPoints[LodLocation.NE.value];
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.backsun.lod.renderer;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* 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-13-2021
|
||||
*/
|
||||
public class NearFarBuffer
|
||||
{
|
||||
public ByteBuffer nearBuffer;
|
||||
|
||||
public ByteBuffer farBuffer;
|
||||
|
||||
|
||||
NearFarBuffer(ByteBuffer newNearBuffer, ByteBuffer newFarBuffer)
|
||||
{
|
||||
nearBuffer = newNearBuffer;
|
||||
farBuffer = newFarBuffer;
|
||||
}
|
||||
}
|
||||
@@ -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.getMinecraft();
|
||||
|
||||
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,55 +0,0 @@
|
||||
package com.backsun.lod.util;
|
||||
|
||||
import com.backsun.lod.util.enums.FogDistance;
|
||||
|
||||
import net.minecraftforge.common.config.Config;
|
||||
import net.minecraftforge.common.config.ConfigManager;
|
||||
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 02-14-2021
|
||||
*/
|
||||
@Config(modid = Reference.MOD_ID)
|
||||
public class LodConfig
|
||||
{
|
||||
// save the config file when it is changed
|
||||
@Mod.EventBusSubscriber(modid = Reference.MOD_ID)
|
||||
private static class EventHandler
|
||||
{
|
||||
@SubscribeEvent
|
||||
public static void onConfigChanged(final ConfigChangedEvent.OnConfigChangedEvent event)
|
||||
{
|
||||
if (event.getModID().equals(Reference.MOD_ID))
|
||||
{
|
||||
ConfigManager.sync(Reference.MOD_ID, Config.Type.INSTANCE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Config.Comment(
|
||||
{"Enable LODs",
|
||||
"If true LODs will be drawn, if false LODs will "
|
||||
+ "not be rendered. However they will "
|
||||
+ "still be generated and stored in your world's save folder."})
|
||||
public static boolean drawLODs = true;
|
||||
|
||||
@Config.Comment(
|
||||
{"Fog Distance",
|
||||
"What distance should Fog be drawn on the LODs?"})
|
||||
public static FogDistance fogDistance = FogDistance.NEAR_AND_FAR;
|
||||
|
||||
@Config.Comment(
|
||||
{"Draw Debugging Checkerboard",
|
||||
"If false the LODs will draw with their normal world colors."
|
||||
+ "If true they will draw as a black and white checkerboard."
|
||||
+ "This can be used for debugging or imagining you are playing a "
|
||||
+ "giant game of chess ;)"})
|
||||
public static boolean drawCheckerBoard = false;
|
||||
|
||||
|
||||
}
|
||||
@@ -1,322 +0,0 @@
|
||||
package com.backsun.lod.util;
|
||||
|
||||
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 net.minecraft.client.Minecraft;
|
||||
import net.minecraft.world.storage.ISaveHandler;
|
||||
|
||||
/**
|
||||
* This object handles creating LodRegions
|
||||
* from files and saving LodRegion objects
|
||||
* to file.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 01-30-2021
|
||||
*/
|
||||
public class LodFileHandler
|
||||
{
|
||||
private LodDimension loadedRegion = null;
|
||||
public long regionLastWriteTime[][];
|
||||
|
||||
// String s = Minecraft.getMinecraftDir().getCanonicalPath() + "/saves/" + world.getSaveHandler().getSaveDirectoryName() + "/data/AA/World" + world.provider.dimensionId + ".dat";
|
||||
private String save_dir;
|
||||
public ISaveHandler saveHandler;
|
||||
|
||||
private final String FILE_NAME_PREFIX = "lod";
|
||||
private final String FILE_EXTENSION = ".txt";
|
||||
|
||||
private ExecutorService fileWritingThreadPool = Executors.newFixedThreadPool(1);
|
||||
/** Is true if the readyToReadAndWrite is false */
|
||||
private boolean waitingToSaveRegions = false;
|
||||
|
||||
|
||||
public LodFileHandler(ISaveHandler newSaveHandler, LodDimension newLoadedRegion)
|
||||
{
|
||||
saveHandler = newSaveHandler;
|
||||
|
||||
loadedRegion = newLoadedRegion;
|
||||
// these two variable are used in sync with the LodDimension
|
||||
regionLastWriteTime = new long[loadedRegion.getWidth()][loadedRegion.getWidth()];
|
||||
for(int i = 0; i < loadedRegion.getWidth(); i++)
|
||||
for(int j = 0; j < loadedRegion.getWidth(); j++)
|
||||
regionLastWriteTime[i][j] = -1;
|
||||
|
||||
if (saveHandler != null && saveHandler.getWorldDirectory() != null)
|
||||
save_dir = getWorldSaveDirectory();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// 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.getMinecraft().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 //
|
||||
//==============//
|
||||
|
||||
|
||||
public synchronized void saveDirtyRegionsToFile()
|
||||
{
|
||||
// we don't currently support reading or writing
|
||||
// files when connected to a server
|
||||
if (!Minecraft.getMinecraft().isIntegratedServerRunning())
|
||||
return;
|
||||
|
||||
if (!readyToReadAndWrite())
|
||||
{
|
||||
// we aren't ready to read and write yet
|
||||
if(!waitingToSaveRegions)
|
||||
{
|
||||
waitingToSaveRegions = true;
|
||||
|
||||
// retry until we are able to read and write
|
||||
// then wake up the fileWritingThreadPool
|
||||
Thread retryReady = new Thread(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
// check once every so often so see
|
||||
// if anything has changed so we can
|
||||
// start reading and writing files
|
||||
while(!readyToReadAndWrite())
|
||||
{
|
||||
this.wait(1000);
|
||||
// get the save handler again, if for some
|
||||
// reason the original handler was null
|
||||
saveHandler = Minecraft.getMinecraft().getIntegratedServer().getWorld(0).getSaveHandler();
|
||||
save_dir = getWorldSaveDirectory();
|
||||
}
|
||||
|
||||
// we can start writing files now
|
||||
fileWritingThreadPool.execute(saveDirtyRegionsThread);
|
||||
waitingToSaveRegions = false;
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
{ /* should never be called */}
|
||||
});
|
||||
|
||||
retryReady.run();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
fileWritingThreadPool.execute(saveDirtyRegionsThread);
|
||||
}
|
||||
private Thread saveDirtyRegionsThread = new Thread(() ->
|
||||
{
|
||||
for(int i = 0; i < loadedRegion.getWidth(); i++)
|
||||
{
|
||||
for(int j = 0; j < loadedRegion.getWidth(); j++)
|
||||
{
|
||||
if(loadedRegion.isRegionDirty[i][j])
|
||||
{
|
||||
saveRegionToDisk(loadedRegion.regions[i][j]);
|
||||
loadedRegion.isRegionDirty[i][j] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
waitingToSaveRegions = false;
|
||||
});
|
||||
|
||||
|
||||
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.
|
||||
* @param regionX
|
||||
* @param regionZ
|
||||
*/
|
||||
private String getFileNameForRegion(int regionX, int regionZ)
|
||||
{
|
||||
if (!readyToReadAndWrite())
|
||||
return null;
|
||||
|
||||
return save_dir + "\\lod_data\\DIM" + loadedRegion.dimension.getId() + "\\" +
|
||||
FILE_NAME_PREFIX + "." + regionX + "." + regionZ + FILE_EXTENSION;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns if this FileHandler is ready to read
|
||||
* and write files.
|
||||
*/
|
||||
public boolean readyToReadAndWrite()
|
||||
{
|
||||
return saveHandler != null && saveHandler.getWorldDirectory() != null &&
|
||||
save_dir != null && !save_dir.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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 getWorldName()
|
||||
{
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
if(mc.isIntegratedServerRunning())
|
||||
{
|
||||
return mc.getIntegratedServer().getWorldName();
|
||||
}
|
||||
else
|
||||
{
|
||||
return mc.getCurrentServerData().serverName + "_version_" + mc.getCurrentServerData().gameVersion;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns null if there was an IO Exception
|
||||
*/
|
||||
private String getWorldSaveDirectory()
|
||||
{
|
||||
try
|
||||
{
|
||||
return saveHandler.getWorldDirectory().getCanonicalPath();
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package com.backsun.lod.util;
|
||||
|
||||
/**
|
||||
*
|
||||
* @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.12.2]";
|
||||
|
||||
/** 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,187 +0,0 @@
|
||||
package com.backsun.lod.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Parameter;
|
||||
|
||||
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 09-21-2020
|
||||
*/
|
||||
public class ReflectionHandler
|
||||
{
|
||||
public Method fovMethod = null;
|
||||
public Field ofFogField = null;
|
||||
|
||||
|
||||
public ReflectionHandler()
|
||||
{
|
||||
setupFovMethod();
|
||||
setupFogField();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This sets the "getFOVModifier" method from the
|
||||
* minecraft "EntityRenderer" class, so that we can get
|
||||
* the FOV of the player at any time.
|
||||
*
|
||||
* This is required since Minecraft is obfuscated so
|
||||
* we can't just look for 'getFOVModifier'
|
||||
* we have to search for it based on its parameters and
|
||||
* return type; which luckily are unique in the EntityRenderer
|
||||
* class.
|
||||
*/
|
||||
private void setupFovMethod()
|
||||
{
|
||||
// get every method from the entity renderer
|
||||
Method[] methods = Minecraft.getMinecraft().entityRenderer.getClass().getDeclaredMethods();
|
||||
|
||||
Class<?> returnType;
|
||||
Parameter[] params;
|
||||
Method returnMethod = null;
|
||||
|
||||
for(Method m : methods)
|
||||
{
|
||||
returnType = m.getReturnType();
|
||||
params = m.getParameters();
|
||||
|
||||
// see if this method has the same return type
|
||||
// and parameters as the 'getFOVModifier' method.
|
||||
if (returnType.equals(float.class) &&
|
||||
params.length == 2 &&
|
||||
params[0].getType().equals(float.class) &&
|
||||
params[1].getType().equals(boolean.class))
|
||||
{
|
||||
|
||||
// only accept the first method that we find
|
||||
if (returnMethod == null)
|
||||
{
|
||||
returnMethod = m;
|
||||
}
|
||||
else
|
||||
{
|
||||
// we found a second method that matches the
|
||||
// outline we were looking for,
|
||||
// to prevent unexpected behavior
|
||||
// dont't set fovMethod.
|
||||
|
||||
// Since we aren't sure that
|
||||
// this method is the right
|
||||
// one, we may accidently mess
|
||||
// up the entityRender by invoking
|
||||
// it and we probably wouldn't get
|
||||
// the FOV from it anyway.
|
||||
|
||||
System.err.println("Error: a second method that matches the parameters and return typ of 'getFOVModifier' was found, LODs won't be rendered.");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only set the method once we have gone through
|
||||
// the whole array of methods, just to
|
||||
// make sure we have the right one.
|
||||
fovMethod = returnMethod;
|
||||
// set up the method so we can invoke it later
|
||||
fovMethod.setAccessible(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to setupFovMethod.
|
||||
*/
|
||||
private void setupFogField()
|
||||
{
|
||||
// get every variable from the entity renderer
|
||||
Field[] vars = Minecraft.getMinecraft().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(Minecraft.getMinecraft().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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the FOV used by the EntityRender.
|
||||
*/
|
||||
public float getFov(Minecraft mc, float partialTicks, boolean useFovSetting)
|
||||
{
|
||||
try
|
||||
{
|
||||
return (float)fovMethod.invoke(mc.entityRenderer, new Object[]{partialTicks, useFovSetting});
|
||||
}
|
||||
catch(InvocationTargetException | IllegalAccessException | IllegalArgumentException e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package com.backsun.lod.util.enums;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 10-17-2020
|
||||
*
|
||||
* TOP, N, S, E, W, BOTTOM
|
||||
*/
|
||||
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
|
||||
{
|
||||
/** valid for both fast and fancy fog qualities. */
|
||||
NEAR,
|
||||
/** valid for both fast and 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,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)
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
# Note: to update code in eclipse run the "eclipse" command in graldew
|
||||
|
||||
|
||||
# used when creating the projection matrix
|
||||
public net.minecraft.client.renderer.GameRenderer func_215311_a(Lnet/minecraft/client/renderer/ActiveRenderInfo;FZ)D # getFOVModifier
|
||||
public net.minecraft.client.renderer.GameRenderer field_78529_t # rendererUpdateCount
|
||||
public net.minecraft.client.renderer.GameRenderer func_228380_a_(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V # hurtCameraEffect
|
||||
public net.minecraft.client.renderer.GameRenderer func_228383_b_(Lcom/mojang/blaze3d/matrix/MatrixStack;F)V # applyBobbing
|
||||
|
||||
# used when accessing built byteBuffers
|
||||
public net.minecraft.client.renderer.BufferBuilder field_179001_a # byteBuffer
|
||||
|
||||
# used when determining where to save files too
|
||||
public net.minecraft.world.storage.DimensionSavedDataManager field_215759_d # folder
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
#=====================#
|
||||
# Examples from Forge #
|
||||
#=====================#
|
||||
|
||||
# Makes public the IScreenFactory class in ScreenManager
|
||||
public net.minecraft.client.gui.ScreenManager$IScreenFactory
|
||||
|
||||
# Makes protected and removes the final modifier from 'random' in MinecraftServer
|
||||
protected-f net.minecraft.server.MinecraftServer field_147146_q #random
|
||||
|
||||
# Makes public the 'createNamedService' method in Util,
|
||||
# accepting a String and returns an ExecutorService
|
||||
public net.minecraft.util.Util func_240979_a_(Ljava/lang/String;)Ljava/util/concurrent/ExecutorService; #createNamedService
|
||||
|
||||
# Makes public the 'func_239776_a_' method in UUIDCodec,
|
||||
# accepting two longs and returning an int[]
|
||||
public net.minecraft.util.UUIDCodec func_239776_a_(JJ)[I #func_239776_a_
|
||||
@@ -0,0 +1,51 @@
|
||||
#// This is an example mods.toml file. It contains the data relating to the loading mods.
|
||||
#// There are several mandatory fields (#mandatory), and many more that are optional (#optional).
|
||||
#// The overall format is standard TOML format, v0.5.0.
|
||||
#// Note that there are a couple of TOML lists in this file.
|
||||
#// Find more information on toml format here: https://github.com/toml-lang/toml
|
||||
#// The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
|
||||
modLoader="javafml" #mandatory
|
||||
|
||||
#// A version range to match for said mod loader - for regular FML @Mod it will be the forge version
|
||||
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="GNU GPLv3"
|
||||
|
||||
#// A URL to refer people to when problems occur with this mod
|
||||
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
|
||||
|
||||
#// The modid of the mod
|
||||
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.5.4" #mandatory
|
||||
|
||||
#// A display name for the mod
|
||||
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://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="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, Leonardo Amato, and Cola" #optional
|
||||
|
||||
#// The description text for the mod (multi line!) (#mandatory)
|
||||
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 |
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "com.seibel.lod.forge.mixins",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"refmap": "lod.refmap.json",
|
||||
"mixins": [
|
||||
"MixinWorldRenderer"
|
||||
],
|
||||
"minVersion": "0.8"
|
||||
}
|
||||
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": "0.1",
|
||||
"mcversion": "1.12.2",
|
||||
"url": "",
|
||||
"updateUrl": "",
|
||||
"authorList": ["James Seibel"],
|
||||
"credits": "TechnoVision and Vike for their modding tutorials.",
|
||||
"logoFile": "",
|
||||
"screenshots": [],
|
||||
"dependencies": ["lodcore"]
|
||||
}
|
||||
]
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"pack": {
|
||||
"description": "examplemod resources",
|
||||
"pack_format": 3,
|
||||
"_comment": "A pack_format of 3 should be used starting with Minecraft 1.11. All resources, including language files, should be lowercase (eg: en_us.lang). A pack_format of 2 will load your mod resources with LegacyV2Adapter, which requires language files to have uppercase letters (eg: en_US.lang)."
|
||||
"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