Compare commits
1312 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 17e375bc61 | |||
| a2c8c90a5e | |||
| b376014df8 | |||
| b9ee54f6ad | |||
| 6c7e1900a3 | |||
| 6f929f40f9 | |||
| b6a8930855 | |||
| 7a91b258de | |||
| 35bef76aeb | |||
| 780d0ad9fb | |||
| c0d5dd6dee | |||
| 3e87e625ba | |||
| 56f9403859 | |||
| 8259c79e9c | |||
| be1e2fe7e6 | |||
| 609ee5c70d | |||
| 207cab9a0f | |||
| c80b025ac1 | |||
| 8610917b86 | |||
| fae4bee871 | |||
| b9608498a2 | |||
| fe59c6b0c9 | |||
| b082b048d6 | |||
| 91712cee2a | |||
| 5adfbb2dee | |||
| ec32d09468 | |||
| 919990820e | |||
| 5cc31efa12 | |||
| 5f48b41693 | |||
| 9530eea287 | |||
| ebbf304c94 | |||
| 7c8ac0c2ff | |||
| eefad5e052 | |||
| 9a1e6e29d4 | |||
| 62ab450d98 | |||
| b4a5da4a74 | |||
| ed82480c89 | |||
| 82449c5edc | |||
| b165726bc9 | |||
| 11910d0f28 | |||
| f66e27b077 | |||
| 835beb607d | |||
| c4e2d3fb0f | |||
| eb3d8d9da5 | |||
| 151d548099 | |||
| c5cdc2760f | |||
| a663bf9f19 | |||
| 7ddd48d132 | |||
| ce10a43cc6 | |||
| 5476af5bb3 | |||
| 25d2cfd7b8 | |||
| 1b754387e0 | |||
| bcad40069f | |||
| 5aa9061006 | |||
| 873e8cec57 | |||
| f6f96c3aea | |||
| aeed672295 | |||
| 832fbe6d15 | |||
| 03deddf666 | |||
| d06413d1b4 | |||
| 8afa50d585 | |||
| 9f28f1f812 | |||
| 985388fd90 | |||
| e27e10082a | |||
| 4e510d96fc | |||
| c0ec02f062 | |||
| bd27a96bde | |||
| d6aeaf8e9d | |||
| 2b9bba4aa7 | |||
| 58b0991891 | |||
| 59cbbef327 | |||
| 7047c81a2b | |||
| 6e2ab47359 | |||
| f879332e1d | |||
| 6fcafecc61 | |||
| a5af93aef1 | |||
| 4b84fd2a67 | |||
| 924efc0cbd | |||
| 288457b5bd | |||
| d29fa86de6 | |||
| 97be227e3d | |||
| 909d6a54c3 | |||
| 228b6a80dc | |||
| 6936a5f96f | |||
| 740560a50a | |||
| 47c28f0f37 | |||
| 1c859cd7da | |||
| e4a97dd76d | |||
| 4fd1e5ea06 | |||
| 6039aeabde | |||
| 17a384f074 | |||
| 25e8f5ec6a | |||
| eac8cacd42 | |||
| 75193d76a3 | |||
| aa24fd341e | |||
| 81adade05b | |||
| e3808dc986 | |||
| d669b2a1fe | |||
| 2bd8dab240 | |||
| 2b423c2edd | |||
| 1a4faf4bdd | |||
| b70829aceb | |||
| bba771d376 | |||
| 75b18f8bd8 | |||
| 60da404900 | |||
| b75eebd0dc | |||
| 72cbd1167a | |||
| e4e51ebf5b | |||
| dd2096bf1b | |||
| 393a94a7a1 | |||
| ef0023ef39 | |||
| f0994fff75 | |||
| 31f41540c0 | |||
| 81fe13b9c0 | |||
| 332df13b29 | |||
| b3af6df0c5 | |||
| 9392e618c0 | |||
| fd361a39a1 | |||
| f41de59f39 | |||
| c701cf987b | |||
| f05e878600 | |||
| dc028db5ed | |||
| c59d7a7d27 | |||
| a3dd346a02 | |||
| dba8061f71 | |||
| 3da2d961fc | |||
| aa83dc7465 | |||
| 392821c081 | |||
| 7e5fc979cc | |||
| 7ebb555b94 | |||
| 3612a2f9e0 | |||
| 42b67825f8 | |||
| 30a636c840 | |||
| e5722c19a9 | |||
| 6b6a9ab0a9 | |||
| 6da74c6f4e | |||
| 0bafa37f66 | |||
| 6ba6b11f6b | |||
| 739653f37a | |||
| 213d70f2d1 | |||
| dda3c7636b | |||
| 3956578043 | |||
| d11f067392 | |||
| 9f9fe6a231 | |||
| 486a30cb93 | |||
| 01545dc295 | |||
| 165a3799f3 | |||
| 308f809d5d | |||
| 003dbdff02 | |||
| 99f8dbb042 | |||
| 4263ea9733 | |||
| c09b07a21b | |||
| 4e0160648b | |||
| ad367f681d | |||
| a5a70cd65b | |||
| 4ff37cfdad | |||
| 9a1abdefa1 | |||
| 37cc7e7b37 | |||
| 04cbb1e92c | |||
| 5033175808 | |||
| 689928708c | |||
| 98327e6fdf | |||
| 5aef0977c0 | |||
| e6738f1c80 | |||
| b55c1b8f56 | |||
| 3764a4cc9e | |||
| d6bbb9d8dc | |||
| a38e7a00e4 | |||
| 2ec84ae3cf | |||
| f03035e3f9 | |||
| 1d914b8f8a | |||
| ee947b36a2 | |||
| ba393f61e5 | |||
| 796c8e7bef | |||
| fe60de314d | |||
| d237db3302 | |||
| f665b452b0 | |||
| 17750691d6 | |||
| 89ba5b9d15 | |||
| cea44a3f8a | |||
| a99c9aff76 | |||
| 1827ab646c | |||
| db00f7ebec | |||
| 0b93c7b5dc | |||
| 97204f3a3c | |||
| 02a6db0a62 | |||
| 577af4d854 | |||
| 68155142c3 | |||
| 43897e1298 | |||
| bf2c520966 | |||
| ee1528f694 | |||
| 8bd7556c89 | |||
| facbb174f5 | |||
| 9d3ce5307c | |||
| 54f3e9e12d | |||
| e294fc79eb | |||
| a750aaf90a | |||
| be8e09eb9b | |||
| 016d26a6f7 | |||
| 539698c456 | |||
| bcc11b8f0c | |||
| c2a960162e | |||
| c42a3a5fb3 | |||
| 59d6289177 | |||
| 4f028d118d | |||
| b555e35016 | |||
| 26b4c3a2d9 | |||
| 2a5199f851 | |||
| 408dbc2169 | |||
| c9ffcfb1e8 | |||
| 3bd1eedcb8 | |||
| 8500ec7a00 | |||
| 223570a0b7 | |||
| de8c063731 | |||
| 0cffa30286 | |||
| 1d3a282c60 | |||
| 9b6cd955b5 | |||
| 8e1559ac61 | |||
| ce597576ba | |||
| d53a7a5fc4 | |||
| 35bb5cdc92 | |||
| 26e9cc21fd | |||
| 71fd448b7f | |||
| 93e18230f0 | |||
| d305741be2 | |||
| 5830c8d87a | |||
| 5161439536 | |||
| deb6ada6cc | |||
| e72a0546be | |||
| e27b43f03a | |||
| daf4f06a30 | |||
| e5ef93a26d | |||
| b158dff2c6 | |||
| 23bbbce749 | |||
| 898be82aab | |||
| dc9ed37de2 | |||
| b390e54801 | |||
| 9736d2169e | |||
| b507f459b3 | |||
| 51a7053d7e | |||
| 3ba40dd910 | |||
| 248f8e5e70 | |||
| 49b0911aaf | |||
| e4b40c9383 | |||
| 328ac93178 | |||
| d91f86aed5 | |||
| 8119cc06ad | |||
| 94c9d0e276 | |||
| e262dfa14a | |||
| 5e0b63347e | |||
| b7df3bad22 | |||
| 6a56c0c96f | |||
| fd8a94d77c | |||
| 7d38fac16d | |||
| 235ffb03a5 | |||
| fa2702209c | |||
| f9f9f98750 | |||
| 0c46947f4d | |||
| b5b57dfaba | |||
| 39e7812f8b | |||
| 025e8b3f9b | |||
| 35e3a4262b | |||
| 562c8154ff | |||
| e23244181a | |||
| 6aa6c32299 | |||
| fbdabf52e7 | |||
| f4c1f1bcd7 | |||
| 965c19d426 | |||
| 239a876fcf | |||
| d53165881f | |||
| 40733ea1fc | |||
| 66a16ee508 | |||
| b1a9a8ac8d | |||
| 06a2f9f336 | |||
| 978bc58c11 | |||
| a5577e80f1 | |||
| 9daf5a013c | |||
| 72e2cb8a64 | |||
| db819698af | |||
| 09e427ab97 | |||
| a6b3a7ea5a | |||
| 4d08339f79 | |||
| 2ba32a8c94 | |||
| ebedd5e181 | |||
| 357c355e26 | |||
| faca159721 | |||
| 3556528932 | |||
| 8513e46fdc | |||
| 323eced2a4 | |||
| 6a87539ca3 | |||
| fe725b6795 | |||
| 02862a770f | |||
| a7759ab8e9 | |||
| da1b2051dd | |||
| 4fdc596474 | |||
| d0c710b7e1 | |||
| 41ee9dcd99 | |||
| 506ce87f5f | |||
| 08e42ebfe5 | |||
| 699d27afd2 | |||
| 4a64ce0bed | |||
| b3b94d29b5 | |||
| 3a30516088 | |||
| 6f469737f3 | |||
| 183720d1e5 | |||
| b2dcc66bd0 | |||
| 5c67be30de | |||
| 4ad4e2c29c | |||
| d1f805d178 | |||
| 73071119fa | |||
| 97c52834f5 | |||
| 3e472e454a | |||
| 7ddab31337 | |||
| fd5b9be523 | |||
| f9dd870067 | |||
| 4908acd7ac | |||
| 87486f6825 | |||
| c721c14e27 | |||
| 3521af9792 | |||
| ff94dba348 | |||
| 31d0a45555 | |||
| 41c1473e04 | |||
| d5f12466b2 | |||
| bdd9ef6b40 | |||
| 9b6895ec68 | |||
| a3854561fc | |||
| a66df74ec9 | |||
| eb4b31e876 | |||
| 6015b9a1dc | |||
| 146d42bbe9 | |||
| 16b14bc424 | |||
| a37e4ca232 | |||
| 8103c16064 | |||
| 6ae41b0caa | |||
| ba81f31027 | |||
| 71c72e26e7 | |||
| 97828f465d | |||
| ec37803572 | |||
| b7a54eff7a | |||
| 9604ce297c | |||
| 5ad961d80e | |||
| 843ec2fef8 | |||
| 1b3e90b669 | |||
| 55aadb73f1 | |||
| e3d87c70c4 | |||
| 8b1205f79e | |||
| 291f5d247c | |||
| ad63825194 | |||
| b0e0cd107d | |||
| 5f60cd8d4d | |||
| d0e17ccab7 | |||
| 38a4643cf3 | |||
| 938adca022 | |||
| e2ec80134e | |||
| 903f166041 | |||
| a9bdbfda4e | |||
| 378349b870 | |||
| 190ce716ff | |||
| d2c3a87fa8 | |||
| 2d5acbbf45 | |||
| 4e973099f9 | |||
| ee4f43cc59 | |||
| 3e64b7400e | |||
| c44daa759c | |||
| 17c662b10f | |||
| 3cfbb69dd9 | |||
| 470668265b | |||
| b6ced30d70 | |||
| d3e0f1e14d | |||
| 910350ba3a | |||
| 8dcf30e776 | |||
| 30d4bcd6a1 | |||
| 66300cbe70 | |||
| 50ae719f24 | |||
| dccad778fb | |||
| f163e31cd2 | |||
| 5499079ada | |||
| 8d1277db1b | |||
| 34fcac25c2 | |||
| cb0516cae8 | |||
| 4fdad05252 | |||
| dc785b4fe1 | |||
| 8df7e1762a | |||
| 43d9b41648 | |||
| 880559f94a | |||
| 6f04ddce87 | |||
| 6eb065f7c9 | |||
| 17ebad9141 | |||
| 9bcc799b0b | |||
| f247410ae4 | |||
| 2f3bb2ec34 | |||
| 5c47170ef4 | |||
| 29d152b312 | |||
| aa48f0f5c6 | |||
| 05ea683fcf | |||
| 65163a2477 | |||
| 9dc4c46b99 | |||
| 69029e6f72 | |||
| faf8579b41 | |||
| ed6dff3b5e | |||
| 2dd2623257 | |||
| 82dfecf04c | |||
| bb5bb23025 | |||
| c73e9b3cb5 | |||
| c28ec0b1d8 | |||
| a587ac4b4c | |||
| 0f19b338b6 | |||
| 9453e806db | |||
| 1bd072bf0a | |||
| 9315fd6211 | |||
| 1decb3764f | |||
| 012312892a | |||
| c9f6a753ec | |||
| 9f6e9f791c | |||
| a297cdb79a | |||
| e0ed760cf9 | |||
| 1c2549c64f | |||
| 433bc9217d | |||
| 514e12580d | |||
| faf38ef8e3 | |||
| 48741a5364 | |||
| 03ff908de1 | |||
| 5eed9dae40 | |||
| 47988ec0da | |||
| b29dac3753 | |||
| 3e3e1a7cf2 | |||
| 79e6977bab | |||
| 0c4ee74254 | |||
| 45d9dbbfcf | |||
| 2428449ab4 | |||
| f863da105b | |||
| d63b2c3b12 | |||
| 15496663f3 | |||
| 340631eb9b | |||
| adcd835642 | |||
| ff5d2e6047 | |||
| bd569dad2f | |||
| 71ab3196ea | |||
| b051815b3c | |||
| 991b3356bb | |||
| 58ad37c056 | |||
| 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 | |||
| bc8188beb0 | |||
| 0fc4c5532b | |||
| 98586d6af9 | |||
| bdd1e2410a | |||
| c0240c71bf | |||
| 65ffc93e0f | |||
| 01183be383 | |||
| 359791ea58 | |||
| 5b3aa82817 | |||
| d77bb48da1 | |||
| 8b941cb95c | |||
| b9d991db63 | |||
| 1a8a7be494 | |||
| d054ac91b1 | |||
| e40ee20460 | |||
| 29b3e9fadc | |||
| 3cc78c62a0 | |||
| 2c719c41d9 | |||
| cd06b42b02 | |||
| e8b46a6fd2 | |||
| 7854f659a3 | |||
| 6cb1d2f8f4 | |||
| f95d57ab6d | |||
| f91479829d | |||
| 829c9531fa | |||
| f9bb248eef | |||
| 03ce4d9c42 | |||
| f181d073a3 | |||
| 63b01f3ec7 | |||
| 14f1b6db54 | |||
| 604089cfa8 | |||
| 712d9db2fa | |||
| 2b5b023472 | |||
| 4a9bc7ca74 | |||
| 804f910584 | |||
| d5b2512e27 | |||
| 280d281604 | |||
| 95bcc71d23 | |||
| b623f1581f | |||
| 62b6d9ea30 | |||
| 6c8d0f98a6 | |||
| dc353cd029 | |||
| 86e4ab7e83 | |||
| c6a96ae710 | |||
| 9e24ee0ef7 | |||
| 72bcc87de7 |
+27
@@ -24,3 +24,30 @@ run
|
|||||||
# Files from Forge MDK
|
# Files from Forge MDK
|
||||||
logs
|
logs
|
||||||
forge*changelog.txt
|
forge*changelog.txt
|
||||||
|
|
||||||
|
.architectury-transformer/
|
||||||
|
build/
|
||||||
|
*.ipr
|
||||||
|
run/
|
||||||
|
*.iws
|
||||||
|
out/
|
||||||
|
*.iml
|
||||||
|
.gradle/
|
||||||
|
output/
|
||||||
|
bin/
|
||||||
|
libs/
|
||||||
|
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
.idea/
|
||||||
|
classes/
|
||||||
|
.metadata
|
||||||
|
.vscode
|
||||||
|
.settings
|
||||||
|
*.launch
|
||||||
|
|
||||||
|
**/src/generated/
|
||||||
|
Merged/
|
||||||
|
|
||||||
|
# file from notepad++
|
||||||
|
*.bak
|
||||||
+100
@@ -0,0 +1,100 @@
|
|||||||
|
# use Eclipse's JDK
|
||||||
|
image: gradle:eclipse-temurin
|
||||||
|
|
||||||
|
# all stages need to be defined here
|
||||||
|
stages:
|
||||||
|
- build_18-1
|
||||||
|
- build_18-2
|
||||||
|
# - zip_artifacts
|
||||||
|
|
||||||
|
variables:
|
||||||
|
# If we have correctness issues when compiling this can be set to false
|
||||||
|
GRADLE_OPTS: "-Dorg.gradle.daemon=true"
|
||||||
|
# Pull core when building
|
||||||
|
GIT_SUBMODULE_STRATEGY: recursive
|
||||||
|
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- echo $CI_JOB_ID
|
||||||
|
# Writing GE_JOB_ID variable to environment file, will need the value in the next stage.
|
||||||
|
- echo GE_JOB_ID=$CI_JOB_ID >> generate_jars.env
|
||||||
|
|
||||||
|
|
||||||
|
# 1.18.1 build
|
||||||
|
build_18-1:
|
||||||
|
stage: build_18-1
|
||||||
|
script: ./gradlew build -PmcVer=1.18.1 --gradle-user-home cache/; ./gradlew merge --gradle-user-home cache/
|
||||||
|
# build using Java 17
|
||||||
|
image: eclipse-temurin:17
|
||||||
|
cache:
|
||||||
|
key: "$CI_COMMIT_REF_NAME_18-1"
|
||||||
|
policy: pull-push
|
||||||
|
paths:
|
||||||
|
- .gradle
|
||||||
|
- cache/
|
||||||
|
|
||||||
|
|
||||||
|
# 1.18.2 build
|
||||||
|
build_18-2:
|
||||||
|
stage: build_18-2
|
||||||
|
script: ./gradlew build -PmcVer=1.18.2 --gradle-user-home cache/; ./gradlew merge --gradle-user-home cache/
|
||||||
|
# build using Java 17
|
||||||
|
image: eclipse-temurin:17
|
||||||
|
cache:
|
||||||
|
key: "$CI_COMMIT_REF_NAME_18-2"
|
||||||
|
policy: pull-push
|
||||||
|
paths:
|
||||||
|
- .gradle
|
||||||
|
- cache/
|
||||||
|
|
||||||
|
# TEMPORARY, there should be a way of either generating artifacts per build or in a separate stage
|
||||||
|
artifacts:
|
||||||
|
# This should only be done after the last build, otherwise there will be duplicate jars
|
||||||
|
name: "Merged_NightlyBuild-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
||||||
|
paths:
|
||||||
|
# relative to the root directory
|
||||||
|
- Merged
|
||||||
|
expire_in: 1 day
|
||||||
|
|
||||||
|
|
||||||
|
# # put artifacts in a zip
|
||||||
|
# # This should only be done after all the builds have been completed
|
||||||
|
# zip_artifacts:
|
||||||
|
# stage: zip_artifacts
|
||||||
|
# # The complier complains if we don't do something with the script line
|
||||||
|
# script: echo 'Building complete. Creating artifact Zip.'
|
||||||
|
# # build using Java 17
|
||||||
|
# image: eclipse-temurin:17
|
||||||
|
# artifacts:
|
||||||
|
# # This should only be done after the last build, otherwise there will be duplicate jars
|
||||||
|
# name: "Merged_NightlyBuild-${CI_COMMIT_SHORT_SHA}-${CI_COMMIT_TIMESTAMP}"
|
||||||
|
# paths:
|
||||||
|
# # relative to the root directory
|
||||||
|
# - Merged
|
||||||
|
# expire_in: 1 day
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# unused deployment stage
|
||||||
|
#deploy:
|
||||||
|
# stage: deploy
|
||||||
|
# image: registry.gitlab.com/gitlab-org/release-cli:latest
|
||||||
|
# script:
|
||||||
|
# - echo 'running release_job'
|
||||||
|
# - echo 'Previous Job ID is printed below'
|
||||||
|
# - echo $GE_JOB_ID
|
||||||
|
# # Specifying that this job requires artifacts from the previous job to succeed
|
||||||
|
# needs:
|
||||||
|
# - job: build
|
||||||
|
# artifacts: true
|
||||||
|
# release:
|
||||||
|
# name: 'Unstable Jars for Latest Commit' #: $CI_COMMIT_SHORT_SHA'
|
||||||
|
# description: 'Created automatically using the release-cli.'
|
||||||
|
# # tag_name is a mendatory field and can not be an empty string
|
||||||
|
# tag_name: 'Unstable-$CI_COMMIT_SHORT_SHA'
|
||||||
|
# assets:
|
||||||
|
# links:
|
||||||
|
# - name: 'Fabric Jars'
|
||||||
|
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/fabric/build/libs'
|
||||||
|
# - name: 'Forge Jars'
|
||||||
|
# url: 'https://gitlab.com/jeseibel/minecraft-lod-mod/cw/-/jobs/${GE_JOB_ID}/artifacts/file/forge/build/libs'
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
[submodule "core"]
|
||||||
|
path = core
|
||||||
|
url = https://gitlab.com/jeseibel/distant-horizons-core.git
|
||||||
|
branch = main
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
# 1.18.1 version based stuff
|
||||||
|
|
||||||
|
minecraft_version=1.18.1
|
||||||
|
java_version = 17
|
||||||
|
|
||||||
|
# Fabric loader
|
||||||
|
fabric_loader_version=0.13.3
|
||||||
|
fabric_api_version=0.46.6+1.18
|
||||||
|
# Fabric mod versions
|
||||||
|
modmenu_version=3.0.1
|
||||||
|
starlight_version_fabric=3554912
|
||||||
|
lithium_version=mc1.18.1-0.7.7
|
||||||
|
sodium_version=3605309
|
||||||
|
iris_version=1.18.x-v1.1.4
|
||||||
|
bclib_version=1.2.5
|
||||||
|
immersive_portals_version = v1.0.4-1.18
|
||||||
|
|
||||||
|
# Fabric mod run
|
||||||
|
# 0 = Don't enable and don't run
|
||||||
|
# 1 = Can be referenced in code but doesn't run
|
||||||
|
# 2 = Can be referenced in code and runs in client
|
||||||
|
enable_starlight=0
|
||||||
|
enable_sodium=1
|
||||||
|
enable_lithium=0
|
||||||
|
enable_iris=0
|
||||||
|
enable_bclib=0
|
||||||
|
|
||||||
|
# Forge loader
|
||||||
|
forge_version=39.1.2
|
||||||
|
# Forge mod versions
|
||||||
|
starlight_version_forge=3559934
|
||||||
|
|
||||||
|
# Forge mod run
|
||||||
|
# 0 = Dont enable and don't run
|
||||||
|
# 1 = Can be referenced in code but doesn't run
|
||||||
|
# 2 = Can be referenced in code and runs in client
|
||||||
|
enable_starlight_forge=0
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
# 1.18.2 version based stuff
|
||||||
|
# architectury_plugin_version = 3.4-SNAPSHOT
|
||||||
|
# dev_architectury_loom_version = 0.10.0-SNAPSHOT
|
||||||
|
minecraft_version=1.18.2
|
||||||
|
java_version = 17
|
||||||
|
|
||||||
|
# Fabric loader
|
||||||
|
fabric_loader_version=0.13.3
|
||||||
|
fabric_api_version=0.48.0+1.18.2
|
||||||
|
# Fabric mod versions
|
||||||
|
modmenu_version=3.1.0
|
||||||
|
starlight_version_fabric=3667443
|
||||||
|
lithium_version=mc1.18.2-0.7.9
|
||||||
|
sodium_version=3669187
|
||||||
|
iris_version=1.18.x-v1.2.2
|
||||||
|
immersive_portals_version = v1.0.4-1.18
|
||||||
|
bclib_version=0
|
||||||
|
|
||||||
|
# Fabric mod run
|
||||||
|
# 0 = Don't enable and don't run
|
||||||
|
# 1 = Can be referenced in code but doesn't run
|
||||||
|
# 2 = Can be referenced in code and runs in client
|
||||||
|
enable_starlight=0
|
||||||
|
enable_sodium=1
|
||||||
|
enable_lithium=0
|
||||||
|
enable_iris=0
|
||||||
|
enable_bclib=0
|
||||||
|
|
||||||
|
# Forge loader
|
||||||
|
forge_version=40.0.18
|
||||||
|
# Forge mod versions
|
||||||
|
starlight_version_forge=0
|
||||||
|
|
||||||
|
# Forge mod run
|
||||||
|
# 0 = Dont enable and don't run
|
||||||
|
# 1 = Can be referenced in code but doesn't run
|
||||||
|
# 2 = Can be referenced in code and runs in client
|
||||||
|
enable_starlight_forge=0
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
# <img src="https://gitlab.com/jeseibel/distant-horizons-core/-/raw/main/_logo%20files/LOD%20logo%20flat%20-%20with%20boarder.png" width="32"> Distant Horizons
|
||||||
|
|
||||||
|
> A mod that adds a Level of Detail System to Minecraft
|
||||||
|
|
||||||
|
|
||||||
|
# What is 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>
|
||||||
|
|
||||||
|
### Versions
|
||||||
|
|
||||||
|
Architectury version: 3.4-SNAPSHOT\
|
||||||
|
Java Compiler plugin: Manifold Preprocessor
|
||||||
|
|
||||||
|
#### 1.18.2 mods
|
||||||
|
Forge version: 40.0.18\
|
||||||
|
Fabric version: 0.13.3\
|
||||||
|
Fabric API version: 0.48.0+1.18.2\
|
||||||
|
Modmenu version: 3.1.0
|
||||||
|
|
||||||
|
#### 1.18.1 mods
|
||||||
|
Forge version: 39.1.2\
|
||||||
|
Fabric version: 0.13.3\
|
||||||
|
Fabric API version: 0.46.6+1.18\
|
||||||
|
Modmenu version: 3.0.1
|
||||||
|
|
||||||
|
|
||||||
|
Notes:\
|
||||||
|
This version has been confirmed to work in IDE and Retail Minecraft.\
|
||||||
|
(Retail running forge version 1.18.1-39.0.5 and fabric version 1.18-0.12.12 and 1.18.1-0.13.2)
|
||||||
|
|
||||||
|
|
||||||
|
## Source Code Installation
|
||||||
|
|
||||||
|
See the Fabric Documentation online for more detailed instructions:\
|
||||||
|
https://fabricmc.net/wiki/tutorial:setup
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
* A Java Development Kit (JDK) for Java 17 (recommended) or newer. Visit https://www.oracle.com/java/technologies/downloads/ for installers.
|
||||||
|
* Git or someway to clone git projects. Visit https://git-scm.com/ for installers.
|
||||||
|
* (Not required) Any Java IDE with plugins that support Manifold, for example Intellij IDEA.
|
||||||
|
|
||||||
|
**If using IntelliJ:**
|
||||||
|
0. Install Manifold plugin
|
||||||
|
1. open IDEA and import the build.gradle
|
||||||
|
2. refresh the Gradle project in IDEA if required
|
||||||
|
|
||||||
|
**If using Ecplise: (Note that Eclispe currently doesn't support Manifold's preprocessor!)**
|
||||||
|
1. run the command: `./gradlew geneclipseruns`
|
||||||
|
2. run the command: `./gradlew eclipse`
|
||||||
|
3. Make sure eclipse has the JDK 17 installed. (This is needed so that eclipse can run minecraft)
|
||||||
|
4. Import the project into eclipse
|
||||||
|
|
||||||
|
## Switching Versions
|
||||||
|
This branch support 2 built versions:
|
||||||
|
- 1.18.2
|
||||||
|
- 1.18.1 (which also runs on 1.18)
|
||||||
|
|
||||||
|
To switch between active versions, change `mcVer=1.18.?` in `gradle.properties` file.
|
||||||
|
|
||||||
|
If running on IDE, to ensure IDE pickup the changed versions, you will need to run a gradle command again to allow gradle to update all the libs. (In IntellJ you will also need to do a gradle sync again if it didn't start it automatically.)
|
||||||
|
>Note: There may be a `java.nio.file.FileSystemException` thrown on running the command after switching versions. To fix it, either restart your IDE (as your IDE is locking up a file) or use tools like LockHunter to unlock the linked file. (Often a lib file under `common\build\lib` or `forge\build\lib` or `fabric\build\lib`). If anyone knows how to solve this issue please comment to this issue: https://gitlab.com/jeseibel/minecraft-lod-mod/-/issues/233
|
||||||
|
|
||||||
|
## Compiling
|
||||||
|
|
||||||
|
**Using GUI**
|
||||||
|
1. Download the zip of the project and extract it
|
||||||
|
2. Download the core from https://gitlab.com/jeseibel/distant-horizons-core and extract into a folder called `core`
|
||||||
|
3. Open a command line in the project folder
|
||||||
|
4. Run the command: `./gradlew assemble`
|
||||||
|
5. Then run command: `./gradlew mergeJars`
|
||||||
|
6. The compiled jar file will be in the folder `Merged`
|
||||||
|
|
||||||
|
**If in terminal:**
|
||||||
|
1. `git clone -b preprocessor_test --recurse-submodules https://gitlab.com/jeseibel/minecraft-lod-mod.git`
|
||||||
|
2. `cd minecraft-lod-mod`
|
||||||
|
3. `./gradlew assemble`
|
||||||
|
4. `./gradlew mergeJars`
|
||||||
|
5. The compiled jar file will be in the folder `Merged`
|
||||||
|
>Note: You can add the arg: `-PmcVer=1.18.?` to tell gradle to build a selected MC version instead of having to manually modify the `gradle.properties` file.
|
||||||
|
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
|
## Useful commands
|
||||||
|
|
||||||
|
Build only Fabric: `./gradlew fabric:assemble` or `./gradlew fabric:build`\
|
||||||
|
Build only Forge: `./gradlew fabric:assemble` or `./gradlew forge:build`\
|
||||||
|
Run the Fabric client (for debugging): `./gradlew fabric:runClient`\
|
||||||
|
Run the Forge client (for debugging): `./gradlew forge:runClient`
|
||||||
|
|
||||||
|
## Open Source Acknowledgements
|
||||||
|
|
||||||
|
XZ for Java (data compression)\
|
||||||
|
https://tukaani.org/xz/java.html
|
||||||
|
|
||||||
|
DHJarMerger (To merge multiple mod versions into one jar)\
|
||||||
|
https://github.com/Ran-helo/DHJarMerger
|
||||||
-70
@@ -1,70 +0,0 @@
|
|||||||
This mod adds a Level Of Detail (LOD) system to Minecraft.
|
|
||||||
This implementation renders simplified chunks outside the normal render distance
|
|
||||||
allowing for an increased view distance without harming performance.
|
|
||||||
|
|
||||||
Or in other words: this mod let's you see farther without turning your game into a slide show.
|
|
||||||
If you want to see a quick demo, check out the video I made here:
|
|
||||||
https://youtu.be/CCT-3s02tYA
|
|
||||||
|
|
||||||
|
|
||||||
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/
|
|
||||||
|
|
||||||
Step 1: Create a system variable called "JAVA_MC_HOME" with the location of the JDK 1.8.0_251 (This is needed for gradle to work correctly)
|
|
||||||
|
|
||||||
Step 2: replace JAVA_HOME with JAVA_MC_HOME in gradle.bat
|
|
||||||
|
|
||||||
Step 3: open a command line in the project folder
|
|
||||||
|
|
||||||
Step 4: run the command: "./gradlew geneclipseruns"
|
|
||||||
|
|
||||||
Step 5: run the command: "./gradlew eclipse"
|
|
||||||
|
|
||||||
Step 6: Make sure the eclipse has the JDK 1.8.0_251 installed. (This is needed so that eclipse can run minecraft)
|
|
||||||
|
|
||||||
Step 7: Import the project into eclipse
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
=========
|
|
||||||
compiling
|
|
||||||
=========
|
|
||||||
|
|
||||||
Step 1: open a command line in the project folder
|
|
||||||
|
|
||||||
Step 2: run the command: "./gradlew build"
|
|
||||||
|
|
||||||
Step 3: the compiled jar file will be in the folder "build\libs"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
==============
|
|
||||||
Other commands
|
|
||||||
==============
|
|
||||||
|
|
||||||
"./gradlew --refresh-dependencies" to refresh local dependencies.
|
|
||||||
"./gradlew clean" to reset everything (this does not affect your code) and then start the process again.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
============
|
|
||||||
Note to self
|
|
||||||
============
|
|
||||||
|
|
||||||
The Minecraft source code is NOT added to your workspace in a editable way. Minecraft is treated like a normal Library. Sources are there for documentation and research purposes only.
|
|
||||||
|
|
||||||
Source code uses mcp mappings not Mojangs.
|
|
||||||
|
|
||||||
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
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 93 KiB |
File diff suppressed because one or more lines are too long
+182
-177
@@ -1,194 +1,199 @@
|
|||||||
|
import io.github.ran.jarmerger.JarMergerPlugin
|
||||||
|
|
||||||
|
|
||||||
buildscript {
|
buildscript {
|
||||||
repositories {
|
dependencies{
|
||||||
maven { url = 'https://files.minecraftforge.net/maven' }
|
classpath files('plugins/DHJarMerger-1.0.jar')
|
||||||
jcenter()
|
|
||||||
mavenCentral()
|
|
||||||
maven { url = 'https://repo.spongepowered.org/maven/' }
|
|
||||||
// potential replacement in case of problems:
|
|
||||||
// https://dist.creeper.host/Sponge/maven
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id "architectury-plugin" version "3.4-SNAPSHOT"
|
||||||
|
id "dev.architectury.loom" version "0.10.0-SNAPSHOT" apply false
|
||||||
|
}
|
||||||
|
|
||||||
|
def writeBuildGradlePredefine() {
|
||||||
|
def excapedMCVersion = rootProject.minecraft_version.replace(".", "_")
|
||||||
|
new File(projectDir, "build.properties").text = "MC_VERSION_${excapedMCVersion}=\n"
|
||||||
|
}
|
||||||
|
|
||||||
|
def loadProperties() {
|
||||||
|
def defaultMcVersion = '1.18.2'
|
||||||
|
if (!project.hasProperty("mcVer")) {
|
||||||
|
println "No mcVer set! Defaulting to ${defaultMcVersion}."
|
||||||
|
println "Tip: Use -PmcVer='${defaultMcVersion}' in cmd arg to set mcVer."
|
||||||
|
}
|
||||||
|
def mcVersion = project.hasProperty("mcVer") ? mcVer : defaultMcVersion
|
||||||
|
|
||||||
|
println "Loading properties file at " + mcVersion + ".properties"
|
||||||
|
def props = new Properties()
|
||||||
|
props.load(new FileInputStream("$rootProject.rootDir/"+"$mcVersion"+".properties"))
|
||||||
|
|
||||||
|
props.each { prop ->
|
||||||
|
rootProject.ext.set(prop.key, prop.value)
|
||||||
|
// println "Added prop [key:" + prop.key + ", value:" + prop.value + "]"
|
||||||
|
}
|
||||||
|
writeBuildGradlePredefine()
|
||||||
|
}
|
||||||
|
loadProperties()
|
||||||
|
|
||||||
|
apply plugin: JarMergerPlugin
|
||||||
|
|
||||||
|
architectury {
|
||||||
|
minecraft = rootProject.minecraft_version
|
||||||
|
}
|
||||||
|
|
||||||
|
subprojects { p ->
|
||||||
|
apply plugin: "dev.architectury.loom"
|
||||||
|
|
||||||
|
loom {
|
||||||
|
silentMojangMappingsLicense()
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
common
|
||||||
|
shadowMe
|
||||||
|
implementation.extendsFrom shadowMe
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true
|
minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
|
||||||
classpath group: 'org.spongepowered', name: 'mixingradle', version: '0.7-SNAPSHOT'
|
// The following line declares the mojmap mappings
|
||||||
|
mappings loom.officialMojangMappings()
|
||||||
|
|
||||||
|
//Manifold
|
||||||
|
annotationProcessor "systems.manifold:manifold-preprocessor:${rootProject.manifold_version}"
|
||||||
|
|
||||||
|
// Toml
|
||||||
|
implementation("com.electronwill.night-config:toml:${rootProject.toml_version}")
|
||||||
|
|
||||||
|
if (p != project(":forge")) {
|
||||||
|
// We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
|
||||||
|
// Do NOT use other classes from fabric loader unless working with fabric
|
||||||
|
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p != project(":core")) {
|
||||||
|
common(project(":core")) { transitive false }
|
||||||
|
shadowMe(project(":core")) { transitive false }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
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.3.2'
|
jar {
|
||||||
group = 'com.backsun.lod'
|
manifest {
|
||||||
archivesBaseName = 'lod_1.16.5'
|
attributes 'Implementation-Title': rootProject.archives_base_name,
|
||||||
|
'Implementation-Version': rootProject.mod_version,
|
||||||
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
|
'Main-Class': 'com.seibel.lod.core.JarMain'
|
||||||
|
|
||||||
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
|
|
||||||
minecraft {
|
|
||||||
// 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 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Include resources generated by data generators.
|
allprojects { p ->
|
||||||
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
apply plugin: "java"
|
||||||
|
apply plugin: "architectury-plugin"
|
||||||
|
apply plugin: "maven-publish"
|
||||||
|
|
||||||
dependencies {
|
archivesBaseName = rootProject.archives_base_name
|
||||||
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
|
version = rootProject.mod_version
|
||||||
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
|
group = rootProject.maven_group
|
||||||
// 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'
|
|
||||||
|
|
||||||
|
|
||||||
// these were added to hopefully allow for cloning
|
|
||||||
// configuredFeatures to allow for safe
|
|
||||||
// multi threaded feature generation. Sadly I couldn't find
|
|
||||||
// a way to duplicate lambda functions (which features use)
|
|
||||||
// so for now I'm not sure what to do.
|
|
||||||
//implementation 'io.github.kostaskougios:cloning:1.10.3'
|
|
||||||
//
|
|
||||||
//implementation ('com.esotericsoftware:kryo:5.1.1') {
|
|
||||||
// exclude group: "org.objenesis"
|
|
||||||
//}
|
|
||||||
//implementation 'org.objenesis:objenesis:3.2'
|
|
||||||
|
|
||||||
|
|
||||||
// You may put jars on which you depend on in ./libs or you may define them like so..
|
|
||||||
// compile "some.group:artifact:version:classifier"
|
|
||||||
// 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
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Example for how to get properties into the manifest for reading by the runtime..
|
|
||||||
jar {
|
|
||||||
manifest {
|
|
||||||
attributes([
|
|
||||||
"Specification-Title": "Level of Detail",
|
|
||||||
"Specification-Version": "1", // We are version 1 of ourselves
|
|
||||||
"Implementation-Title": project.name,
|
|
||||||
"Implementation-Version": "{version}",
|
|
||||||
"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 {
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
// used to download and compile dependencies from git repos
|
||||||
|
maven { url 'https://jitpack.io' }
|
||||||
|
|
||||||
|
// For Manifold Preprocessor
|
||||||
|
maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' }
|
||||||
|
|
||||||
|
// Required for importing Modrinth mods
|
||||||
maven {
|
maven {
|
||||||
url "file:///${project.projectDir}/mcmodsrepo"
|
name = "Modrinth"
|
||||||
|
url = "https://api.modrinth.com/maven"
|
||||||
|
content {
|
||||||
|
includeGroup "maven.modrinth"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Required for importing CursedForge mods
|
||||||
|
maven {
|
||||||
|
url "https://www.cursemaven.com"
|
||||||
|
content {
|
||||||
|
includeGroup "curse.maven"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// These 2 are for importing mods that arnt on CursedForge, Modrinth, GitHub, GitLab or anywhere opensource
|
||||||
|
flatDir {
|
||||||
|
dirs "${rootDir}/mods/fabric"
|
||||||
|
content {
|
||||||
|
includeGroup "fabric-mod"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
flatDir {
|
||||||
|
dirs "${rootDir}/mods/forge"
|
||||||
|
content {
|
||||||
|
includeGroup "forge-mod"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
mixin {
|
|
||||||
add sourceSets.main, "lod.refmap.json"
|
// Put stuff from gradle.properties into the mod info
|
||||||
|
processResources {
|
||||||
|
def resourceTargets = ["fabric.mod.json", "META-INF/mods.toml"] // Location of where to put
|
||||||
|
def intoTargets = ["$buildDir/resources/main/"] // Location of the built resources folder
|
||||||
|
def replaceProperties = [
|
||||||
|
version: mod_version,
|
||||||
|
mod_name: mod_name,
|
||||||
|
authors: mod_authors,
|
||||||
|
description: mod_description,
|
||||||
|
homepage: mod_homepage,
|
||||||
|
source: mod_source,
|
||||||
|
issues: mod_issues,
|
||||||
|
minecraft_version: minecraft_version,
|
||||||
|
java_version: java_version
|
||||||
|
] // The left side is what gets replaced in the mod info and the right side is where to get it from in the gradle.properties
|
||||||
|
//TODO: Make Forge loader version also be relaced with non hardcoded value instead of "[36,41)"
|
||||||
|
|
||||||
|
inputs.properties replaceProperties
|
||||||
|
replaceProperties.put 'project', project
|
||||||
|
filesMatching(resourceTargets) {
|
||||||
|
expand replaceProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
intoTargets.each { target ->
|
||||||
|
if (file(target).exists()) {
|
||||||
|
copy {
|
||||||
|
from(sourceSets.main.resources) {
|
||||||
|
include resourceTargets
|
||||||
|
expand replaceProperties
|
||||||
|
}
|
||||||
|
into target
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tasks.withType(JavaCompile) {
|
||||||
|
// Add Manifold Preprocessor
|
||||||
|
// def excapedMCVersion = rootProject.minecraft_version.replace(".", "_")
|
||||||
|
// options.compilerArgs += ['-Xplugin:Manifold', "-AMC_VERSION_${excapedMCVersion}"]
|
||||||
|
//
|
||||||
|
options.compilerArgs += ['-Xplugin:Manifold']
|
||||||
|
|
||||||
|
// println options.compilerArgs
|
||||||
|
if (p != project(":core")) {
|
||||||
|
options.release = rootProject.java_version as Integer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
withSourcesJar()
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == project(":core") || p == project(":common")) {
|
||||||
|
runClient.enabled = false
|
||||||
|
runServer.enabled = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
MC_VERSION_1_18_2=
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
loom {
|
||||||
|
accessWidenerPath.set(file("src/main/resources/lod.accesswidener"))
|
||||||
|
}
|
||||||
|
|
||||||
|
architectury {
|
||||||
|
common()
|
||||||
|
}
|
||||||
|
|
||||||
|
afterEvaluate {
|
||||||
|
tasks {
|
||||||
|
remapJar {
|
||||||
|
remapAccessWidener.set(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
mavenCommon(MavenPublication) {
|
||||||
|
artifactId = rootProject.archives_base_name
|
||||||
|
from components.java
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
||||||
|
repositories {
|
||||||
|
// Add repositories to publish to here.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,402 @@
|
|||||||
|
/*
|
||||||
|
* 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.common;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.config.*;
|
||||||
|
import com.seibel.lod.core.enums.config.*;
|
||||||
|
import com.seibel.lod.core.enums.rendering.*;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IAdvanced.*;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.*;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IFogQuality.IAdvancedFog;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IGraphics.IFogQuality.IAdvancedFog.IHeightFog;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IMultiplayer;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton.IClient.IWorldGenerator;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This handles any configuration the user has access to.
|
||||||
|
* @author coolGi2007
|
||||||
|
* @version 12-12-2021
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Config
|
||||||
|
//public class Config extends TinyConfig
|
||||||
|
{
|
||||||
|
// CONFIG STRUCTURE
|
||||||
|
// -> Client
|
||||||
|
// |
|
||||||
|
// |-> Graphics
|
||||||
|
// | |-> Quality
|
||||||
|
// | |-> FogQuality
|
||||||
|
// | |-> AdvancedGraphics
|
||||||
|
// |
|
||||||
|
// |-> World Generation
|
||||||
|
// |
|
||||||
|
// |-> Advanced
|
||||||
|
// |-> Threads
|
||||||
|
// |-> Buffers
|
||||||
|
// |-> Debugging
|
||||||
|
|
||||||
|
// Since the original config system uses forge stuff, that means we have to rewrite the whole config system
|
||||||
|
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static Client client;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _optionsButton = ILodConfigWrapperSingleton.IClient.OPTIONS_BUTTON_DESC;
|
||||||
|
// I know this option should be in Client
|
||||||
|
// This is a hacky method to not show the button in the options screen but show it in the mod menu
|
||||||
|
// Tough it is in client in the wrapper singleton
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static boolean optionsButton = true;
|
||||||
|
|
||||||
|
public static class Client
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static Graphics graphics;
|
||||||
|
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static WorldGenerator worldGenerator;
|
||||||
|
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static Multiplayer multiplayer;
|
||||||
|
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static Advanced advanced;
|
||||||
|
|
||||||
|
|
||||||
|
public static class Graphics
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static Quality quality;
|
||||||
|
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static FogQuality fogQuality;
|
||||||
|
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static AdvancedGraphics advancedGraphics;
|
||||||
|
|
||||||
|
|
||||||
|
public static class Quality
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _drawResolution = IQuality.DRAW_RESOLUTION_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static HorizontalResolution drawResolution = IQuality.DRAW_RESOLUTION_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _lodChunkRenderDistance = IQuality.LOD_CHUNK_RENDER_DISTANCE_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 16, maxValue = 2048)
|
||||||
|
public static int lodChunkRenderDistance = IQuality.LOD_CHUNK_RENDER_DISTANCE_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _verticalQuality = IQuality.VERTICAL_QUALITY_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static VerticalQuality verticalQuality = IQuality.VERTICAL_QUALITY_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _horizontalScale = IQuality.HORIZONTAL_SCALE_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 2, maxValue = 32)
|
||||||
|
public static int horizontalScale = IQuality.HORIZONTAL_SCALE_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _horizontalQuality = IQuality.HORIZONTAL_SCALE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static HorizontalQuality horizontalQuality = IQuality.HORIZONTAL_QUALITY_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _dropoffQuality = IQuality.DROPOFF_QUALITY_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static DropoffQuality dropoffQuality = IQuality.DROPOFF_QUALITY_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _lodBiomeBlending = IQuality.LOD_BIOME_BLENDING_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0, maxValue = 7)
|
||||||
|
public static int lodBiomeBlending = IQuality.LOD_BIOME_BLENDING_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class FogQuality
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _fogDistance = IFogQuality.FOG_DISTANCE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static FogDistance fogDistance = IFogQuality.FOG_DISTANCE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _fogDrawMode = IFogQuality.FOG_DRAW_MODE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static FogDrawMode fogDrawMode = IFogQuality.FOG_DRAW_MODE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _fogColorMode = IFogQuality.FOG_COLOR_MODE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static FogColorMode fogColorMode = IFogQuality.FOG_COLOR_MODE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _disableVanillaFog = IFogQuality.DISABLE_VANILLA_FOG_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static boolean disableVanillaFog = IFogQuality.DISABLE_VANILLA_FOG_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static AdvancedFog advancedFog;
|
||||||
|
|
||||||
|
public static class AdvancedFog {
|
||||||
|
static final double SQRT2 = 1.4142135623730951;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _farFogStart = IAdvancedFog.FAR_FOG_START_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
|
||||||
|
public static double farFogStart = IAdvancedFog.FAR_FOG_START_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _farFogEnd = IAdvancedFog.FAR_FOG_END_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
|
||||||
|
public static double farFogEnd = IAdvancedFog.FAR_FOG_END_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _farFogMin = IAdvancedFog.FAR_FOG_MIN_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = -5.0, maxValue = SQRT2)
|
||||||
|
public static double farFogMin = IAdvancedFog.FAR_FOG_MIN_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _farFogMax = IAdvancedFog.FAR_FOG_MAX_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = 5.0)
|
||||||
|
public static double farFogMax = IAdvancedFog.FAR_FOG_MAX_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _farFogType = IAdvancedFog.FAR_FOG_TYPE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static FogSetting.FogType farFogType = IAdvancedFog.FAR_FOG_TYPE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _farFogDensity = IAdvancedFog.FAR_FOG_DENSITY_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0.01, maxValue = 50.0)
|
||||||
|
public static double farFogDensity = IAdvancedFog.FAR_FOG_DENSITY_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static HeightFog heightFog;
|
||||||
|
|
||||||
|
public static class HeightFog {
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _heightFogMixMode = IHeightFog.HEIGHT_FOG_MIX_MODE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static HeightFogMixMode heightFogMixMode = IHeightFog.HEIGHT_FOG_MIX_MODE_DEFAULT;
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _heightFogMode = IHeightFog.HEIGHT_FOG_MODE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static HeightFogMode heightFogMode = IHeightFog.HEIGHT_FOG_MODE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _heightFogHeight = IHeightFog.HEIGHT_FOG_HEIGHT_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = -4096.0, maxValue = 4096.0)
|
||||||
|
public static double heightFogHeight = IHeightFog.HEIGHT_FOG_HEIGHT_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _heightFogStart = IHeightFog.HEIGHT_FOG_START_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
|
||||||
|
public static double heightFogStart = IHeightFog.HEIGHT_FOG_START_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _heightFogEnd = IHeightFog.HEIGHT_FOG_END_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = SQRT2)
|
||||||
|
public static double heightFogEnd = IHeightFog.HEIGHT_FOG_END_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _heightFogMin = IHeightFog.HEIGHT_FOG_MIN_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = -5.0, maxValue = SQRT2)
|
||||||
|
public static double heightFogMin = IHeightFog.HEIGHT_FOG_MIN_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _heightFogMax = IHeightFog.HEIGHT_FOG_MAX_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0.0, maxValue = 5.0)
|
||||||
|
public static double heightFogMax = IHeightFog.HEIGHT_FOG_MAX_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _heightFogType = IHeightFog.HEIGHT_FOG_TYPE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static FogSetting.FogType heightFogType = IHeightFog.HEIGHT_FOG_TYPE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _heightFogDensity = IHeightFog.HEIGHT_FOG_DENSITY_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0.01, maxValue = 50.0)
|
||||||
|
public static double heightFogDensity = IHeightFog.HEIGHT_FOG_DENSITY_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class AdvancedGraphics
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _disableDirectionalCulling = IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static boolean disableDirectionalCulling = IAdvancedGraphics.DISABLE_DIRECTIONAL_CULLING_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _vanillaOverdraw = IAdvancedGraphics.VANILLA_OVERDRAW_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static VanillaOverdraw vanillaOverdraw = IAdvancedGraphics.VANILLA_OVERDRAW_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _useExtendedNearClipPlane = IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static boolean useExtendedNearClipPlane = IAdvancedGraphics.USE_EXTENDED_NEAR_CLIP_PLANE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _brightnessMultiplier = IAdvancedGraphics.BRIGHTNESS_MULTIPLIER_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static double brightnessMultiplier = IAdvancedGraphics.BRIGHTNESS_MULTIPLIER_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _saturationMultiplier = IAdvancedGraphics.SATURATION_MULTIPLIER_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static double saturationMultiplier = IAdvancedGraphics.SATURATION_MULTIPLIER_DEFAULT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _backsideCullingRange = IAdvancedGraphics.VANILLA_CULLING_RANGE_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0, maxValue = 512)
|
||||||
|
public static int backsideCullingRange = IAdvancedGraphics.VANILLA_CULLING_RANGE_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class WorldGenerator
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _enableDistantGeneration = IWorldGenerator.ENABLE_DISTANT_GENERATION_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static boolean enableDistantGeneration = IWorldGenerator.ENABLE_DISTANT_GENERATION_DEFAULT;
|
||||||
|
|
||||||
|
// @ConfigAnnotations.FileComment
|
||||||
|
// public static String _distanceGenerationMode = IWorldGenerator.getDistanceGenerationModeDesc();
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static DistanceGenerationMode distanceGenerationMode = IWorldGenerator.DISTANCE_GENERATION_MODE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _lightGenerationMode = IWorldGenerator.LIGHT_GENERATION_MODE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static LightGenerationMode lightGenerationMode = IWorldGenerator.LIGHT_GENERATION_MODE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _generationPriority = IWorldGenerator.GENERATION_PRIORITY_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static GenerationPriority generationPriority = IWorldGenerator.GENERATION_PRIORITY_DEFAULT;
|
||||||
|
|
||||||
|
/*
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _allowUnstableFeatureGeneration = IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DESC;
|
||||||
|
// FIXME: Temperary override. In 1.18, the newer Unstable gnerator is more usable
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static boolean allowUnstableFeatureGeneration = true;//IWorldGenerator.ALLOW_UNSTABLE_FEATURE_GENERATION_DEFAULT;
|
||||||
|
*/
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static BlocksToAvoid blocksToAvoid = IWorldGenerator.BLOCKS_TO_AVOID_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Multiplayer
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _serverFolderNameMode = IMultiplayer.SERVER_FOLDER_NAME_MODE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static ServerFolderNameMode serverFolderNameMode = IMultiplayer.SERVER_FOLDER_NAME_MODE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _multiDimensionRequiredSimilarity = IMultiplayer.MULTI_DIMENSION_REQUIRED_SIMILARITY_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static double multiDimensionRequiredSimilarity = IMultiplayer.MULTI_DIMENSION_REQUIRED_SIMILARITY_DEFAULT;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Advanced
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static Threading threading;
|
||||||
|
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static Debugging debugging;
|
||||||
|
|
||||||
|
@ConfigAnnotations.ScreenEntry
|
||||||
|
public static Buffers buffers;
|
||||||
|
|
||||||
|
|
||||||
|
public static class Threading
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 1, maxValue = 50)
|
||||||
|
public static int numberOfWorldGenerationThreads = IThreading.NUMBER_OF_WORLD_GENERATION_THREADS_DEFAULT.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _numberOfBufferBuilderThreads = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 1, maxValue = 50)
|
||||||
|
public static int numberOfBufferBuilderThreads = IThreading.NUMBER_OF_BUFFER_BUILDER_THREADS_MIN_DEFAULT_MAX.defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Debugging
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _drawLods = IDebugging.DRAW_LODS_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static boolean drawLods = IDebugging.DRAW_LODS_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _debugMode = IDebugging.DEBUG_MODE_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static DebugMode debugMode = IDebugging.DEBUG_MODE_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _enableDebugKeybindings = IDebugging.DEBUG_KEYBINDINGS_ENABLED_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static boolean enableDebugKeybindings = IDebugging.DEBUG_KEYBINDINGS_ENABLED_DEFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Buffers
|
||||||
|
{
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _gpuUploadMethod = IBuffers.GPU_UPLOAD_METHOD_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static GpuUploadMethod gpuUploadMethod = IBuffers.GPU_UPLOAD_METHOD_DEFAULT;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _gpuUploadPerMegabyteInMilliseconds = IBuffers.GPU_UPLOAD_PER_MEGABYTE_IN_MILLISECONDS_DESC;
|
||||||
|
@ConfigAnnotations.Entry(minValue = 0, maxValue = 50)
|
||||||
|
public static int gpuUploadPerMegabyteInMilliseconds = IBuffers.GPU_UPLOAD_PER_MEGABYTE_IN_MILLISECONDS_DEFAULT.defaultValue;
|
||||||
|
|
||||||
|
@ConfigAnnotations.FileComment
|
||||||
|
public static String _rebuildTimes = IBuffers.REBUILD_TIMES_DESC;
|
||||||
|
@ConfigAnnotations.Entry
|
||||||
|
public static BufferRebuildTimes rebuildTimes = IBuffers.REBUILD_TIMES_DEFAULT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package com.seibel.lod.common;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.forge.LodForgeMethodCaller;
|
||||||
|
import com.seibel.lod.common.networking.NetworkInterface;
|
||||||
|
import com.seibel.lod.common.wrappers.DependencySetup;
|
||||||
|
import com.seibel.lod.common.wrappers.config.ConfigGui;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is the common main class
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
public class LodCommonMain {
|
||||||
|
public static boolean forge = false;
|
||||||
|
public static boolean serverSided;
|
||||||
|
public static LodForgeMethodCaller forgeMethodCaller;
|
||||||
|
public static NetworkInterface networkInterface;
|
||||||
|
|
||||||
|
public static void startup(LodForgeMethodCaller caller, boolean serverSided, NetworkInterface networkInterface) {
|
||||||
|
LodCommonMain.serverSided = serverSided;
|
||||||
|
if (caller != null) {
|
||||||
|
LodCommonMain.forge = true;
|
||||||
|
forgeMethodCaller = caller;
|
||||||
|
}
|
||||||
|
|
||||||
|
DependencySetup.createInitialBindings();
|
||||||
|
|
||||||
|
LodCommonMain.networkInterface = networkInterface;
|
||||||
|
if (!serverSided) {
|
||||||
|
networkInterface.register_Client();
|
||||||
|
} else {
|
||||||
|
networkInterface.register_Server();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void initConfig() {
|
||||||
|
ConfigGui.init(Config.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.seibel.lod.common.forge;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
|
||||||
|
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used for calling methods that forge modified
|
||||||
|
* (forge modifies vanilla methods for some reason)
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
public interface LodForgeMethodCaller {
|
||||||
|
List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random);
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.seibel.lod.common.networking;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is packet handler for our mod
|
||||||
|
* It basically handles the packets sent from the server & client
|
||||||
|
*
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
public class NetworkHandler {
|
||||||
|
// If you need the response sender then tell me
|
||||||
|
// I'll add extra code to get the response sender
|
||||||
|
public static void receivePacketClient(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf) {
|
||||||
|
// TODO: Server sided stuff here
|
||||||
|
// You can make client execute something by using client.execute(Runnable)
|
||||||
|
// In the fabric docs it says that client.execute is ran on the render thread?
|
||||||
|
}
|
||||||
|
|
||||||
|
// If you need the response sender then tell me
|
||||||
|
// I'll add extra code to get the response sender
|
||||||
|
public static void receivePacketServer(MinecraftServer server, ServerPlayer client, ServerGamePacketListenerImpl handler, FriendlyByteBuf buf) {
|
||||||
|
// TODO: Server sided stuff here
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package com.seibel.lod.common.networking;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
public interface NetworkInterface {
|
||||||
|
void register_Client();
|
||||||
|
void register_Server();
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package com.seibel.lod.common.networking;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.ModInfo;
|
||||||
|
import io.netty.buffer.Unpooled;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.network.protocol.Packet;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket;
|
||||||
|
import net.minecraft.network.protocol.game.ServerboundCustomPayloadPacket;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class holds most of the networking code for the mod.
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
public class Networking {
|
||||||
|
public static final ResourceLocation resourceLocation_meow = new ResourceLocation("lod", "meow");
|
||||||
|
|
||||||
|
public static FriendlyByteBuf createNew() {
|
||||||
|
// TODO: Probably replace the Unpooled.buffer()
|
||||||
|
FriendlyByteBuf buf = new FriendlyByteBuf(Unpooled.buffer());
|
||||||
|
buf.writeInt(ModInfo.PROTOCOL_VERSION);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* All code below is from the fabric api and might have been modified to work with Distant Horizons
|
||||||
|
* Which is licensed under the Apache License 2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a packet to a player.
|
||||||
|
*
|
||||||
|
* @param player the player to send the packet to
|
||||||
|
* @param buf the payload of the packet.
|
||||||
|
*/
|
||||||
|
public static void send(ServerPlayer player, FriendlyByteBuf buf) {
|
||||||
|
Objects.requireNonNull(player, "Server player entity cannot be null");
|
||||||
|
Objects.requireNonNull(resourceLocation_meow, "Channel name cannot be null");
|
||||||
|
Objects.requireNonNull(buf, "Packet byte buf cannot be null");
|
||||||
|
|
||||||
|
player.connection.send(createS2CPacket(resourceLocation_meow, buf));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a packet to the connected server.
|
||||||
|
*
|
||||||
|
* @param buf the payload of the packet
|
||||||
|
* @throws IllegalStateException if the client is not connected to a server
|
||||||
|
*/
|
||||||
|
public static void send(FriendlyByteBuf buf) throws IllegalStateException {
|
||||||
|
// You cant send without a client player, so this is fine
|
||||||
|
if (Minecraft.getInstance().getConnection() != null) {
|
||||||
|
Minecraft.getInstance().getConnection().send(createC2SPacket(resourceLocation_meow, buf));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Cannot send packets when not in game!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a packet which may be sent to the connected client.
|
||||||
|
*
|
||||||
|
* @param channelName the channel name
|
||||||
|
* @param buf the packet byte buf which represents the payload of the packet
|
||||||
|
* @return a new packet
|
||||||
|
*/
|
||||||
|
public static Packet<?> createS2CPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
|
||||||
|
Objects.requireNonNull(channelName, "Channel cannot be null");
|
||||||
|
Objects.requireNonNull(buf, "Buf cannot be null");
|
||||||
|
|
||||||
|
return createPlayS2CPacket(channelName, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Packet<?> createPlayS2CPacket(ResourceLocation channel, FriendlyByteBuf buf) {
|
||||||
|
return new ClientboundCustomPayloadPacket(channel, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a packet which may be sent to a the connected server.
|
||||||
|
*
|
||||||
|
* @param channelName the channel name
|
||||||
|
* @param buf the packet byte buf which represents the payload of the packet
|
||||||
|
* @return a new packet
|
||||||
|
*/
|
||||||
|
public static Packet<?> createC2SPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
|
||||||
|
Objects.requireNonNull(channelName, "Channel name cannot be null");
|
||||||
|
Objects.requireNonNull(buf, "Buf cannot be null");
|
||||||
|
|
||||||
|
return createPlayC2SPacket(channelName, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Packet<?> createPlayC2SPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
|
||||||
|
return new ServerboundCustomPayloadPacket(channelName, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
package com.seibel.lod.common.wrappers;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.LodCommonMain;
|
||||||
|
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.minecraft.MinecraftRenderWrapper;
|
||||||
|
import com.seibel.lod.core.handlers.IReflectionHandler;
|
||||||
|
import com.seibel.lod.core.handlers.ReflectionHandler;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @author Ran
|
||||||
|
* @version 12-1-2021
|
||||||
|
*/
|
||||||
|
public class DependencySetup {
|
||||||
|
public static void createInitialBindings()
|
||||||
|
{
|
||||||
|
SingletonHandler.bind(IVersionConstants.class, VersionConstants.INSTANCE);
|
||||||
|
if (!LodCommonMain.serverSided)
|
||||||
|
{
|
||||||
|
SingletonHandler.bind(IMinecraftClientWrapper.class, MinecraftClientWrapper.INSTANCE);
|
||||||
|
SingletonHandler.bind(IMinecraftRenderWrapper.class, MinecraftRenderWrapper.INSTANCE);
|
||||||
|
SingletonHandler.bind(IReflectionHandler.class, ReflectionHandler.createSingleton(MinecraftClientWrapper.INSTANCE.getOptions().getClass().getDeclaredFields(), MinecraftClientWrapper.INSTANCE.getOptions()));
|
||||||
|
}
|
||||||
|
|
||||||
|
SingletonHandler.bind(IWrapperFactory.class, WrapperFactory.INSTANCE);
|
||||||
|
DependencySetupDoneCheck.isDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.seibel.lod.common.wrappers;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class DependencySetupDoneCheck
|
||||||
|
{
|
||||||
|
public static boolean isDone = false;
|
||||||
|
public static Supplier<Boolean> getIsCurrentThreadDistantGeneratorThread = (() -> {return false;});
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.common.wrappers;
|
||||||
|
|
||||||
|
import java.nio.FloatBuffer;
|
||||||
|
|
||||||
|
import com.mojang.math.Matrix4f;
|
||||||
|
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
|
||||||
|
import com.seibel.lod.core.enums.LodDirection;
|
||||||
|
import com.seibel.lod.core.objects.math.Mat4f;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static final Direction[] directions;
|
||||||
|
static final LodDirection[] lodDirections;
|
||||||
|
static {
|
||||||
|
LodDirection[] lodDirs = LodDirection.values();
|
||||||
|
directions = new Direction[lodDirs.length];
|
||||||
|
lodDirections = new LodDirection[lodDirs.length];
|
||||||
|
for (LodDirection lodDir : lodDirs) {
|
||||||
|
Direction dir = Direction.byName(lodDir.name());
|
||||||
|
directions[lodDir.ordinal()] = dir;
|
||||||
|
lodDirections[dir.ordinal()] = lodDir;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockPos Convert(AbstractBlockPosWrapper wrappedPos) {
|
||||||
|
return new BlockPos(wrappedPos.getX(),wrappedPos.getY(), wrappedPos.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static Direction Convert(LodDirection lodDirection)
|
||||||
|
{
|
||||||
|
return directions[lodDirection.ordinal()];
|
||||||
|
}
|
||||||
|
public static LodDirection Convert(Direction direction)
|
||||||
|
{
|
||||||
|
return lodDirections[direction.ordinal()];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
package com.seibel.lod.common.wrappers;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 12-11-2021
|
||||||
|
*/
|
||||||
|
public class VersionConstants implements IVersionConstants
|
||||||
|
{
|
||||||
|
public static final VersionConstants INSTANCE = new VersionConstants();
|
||||||
|
|
||||||
|
|
||||||
|
private VersionConstants()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinimumWorldHeight()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWorldGenerationCountPerThread()
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVanillaRenderedChunkSquare()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* 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.common.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.AbstractBatchGenerationEnvionmentWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.chunk.ChunkPosWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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(long xAndZPositionCombined)
|
||||||
|
{
|
||||||
|
return new ChunkPosWrapper(xAndZPositionCombined);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AbstractBatchGenerationEnvionmentWrapper createBatchGenerator(LodBuilder newLodBuilder,
|
||||||
|
LodDimension newLodDimension, IWorldWrapper worldWrapper)
|
||||||
|
{
|
||||||
|
return new BatchGenerationEnvironment(worldWrapper, newLodBuilder, newLodDimension);
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-21
@@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of the LOD Mod, licensed under the GNU GPL v3 License.
|
* 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
|
* Copyright (C) 2020 James Seibel
|
||||||
*
|
*
|
||||||
@@ -15,29 +16,19 @@
|
|||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
package com.seibel.lod.enums;
|
|
||||||
|
package com.seibel.lod.common.wrappers;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NE, SE, SW, NW
|
* Stores any variables or code that
|
||||||
|
* may be shared between wrapper objects.
|
||||||
*
|
*
|
||||||
* @author James Seibel
|
* @author James Seibel
|
||||||
* @version 1-20-2020
|
* @version 11-20-2021
|
||||||
*/
|
*/
|
||||||
public enum LodCorner
|
public class WrapperUtil {
|
||||||
{
|
/** If we ever need to use a heightmap for any reason, use this one. */
|
||||||
/** -Z, +X */
|
public static final Heightmap.Types DEFAULT_HEIGHTMAP = Heightmap.Types.WORLD_SURFACE_WG;
|
||||||
NE(0),
|
|
||||||
/** +Z, +X */
|
|
||||||
SE(1),
|
|
||||||
/** +Z, -X */
|
|
||||||
SW(2),
|
|
||||||
/** -Z, -X */
|
|
||||||
NW(3);
|
|
||||||
|
|
||||||
public final int value;
|
|
||||||
|
|
||||||
private LodCorner(int newValue)
|
|
||||||
{
|
|
||||||
value = newValue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.block;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.world.level.LevelReader;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
|
||||||
|
public class BlockDetailMap
|
||||||
|
{
|
||||||
|
|
||||||
|
private static ConcurrentHashMap<BlockState, BlockDetailWrapper> map = new ConcurrentHashMap<BlockState, BlockDetailWrapper>();
|
||||||
|
|
||||||
|
private BlockDetailMap() {}
|
||||||
|
|
||||||
|
public static BlockDetailWrapper getOrMakeBlockDetailCache(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||||
|
BlockDetailWrapper cache = map.get(bs);
|
||||||
|
if (cache != null) return cache;
|
||||||
|
if (bs.getFluidState().isEmpty()) {
|
||||||
|
cache = BlockDetailWrapper.make(bs, pos, getter);
|
||||||
|
} else {
|
||||||
|
cache = BlockDetailWrapper.make(bs.getFluidState().createLegacyBlock(), pos, getter);
|
||||||
|
}
|
||||||
|
BlockDetailWrapper cacheCAS = map.putIfAbsent(bs, cache);
|
||||||
|
return cacheCAS==null ? cache : cacheCAS;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,315 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.block;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.Config;
|
||||||
|
import com.seibel.lod.common.wrappers.McObjectConverter;
|
||||||
|
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
import com.seibel.lod.core.api.ApiShared;
|
||||||
|
import com.seibel.lod.core.enums.LodDirection;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.util.ColorUtil;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||||
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.color.block.BlockTintCache;
|
||||||
|
import net.minecraft.client.renderer.BiomeColors;
|
||||||
|
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Cursor3D;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.*;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.FlowerBlock;
|
||||||
|
import net.minecraft.world.level.block.LeavesBlock;
|
||||||
|
import net.minecraft.world.level.block.RenderShape;
|
||||||
|
import net.minecraft.world.level.block.RotatedPillarBlock;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
public class BlockDetailWrapper extends IBlockDetailWrapper
|
||||||
|
{
|
||||||
|
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||||
|
|
||||||
|
public static final int FLOWER_COLOR_SCALE = 5;
|
||||||
|
|
||||||
|
public static final Random random = new Random(0);
|
||||||
|
|
||||||
|
enum ColorMode {
|
||||||
|
Default,
|
||||||
|
Flower,
|
||||||
|
Leaves;
|
||||||
|
static ColorMode getColorMode(Block b) {
|
||||||
|
if (b instanceof LeavesBlock) return Leaves;
|
||||||
|
if (b instanceof FlowerBlock) return Flower;
|
||||||
|
return Default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//TODO: Perhaps make this not just use the first frame?
|
||||||
|
private static int calculateColorFromTexture(TextureAtlasSprite texture, ColorMode colorMode) {
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
double alpha = 0;
|
||||||
|
double red = 0;
|
||||||
|
double green = 0;
|
||||||
|
double blue = 0;
|
||||||
|
int tempColor;
|
||||||
|
|
||||||
|
{
|
||||||
|
// 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++)
|
||||||
|
{
|
||||||
|
//note: Minecraft color format is: 0xAA BB GG RR
|
||||||
|
//________ DH mod color format is: 0xAA RR GG BB
|
||||||
|
//OpenGL RGBA format native order: 0xRR GG BB AA
|
||||||
|
//_ OpenGL RGBA format Java Order: 0xAA BB GG RR
|
||||||
|
tempColor = TextureAtlasSpriteWrapper.getPixelRGBA(texture, 0, u, v);
|
||||||
|
|
||||||
|
double r = ((tempColor & 0x000000FF) )/255.;
|
||||||
|
double g = ((tempColor & 0x0000FF00) >>> 8)/255.;
|
||||||
|
double b = ((tempColor & 0x00FF0000) >>> 16)/255.;
|
||||||
|
double a = ((tempColor & 0xFF000000) >>> 24)/255.;
|
||||||
|
int scale = 1;
|
||||||
|
|
||||||
|
if (colorMode == ColorMode.Leaves) {
|
||||||
|
r *= a;
|
||||||
|
g *= a;
|
||||||
|
b *= a;
|
||||||
|
a = 1.;
|
||||||
|
} else if (a==0.) {
|
||||||
|
continue;
|
||||||
|
} else if (colorMode == ColorMode.Flower && (g+0.1<b || g+0.1<r)) {
|
||||||
|
scale = FLOWER_COLOR_SCALE;
|
||||||
|
}
|
||||||
|
|
||||||
|
count += scale;
|
||||||
|
alpha += a*a*scale;
|
||||||
|
red += r*r*scale;
|
||||||
|
green += g*g*scale;
|
||||||
|
blue += b*b*scale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
// this block is entirely transparent
|
||||||
|
tempColor = ColorUtil.rgbToInt(255,255,0,255);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// determine the average color
|
||||||
|
tempColor = ColorUtil.rgbToInt(
|
||||||
|
(int) (Math.sqrt(alpha/count)*255.),
|
||||||
|
(int) (Math.sqrt(red / count)*255.),
|
||||||
|
(int) (Math.sqrt(green / count)*255.),
|
||||||
|
(int) (Math.sqrt(blue / count)*255.));
|
||||||
|
}
|
||||||
|
// TODO: Remove this when transparency is added!
|
||||||
|
double colorAlpha = ColorUtil.getAlpha(tempColor)/255.;
|
||||||
|
tempColor = ColorUtil.rgbToInt(
|
||||||
|
ColorUtil.getAlpha(tempColor),
|
||||||
|
(int)(ColorUtil.getRed(tempColor) * colorAlpha),
|
||||||
|
(int)(ColorUtil.getGreen(tempColor) * colorAlpha),
|
||||||
|
(int)(ColorUtil.getBlue(tempColor) * colorAlpha)
|
||||||
|
);
|
||||||
|
return tempColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private static final Block[] BLOCK_TO_AVOID = {Blocks.AIR, Blocks.CAVE_AIR, Blocks.BARRIER};
|
||||||
|
|
||||||
|
private static final Direction[] DIRECTION_ORDER = {Direction.UP, Direction.NORTH, Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.DOWN};
|
||||||
|
|
||||||
|
private static boolean isBlockToBeAvoid(Block b) {
|
||||||
|
for (Block bta : BLOCK_TO_AVOID)
|
||||||
|
if (bta==b) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final BlockState state;
|
||||||
|
final BlockPos samplePos;
|
||||||
|
final LevelReader sampleGetter;
|
||||||
|
|
||||||
|
boolean isShapeResolved = false;
|
||||||
|
boolean[] dontOccludeFaces = null;
|
||||||
|
boolean noCollision = false;
|
||||||
|
boolean noFullFace = false;
|
||||||
|
|
||||||
|
boolean isColorResolved = false;
|
||||||
|
int baseColor = 0; //TODO: Impl per-face color
|
||||||
|
boolean needShade = true;
|
||||||
|
boolean needPostTinting = false;
|
||||||
|
int tintIndex = 0;
|
||||||
|
|
||||||
|
public static BlockDetailWrapper NULL_BLOCK_DETAIL = new BlockDetailWrapper();
|
||||||
|
|
||||||
|
public BlockDetailWrapper(BlockState state, BlockPos pos, LevelReader getter) {
|
||||||
|
this.state = state;
|
||||||
|
this.samplePos = pos;
|
||||||
|
this.sampleGetter = getter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockDetailWrapper() {
|
||||||
|
this.state = null;
|
||||||
|
this.samplePos = null;
|
||||||
|
this.sampleGetter = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static BlockDetailWrapper make(BlockState bs, BlockPos pos, LevelReader getter) {
|
||||||
|
if(!bs.getFluidState().isEmpty()) { // Is a fluidBlock
|
||||||
|
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
|
||||||
|
if (bs.isAir()) return NULL_BLOCK_DETAIL;
|
||||||
|
return new BlockDetailWrapper(bs, pos, getter);
|
||||||
|
} else {
|
||||||
|
if (bs.getRenderShape() != RenderShape.MODEL) return NULL_BLOCK_DETAIL;
|
||||||
|
if (isBlockToBeAvoid(bs.getBlock())) return NULL_BLOCK_DETAIL;
|
||||||
|
return new BlockDetailWrapper(bs, pos, getter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resolveShapes() {
|
||||||
|
if (isShapeResolved) return;
|
||||||
|
if (state.getFluidState().isEmpty()) {
|
||||||
|
noCollision = state.getCollisionShape(sampleGetter, samplePos).isEmpty();
|
||||||
|
dontOccludeFaces = new boolean[6];
|
||||||
|
if (state.canOcclude()) {
|
||||||
|
/* FIXME: Figure out how or if needed to impl per-face culling?
|
||||||
|
for (Direction dir : Direction.values()) {
|
||||||
|
dontOccludeFaces[McObjectConverter.Convert(dir).ordinal()]
|
||||||
|
= state.getFaceOcclusionShape(sampleGetter, samplePos, dir).isEmpty();
|
||||||
|
}*/
|
||||||
|
} else {
|
||||||
|
Arrays.fill(dontOccludeFaces, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
VoxelShape voxelShape = state.getShape(sampleGetter, samplePos);
|
||||||
|
if (voxelShape.isEmpty()) {
|
||||||
|
noFullFace = true;
|
||||||
|
} else {
|
||||||
|
AABB bbox = voxelShape.bounds();
|
||||||
|
double xWidth = (bbox.maxX - bbox.minX);
|
||||||
|
double yWidth = (bbox.maxY - bbox.minY);
|
||||||
|
double zWidth = (bbox.maxZ - bbox.minZ);
|
||||||
|
noFullFace = xWidth < 1 && zWidth < 1 && yWidth < 1;
|
||||||
|
}
|
||||||
|
} else { // Liquid Block
|
||||||
|
dontOccludeFaces = new boolean[6];
|
||||||
|
}
|
||||||
|
isShapeResolved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void resolveColors() {
|
||||||
|
if (isColorResolved) return;
|
||||||
|
if (state.getFluidState().isEmpty()) {
|
||||||
|
List<BakedQuad> quads = null;
|
||||||
|
for (Direction direction : DIRECTION_ORDER)
|
||||||
|
{
|
||||||
|
quads = Minecraft.getInstance().getModelManager().getBlockModelShaper().
|
||||||
|
getBlockModel(state).getQuads(state, direction, random);
|
||||||
|
if (!quads.isEmpty() &&
|
||||||
|
!(state.getBlock() instanceof RotatedPillarBlock && direction == Direction.UP))
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if (quads != null && !quads.isEmpty()) {
|
||||||
|
needPostTinting = quads.get(0).isTinted();
|
||||||
|
needShade = quads.get(0).isShade();
|
||||||
|
tintIndex = quads.get(0).getTintIndex();
|
||||||
|
baseColor = calculateColorFromTexture(quads.get(0).getSprite(),
|
||||||
|
ColorMode.getColorMode(state.getBlock()));
|
||||||
|
}
|
||||||
|
} else { // Liquid Block
|
||||||
|
|
||||||
|
needPostTinting = true;
|
||||||
|
needShade = false;
|
||||||
|
tintIndex = 0;
|
||||||
|
baseColor = calculateColorFromTexture(Minecraft.getInstance().getModelManager().getBlockModelShaper().getParticleIcon(state),
|
||||||
|
ColorMode.getColorMode(state.getBlock()));
|
||||||
|
|
||||||
|
}
|
||||||
|
isColorResolved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private BlockAndTintGetter wrapColorResolver(LevelReader level) {
|
||||||
|
int blendDistance = CONFIG.client().graphics().quality().getLodBiomeBlending();
|
||||||
|
if (blendDistance == 0) {
|
||||||
|
return new TintGetterOverrideFast(level);
|
||||||
|
} else {
|
||||||
|
return new TintGetterOverrideSmooth(level, blendDistance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAndResolveFaceColor(LodDirection dir, IChunkWrapper chunk, AbstractBlockPosWrapper blockPos)
|
||||||
|
{
|
||||||
|
// FIXME: impl per-face colors
|
||||||
|
resolveColors();
|
||||||
|
if (!needPostTinting) return baseColor;
|
||||||
|
int tintColor = Minecraft.getInstance().getBlockColors()
|
||||||
|
.getColor(state, wrapColorResolver(((ChunkWrapper)chunk).getColorResolver()),
|
||||||
|
McObjectConverter.Convert(blockPos), tintIndex);
|
||||||
|
if (tintColor == -1) return baseColor;
|
||||||
|
return ColorUtil.multiplyARGBwithRGB(baseColor, tintColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasFaceCullingFor(LodDirection dir)
|
||||||
|
{
|
||||||
|
resolveShapes();
|
||||||
|
return !dontOccludeFaces[dir.ordinal()];
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNoCollision()
|
||||||
|
{
|
||||||
|
resolveShapes();
|
||||||
|
return noCollision;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean noFaceIsFullFace()
|
||||||
|
{
|
||||||
|
resolveShapes();
|
||||||
|
return noFullFace;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String serialize()
|
||||||
|
{
|
||||||
|
// FIXME: Impl this for the blockState Storage stuff
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected boolean isSame(IBlockDetailWrapper iBlockDetail)
|
||||||
|
{
|
||||||
|
return ((BlockDetailWrapper)iBlockDetail).state.getBlock().equals(state.getBlock());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.block;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.enums.LodDirection;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 11-21-2021
|
||||||
|
*/
|
||||||
|
public class BlockPosWrapper extends AbstractBlockPosWrapper
|
||||||
|
{
|
||||||
|
private final BlockPos.MutableBlockPos blockPos;
|
||||||
|
|
||||||
|
|
||||||
|
public BlockPosWrapper()
|
||||||
|
{
|
||||||
|
this.blockPos = new BlockPos.MutableBlockPos(0,0,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
public BlockPosWrapper(int x, int y, int z)
|
||||||
|
{
|
||||||
|
this.blockPos = new BlockPos.MutableBlockPos(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.MutableBlockPos 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.block;
|
||||||
|
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For wrapping/utilizing around TextureAtlasSprite
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
public class TextureAtlasSpriteWrapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This code is from Minecraft Forge
|
||||||
|
* Which is licensed under the terms of GNU Lesser General Public License
|
||||||
|
* as published by the Free Software Foundation version 2.1
|
||||||
|
* of the License.
|
||||||
|
*
|
||||||
|
* The code has been modified to use TextureAtlasSprite
|
||||||
|
*/
|
||||||
|
public static int getPixelRGBA(TextureAtlasSprite sprite, int frameIndex, int x, int y) {
|
||||||
|
if (sprite.animatedTexture != null) {
|
||||||
|
x += sprite.animatedTexture.getFrameX(frameIndex) * sprite.width;
|
||||||
|
y += sprite.animatedTexture.getFrameY(frameIndex) * sprite.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sprite.mainImage[0].getPixelRGBA(x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
+196
@@ -0,0 +1,196 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.block;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||||
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.client.color.block.BlockTintCache;
|
||||||
|
import net.minecraft.client.renderer.BiomeColors;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Cursor3D;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.*;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class TintGetterOverrideFast implements BlockAndTintGetter {
|
||||||
|
LevelReader parent;
|
||||||
|
private final Object2ObjectArrayMap<ColorResolver, ConcurrentHashMap<Biome, Integer>> tintCaches;
|
||||||
|
|
||||||
|
public TintGetterOverrideFast(LevelReader parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
|
||||||
|
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
|
||||||
|
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
|
||||||
|
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new ConcurrentHashMap<Biome, Integer>());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Biome _getBiome(BlockPos pos) {
|
||||||
|
#if MC_VERSION_1_18_2
|
||||||
|
return parent.getBiome(pos).value();
|
||||||
|
#elif MC_VERSION_1_18_1
|
||||||
|
return parent.getBiome(pos);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
|
||||||
|
Biome b = _getBiome(blockPos);
|
||||||
|
return tintCaches.get(colorResolver).computeIfAbsent(b, (key) -> colorResolver.getColor(b, blockPos.getX(), blockPos.getZ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getShade(Direction direction, boolean bl) {
|
||||||
|
return parent.getShade(direction, bl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LevelLightEngine getLightEngine() {
|
||||||
|
return parent.getLightEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
|
||||||
|
return parent.getBrightness(lightLayer, blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawBrightness(BlockPos blockPos, int i) {
|
||||||
|
return parent.getRawBrightness(blockPos, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canSeeSky(BlockPos blockPos) {
|
||||||
|
return parent.canSeeSky(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public BlockEntity getBlockEntity(BlockPos blockPos) {
|
||||||
|
return parent.getBlockEntity(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType) {
|
||||||
|
return parent.getBlockEntity(blockPos, blockEntityType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getBlockState(BlockPos blockPos) {
|
||||||
|
return parent.getBlockState(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FluidState getFluidState(BlockPos blockPos) {
|
||||||
|
return parent.getFluidState(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLightEmission(BlockPos blockPos) {
|
||||||
|
return parent.getLightEmission(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxLightLevel() {
|
||||||
|
return parent.getMaxLightLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<BlockState> getBlockStates(AABB aABB) {
|
||||||
|
return parent.getBlockStates(aABB);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext) {
|
||||||
|
return parent.isBlockInLine(clipBlockStateContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockHitResult clip(ClipContext clipContext) {
|
||||||
|
return parent.clip(clipContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState) {
|
||||||
|
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier) {
|
||||||
|
return parent.getBlockFloorHeight(voxelShape, supplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBlockFloorHeight(BlockPos blockPos) {
|
||||||
|
return parent.getBlockFloorHeight(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return parent.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinBuildHeight() {
|
||||||
|
return parent.getMinBuildHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxBuildHeight() {
|
||||||
|
return parent.getMaxBuildHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionsCount() {
|
||||||
|
return parent.getSectionsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinSection() {
|
||||||
|
return parent.getMinSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxSection() {
|
||||||
|
return parent.getMaxSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOutsideBuildHeight(BlockPos blockPos) {
|
||||||
|
return parent.isOutsideBuildHeight(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOutsideBuildHeight(int i) {
|
||||||
|
return parent.isOutsideBuildHeight(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionIndex(int i) {
|
||||||
|
return parent.getSectionIndex(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionIndexFromSectionY(int i) {
|
||||||
|
return parent.getSectionIndexFromSectionY(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionYFromSectionIndex(int i) {
|
||||||
|
return parent.getSectionYFromSectionIndex(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
+219
@@ -0,0 +1,219 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.block;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||||
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.client.color.block.BlockTintCache;
|
||||||
|
import net.minecraft.client.renderer.BiomeColors;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Cursor3D;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.*;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
import net.minecraft.world.level.material.FluidState;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.BlockHitResult;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class TintGetterOverrideSmooth implements BlockAndTintGetter {
|
||||||
|
LevelReader parent;
|
||||||
|
private final Object2ObjectArrayMap<ColorResolver, BlockTintCache> tintCaches;
|
||||||
|
public int smoothingRange;
|
||||||
|
|
||||||
|
public TintGetterOverrideSmooth(LevelReader parent, int smoothingRange) {
|
||||||
|
this.parent = parent;
|
||||||
|
this.smoothingRange = smoothingRange;
|
||||||
|
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
|
||||||
|
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.GRASS_COLOR_RESOLVER)));
|
||||||
|
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.FOLIAGE_COLOR_RESOLVER)));
|
||||||
|
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache((pos) -> calculateBlockTint(pos, BiomeColors.WATER_COLOR_RESOLVER)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private Biome _getBiome(BlockPos pos) {
|
||||||
|
#if MC_VERSION_1_18_2
|
||||||
|
return parent.getBiome(pos).value();
|
||||||
|
#elif MC_VERSION_1_18_1
|
||||||
|
return parent.getBiome(pos);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
||||||
|
{
|
||||||
|
int i = smoothingRange;
|
||||||
|
if (i == 0)
|
||||||
|
return colorResolver.getColor(_getBiome(blockPos), blockPos.getX(), blockPos.getZ());
|
||||||
|
int j = (i * 2 + 1) * (i * 2 + 1);
|
||||||
|
int k = 0;
|
||||||
|
int l = 0;
|
||||||
|
int m = 0;
|
||||||
|
Cursor3D cursor3D = new Cursor3D(blockPos.getX() - i, blockPos.getY(), blockPos.getZ() - i, blockPos.getX() + i, blockPos.getY(), blockPos.getZ() + i);
|
||||||
|
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
||||||
|
while (cursor3D.advance())
|
||||||
|
{
|
||||||
|
mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
|
||||||
|
int n = colorResolver.getColor(_getBiome(mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
|
||||||
|
k += (n & 0xFF0000) >> 16;
|
||||||
|
l += (n & 0xFF00) >> 8;
|
||||||
|
m += n & 0xFF;
|
||||||
|
}
|
||||||
|
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver) {
|
||||||
|
BlockTintCache blockTintCache = this.tintCaches.get(colorResolver);
|
||||||
|
return blockTintCache.getColor(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public float getShade(Direction direction, boolean bl) {
|
||||||
|
return parent.getShade(direction, bl);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LevelLightEngine getLightEngine() {
|
||||||
|
return parent.getLightEngine();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
|
||||||
|
return parent.getBrightness(lightLayer, blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawBrightness(BlockPos blockPos, int i) {
|
||||||
|
return parent.getRawBrightness(blockPos, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canSeeSky(BlockPos blockPos) {
|
||||||
|
return parent.canSeeSky(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public BlockEntity getBlockEntity(BlockPos blockPos) {
|
||||||
|
return parent.getBlockEntity(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <T extends BlockEntity> Optional<T> getBlockEntity(BlockPos blockPos, BlockEntityType<T> blockEntityType) {
|
||||||
|
return parent.getBlockEntity(blockPos, blockEntityType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockState getBlockState(BlockPos blockPos) {
|
||||||
|
return parent.getBlockState(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FluidState getFluidState(BlockPos blockPos) {
|
||||||
|
return parent.getFluidState(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLightEmission(BlockPos blockPos) {
|
||||||
|
return parent.getLightEmission(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxLightLevel() {
|
||||||
|
return parent.getMaxLightLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<BlockState> getBlockStates(AABB aABB) {
|
||||||
|
return parent.getBlockStates(aABB);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockHitResult isBlockInLine(ClipBlockStateContext clipBlockStateContext) {
|
||||||
|
return parent.isBlockInLine(clipBlockStateContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockHitResult clip(ClipContext clipContext) {
|
||||||
|
return parent.clip(clipContext);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public BlockHitResult clipWithInteractionOverride(Vec3 vec3, Vec3 vec32, BlockPos blockPos, VoxelShape voxelShape, BlockState blockState) {
|
||||||
|
return parent.clipWithInteractionOverride(vec3, vec32, blockPos, voxelShape, blockState);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBlockFloorHeight(VoxelShape voxelShape, Supplier<VoxelShape> supplier) {
|
||||||
|
return parent.getBlockFloorHeight(voxelShape, supplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBlockFloorHeight(BlockPos blockPos) {
|
||||||
|
return parent.getBlockFloorHeight(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return parent.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinBuildHeight() {
|
||||||
|
return parent.getMinBuildHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxBuildHeight() {
|
||||||
|
return parent.getMaxBuildHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionsCount() {
|
||||||
|
return parent.getSectionsCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinSection() {
|
||||||
|
return parent.getMinSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxSection() {
|
||||||
|
return parent.getMaxSection();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOutsideBuildHeight(BlockPos blockPos) {
|
||||||
|
return parent.isOutsideBuildHeight(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isOutsideBuildHeight(int i) {
|
||||||
|
return parent.isOutsideBuildHeight(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionIndex(int i) {
|
||||||
|
return parent.getSectionIndex(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionIndexFromSectionY(int i) {
|
||||||
|
return parent.getSectionIndexFromSectionY(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSectionYFromSectionIndex(int i) {
|
||||||
|
return parent.getSectionYFromSectionIndex(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.chunk;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.util.LevelPosUtil;
|
||||||
|
import com.seibel.lod.core.util.LodUtil;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 11-21-2021
|
||||||
|
*/
|
||||||
|
public class ChunkPosWrapper extends AbstractChunkPosWrapper
|
||||||
|
{
|
||||||
|
private final net.minecraft.world.level.ChunkPos chunkPos;
|
||||||
|
|
||||||
|
public ChunkPosWrapper()
|
||||||
|
{
|
||||||
|
this.chunkPos = new ChunkPos(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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(long l) {
|
||||||
|
this.chunkPos = new ChunkPos(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ChunkPosWrapper(ChunkPos pos)
|
||||||
|
{
|
||||||
|
this.chunkPos = pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@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 LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.x, LodUtil.REGION_DETAIL_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRegionZ()
|
||||||
|
{
|
||||||
|
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunkPos.z, LodUtil.REGION_DETAIL_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLong() {
|
||||||
|
return chunkPos.toLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkPos getChunkPos()
|
||||||
|
{
|
||||||
|
return chunkPos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o)
|
||||||
|
{
|
||||||
|
// If the object is compared with itself then return true
|
||||||
|
if (o == this) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// Check if o is an instance of RegionPos or not
|
||||||
|
if (!(o instanceof ChunkPosWrapper)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ChunkPosWrapper c = (ChunkPosWrapper) o;
|
||||||
|
return c.chunkPos.equals(chunkPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode()
|
||||||
|
{
|
||||||
|
return Objects.hash(chunkPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractBlockPosWrapper getWorldPosition()
|
||||||
|
{
|
||||||
|
// the parameter here is the y position
|
||||||
|
BlockPos blockPos = chunkPos.getMiddleBlockPosition(0);
|
||||||
|
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,208 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.chunk;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.block.BlockDetailWrapper;
|
||||||
|
import com.seibel.lod.core.enums.LodDirection;
|
||||||
|
import com.seibel.lod.core.util.LevelPosUtil;
|
||||||
|
import com.seibel.lod.core.util.LodUtil;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.WrapperUtil;
|
||||||
|
import com.seibel.lod.common.wrappers.block.BlockDetailMap;
|
||||||
|
import com.seibel.lod.common.wrappers.world.BiomeWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.QuartPos;
|
||||||
|
import net.minecraft.world.level.LevelReader;
|
||||||
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
import net.minecraft.world.level.block.LiquidBlockContainer;
|
||||||
|
import net.minecraft.world.level.block.SimpleWaterloggedBlock;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 3-5-2022
|
||||||
|
*/
|
||||||
|
public class ChunkWrapper implements IChunkWrapper
|
||||||
|
{
|
||||||
|
private final ChunkAccess chunk;
|
||||||
|
private final LevelReader lightSource;
|
||||||
|
|
||||||
|
|
||||||
|
public ChunkWrapper(ChunkAccess chunk, LevelReader lightSource)
|
||||||
|
{
|
||||||
|
this.chunk = chunk;
|
||||||
|
this.lightSource = lightSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight(){
|
||||||
|
return chunk.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMinBuildHeight()
|
||||||
|
{
|
||||||
|
return chunk.getMinBuildHeight();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getMaxBuildHeight()
|
||||||
|
{
|
||||||
|
return chunk.getMaxBuildHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeightMapValue(int xRel, int zRel)
|
||||||
|
{
|
||||||
|
return chunk.getOrCreateHeightmapUnprimed(WrapperUtil.DEFAULT_HEIGHTMAP).getFirstAvailable(xRel, zRel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBiomeWrapper getBiome(int x, int y, int z)
|
||||||
|
{
|
||||||
|
#if MC_VERSION_1_18_2
|
||||||
|
return BiomeWrapper.getBiomeWrapper(chunk.getNoiseBiome(
|
||||||
|
QuartPos.fromBlock(x), QuartPos.fromBlock(y), QuartPos.fromBlock(z)).value());
|
||||||
|
#elif MC_VERSION_1_18_1
|
||||||
|
return BiomeWrapper.getBiomeWrapper(chunk.getNoiseBiome(
|
||||||
|
QuartPos.fromBlock(x), QuartPos.fromBlock(y), QuartPos.fromBlock(z)));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBlockDetailWrapper getBlockDetail(int x, int y, int z) {
|
||||||
|
BlockPos pos = new BlockPos(x,y,z);
|
||||||
|
BlockState blockState = chunk.getBlockState(pos);
|
||||||
|
IBlockDetailWrapper blockDetail = BlockDetailMap.getOrMakeBlockDetailCache(blockState, pos, lightSource);
|
||||||
|
return blockDetail == BlockDetailWrapper.NULL_BLOCK_DETAIL ? null : blockDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBlockDetailWrapper getBlockDetailAtFace(int x, int y, int z, LodDirection dir) {
|
||||||
|
int fy = y+dir.getNormal().y;
|
||||||
|
if (fy < getMinBuildHeight() || fy > getMaxBuildHeight()) return null;
|
||||||
|
BlockPos pos = new BlockPos(x+dir.getNormal().x,fy,z+dir.getNormal().z);
|
||||||
|
BlockState blockState;
|
||||||
|
if (blockPosInsideChunk(x,y,z))
|
||||||
|
blockState = chunk.getBlockState(pos);
|
||||||
|
else {
|
||||||
|
blockState = lightSource.getBlockState(pos);
|
||||||
|
}
|
||||||
|
if (blockState == null || blockState.isAir()) return null;
|
||||||
|
IBlockDetailWrapper blockDetail = BlockDetailMap.getOrMakeBlockDetailCache(blockState, pos, lightSource);
|
||||||
|
return blockDetail == BlockDetailWrapper.NULL_BLOCK_DETAIL ? null : blockDetail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChunkAccess getChunk() {
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChunkPosX(){
|
||||||
|
return chunk.getPos().x;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getChunkPosZ(){
|
||||||
|
return chunk.getPos().z;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRegionPosX(){
|
||||||
|
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().x, LodUtil.REGION_DETAIL_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRegionPosZ(){
|
||||||
|
return LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, chunk.getPos().z, LodUtil.REGION_DETAIL_LEVEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxY(int x, int z) {
|
||||||
|
return chunk.getHeight(Heightmap.Types.MOTION_BLOCKING, Math.floorMod(x, 16), Math.floorMod(z, 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxX(){
|
||||||
|
return chunk.getPos().getMaxBlockX();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getMaxZ(){
|
||||||
|
return chunk.getPos().getMaxBlockZ();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getMinX(){
|
||||||
|
return chunk.getPos().getMinBlockX();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getMinZ() {
|
||||||
|
return chunk.getPos().getMinBlockZ();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getLongChunkPos() {
|
||||||
|
return chunk.getPos().toLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLightCorrect(){
|
||||||
|
//return true;
|
||||||
|
if (chunk instanceof LevelChunk) {
|
||||||
|
return ((LevelChunk) chunk).isClientLightReady();
|
||||||
|
}
|
||||||
|
return chunk.isLightCorrect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWaterLogged(int x, int y, int z)
|
||||||
|
{
|
||||||
|
BlockState blockState = chunk.getBlockState(new BlockPos(x,y,z));
|
||||||
|
|
||||||
|
//This type of block is always in water
|
||||||
|
return (!(blockState.getBlock() instanceof LiquidBlockContainer) && (blockState.getBlock() instanceof SimpleWaterloggedBlock))
|
||||||
|
&& (blockState.hasProperty(BlockStateProperties.WATERLOGGED) && blockState.getValue(BlockStateProperties.WATERLOGGED));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEmittedBrightness(int x, int y, int z)
|
||||||
|
{
|
||||||
|
return chunk.getLightEmission(new BlockPos(x,y,z));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getBlockLight(int x, int y, int z) {
|
||||||
|
if (lightSource == null) return -1;
|
||||||
|
return lightSource.getBrightness(LightLayer.BLOCK, new BlockPos(x,y,z));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSkyLight(int x, int y, int z) {
|
||||||
|
if (lightSource == null) return -1;
|
||||||
|
return lightSource.getBrightness(LightLayer.SKY, new BlockPos(x,y,z));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doesNearbyChunksExist() {
|
||||||
|
if (lightSource instanceof LightedWorldGenRegion) return true;
|
||||||
|
for (int dx = -1; dx <= 1; dx++) {
|
||||||
|
for (int dz = -1; dz <= 1; dz++) {
|
||||||
|
if (dx==0 && dz==0) continue;
|
||||||
|
if (lightSource.getChunk(dx+getChunkPosX(), dz+getChunkPosZ(), ChunkStatus.BIOMES, false) == null) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LevelReader getColorResolver()
|
||||||
|
{
|
||||||
|
return lightSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,762 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.config;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.AbstractMap;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
// Logger (for debug stuff)
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
// Uses https://github.com/TheElectronWill/night-config for toml (only for Fabric since Forge already includes this)
|
||||||
|
|
||||||
|
import com.electronwill.nightconfig.core.file.CommentedFileConfig;
|
||||||
|
|
||||||
|
// Gets info from our own mod
|
||||||
|
|
||||||
|
import com.seibel.lod.common.LodCommonMain;
|
||||||
|
import com.seibel.lod.core.ModInfo;
|
||||||
|
import com.seibel.lod.core.config.*;
|
||||||
|
|
||||||
|
// Minecraft imports
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import net.minecraft.ChatFormatting;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.Font;
|
||||||
|
import net.minecraft.client.gui.GuiComponent;
|
||||||
|
import net.minecraft.client.gui.components.AbstractWidget;
|
||||||
|
import net.minecraft.client.gui.components.Button;
|
||||||
|
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
|
||||||
|
import net.minecraft.client.gui.components.EditBox;
|
||||||
|
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||||
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraft.network.chat.CommonComponents;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.network.chat.TranslatableComponent;
|
||||||
|
import net.minecraft.client.resources.language.I18n; // translation
|
||||||
|
import net.minecraft.client.gui.narration.NarratableEntry; // Remove in 1.16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based upon TinyConfig
|
||||||
|
* https://github.com/Minenash/TinyConfig
|
||||||
|
*
|
||||||
|
* This config should work for both Fabric and Forge as long as you use Mojang mappings
|
||||||
|
*
|
||||||
|
* Credits to Motschen
|
||||||
|
*
|
||||||
|
* @author coolGi2007
|
||||||
|
* @version 1-14-2022
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public abstract class ConfigGui
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
TODO list
|
||||||
|
|
||||||
|
Fix floats not working
|
||||||
|
Make a wiki
|
||||||
|
Make it so you can enable and disable buttons from showing
|
||||||
|
Make min and max not final
|
||||||
|
Move the ConfigScreenConfigs class to the config class that extends this
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
List of hacky things that are done that should be done properly
|
||||||
|
|
||||||
|
The buttons that don't show are still loaded but just not rendered
|
||||||
|
The screen with is set to double so the scroll bar doesn't show
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
private static final Pattern INTEGER_ONLY_REGEX = Pattern.compile("(-?[0-9]*)");
|
||||||
|
private static final Pattern DECIMAL_ONLY_REGEX = Pattern.compile("-?([\\d]+\\.?[\\d]*|[\\d]*\\.?[\\d]+|\\.)");
|
||||||
|
|
||||||
|
private static final List<EntryInfo> entries = new ArrayList<>();
|
||||||
|
public static final Map<String,EntryInfo> entryMap = new HashMap<>();
|
||||||
|
|
||||||
|
// Change these to your own mod
|
||||||
|
private static final String MOD_NAME = ModInfo.NAME; // For file saving and identifying
|
||||||
|
private static final String MOD_NAME_READABLE = ModInfo.READABLE_NAME; // For logs
|
||||||
|
// private static final Logger LOGGER = ApiShared.LOGGER; // For logs
|
||||||
|
private static final Logger LOGGER = LogManager.getLogger(ModInfo.NAME); // For logs (this inits before ClientAPI so this is a temp fix)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// Initializers //
|
||||||
|
//==============//
|
||||||
|
|
||||||
|
private static class ConfigScreenConfigs
|
||||||
|
{
|
||||||
|
// This contains all the configs for the configs
|
||||||
|
public static final int SpaceFromRightScreen = 10;
|
||||||
|
public static final int ButtonWidthSpacing = 5;
|
||||||
|
public static final int ResetButtonWidth = 40;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class EntryInfo<T>
|
||||||
|
{
|
||||||
|
Field field;
|
||||||
|
Object widget;
|
||||||
|
int width = 0;
|
||||||
|
int max;
|
||||||
|
Map.Entry<EditBox, Component> error;
|
||||||
|
Object defaultValue;
|
||||||
|
Object value;
|
||||||
|
String tempValue;
|
||||||
|
boolean inLimits = true;
|
||||||
|
TranslatableComponent name;
|
||||||
|
int index;
|
||||||
|
/** Hides the button */
|
||||||
|
boolean hideOption = false;
|
||||||
|
/** This asks if it is a button to goto a new screen */
|
||||||
|
boolean screenButton = false;
|
||||||
|
/** This is only called if button is true */
|
||||||
|
String gotoScreen = "";
|
||||||
|
String category;
|
||||||
|
Class<T> varClass;
|
||||||
|
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
|
boolean fileComment = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Path configFilePath;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static void init(Class<?> config)
|
||||||
|
{
|
||||||
|
Minecraft mc = Minecraft.getInstance();
|
||||||
|
configFilePath = mc.gameDirectory.toPath().resolve("config").resolve(MOD_NAME + ".toml");
|
||||||
|
|
||||||
|
initNestedClass(config, "");
|
||||||
|
|
||||||
|
for (EntryInfo info : entries) {
|
||||||
|
if (info.field.isAnnotationPresent(ConfigAnnotations.Entry.class)) {
|
||||||
|
try {
|
||||||
|
info.value = info.field.get(null);
|
||||||
|
info.tempValue = info.value.toString();
|
||||||
|
} catch (IllegalAccessException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadFromFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void initNestedClass(Class<?> config, String category)
|
||||||
|
{
|
||||||
|
for (Field field : config.getFields())
|
||||||
|
{
|
||||||
|
EntryInfo info = new EntryInfo();
|
||||||
|
if (field.isAnnotationPresent(ConfigAnnotations.Entry.class) || field.isAnnotationPresent(ConfigAnnotations.Comment.class) || field.isAnnotationPresent(ConfigAnnotations.ScreenEntry.class))
|
||||||
|
{
|
||||||
|
// If putting in your own mod then put your own check for server sided
|
||||||
|
info.category = category;
|
||||||
|
if (!LodCommonMain.serverSided)
|
||||||
|
initClient(field, info, category);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field.isAnnotationPresent(ConfigAnnotations.Entry.class))
|
||||||
|
{
|
||||||
|
entryMap.put((!category.isEmpty() ? category + "." : "") + field.getName(), info);
|
||||||
|
info.varClass = field.getType();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
info.defaultValue = field.get(null);
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (field.isAnnotationPresent(ConfigAnnotations.ScreenEntry.class))
|
||||||
|
initNestedClass(field.getType(), (!category.isEmpty() ? category + "." : "") + field.getName());
|
||||||
|
|
||||||
|
// File comment (WILL BE REMOVED SOON)
|
||||||
|
if (field.isAnnotationPresent(ConfigAnnotations.FileComment.class)) {
|
||||||
|
entryMap.put((!category.isEmpty() ? category + "." : "") + field.getName(), info);
|
||||||
|
info.fileComment = true;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
info.value = info.defaultValue = field.get(null);
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException ignored) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
info.field = field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This adds the buttons to the queue to be rendered */
|
||||||
|
private static void initClient(Field field, EntryInfo info, String category)
|
||||||
|
{
|
||||||
|
Class<?> fieldClass = field.getType();
|
||||||
|
ConfigAnnotations.Entry entry = field.getAnnotation(ConfigAnnotations.Entry.class);
|
||||||
|
ConfigAnnotations.ScreenEntry screenEntry = field.getAnnotation(ConfigAnnotations.ScreenEntry.class);
|
||||||
|
|
||||||
|
if (entry != null)
|
||||||
|
info.width = entry.width();
|
||||||
|
else if (screenEntry != null)
|
||||||
|
info.width = screenEntry.width();
|
||||||
|
|
||||||
|
if (entry != null)
|
||||||
|
{
|
||||||
|
if (!entry.name().equals(""))
|
||||||
|
info.name = new TranslatableComponent(entry.name());
|
||||||
|
|
||||||
|
|
||||||
|
if (fieldClass == int.class)
|
||||||
|
{
|
||||||
|
// For int
|
||||||
|
textField(info, Integer::parseInt, INTEGER_ONLY_REGEX, entry.minValue(), entry.maxValue(), true);
|
||||||
|
}
|
||||||
|
else if (fieldClass == double.class)
|
||||||
|
{
|
||||||
|
// For double
|
||||||
|
textField(info, Double::parseDouble, DECIMAL_ONLY_REGEX, entry.minValue(), entry.maxValue(), false);
|
||||||
|
}
|
||||||
|
else if (fieldClass == String.class || fieldClass == List.class)
|
||||||
|
{
|
||||||
|
// For string or list
|
||||||
|
info.max = entry.maxValue() == Double.MAX_VALUE ? Integer.MAX_VALUE : (int) entry.maxValue();
|
||||||
|
textField(info, String::length, null, Math.min(entry.minValue(), 0), Math.max(entry.maxValue(), 1), true);
|
||||||
|
}
|
||||||
|
else if (fieldClass == boolean.class)
|
||||||
|
{
|
||||||
|
// For boolean
|
||||||
|
Function<Object, Component> func = value -> new TextComponent((Boolean) value ? "True" : "False").withStyle((Boolean) value ? ChatFormatting.GREEN : ChatFormatting.RED);
|
||||||
|
info.widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(button -> {
|
||||||
|
info.value = !(Boolean) info.value;
|
||||||
|
button.setMessage(func.apply(info.value));
|
||||||
|
}, func);
|
||||||
|
}
|
||||||
|
else if (fieldClass.isEnum())
|
||||||
|
{
|
||||||
|
// For enum
|
||||||
|
List<?> values = Arrays.asList(field.getType().getEnumConstants());
|
||||||
|
Function<Object, Component> func = value -> new TranslatableComponent(MOD_NAME + ".config." + "enum." + fieldClass.getSimpleName() + "." + info.value.toString());
|
||||||
|
info.widget = new AbstractMap.SimpleEntry<Button.OnPress, Function<Object, Component>>(button -> {
|
||||||
|
int index = values.indexOf(info.value) + 1;
|
||||||
|
info.value = values.get(index >= values.size() ? 0 : index);
|
||||||
|
button.setMessage(func.apply(info.value));
|
||||||
|
}, func);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (screenEntry != null)
|
||||||
|
{
|
||||||
|
if (!screenEntry.name().equals(""))
|
||||||
|
info.name = new TranslatableComponent(screenEntry.name());
|
||||||
|
|
||||||
|
info.screenButton = true;
|
||||||
|
info.gotoScreen = (!info.category.isEmpty() ? info.category + "." : "") + field.getName();
|
||||||
|
}
|
||||||
|
entries.add(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** creates a text field */
|
||||||
|
private static void textField(EntryInfo info, Function<String, Number> func, Pattern pattern, double minValue, double maxValue, boolean cast)
|
||||||
|
{
|
||||||
|
boolean isNumber = pattern != null;
|
||||||
|
info.widget = (BiFunction<EditBox, Button, Predicate<String>>) (editBox, button) -> stringValue ->
|
||||||
|
{
|
||||||
|
stringValue = stringValue.trim();
|
||||||
|
if (!(stringValue.isEmpty() || !isNumber || pattern.matcher(stringValue).matches()))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
Number value = 0;
|
||||||
|
boolean inLimits = false;
|
||||||
|
info.error = null;
|
||||||
|
if (isNumber && !stringValue.isEmpty() && !stringValue.equals("-") && !stringValue.equals("."))
|
||||||
|
{
|
||||||
|
value = func.apply(stringValue);
|
||||||
|
inLimits = value.doubleValue() >= minValue && value.doubleValue() <= maxValue;
|
||||||
|
info.error = inLimits ? null : new AbstractMap.SimpleEntry<>(editBox, new TextComponent(value.doubleValue() < minValue ?
|
||||||
|
"§cMinimum " + "length" + (cast ? " is " + (int) minValue : " is " + minValue) :
|
||||||
|
"§cMaximum " + "length" + (cast ? " is " + (int) maxValue : " is " + maxValue)));
|
||||||
|
}
|
||||||
|
|
||||||
|
info.tempValue = stringValue;
|
||||||
|
editBox.setTextColor(inLimits ? 0xFFFFFFFF : 0xFFFF7777);
|
||||||
|
info.inLimits = inLimits;
|
||||||
|
button.active = entries.stream().allMatch(e -> e.inLimits);
|
||||||
|
|
||||||
|
|
||||||
|
if (inLimits && info.field.getType() != List.class)
|
||||||
|
{
|
||||||
|
info.value = value;
|
||||||
|
}
|
||||||
|
else if (inLimits)
|
||||||
|
{
|
||||||
|
if (((List<String>) info.value).size() == info.index)
|
||||||
|
((List<String>) info.value).add("");
|
||||||
|
((List<String>) info.value).set(info.index, Arrays.stream(info.tempValue.replace("[", "").replace("]", "").split(", ")).collect(Collectors.toList()).get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===============//
|
||||||
|
// File Handling //
|
||||||
|
//===============//
|
||||||
|
|
||||||
|
/** Grabs what is in the config and puts it in modid.toml */
|
||||||
|
public static void saveToFile()
|
||||||
|
{
|
||||||
|
CommentedFileConfig config = CommentedFileConfig.builder(configFilePath.toFile()).build();
|
||||||
|
|
||||||
|
// First try to create a config file
|
||||||
|
try {
|
||||||
|
if (!Files.exists(configFilePath))
|
||||||
|
Files.createFile(configFilePath);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
LOGGER.info("Failed creating config file for " + MOD_NAME_READABLE + " at the path [" + configFilePath.toString() + "].");
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
loadFileWithErrorCheck(config);
|
||||||
|
|
||||||
|
|
||||||
|
// Just put this here for the future
|
||||||
|
config.setComment("_Version", " DONT TOUCH THIS, IF YOU DO THEN CONFIG FILE WOULD BREAK");
|
||||||
|
config.set("_Versions", ModInfo.VERSION);
|
||||||
|
|
||||||
|
|
||||||
|
for (EntryInfo info : entries) {
|
||||||
|
if (info.field.isAnnotationPresent(ConfigAnnotations.Entry.class)) {
|
||||||
|
editSingleOption.saveOption(info, config);
|
||||||
|
|
||||||
|
if (editSingleOption.getEntry((info.category.isEmpty() ? "" : info.category + ".") + "_" + info.field.getName()) != null)
|
||||||
|
config.setComment((info.category.isEmpty() ? "" : info.category + ".") + info.field.getName(), String.valueOf(editSingleOption.getEntry((info.category.isEmpty() ? "" : info.category + ".") + "_" + info.field.getName()).defaultValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.save();
|
||||||
|
config.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Grabs what is in modid.toml and puts it into the config
|
||||||
|
* If the file doesn't exist then it runs saveToFile
|
||||||
|
*/
|
||||||
|
public static void loadFromFile()
|
||||||
|
{
|
||||||
|
CommentedFileConfig config = CommentedFileConfig.builder(configFilePath.toFile()).autosave().build();
|
||||||
|
|
||||||
|
// First checks if the config file was already made
|
||||||
|
if (!Files.exists(configFilePath)) {
|
||||||
|
LOGGER.info("Config file not found for " + MOD_NAME_READABLE + ". Creating config...");
|
||||||
|
saveToFile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadFileWithErrorCheck(config);
|
||||||
|
|
||||||
|
|
||||||
|
// Just put this here for the future
|
||||||
|
config.setComment("_Version", " DONT TOUCH THIS, IF YOU DO THEN CONFIG FILE WOULD BREAK");
|
||||||
|
config.set("_Versions", ModInfo.VERSION);
|
||||||
|
|
||||||
|
|
||||||
|
// Puts everything into its variable
|
||||||
|
for (EntryInfo info : entries) {
|
||||||
|
if (info.field.isAnnotationPresent(ConfigAnnotations.Entry.class)) {
|
||||||
|
editSingleOption.loadOption(info, config);
|
||||||
|
|
||||||
|
// File comments (WILL REMOVE SOON)
|
||||||
|
if (editSingleOption.getEntry((info.category.isEmpty() ? "" : info.category + ".") + "_" + info.field.getName()) != null)
|
||||||
|
config.setComment((info.category.isEmpty() ? "" : info.category + ".") + info.field.getName(), String.valueOf(editSingleOption.getEntry((info.category.isEmpty() ? "" : info.category + ".") + "_" + info.field.getName()).defaultValue));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
config.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class editSingleOption {
|
||||||
|
/** Get the entry info of an item using its string name */
|
||||||
|
public static EntryInfo getEntry(String name)
|
||||||
|
{
|
||||||
|
return entryMap.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Save a single item using its string name */
|
||||||
|
public static void saveOption(String name)
|
||||||
|
{
|
||||||
|
saveOption(entryMap.get(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Saves a single item using entry info */
|
||||||
|
public static void saveOption(EntryInfo info)
|
||||||
|
{
|
||||||
|
CommentedFileConfig config = CommentedFileConfig.builder(configFilePath.toFile()).autosave().build();
|
||||||
|
|
||||||
|
loadFileWithErrorCheck(config);
|
||||||
|
|
||||||
|
saveOption(info, config);
|
||||||
|
|
||||||
|
config.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Saves a single item using its entry info and its config builder */
|
||||||
|
public static void saveOption(EntryInfo info, CommentedFileConfig config)
|
||||||
|
{
|
||||||
|
config.set((info.category.isEmpty() ? "" : info.category + ".") + info.field.getName(), info.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Load a single item using its string name */
|
||||||
|
public static void loadOption(String name)
|
||||||
|
{
|
||||||
|
loadOption(entryMap.get(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Load a single item using entry info */
|
||||||
|
public static void loadOption(EntryInfo info)
|
||||||
|
{
|
||||||
|
CommentedFileConfig config = CommentedFileConfig.builder(configFilePath.toFile()).autosave().build();
|
||||||
|
|
||||||
|
loadFileWithErrorCheck(config);
|
||||||
|
|
||||||
|
loadOption(info, config);
|
||||||
|
|
||||||
|
config.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Loads a single item using its entry info and its config builder */
|
||||||
|
public static void loadOption(EntryInfo info, CommentedFileConfig config)
|
||||||
|
{
|
||||||
|
String itemPath = (info.category.isEmpty() ? "" : info.category + ".") + info.field.getName();
|
||||||
|
if (config.contains(itemPath)) {
|
||||||
|
if (info.field.getType().isEnum())
|
||||||
|
info.value = config.getEnum(itemPath, info.varClass);
|
||||||
|
else
|
||||||
|
info.value = config.get(itemPath);
|
||||||
|
} else
|
||||||
|
config.set(itemPath, info.value);
|
||||||
|
|
||||||
|
try {
|
||||||
|
info.field.set(null, info.value);
|
||||||
|
} catch (IllegalAccessException ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Dose config.load(); but with error checking to avoid crashes */
|
||||||
|
public static void loadFileWithErrorCheck(CommentedFileConfig config) {
|
||||||
|
try {
|
||||||
|
config.load();
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.info("Error loading config for " + MOD_NAME_READABLE + " at the path [" + configFilePath.toString() + "].");
|
||||||
|
LOGGER.info("Creating a new config...");
|
||||||
|
try {
|
||||||
|
Files.deleteIfExists(configFilePath);
|
||||||
|
saveToFile();
|
||||||
|
} catch (Exception f) {
|
||||||
|
LOGGER.info("Failed creating config file for " + MOD_NAME_READABLE + " at the path [" + configFilePath.toString() + "].");
|
||||||
|
f.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//==============//
|
||||||
|
// GUI handling //
|
||||||
|
//==============//
|
||||||
|
|
||||||
|
public static Screen getScreen(Screen parent, String category)
|
||||||
|
{
|
||||||
|
return new ConfigScreen(parent, category);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ConfigScreen extends Screen
|
||||||
|
{
|
||||||
|
protected ConfigScreen(Screen parent, String category)
|
||||||
|
{
|
||||||
|
super(new TranslatableComponent(
|
||||||
|
I18n.exists(MOD_NAME + ".config" + (category.isEmpty()? "." + category : "") + ".title") ?
|
||||||
|
MOD_NAME + ".config.title" :
|
||||||
|
MOD_NAME + ".config" + (category.isEmpty() ? "" : "." + category) + ".title")
|
||||||
|
);
|
||||||
|
this.parent = parent;
|
||||||
|
this.category = category;
|
||||||
|
this.translationPrefix = MOD_NAME + ".config.";
|
||||||
|
}
|
||||||
|
|
||||||
|
private final String translationPrefix;
|
||||||
|
private final Screen parent;
|
||||||
|
private final String category;
|
||||||
|
private ConfigListWidget list;
|
||||||
|
private boolean reload = false;
|
||||||
|
|
||||||
|
// Real Time config update //
|
||||||
|
@Override
|
||||||
|
public void tick()
|
||||||
|
{
|
||||||
|
super.tick();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** When you close it, it goes to the previous screen and saves */
|
||||||
|
@Override
|
||||||
|
public void onClose()
|
||||||
|
{
|
||||||
|
saveToFile();
|
||||||
|
Objects.requireNonNull(minecraft).setScreen(this.parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init()
|
||||||
|
{
|
||||||
|
super.init();
|
||||||
|
if (!reload)
|
||||||
|
loadFromFile();
|
||||||
|
|
||||||
|
// addRenderableWidget in 1.17 and over
|
||||||
|
// addButton in 1.16 and below
|
||||||
|
this.addRenderableWidget(new Button(this.width / 2 - 154, this.height - 28, 150, 20, CommonComponents.GUI_CANCEL, button -> {
|
||||||
|
loadFromFile();
|
||||||
|
Objects.requireNonNull(minecraft).setScreen(parent);
|
||||||
|
}));
|
||||||
|
|
||||||
|
Button done = this.addRenderableWidget(new Button(this.width / 2 + 4, this.height - 28, 150, 20, CommonComponents.GUI_DONE, (button) -> {
|
||||||
|
saveToFile();
|
||||||
|
Objects.requireNonNull(minecraft).setScreen(parent);
|
||||||
|
}));
|
||||||
|
|
||||||
|
this.list = new ConfigListWidget(this.minecraft, this.width * 2, this.height, 32, this.height - 32, 25);
|
||||||
|
if (this.minecraft != null && this.minecraft.level != null)
|
||||||
|
this.list.setRenderBackground(false);
|
||||||
|
this.addWidget(this.list);
|
||||||
|
for (EntryInfo info : entries)
|
||||||
|
{
|
||||||
|
if (info.category.matches(category) && !info.hideOption)
|
||||||
|
{
|
||||||
|
TranslatableComponent name = (info.name == null ? new TranslatableComponent(translationPrefix + (!info.category.isEmpty() ? info.category + "." : "") + info.field.getName()) : info.name);
|
||||||
|
Button resetButton = new Button(this.width - ConfigScreenConfigs.SpaceFromRightScreen - info.width - ConfigScreenConfigs.ButtonWidthSpacing - ConfigScreenConfigs.ResetButtonWidth, 0, ConfigScreenConfigs.ResetButtonWidth, 20, new TextComponent("Reset").withStyle(ChatFormatting.RED), (button -> {
|
||||||
|
info.value = info.defaultValue;
|
||||||
|
info.tempValue = info.defaultValue.toString();
|
||||||
|
info.index = 0;
|
||||||
|
this.reload = true;
|
||||||
|
Objects.requireNonNull(minecraft).setScreen(this);
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (info.widget instanceof Map.Entry)
|
||||||
|
{
|
||||||
|
Map.Entry<Button.OnPress, Function<Object, Component>> widget = (Map.Entry<Button.OnPress, Function<Object, Component>>) info.widget;
|
||||||
|
if (info.field.getType().isEnum())
|
||||||
|
widget.setValue(value -> new TranslatableComponent(translationPrefix + "enum." + info.field.getType().getSimpleName() + "." + info.value.toString()));
|
||||||
|
this.list.addButton(new Button(this.width - info.width - ConfigScreenConfigs.SpaceFromRightScreen, 0, info.width, 20, widget.getValue().apply(info.value), widget.getKey()), resetButton, null, name);
|
||||||
|
}
|
||||||
|
else if (info.field.getType() == List.class)
|
||||||
|
{
|
||||||
|
if (!reload)
|
||||||
|
info.index = 0;
|
||||||
|
EditBox widget = new EditBox(font, this.width - info.width - ConfigScreenConfigs.SpaceFromRightScreen, 0, info.width, 20, null);
|
||||||
|
widget.setMaxLength(info.width);
|
||||||
|
if (info.index < ((List<String>) info.value).size())
|
||||||
|
widget.insertText((String.valueOf(((List<String>) info.value).get(info.index))));
|
||||||
|
else
|
||||||
|
widget.insertText("");
|
||||||
|
Predicate<String> processor = ((BiFunction<EditBox, Button, Predicate<String>>) info.widget).apply(widget, done);
|
||||||
|
widget.setFilter(processor);
|
||||||
|
resetButton.setWidth(20);
|
||||||
|
resetButton.setMessage(new TextComponent("R").withStyle(ChatFormatting.RED));
|
||||||
|
Button cycleButton = new Button(this.width - 185, 0, 20, 20, new TextComponent(String.valueOf(info.index)).withStyle(ChatFormatting.GOLD), (button -> {
|
||||||
|
((List<String>) info.value).remove("");
|
||||||
|
this.reload = true;
|
||||||
|
info.index = info.index + 1;
|
||||||
|
if (info.index > ((List<String>) info.value).size())
|
||||||
|
info.index = 0;
|
||||||
|
Objects.requireNonNull(minecraft).setScreen(this);
|
||||||
|
}));
|
||||||
|
this.list.addButton(widget, resetButton, cycleButton, name);
|
||||||
|
}
|
||||||
|
else if (info.widget != null)
|
||||||
|
{
|
||||||
|
EditBox widget = new EditBox(font, this.width - info.width - ConfigScreenConfigs.SpaceFromRightScreen + 2, 0, info.width - 4, 20, null);
|
||||||
|
widget.setMaxLength(info.width);
|
||||||
|
widget.insertText(String.valueOf(info.value));
|
||||||
|
Predicate<String> processor = ((BiFunction<EditBox, Button, Predicate<String>>) info.widget).apply(widget, done);
|
||||||
|
widget.setFilter(processor);
|
||||||
|
this.list.addButton(widget, resetButton, null, name);
|
||||||
|
}
|
||||||
|
else if (info.screenButton)
|
||||||
|
{
|
||||||
|
Button widget = new Button(this.width / 2 - info.width, this.height - 28, info.width * 2, 20, name, (button -> {
|
||||||
|
saveToFile();
|
||||||
|
Objects.requireNonNull(minecraft).setScreen(ConfigGui.getScreen(this, info.gotoScreen));
|
||||||
|
}));
|
||||||
|
this.list.addButton(widget, null, null, null);
|
||||||
|
}
|
||||||
|
else if (!info.fileComment)
|
||||||
|
{
|
||||||
|
this.list.addButton(null, null, null, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack matrices, int mouseX, int mouseY, float delta)
|
||||||
|
{
|
||||||
|
this.renderBackground(matrices); // Renders background
|
||||||
|
this.list.render(matrices, mouseX, mouseY, delta); // Render buttons
|
||||||
|
drawCenteredString(matrices, font, title, width / 2, 15, 0xFFFFFF); // Render title
|
||||||
|
|
||||||
|
// Render the tooltip only if it can find a tooltip in the language file
|
||||||
|
for (EntryInfo info : entries) {
|
||||||
|
if (info.category.matches(category) && !info.hideOption) {
|
||||||
|
if (list.getHoveredButton(mouseX,mouseY).isPresent()) {
|
||||||
|
AbstractWidget buttonWidget = list.getHoveredButton(mouseX,mouseY).get();
|
||||||
|
Component text = ButtonEntry.buttonsWithText.get(buttonWidget);
|
||||||
|
TranslatableComponent name = new TranslatableComponent(this.translationPrefix + (info.category.isEmpty() ? "" : info.category + ".") + info.field.getName());
|
||||||
|
String key = translationPrefix + (info.category.isEmpty() ? "" : info.category + ".") + info.field.getName() + ".@tooltip";
|
||||||
|
|
||||||
|
if (info.error != null && text.equals(name)) renderTooltip(matrices, (Component) info.error.getValue(), mouseX, mouseY);
|
||||||
|
else if (I18n.exists(key) && (text != null && text.equals(name))) {
|
||||||
|
List<Component> list = new ArrayList<>();
|
||||||
|
for (String str : I18n.get(key).split("\n"))
|
||||||
|
list.add(new TextComponent(str));
|
||||||
|
renderComponentTooltip(matrices, list, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
super.render(matrices, mouseX, mouseY, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static class ConfigListWidget extends ContainerObjectSelectionList<ButtonEntry>
|
||||||
|
{
|
||||||
|
Font textRenderer;
|
||||||
|
|
||||||
|
public ConfigListWidget(Minecraft minecraftClient, int i, int j, int k, int l, int m)
|
||||||
|
{
|
||||||
|
super(minecraftClient, i, j, k, l, m);
|
||||||
|
this.centerListVertically = false;
|
||||||
|
textRenderer = minecraftClient.font;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addButton(AbstractWidget button, AbstractWidget resetButton, AbstractWidget indexButton, Component text)
|
||||||
|
{
|
||||||
|
this.addEntry(ButtonEntry.create(button, text, resetButton, indexButton));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRowWidth()
|
||||||
|
{
|
||||||
|
return 10000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<AbstractWidget> getHoveredButton(double mouseX, double mouseY)
|
||||||
|
{
|
||||||
|
for (ButtonEntry buttonEntry : this.children())
|
||||||
|
{
|
||||||
|
if (buttonEntry.button != null && buttonEntry.button.isMouseOver(mouseX, mouseY))
|
||||||
|
{
|
||||||
|
return Optional.of(buttonEntry.button);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static class ButtonEntry extends ContainerObjectSelectionList.Entry<ButtonEntry>
|
||||||
|
{
|
||||||
|
private static final Font textRenderer = Minecraft.getInstance().font;
|
||||||
|
public final AbstractWidget button;
|
||||||
|
private final AbstractWidget resetButton;
|
||||||
|
private final AbstractWidget indexButton;
|
||||||
|
private final Component text;
|
||||||
|
private final List<AbstractWidget> children = new ArrayList<>();
|
||||||
|
public static final Map<AbstractWidget, Component> buttonsWithText = new HashMap<>();
|
||||||
|
|
||||||
|
private ButtonEntry(AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton)
|
||||||
|
{
|
||||||
|
buttonsWithText.put(button, text);
|
||||||
|
this.button = button;
|
||||||
|
this.resetButton = resetButton;
|
||||||
|
this.text = text;
|
||||||
|
this.indexButton = indexButton;
|
||||||
|
if (button != null)
|
||||||
|
children.add(button);
|
||||||
|
if (resetButton != null)
|
||||||
|
children.add(resetButton);
|
||||||
|
if (indexButton != null)
|
||||||
|
children.add(indexButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ButtonEntry create(AbstractWidget button, Component text, AbstractWidget resetButton, AbstractWidget indexButton)
|
||||||
|
{
|
||||||
|
return new ButtonEntry(button, text, resetButton, indexButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(PoseStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta)
|
||||||
|
{
|
||||||
|
if (button != null)
|
||||||
|
{
|
||||||
|
button.y = y;
|
||||||
|
button.render(matrices, mouseX, mouseY, tickDelta);
|
||||||
|
}
|
||||||
|
if (resetButton != null)
|
||||||
|
{
|
||||||
|
resetButton.y = y;
|
||||||
|
resetButton.render(matrices, mouseX, mouseY, tickDelta);
|
||||||
|
}
|
||||||
|
if (indexButton != null)
|
||||||
|
{
|
||||||
|
indexButton.y = y;
|
||||||
|
indexButton.render(matrices, mouseX, mouseY, tickDelta);
|
||||||
|
}
|
||||||
|
if (text != null && (!text.getString().contains("spacer") || button != null))
|
||||||
|
GuiComponent.drawString(matrices, textRenderer, text, 12, y + 5, 0xFFFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<? extends GuiEventListener> children()
|
||||||
|
{
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for 1.17 and over
|
||||||
|
// Remove in 1.16 and below
|
||||||
|
@Override
|
||||||
|
public List<? extends NarratableEntry> narratables()
|
||||||
|
{
|
||||||
|
return children;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+786
@@ -0,0 +1,786 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.config;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.enums.config.*;
|
||||||
|
import com.seibel.lod.core.enums.rendering.*;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||||
|
import com.seibel.lod.common.Config;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This holds the config defaults and setters/getters
|
||||||
|
* that should be hooked into the host mod loader (Fabric, Forge, etc.).
|
||||||
|
*
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 11-16-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 IMultiplayer multiplayer;
|
||||||
|
public final IAdvanced advanced;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IGraphics graphics()
|
||||||
|
{
|
||||||
|
return graphics;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IWorldGenerator worldGenerator()
|
||||||
|
{
|
||||||
|
return worldGenerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IMultiplayer multiplayer() {
|
||||||
|
return multiplayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IAdvanced advanced()
|
||||||
|
{
|
||||||
|
return advanced;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getOptionsButton()
|
||||||
|
{
|
||||||
|
return Config.optionsButton;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setOptionsButton(boolean newOptionsButton)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("optionsButton").value = newOptionsButton;
|
||||||
|
ConfigGui.editSingleOption.saveOption("optionsButton");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// Client Configs //
|
||||||
|
//================//
|
||||||
|
public Client()
|
||||||
|
{
|
||||||
|
graphics = new Graphics();
|
||||||
|
worldGenerator = new WorldGenerator();
|
||||||
|
multiplayer = new Multiplayer();
|
||||||
|
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();
|
||||||
|
fogQuality = new FogQuality();
|
||||||
|
advancedGraphics = new AdvancedGraphics();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Quality implements IQuality
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public HorizontalResolution getDrawResolution()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.Quality.drawResolution;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setDrawResolution(HorizontalResolution newHorizontalResolution)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.quality.drawResolution").value = newHorizontalResolution;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.quality.drawResolution");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLodChunkRenderDistance()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.Quality.lodChunkRenderDistance;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setLodChunkRenderDistance(int newLodChunkRenderDistance)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.quality.lodChunkRenderDistance").value = newLodChunkRenderDistance;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.quality.lodChunkRenderDistance");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VerticalQuality getVerticalQuality()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.Quality.verticalQuality;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setVerticalQuality(VerticalQuality newVerticalQuality)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.quality.verticalQuality").value = newVerticalQuality;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.quality.verticalQuality");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHorizontalScale()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.Quality.horizontalScale;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setHorizontalScale(int newHorizontalScale)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.quality.horizontalScale").value = newHorizontalScale;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.quality.horizontalScale");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HorizontalQuality getHorizontalQuality()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.Quality.horizontalQuality;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setHorizontalQuality(HorizontalQuality newHorizontalQuality)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.quality.horizontalQuality").value = newHorizontalQuality;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.quality.horizontalQuality");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DropoffQuality getDropoffQuality() {
|
||||||
|
return Config.Client.Graphics.Quality.dropoffQuality;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setDropoffQuality(DropoffQuality newDropoffQuality) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.quality.dropoffQuality").value = newDropoffQuality;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.quality.dropoffQuality");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLodBiomeBlending() {
|
||||||
|
return Config.Client.Graphics.Quality.lodBiomeBlending;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLodBiomeBlending(int newLodBiomeBlending) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.quality.lodBiomeBlending").value = newLodBiomeBlending;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.quality.lodBiomeBlending");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class FogQuality implements IFogQuality
|
||||||
|
{
|
||||||
|
public final IAdvancedFog advancedFog;
|
||||||
|
|
||||||
|
FogQuality()
|
||||||
|
{
|
||||||
|
advancedFog = new AdvancedFog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FogDistance getFogDistance()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.FogQuality.fogDistance;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setFogDistance(FogDistance newFogDistance)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.fogDistance").value = newFogDistance;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.fogDistance");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FogDrawMode getFogDrawMode()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.FogQuality.fogDrawMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFogDrawMode(FogDrawMode setFogDrawMode)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.fogDrawMode").value = setFogDrawMode;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.fogDrawMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FogColorMode getFogColorMode()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.FogQuality.fogColorMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFogColorMode(FogColorMode newFogColorMode)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.fogColorMode").value = newFogColorMode;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.fogColorMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getDisableVanillaFog()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.FogQuality.disableVanillaFog;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setDisableVanillaFog(boolean newDisableVanillaFog)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.disableVanillaFog").value = newDisableVanillaFog;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.disableVanillaFog");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IAdvancedFog advancedFog() {
|
||||||
|
return advancedFog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AdvancedFog implements IAdvancedFog {
|
||||||
|
public final IHeightFog heightFog;
|
||||||
|
|
||||||
|
public AdvancedFog() {
|
||||||
|
heightFog = new HeightFog();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getFarFogStart() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogStart;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getFarFogEnd() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogEnd;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getFarFogMin() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogMin;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getFarFogMax() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogMax;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public FogSetting.FogType getFarFogType() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogType;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getFarFogDensity() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.farFogDensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFarFogStart(double newFarFogStart) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogStart").value = newFarFogStart;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogStart");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setFarFogEnd(double newFarFogEnd) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogEnd").value = newFarFogEnd;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogEnd");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setFarFogMin(double newFarFogMin) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogMin").value = newFarFogMin;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogMin");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setFarFogMax(double newFarFogMax) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogMax").value = newFarFogMax;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogMax");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setFarFogType(FogSetting.FogType newFarFogType) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogType").value = newFarFogType;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogType");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setFarFogDensity(double newFarFogDensity) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.farFogDensity").value = newFarFogDensity;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.farFogDensity");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IHeightFog heightFog() {
|
||||||
|
return heightFog;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HeightFog implements IHeightFog {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HeightFogMixMode getHeightFogMixMode() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMixMode;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public HeightFogMode getHeightFogMode() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMode;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getHeightFogHeight() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogHeight;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getHeightFogStart() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogStart;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getHeightFogEnd() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogEnd;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getHeightFogMin() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMin;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getHeightFogMax() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogMax;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public FogSetting.FogType getHeightFogType() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogType;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public double getHeightFogDensity() {
|
||||||
|
return Config.Client.Graphics.FogQuality.AdvancedFog.heightFog.heightFogDensity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setHeightFogMixMode(HeightFogMixMode newHeightFogMixMode) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMixMode").value = newHeightFogMixMode;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMixMode");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setHeightFogMode(HeightFogMode newHeightFogMode) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMode").value = newHeightFogMode;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMode");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setHeightFogHeight(double newHeightFogHeight) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogHeight").value = newHeightFogHeight;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogHeight");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setHeightFogStart(double newHeightFogStart) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogStart").value = newHeightFogStart;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogStart");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setHeightFogEnd(double newHeightFogEnd) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogEnd").value = newHeightFogEnd;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogEnd");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setHeightFogMin(double newHeightFogMin) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMin").value = newHeightFogMin;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMin");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setHeightFogMax(double newHeightFogMax) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogMax").value = newHeightFogMax;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogMax");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setHeightFogType(FogSetting.FogType newHeightFogType) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogType").value = newHeightFogType;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogType");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setHeightFogDensity(double newHeightFogDensity) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.fogQuality.advancedFog.heightFog.heightFogDensity").value = newHeightFogDensity;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.fogQuality.advancedFog.heightFog.heightFogDensity");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class AdvancedGraphics implements IAdvancedGraphics
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean getDisableDirectionalCulling()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.AdvancedGraphics.disableDirectionalCulling;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setDisableDirectionalCulling(boolean newDisableDirectionalCulling)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.disableDirectionalCulling").value = newDisableDirectionalCulling;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.disableDirectionalCulling");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VanillaOverdraw getVanillaOverdraw()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.AdvancedGraphics.vanillaOverdraw;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setVanillaOverdraw(VanillaOverdraw newVanillaOverdraw)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.vanillaOverdraw").value = newVanillaOverdraw;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.vanillaOverdraw");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
@Override
|
||||||
|
public int getBacksideCullingRange()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.AdvancedGraphics.backsideCullingRange;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setBacksideCullingRange(int newBacksideCullingRange)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.backsideCullingRange").value = newBacksideCullingRange;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.backsideCullingRange");
|
||||||
|
}*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getUseExtendedNearClipPlane()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.AdvancedGraphics.useExtendedNearClipPlane;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setUseExtendedNearClipPlane(boolean newUseExtendedNearClipPlane)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.useExtendedNearClipPlane").value = newUseExtendedNearClipPlane;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.useExtendedNearClipPlane");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getBrightnessMultiplier()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.AdvancedGraphics.brightnessMultiplier;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setBrightnessMultiplier(double newBrightnessMultiplier)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.brightnessMultiplier").value = newBrightnessMultiplier;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.brightnessMultiplier");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getSaturationMultiplier()
|
||||||
|
{
|
||||||
|
return Config.Client.Graphics.AdvancedGraphics.saturationMultiplier;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setSaturationMultiplier(double newSaturationMultiplier)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.graphics.advancedGraphics.saturationMultiplier").value = newSaturationMultiplier;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.graphics.advancedGraphics.saturationMultiplier");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//========================//
|
||||||
|
// WorldGenerator Configs //
|
||||||
|
//========================//
|
||||||
|
public static class WorldGenerator implements IWorldGenerator
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public GenerationPriority getGenerationPriority()
|
||||||
|
{
|
||||||
|
return Config.Client.WorldGenerator.generationPriority;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setGenerationPriority(GenerationPriority newGenerationPriority)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.worldGenerator.generationPriority").value = newGenerationPriority;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.worldGenerator.generationPriority");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DistanceGenerationMode getDistanceGenerationMode()
|
||||||
|
{
|
||||||
|
return Config.Client.WorldGenerator.distanceGenerationMode;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setDistanceGenerationMode(DistanceGenerationMode newDistanceGenerationMode)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.worldGenerator.distanceGenerationMode").value = newDistanceGenerationMode;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.worldGenerator.distanceGenerationMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@Override
|
||||||
|
public boolean getAllowUnstableFeatureGeneration()
|
||||||
|
{
|
||||||
|
return Config.Client.WorldGenerator.allowUnstableFeatureGeneration;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setAllowUnstableFeatureGeneration(boolean newAllowUnstableFeatureGeneration)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.worldGenerator.allowUnstableFeatureGeneration").value = newAllowUnstableFeatureGeneration;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.worldGenerator.allowUnstableFeatureGeneration");
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlocksToAvoid getBlocksToAvoid()
|
||||||
|
{
|
||||||
|
return Config.Client.WorldGenerator.blocksToAvoid;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setBlockToAvoid(BlocksToAvoid newBlockToAvoid)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.worldGenerator.blocksToAvoid").value = newBlockToAvoid;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.worldGenerator.blocksToAvoid");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public boolean getEnableDistantGeneration()
|
||||||
|
{
|
||||||
|
return (boolean) ConfigGui.editSingleOption.getEntry("client.worldGenerator.enableDistantGeneration").value;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setEnableDistantGeneration(boolean newEnableDistantGeneration)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.worldGenerator.enableDistantGeneration").value = newEnableDistantGeneration;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.worldGenerator.enableDistantGeneration");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public LightGenerationMode getLightGenerationMode()
|
||||||
|
{
|
||||||
|
return Config.Client.WorldGenerator.lightGenerationMode;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setLightGenerationMode(LightGenerationMode newLightGenerationMode)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.worldGenerator.lightGenerationMode").value = newLightGenerationMode;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.worldGenerator.lightGenerationMode");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=====================//
|
||||||
|
// Multiplayer Configs //
|
||||||
|
//=====================//
|
||||||
|
public static class Multiplayer implements IMultiplayer
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public ServerFolderNameMode getServerFolderNameMode()
|
||||||
|
{
|
||||||
|
return Config.Client.Multiplayer.serverFolderNameMode;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setServerFolderNameMode(ServerFolderNameMode newServerFolderNameMode)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.multiplayer.serverFolderNameMode").value = newServerFolderNameMode;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.multiplayer.serverFolderNameMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getMultiDimensionRequiredSimilarity()
|
||||||
|
{
|
||||||
|
return Config.Client.Multiplayer.multiDimensionRequiredSimilarity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setMultiDimensionRequiredSimilarity(double newMultiDimensionMinimumSimilarityPercent)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.multiplayer.multiDimensionMinimumSimilarityPercent").value = newMultiDimensionMinimumSimilarityPercent;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.multiplayer.multiDimensionMinimumSimilarityPercent");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//============================//
|
||||||
|
// 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 Config.Client.Advanced.Threading.numberOfWorldGenerationThreads;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setNumberOfWorldGenerationThreads(int newNumberOfWorldGenerationThreads)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.advanced.threading.numberOfWorldGenerationThreads").value = newNumberOfWorldGenerationThreads;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.advanced.threading.numberOfWorldGenerationThreads");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getNumberOfBufferBuilderThreads()
|
||||||
|
{
|
||||||
|
return Config.Client.Advanced.Threading.numberOfBufferBuilderThreads;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setNumberOfBufferBuilderThreads(int newNumberOfWorldBuilderThreads)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.advanced.threading.numberOfBufferBuilderThreads").value = newNumberOfWorldBuilderThreads;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.advanced.threading.numberOfBufferBuilderThreads");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//===============//
|
||||||
|
// Debug Options //
|
||||||
|
//===============//
|
||||||
|
public static class Debugging implements IDebugging
|
||||||
|
{
|
||||||
|
@Override
|
||||||
|
public boolean getDrawLods()
|
||||||
|
{
|
||||||
|
return (boolean) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.drawLods").value;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setDrawLods(boolean newDrawLods)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.drawLods").value = newDrawLods;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.drawLods");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DebugMode getDebugMode()
|
||||||
|
{
|
||||||
|
return (DebugMode) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugMode").value;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setDebugMode(DebugMode newDebugMode)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.debugMode").value = newDebugMode;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.debugMode");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getDebugKeybindingsEnabled()
|
||||||
|
{
|
||||||
|
return (boolean) ConfigGui.editSingleOption.getEntry("client.advanced.debugging.enableDebugKeybindings").value;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setDebugKeybindingsEnabled(boolean newEnableDebugKeybindings)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.advanced.debugging.enableDebugKeybindings").value = newEnableDebugKeybindings;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.advanced.debugging.enableDebugKeybindings");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class Buffers implements IBuffers
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public GpuUploadMethod getGpuUploadMethod()
|
||||||
|
{
|
||||||
|
return Config.Client.Advanced.Buffers.gpuUploadMethod;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setGpuUploadMethod(GpuUploadMethod newDisableVanillaFog)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.advanced.buffers.gpuUploadMethod").value = newDisableVanillaFog;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.advanced.buffers.gpuUploadMethod");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getGpuUploadPerMegabyteInMilliseconds()
|
||||||
|
{
|
||||||
|
return Config.Client.Advanced.Buffers.gpuUploadPerMegabyteInMilliseconds;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setGpuUploadPerMegabyteInMilliseconds(int newMilliseconds) {
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.advanced.buffers.gpuUploadPerMegabyteInMilliseconds").value = newMilliseconds;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.advanced.buffers.gpuUploadPerMegabyteInMilliseconds");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BufferRebuildTimes getRebuildTimes()
|
||||||
|
{
|
||||||
|
return Config.Client.Advanced.Buffers.rebuildTimes;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void setRebuildTimes(BufferRebuildTimes newBufferRebuildTimes)
|
||||||
|
{
|
||||||
|
ConfigGui.editSingleOption.getEntry("client.advanced.buffers.newBufferRebuildTimes").value = newBufferRebuildTimes;
|
||||||
|
ConfigGui.editSingleOption.saveOption("client.advanced.buffers.newBufferRebuildTimes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.config;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import net.minecraft.client.gui.components.ImageButton;
|
||||||
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a button with a texture on it
|
||||||
|
*/
|
||||||
|
public class TexturedButtonWidget extends ImageButton {
|
||||||
|
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, ResourceLocation texture, OnPress pressAction) {
|
||||||
|
super(x, y, width, height, u, v, texture, pressAction);
|
||||||
|
}
|
||||||
|
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction) {
|
||||||
|
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction, Component text) {
|
||||||
|
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TexturedButtonWidget(int x, int y, int width, int height, int u, int v, int hoveredVOffset, ResourceLocation texture, int textureWidth, int textureHeight, OnPress pressAction, OnTooltip tooltipSupplier, Component text) {
|
||||||
|
super(x, y, width, height, u, v, hoveredVOffset, texture, textureWidth, textureHeight, pressAction, tooltipSupplier, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void renderButton(PoseStack matrices, int mouseX, int mouseY, float delta) {
|
||||||
|
RenderSystem.setShader(GameRenderer::getPositionTexShader);
|
||||||
|
RenderSystem.setShaderTexture(0, WIDGETS_LOCATION);
|
||||||
|
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, this.alpha);
|
||||||
|
int i = this.getYImage(this.isHovered);
|
||||||
|
RenderSystem.enableBlend();
|
||||||
|
RenderSystem.defaultBlendFunc();
|
||||||
|
RenderSystem.enableDepthTest();
|
||||||
|
this.blit(matrices, this.x, this.y, 0, 46 + i * 20, this.width / 2, this.height);
|
||||||
|
this.blit(matrices, this.x + this.width / 2, this.y, 200 - this.width / 2, 46 + i * 20, this.width / 2, this.height);
|
||||||
|
|
||||||
|
super.renderButton(matrices, mouseX, mouseY, delta);
|
||||||
|
}
|
||||||
|
}
|
||||||
+430
@@ -0,0 +1,430 @@
|
|||||||
|
/*
|
||||||
|
* 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.common.wrappers.minecraft;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
import com.mojang.blaze3d.platform.Window;
|
||||||
|
import com.seibel.lod.core.ModInfo;
|
||||||
|
import com.seibel.lod.core.api.ApiShared;
|
||||||
|
import com.seibel.lod.core.enums.LodDirection;
|
||||||
|
import com.seibel.lod.core.util.LodUtil;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
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.common.wrappers.McObjectConverter;
|
||||||
|
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.chunk.ChunkPosWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.misc.LightMapWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.world.DimensionTypeWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||||
|
|
||||||
|
import net.minecraft.CrashReport;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.Options;
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
|
import net.minecraft.client.multiplayer.ServerData;
|
||||||
|
import net.minecraft.client.player.LocalPlayer;
|
||||||
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
import net.minecraft.client.resources.model.ModelManager;
|
||||||
|
import net.minecraft.client.server.IntegratedServer;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.network.chat.TextComponent;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.dimension.DimensionType;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A singleton that wraps the Minecraft class
|
||||||
|
* to allow for easier movement between Minecraft versions.
|
||||||
|
*
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 3-5-2022
|
||||||
|
*/
|
||||||
|
public class MinecraftClientWrapper implements IMinecraftClientWrapper
|
||||||
|
{
|
||||||
|
public static final MinecraftClientWrapper INSTANCE = new MinecraftClientWrapper();
|
||||||
|
|
||||||
|
public final Minecraft mc = Minecraft.getInstance();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lightmap for the current:
|
||||||
|
* Time, dimension, brightness setting, etc.
|
||||||
|
*/
|
||||||
|
private NativeImage lightMap = null;
|
||||||
|
|
||||||
|
private ProfilerWrapper profilerWrapper;
|
||||||
|
|
||||||
|
|
||||||
|
private MinecraftClientWrapper()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//================//
|
||||||
|
// 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) {
|
||||||
|
if (mc.level != null)
|
||||||
|
{
|
||||||
|
Direction mcDir = McObjectConverter.Convert(lodDirection);
|
||||||
|
return mc.level.getShade(mcDir, true);
|
||||||
|
}
|
||||||
|
else return 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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()
|
||||||
|
{
|
||||||
|
if (mc.player != null)
|
||||||
|
return DimensionTypeWrapper.getDimensionTypeWrapper(mc.player.level.dimensionType());
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 blockLight x location in texture space
|
||||||
|
* @param skyLight z location in texture space
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getColorIntFromLightMap(int blockLight, int skyLight)
|
||||||
|
{
|
||||||
|
if (lightMap == null)
|
||||||
|
{
|
||||||
|
sendChatMessage("new");
|
||||||
|
// make sure the lightMap is up-to-date
|
||||||
|
getCurrentLightMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
return lightMap.getPixelRGBA(blockLight, skyLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the Color at the given pixel coordinates
|
||||||
|
* from the current lightmap.
|
||||||
|
* @param blockLight x location in texture space
|
||||||
|
* @param skyLight z location in texture space
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Color getColorFromLightMap(int blockLight, int skyLight) {
|
||||||
|
if (lightMap == null) {
|
||||||
|
// make sure the lightMap is up-to-date
|
||||||
|
getCurrentLightMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
return LodUtil.intToColor(lightMap.getPixelRGBA(blockLight, skyLight));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//=============//
|
||||||
|
// Simple gets //
|
||||||
|
//=============//
|
||||||
|
|
||||||
|
public LocalPlayer 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()
|
||||||
|
{
|
||||||
|
ChunkPos playerPos = getPlayer().chunkPosition();
|
||||||
|
return new ChunkPosWrapper(playerPos.x, playerPos.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Options getOptions()
|
||||||
|
{
|
||||||
|
return mc.options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ModelManager getModelManager()
|
||||||
|
{
|
||||||
|
return mc.getModelManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClientLevel getClientLevel()
|
||||||
|
{
|
||||||
|
return mc.level;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IWorldWrapper getWrappedServerWorld()
|
||||||
|
{
|
||||||
|
if (mc.level == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
DimensionType dimension = mc.level.dimensionType();
|
||||||
|
IntegratedServer server = mc.getSingleplayerServer();
|
||||||
|
|
||||||
|
if (server == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
ServerLevel serverWorld = null;
|
||||||
|
Iterable<ServerLevel> worlds = server.getAllLevels();
|
||||||
|
for (ServerLevel world : worlds)
|
||||||
|
{
|
||||||
|
if (world.dimensionType() == dimension)
|
||||||
|
{
|
||||||
|
serverWorld = world;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return WorldWrapper.getWorldWrapper(serverWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldWrapper getWrappedClientLevel()
|
||||||
|
{
|
||||||
|
return WorldWrapper.getWorldWrapper(mc.level);
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorldWrapper getWrappedServerLevel()
|
||||||
|
{
|
||||||
|
|
||||||
|
if (mc.level == null)
|
||||||
|
return null;
|
||||||
|
DimensionType dimension = mc.level.dimensionType();
|
||||||
|
IntegratedServer server = mc.getSingleplayerServer();
|
||||||
|
if (server == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Iterable<ServerLevel> worlds = server.getAllLevels();
|
||||||
|
ServerLevel returnWorld = null;
|
||||||
|
|
||||||
|
for (ServerLevel world : worlds)
|
||||||
|
{
|
||||||
|
if (world.dimensionType() == dimension)
|
||||||
|
{
|
||||||
|
returnWorld = world;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return WorldWrapper.getWorldWrapper(returnWorld);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@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 ClientPacketListener getConnection()
|
||||||
|
{
|
||||||
|
return mc.getConnection();
|
||||||
|
}
|
||||||
|
|
||||||
|
public GameRenderer getGameRenderer()
|
||||||
|
{
|
||||||
|
return mc.gameRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Entity getCameraEntity()
|
||||||
|
{
|
||||||
|
return mc.cameraEntity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Window 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 LevelRenderer getLevelRenderer()
|
||||||
|
{
|
||||||
|
return mc.levelRenderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns all worlds available to the server */
|
||||||
|
@Override
|
||||||
|
public ArrayList<IWorldWrapper> getAllServerWorlds()
|
||||||
|
{
|
||||||
|
ArrayList<IWorldWrapper> worlds = new ArrayList<IWorldWrapper>();
|
||||||
|
|
||||||
|
Iterable<ServerLevel> serverWorlds = mc.getSingleplayerServer().getAllLevels();
|
||||||
|
for (ServerLevel world : serverWorlds)
|
||||||
|
{
|
||||||
|
worlds.add(WorldWrapper.getWorldWrapper(world));
|
||||||
|
}
|
||||||
|
|
||||||
|
return worlds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sendChatMessage(String string)
|
||||||
|
{
|
||||||
|
getPlayer().sendMessage(new TextComponent(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)
|
||||||
|
{
|
||||||
|
ApiShared.LOGGER.error(ModInfo.READABLE_NAME + " had the following error: [" + errorMessage + "]. Crashing Minecraft...");
|
||||||
|
CrashReport report = new CrashReport(errorMessage, exception);
|
||||||
|
Minecraft.crash(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+328
@@ -0,0 +1,328 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.minecraft;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.pipeline.RenderTarget;
|
||||||
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.seibel.lod.common.wrappers.misc.LightMapWrapper;
|
||||||
|
import com.seibel.lod.core.api.ApiShared;
|
||||||
|
import com.seibel.lod.core.api.ClientApi;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.util.LodUtil;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.LightTexture;
|
||||||
|
|
||||||
|
import com.mojang.math.Vector3f;
|
||||||
|
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.IWrapperFactory;
|
||||||
|
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.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||||
|
import com.seibel.lod.common.wrappers.McObjectConverter;
|
||||||
|
import com.seibel.lod.common.wrappers.WrapperFactory;
|
||||||
|
import com.seibel.lod.common.wrappers.block.BlockPosWrapper;
|
||||||
|
|
||||||
|
import net.minecraft.client.Camera;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer;
|
||||||
|
import net.minecraft.client.renderer.GameRenderer;
|
||||||
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.world.effect.MobEffects;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
import net.minecraft.world.level.material.FogType;
|
||||||
|
import net.minecraft.world.phys.AABB;
|
||||||
|
import net.minecraft.world.phys.Vec3;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A singleton that contains everything
|
||||||
|
* related to rendering in Minecraft.
|
||||||
|
*
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 12-12-2021
|
||||||
|
*/
|
||||||
|
public class MinecraftRenderWrapper implements IMinecraftRenderWrapper
|
||||||
|
{
|
||||||
|
public static final MinecraftRenderWrapper INSTANCE = new MinecraftRenderWrapper();
|
||||||
|
|
||||||
|
private static final Minecraft MC = Minecraft.getInstance();
|
||||||
|
private static final GameRenderer GAME_RENDERER = MC.gameRenderer;
|
||||||
|
private static final IWrapperFactory FACTORY = WrapperFactory.INSTANCE;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3f getLookAtVector()
|
||||||
|
{
|
||||||
|
Camera camera = GAME_RENDERER.getMainCamera();
|
||||||
|
Vector3f cameraDir = camera.getLookVector();
|
||||||
|
return new Vec3f(cameraDir.x(), cameraDir.y(), cameraDir.z());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractBlockPosWrapper getCameraBlockPosition()
|
||||||
|
{
|
||||||
|
Camera camera = GAME_RENDERER.getMainCamera();
|
||||||
|
BlockPos blockPos = camera.getBlockPosition();
|
||||||
|
return new BlockPosWrapper(blockPos.getX(), blockPos.getY(), blockPos.getZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean playerHasBlindnessEffect()
|
||||||
|
{
|
||||||
|
return MC.player.getActiveEffectsMap().get(MobEffects.BLINDNESS) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Vec3d getCameraExactPosition()
|
||||||
|
{
|
||||||
|
Camera camera = GAME_RENDERER.getMainCamera();
|
||||||
|
Vec3 projectedView = camera.getPosition();
|
||||||
|
|
||||||
|
return new Vec3d(projectedView.x, projectedView.y, projectedView.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mat4f getDefaultProjectionMatrix(float partialTicks)
|
||||||
|
{
|
||||||
|
return McObjectConverter.Convert(GAME_RENDERER.getProjectionMatrix(GAME_RENDERER.getFov(GAME_RENDERER.getMainCamera(), partialTicks, true)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double getGamma()
|
||||||
|
{
|
||||||
|
return MC.options.gamma;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getFogColor(float partialTicks) {
|
||||||
|
FogRenderer.setupColor(GAME_RENDERER.getMainCamera(), partialTicks, MC.level, 1, GAME_RENDERER.getDarkenWorldAmount(partialTicks));
|
||||||
|
float[] colorValues = RenderSystem.getShaderFogColor();
|
||||||
|
return new Color(colorValues[0], colorValues[1], colorValues[2], colorValues[3]);
|
||||||
|
}
|
||||||
|
// getSpecialFogColor() is the same as getFogColor()
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Color getSkyColor() {
|
||||||
|
if (MC.level.dimensionType().hasSkyLight()) {
|
||||||
|
Vec3 colorValues = MC.level.getSkyColor(MC.gameRenderer.getMainCamera().getPosition(), 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 GAME_RENDERER.getFov(GAME_RENDERER.getMainCamera(), partialTicks, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Measured in chunks */
|
||||||
|
@Override
|
||||||
|
public int getRenderDistance()
|
||||||
|
{
|
||||||
|
return MC.options.getEffectiveRenderDistance();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getScreenWidth()
|
||||||
|
{
|
||||||
|
return MC.getWindow().getWidth();
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getScreenHeight()
|
||||||
|
{
|
||||||
|
return MC.getWindow().getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
private RenderTarget getRenderTarget() {
|
||||||
|
RenderTarget r = null; //MC.levelRenderer.getCloudsTarget();
|
||||||
|
return r!=null ? r : MC.getMainRenderTarget();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTargetFrameBuffer() {
|
||||||
|
return getRenderTarget().frameBufferId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTargetFrameBufferViewportWidth() {
|
||||||
|
return getRenderTarget().viewWidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTargetFrameBufferViewportHeight() {
|
||||||
|
return getRenderTarget().viewHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method returns the ChunkPos of all chunks that Minecraft
|
||||||
|
* is going to render this frame. <br><br>
|
||||||
|
* <p>
|
||||||
|
*/
|
||||||
|
|
||||||
|
public boolean usingBackupGetVanillaRenderedChunks = true;
|
||||||
|
@Override
|
||||||
|
public HashSet<AbstractChunkPosWrapper> getVanillaRenderedChunks()
|
||||||
|
{
|
||||||
|
ISodiumAccessor sodium = ModAccessorHandler.get(ISodiumAccessor.class);
|
||||||
|
if (sodium != null)
|
||||||
|
{
|
||||||
|
return sodium.getNormalRenderedChunks();
|
||||||
|
}
|
||||||
|
IOptifineAccessor optifine = ModAccessorHandler.get(IOptifineAccessor.class);
|
||||||
|
if (optifine != null)
|
||||||
|
{
|
||||||
|
HashSet<AbstractChunkPosWrapper> pos = optifine.getNormalRenderedChunks();
|
||||||
|
if (pos == null)
|
||||||
|
pos = getMaximumRenderedChunks();
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
if (!usingBackupGetVanillaRenderedChunks) {
|
||||||
|
try {
|
||||||
|
LevelRenderer levelRenderer = MC.levelRenderer;
|
||||||
|
LinkedHashSet<LevelRenderer.RenderChunkInfo> chunks = levelRenderer.renderChunkStorage.get().renderChunks;
|
||||||
|
return (chunks.stream().map((chunk) -> {
|
||||||
|
#if MC_VERSION_1_18_2
|
||||||
|
AABB chunkBoundingBox = chunk.chunk.getBoundingBox();
|
||||||
|
#elif MC_VERSION_1_18_1
|
||||||
|
AABB chunkBoundingBox = chunk.chunk.bb;
|
||||||
|
#endif
|
||||||
|
return FACTORY.createChunkPos(Math.floorDiv((int) chunkBoundingBox.minX, 16),
|
||||||
|
Math.floorDiv((int) chunkBoundingBox.minZ, 16));
|
||||||
|
}).collect(Collectors.toCollection(HashSet::new)));
|
||||||
|
} catch (LinkageError e) {
|
||||||
|
try {
|
||||||
|
MinecraftClientWrapper.INSTANCE.sendChatMessage(
|
||||||
|
"\u00A7e\u00A7l\u00A7uWARNING: Distant Horizons: getVanillaRenderedChunks method failed."
|
||||||
|
+ " Using Backup Method.");
|
||||||
|
MinecraftClientWrapper.INSTANCE.sendChatMessage(
|
||||||
|
"\u00A7eOverdraw prevention will be worse than normal.");
|
||||||
|
} catch (Exception e2) {}
|
||||||
|
ApiShared.LOGGER.error("getVanillaRenderedChunks Error: ", e);
|
||||||
|
usingBackupGetVanillaRenderedChunks = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return getMaximumRenderedChunks();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] getLightmapPixels()
|
||||||
|
{
|
||||||
|
LightTexture tex = GAME_RENDERER.lightTexture();
|
||||||
|
tex.tick(); // This call makes no sense, but it fixes pause menu flicker bug
|
||||||
|
NativeImage lightMapPixels = tex.lightPixels;
|
||||||
|
LightMapWrapper lightMap = new LightMapWrapper(lightMapPixels);
|
||||||
|
|
||||||
|
|
||||||
|
int lightMapHeight = getLightmapTextureHeight();
|
||||||
|
int lightMapWidth = getLightmapTextureWidth();
|
||||||
|
|
||||||
|
int[] pixels = new int[lightMapWidth * lightMapHeight];
|
||||||
|
for (int u = 0; u < lightMapWidth; u++)
|
||||||
|
{
|
||||||
|
for (int v = 0; v < lightMapWidth; v++)
|
||||||
|
{
|
||||||
|
// this could probably be kept as a int, but
|
||||||
|
// it is easier to test and see the colors when debugging this way.
|
||||||
|
// When creating a new release this should be changed to the int version.
|
||||||
|
Color c = LodUtil.intToColor(lightMap.getLightValue(u, v));
|
||||||
|
|
||||||
|
// these should both create a totally white image
|
||||||
|
// int col =
|
||||||
|
// Integer.MAX_VALUE;
|
||||||
|
// int col =
|
||||||
|
// 0b11111111 + // red
|
||||||
|
// (0b11111111 << 8) + // green
|
||||||
|
// (0b11111111 << 16) + // blue
|
||||||
|
// (0b11111111 << 24); // blue
|
||||||
|
|
||||||
|
int col =
|
||||||
|
((c.getRed() & 0xFF) << 16) | // blue
|
||||||
|
((c.getGreen() & 0xFF) << 8) | // green
|
||||||
|
((c.getBlue() & 0xFF)) | // red
|
||||||
|
((c.getAlpha() & 0xFF) << 24); // alpha
|
||||||
|
|
||||||
|
// 2D array stored in a 1D array.
|
||||||
|
// Thank you Tim from College ;)
|
||||||
|
pixels[u * lightMapWidth + v] = col;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pixels;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLightmapTextureHeight()
|
||||||
|
{
|
||||||
|
int height = -1;
|
||||||
|
|
||||||
|
LightTexture lightTexture = GAME_RENDERER.lightTexture();
|
||||||
|
if (lightTexture != null)
|
||||||
|
{
|
||||||
|
NativeImage tex = lightTexture.lightPixels;
|
||||||
|
if (tex != null)
|
||||||
|
{
|
||||||
|
height = tex.getHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLightmapTextureWidth()
|
||||||
|
{
|
||||||
|
int width = -1;
|
||||||
|
|
||||||
|
LightTexture lightTexture = GAME_RENDERER.lightTexture();
|
||||||
|
if (lightTexture != null)
|
||||||
|
{
|
||||||
|
NativeImage tex = lightTexture.lightPixels;
|
||||||
|
if (tex != null)
|
||||||
|
{
|
||||||
|
width = tex.getWidth();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return width;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLightmapGLFormat() {
|
||||||
|
int glFormat = -1;
|
||||||
|
|
||||||
|
LightTexture lightTexture = GAME_RENDERER.lightTexture();
|
||||||
|
if (lightTexture != null) {
|
||||||
|
NativeImage tex = lightTexture.lightPixels;
|
||||||
|
if (tex != null) {
|
||||||
|
glFormat = tex.format().glFormat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return glFormat;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isFogStateSpecial() {
|
||||||
|
Entity entity = GAME_RENDERER.getMainCamera().getEntity();
|
||||||
|
boolean isBlind = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
|
||||||
|
return GAME_RENDERER.getMainCamera().getFluidInCamera() != FogType.NONE || isBlind;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean tryDisableVanillaFog() {
|
||||||
|
return true; // Handled via MixinFogRenderer in both forge and fabric
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.minecraft;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||||
|
|
||||||
|
import net.minecraft.util.profiling.ProfilerFiller;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 11-20-2021
|
||||||
|
*/
|
||||||
|
public class ProfilerWrapper implements IProfilerWrapper
|
||||||
|
{
|
||||||
|
public ProfilerFiller profiler;
|
||||||
|
|
||||||
|
public ProfilerWrapper(ProfilerFiller 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,29 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.misc;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.platform.NativeImage;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.misc.ILightMapWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 11-21-2021
|
||||||
|
*/
|
||||||
|
public class LightMapWrapper implements ILightMapWrapper
|
||||||
|
{
|
||||||
|
static NativeImage lightMap = null;
|
||||||
|
|
||||||
|
public LightMapWrapper(NativeImage newLightMap)
|
||||||
|
{
|
||||||
|
lightMap = newLightMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setLightMap(NativeImage newLightMap)
|
||||||
|
{
|
||||||
|
lightMap = newLightMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getLightValue(int skyLight, int blockLight)
|
||||||
|
{
|
||||||
|
return lightMap.getPixelRGBA(skyLight, blockLight);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
* 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.common.wrappers.world;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.util.LodUtil;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.material.MaterialColor;
|
||||||
|
|
||||||
|
//This class wraps the minecraft BlockPos.Mutable (and BlockPos) class
|
||||||
|
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 IBiomeWrapper 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;
|
||||||
|
|
||||||
|
switch (biome.biomeCategory)
|
||||||
|
{
|
||||||
|
|
||||||
|
case NETHER:
|
||||||
|
colorInt = Blocks.NETHERRACK.defaultBlockState().getMaterial().getColor().col;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case THEEND:
|
||||||
|
colorInt = Blocks.END_STONE.defaultBlockState().getMaterial().getColor().col;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BEACH:
|
||||||
|
case DESERT:
|
||||||
|
colorInt = Blocks.SAND.defaultBlockState().getMaterial().getColor().col;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EXTREME_HILLS:
|
||||||
|
colorInt = Blocks.STONE.defaultMaterialColor().col;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MUSHROOM:
|
||||||
|
colorInt = MaterialColor.COLOR_LIGHT_GRAY.col;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ICY:
|
||||||
|
colorInt = Blocks.SNOW.defaultMaterialColor().col;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MESA:
|
||||||
|
colorInt = Blocks.RED_SAND.defaultMaterialColor().col;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OCEAN:
|
||||||
|
case RIVER:
|
||||||
|
colorInt = biome.getWaterColor();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case NONE:
|
||||||
|
case FOREST:
|
||||||
|
case TAIGA:
|
||||||
|
case JUNGLE:
|
||||||
|
case PLAINS:
|
||||||
|
case SAVANNA:
|
||||||
|
case SWAMP:
|
||||||
|
default:
|
||||||
|
Color tmp = LodUtil.intToColor(biome.getGrassColor(x, z));
|
||||||
|
tmp = tmp.darker();
|
||||||
|
colorInt = LodUtil.colorToInt(tmp);
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return colorInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public String getName()
|
||||||
|
{
|
||||||
|
return biome.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@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 obj)
|
||||||
|
{
|
||||||
|
if (this == obj)
|
||||||
|
return true;
|
||||||
|
if (!(obj instanceof BiomeWrapper))
|
||||||
|
return false;
|
||||||
|
BiomeWrapper that = (BiomeWrapper) obj;
|
||||||
|
return Objects.equals(biome, that.biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override public int hashCode()
|
||||||
|
{
|
||||||
|
return Objects.hash(biome);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
/*
|
||||||
|
* 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.common.wrappers.world;
|
||||||
|
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.dimension.DimensionType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 11-21-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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearMap()
|
||||||
|
{
|
||||||
|
dimensionTypeWrapperMap.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@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,187 @@
|
|||||||
|
/*
|
||||||
|
* 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.common.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.chunk.AbstractChunkPosWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.server.level.ServerChunkCache;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkSource;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author James Seibel
|
||||||
|
* @author ??
|
||||||
|
* @version 11-21-2021
|
||||||
|
*/
|
||||||
|
public class WorldWrapper implements IWorldWrapper
|
||||||
|
{
|
||||||
|
private static final ConcurrentMap<LevelAccessor, WorldWrapper> worldWrapperMap = new ConcurrentHashMap<>();
|
||||||
|
private final LevelAccessor world;
|
||||||
|
public final WorldType worldType;
|
||||||
|
|
||||||
|
|
||||||
|
public WorldWrapper(LevelAccessor newWorld)
|
||||||
|
{
|
||||||
|
world = newWorld;
|
||||||
|
|
||||||
|
if (world.getClass() == ServerLevel.class)
|
||||||
|
worldType = WorldType.ServerWorld;
|
||||||
|
else if (world.getClass() == ClientLevel.class)
|
||||||
|
worldType = WorldType.ClientWorld;
|
||||||
|
else
|
||||||
|
worldType = WorldType.Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public static WorldWrapper getWorldWrapper(LevelAccessor 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(int x, int y, int z)
|
||||||
|
{
|
||||||
|
return world.getBrightness(LightLayer.BLOCK, new BlockPos(x,y,z));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSkyLight(int x, int y, int z)
|
||||||
|
{
|
||||||
|
return world.getBrightness(LightLayer.SKY, new BlockPos(x,y,z));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LevelAccessor getWorld()
|
||||||
|
{
|
||||||
|
return world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasCeiling()
|
||||||
|
{
|
||||||
|
return world.dimensionType().hasCeiling();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasSkyLight()
|
||||||
|
{
|
||||||
|
return world.dimensionType().hasSkyLight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight()
|
||||||
|
{
|
||||||
|
return world.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public short getMinHeight()
|
||||||
|
{
|
||||||
|
return (short) world.getMinBuildHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @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.");
|
||||||
|
|
||||||
|
ServerChunkCache chunkSource = ((ServerLevel) world).getChunkSource();
|
||||||
|
return chunkSource.getDataStorage().dataFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** @throws UnsupportedOperationException if the WorldWrapper isn't for a ServerWorld */
|
||||||
|
public ServerLevel getServerWorld() throws UnsupportedOperationException
|
||||||
|
{
|
||||||
|
if (worldType != WorldType.ServerWorld)
|
||||||
|
throw new UnsupportedOperationException("getSaveFolder can only be called for ServerWorlds.");
|
||||||
|
|
||||||
|
return (ServerLevel) world;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getSeaLevel()
|
||||||
|
{
|
||||||
|
// TODO this is depreciated, what should we use instead?
|
||||||
|
return world.getSeaLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IChunkWrapper tryGetChunk(AbstractChunkPosWrapper pos) {
|
||||||
|
ChunkAccess chunk = world.getChunk(pos.getX(), pos.getZ(), ChunkStatus.EMPTY, false);
|
||||||
|
if (chunk == null) return null;
|
||||||
|
return new ChunkWrapper(chunk, world);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasChunkLoaded(int chunkX, int chunkZ) {
|
||||||
|
// world.hasChunk(chunkX, chunkZ); THIS DOES NOT WORK FOR CLIENT LEVEL CAUSE MOJANG ALWAYS RETURN TRUE FOR THAT!
|
||||||
|
ChunkSource source = world.getChunkSource();
|
||||||
|
return source.hasChunk(chunkX, chunkZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
+607
@@ -0,0 +1,607 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||||
|
* licensed under the GNU GPL v3 License.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021 Tom Lee (TomTheFurry)
|
||||||
|
*
|
||||||
|
* 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.common.wrappers.worldGeneration;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.api.ApiShared;
|
||||||
|
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.enums.config.LightGenerationMode;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||||
|
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||||
|
import com.seibel.lod.core.util.LodThreadFactory;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.DependencySetupDoneCheck;
|
||||||
|
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.ChunkLoader;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightGetterAdaptor;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.LightedWorldGenRegion;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenLevelLightEngine;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.step.StepBiomes;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.step.StepFeatures;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.step.StepLight;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.step.StepNoise;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.step.StepStructureReference;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.step.StepStructureStart;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.step.StepSurface;
|
||||||
|
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
import net.minecraft.world.level.chunk.UpgradeData;
|
||||||
|
import net.minecraft.world.level.levelgen.DebugLevelSource;
|
||||||
|
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||||
|
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Total: 3.135214124s
|
||||||
|
=====================================
|
||||||
|
Empty Chunks: 0.000558328s
|
||||||
|
StructureStart Step: 0.025177207s
|
||||||
|
StructureReference Step: 0.00189559s
|
||||||
|
Biome Step: 0.13789155s
|
||||||
|
Noise Step: 1.570347555s
|
||||||
|
Surface Step: 0.741238194s
|
||||||
|
Carver Step: 0.000009923s
|
||||||
|
Feature Step: 0.389072425s
|
||||||
|
Lod Generation: 0.269023348s
|
||||||
|
*/
|
||||||
|
|
||||||
|
public final class BatchGenerationEnvironment extends AbstractBatchGenerationEnvionmentWrapper
|
||||||
|
{
|
||||||
|
public static final boolean ENABLE_PERF_LOGGING = false;
|
||||||
|
public static final boolean ENABLE_EVENT_LOGGING = false;
|
||||||
|
public static final boolean ENABLE_LOAD_EVENT_LOGGING = false;
|
||||||
|
//TODO: Make actual proper support for StarLight
|
||||||
|
|
||||||
|
public static class PrefEvent
|
||||||
|
{
|
||||||
|
long beginNano = 0;
|
||||||
|
long emptyNano = 0;
|
||||||
|
long structStartNano = 0;
|
||||||
|
long structRefNano = 0;
|
||||||
|
long biomeNano = 0;
|
||||||
|
long noiseNano = 0;
|
||||||
|
long surfaceNano = 0;
|
||||||
|
long carverNano = 0;
|
||||||
|
long featureNano = 0;
|
||||||
|
long lightNano = 0;
|
||||||
|
long endNano = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "beginNano: " + beginNano + ",\n" +
|
||||||
|
"emptyNano: " + emptyNano + ",\n" +
|
||||||
|
"structStartNano: " + structStartNano + ",\n" +
|
||||||
|
"structRefNano: " + structRefNano + ",\n" +
|
||||||
|
"biomeNano: " + biomeNano + ",\n" +
|
||||||
|
"noiseNano: " + noiseNano + ",\n" +
|
||||||
|
"surfaceNano: " + surfaceNano + ",\n" +
|
||||||
|
"carverNano: " + carverNano + ",\n" +
|
||||||
|
"featureNano: " + featureNano + ",\n" +
|
||||||
|
"lightNano: " + lightNano + ",\n" +
|
||||||
|
"endNano: " + endNano + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PerfCalculator
|
||||||
|
{
|
||||||
|
public static final int SIZE = 50;
|
||||||
|
Rolling totalTime = new Rolling(SIZE);
|
||||||
|
Rolling emptyTime = new Rolling(SIZE);
|
||||||
|
Rolling structStartTime = new Rolling(SIZE);
|
||||||
|
Rolling structRefTime = new Rolling(SIZE);
|
||||||
|
Rolling biomeTime = new Rolling(SIZE);
|
||||||
|
Rolling noiseTime = new Rolling(SIZE);
|
||||||
|
Rolling surfaceTime = new Rolling(SIZE);
|
||||||
|
Rolling carverTime = new Rolling(SIZE);
|
||||||
|
Rolling featureTime = new Rolling(SIZE);
|
||||||
|
Rolling lightTime = new Rolling(SIZE);
|
||||||
|
Rolling lodTime = new Rolling(SIZE);
|
||||||
|
|
||||||
|
public void recordEvent(PrefEvent e)
|
||||||
|
{
|
||||||
|
long preTime = e.beginNano;
|
||||||
|
totalTime.add(e.endNano - preTime);
|
||||||
|
if (e.emptyNano != 0)
|
||||||
|
{
|
||||||
|
emptyTime.add(e.emptyNano - preTime);
|
||||||
|
preTime = e.emptyNano;
|
||||||
|
}
|
||||||
|
if (e.structStartNano != 0)
|
||||||
|
{
|
||||||
|
structStartTime.add(e.structStartNano - preTime);
|
||||||
|
preTime = e.structStartNano;
|
||||||
|
}
|
||||||
|
if (e.structRefNano != 0)
|
||||||
|
{
|
||||||
|
structRefTime.add(e.structRefNano - preTime);
|
||||||
|
preTime = e.structRefNano;
|
||||||
|
}
|
||||||
|
if (e.biomeNano != 0)
|
||||||
|
{
|
||||||
|
biomeTime.add(e.biomeNano - preTime);
|
||||||
|
preTime = e.biomeNano;
|
||||||
|
}
|
||||||
|
if (e.noiseNano != 0)
|
||||||
|
{
|
||||||
|
noiseTime.add(e.noiseNano - preTime);
|
||||||
|
preTime = e.noiseNano;
|
||||||
|
}
|
||||||
|
if (e.surfaceNano != 0)
|
||||||
|
{
|
||||||
|
surfaceTime.add(e.surfaceNano - preTime);
|
||||||
|
preTime = e.surfaceNano;
|
||||||
|
}
|
||||||
|
if (e.carverNano != 0)
|
||||||
|
{
|
||||||
|
carverTime.add(e.carverNano - preTime);
|
||||||
|
preTime = e.carverNano;
|
||||||
|
}
|
||||||
|
if (e.featureNano != 0)
|
||||||
|
{
|
||||||
|
featureTime.add(e.featureNano - preTime);
|
||||||
|
preTime = e.featureNano;
|
||||||
|
}
|
||||||
|
if (e.lightNano != 0)
|
||||||
|
{
|
||||||
|
lightTime.add(e.lightNano - preTime);
|
||||||
|
preTime = e.lightNano;
|
||||||
|
}
|
||||||
|
if (e.endNano != 0)
|
||||||
|
{
|
||||||
|
lodTime.add(e.endNano - preTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return "Total: " + Duration.ofNanos((long) totalTime.getAverage()) + ", Empty/LoadChunk: "
|
||||||
|
+ Duration.ofNanos((long) emptyTime.getAverage()) + ", StructStart: "
|
||||||
|
+ Duration.ofNanos((long) structStartTime.getAverage()) + ", StructRef: "
|
||||||
|
+ Duration.ofNanos((long) structRefTime.getAverage()) + ", Biome: "
|
||||||
|
+ Duration.ofNanos((long) biomeTime.getAverage()) + ", Noise: "
|
||||||
|
+ Duration.ofNanos((long) noiseTime.getAverage()) + ", Surface: "
|
||||||
|
+ Duration.ofNanos((long) surfaceTime.getAverage()) + ", Carver: "
|
||||||
|
+ Duration.ofNanos((long) carverTime.getAverage()) + ", Feature: "
|
||||||
|
+ Duration.ofNanos((long) featureTime.getAverage()) + ", Light: "
|
||||||
|
+ Duration.ofNanos((long) lightTime.getAverage()) + ", Lod: "
|
||||||
|
+ Duration.ofNanos((long) lodTime.getAverage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final int TIMEOUT_SECONDS = 60;
|
||||||
|
|
||||||
|
//=================Generation Step===================
|
||||||
|
|
||||||
|
public final LinkedList<GenerationEvent> events = new LinkedList<>();
|
||||||
|
public final GlobalParameters params;
|
||||||
|
public final StepStructureStart stepStructureStart = new StepStructureStart(this);
|
||||||
|
public final StepStructureReference stepStructureReference = new StepStructureReference(this);
|
||||||
|
public final StepBiomes stepBiomes = new StepBiomes(this);
|
||||||
|
public final StepNoise stepNoise = new StepNoise(this);
|
||||||
|
public final StepSurface stepSurface = new StepSurface(this);
|
||||||
|
public final StepFeatures stepFeatures = new StepFeatures(this);
|
||||||
|
public final StepLight stepLight = new StepLight(this);
|
||||||
|
public boolean unsafeThreadingRecorded = false;
|
||||||
|
//public boolean safeMode = false;
|
||||||
|
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||||
|
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
|
||||||
|
public static final long EXCEPTION_TIMER_RESET_TIME = TimeUnit.NANOSECONDS.convert(1, TimeUnit.SECONDS);
|
||||||
|
public static final int EXCEPTION_COUNTER_TRIGGER = 20;
|
||||||
|
public static final int RANGE_TO_RANGE_EMPTY_EXTENSION = 1;
|
||||||
|
public int unknownExceptionCount = 0;
|
||||||
|
public long lastExceptionTriggerTime = 0;
|
||||||
|
|
||||||
|
public static final LodThreadFactory threadFactory = new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY);
|
||||||
|
|
||||||
|
public static ThreadLocal<Boolean> isDistantGeneratorThread = new ThreadLocal<>();
|
||||||
|
|
||||||
|
public static boolean isCurrentThreadDistantGeneratorThread() {
|
||||||
|
return (isDistantGeneratorThread.get() != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
static {
|
||||||
|
DependencySetupDoneCheck.getIsCurrentThreadDistantGeneratorThread = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExecutorService executors = Executors.newFixedThreadPool(
|
||||||
|
CONFIG.client().advanced().threading().getNumberOfWorldGenerationThreads(), threadFactory);
|
||||||
|
|
||||||
|
public <T> T joinSync(CompletableFuture<T> f) {
|
||||||
|
if (!unsafeThreadingRecorded && !f.isDone()) {
|
||||||
|
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons: Unsafe Threading in Chunk Generator Detected!");
|
||||||
|
MC.sendChatMessage("\u00A7eTo increase stability, it is recommended to set world generation threads count to 1.");
|
||||||
|
ApiShared.LOGGER.error("Unsafe Threading in Chunk Generator: ", new RuntimeException("Concurrent future"));
|
||||||
|
unsafeThreadingRecorded = true;
|
||||||
|
}
|
||||||
|
return f.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resizeThreadPool(int newThreadCount)
|
||||||
|
{
|
||||||
|
executors = Executors.newFixedThreadPool(newThreadCount,
|
||||||
|
new LodThreadFactory("Gen-Worker-Thread", Thread.MIN_PRIORITY));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tryAddPoint(int px, int pz, int range, Steps target, boolean genAllDetails)
|
||||||
|
{
|
||||||
|
int boxSize = range * 2 + 1;
|
||||||
|
int x = Math.floorDiv(px, boxSize) * boxSize + range;
|
||||||
|
int z = Math.floorDiv(pz, boxSize) * boxSize + range;
|
||||||
|
|
||||||
|
for (GenerationEvent event : events)
|
||||||
|
{
|
||||||
|
if (event.tooClose(x, z, range))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// System.out.println(x + ", "+z);
|
||||||
|
events.add(new GenerationEvent(new ChunkPos(x, z), range, this, target, genAllDetails));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAllFutures()
|
||||||
|
{
|
||||||
|
if (unknownExceptionCount > 0) {
|
||||||
|
if (System.nanoTime() - lastExceptionTriggerTime >= EXCEPTION_TIMER_RESET_TIME) {
|
||||||
|
unknownExceptionCount = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update all current out standing jobs
|
||||||
|
Iterator<GenerationEvent> iter = events.iterator();
|
||||||
|
while (iter.hasNext())
|
||||||
|
{
|
||||||
|
GenerationEvent event = iter.next();
|
||||||
|
if (event.isCompleted())
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
event.join();
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
ApiShared.LOGGER.error("Batching World Generator: Event {} gotten an exception", event);
|
||||||
|
ApiShared.LOGGER.error("Exception: ", e);
|
||||||
|
unknownExceptionCount++;
|
||||||
|
lastExceptionTriggerTime = System.nanoTime();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (event.hasTimeout(TIMEOUT_SECONDS, TimeUnit.SECONDS))
|
||||||
|
{
|
||||||
|
ApiShared.LOGGER.error("Batching World Generator: " + event + " timed out and terminated!");
|
||||||
|
ApiShared.LOGGER.info("Dump PrefEvent: " + event.pEvent);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!event.terminate())
|
||||||
|
ApiShared.LOGGER.error("Failed to terminate the stuck generation event!");
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
iter.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (unknownExceptionCount > EXCEPTION_COUNTER_TRIGGER) {
|
||||||
|
try {
|
||||||
|
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons: Too many exceptions in Batching World Generator! Disabling the generator.");
|
||||||
|
} catch (Exception e) {}
|
||||||
|
ApiShared.LOGGER.error("Too many exceptions in Batching World Generator! Now disabling.");
|
||||||
|
unknownExceptionCount = 0;
|
||||||
|
CONFIG.client().worldGenerator().setEnableDistantGeneration(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public BatchGenerationEnvironment(IWorldWrapper serverlevel, LodBuilder lodBuilder, LodDimension lodDim)
|
||||||
|
{
|
||||||
|
super(serverlevel, lodBuilder, lodDim);
|
||||||
|
ApiShared.LOGGER.info("================WORLD_GEN_STEP_INITING=============");
|
||||||
|
ChunkGenerator generator = ((WorldWrapper) serverlevel).getServerWorld().getChunkSource().getGenerator();
|
||||||
|
if (!(generator instanceof NoiseBasedChunkGenerator ||
|
||||||
|
generator instanceof DebugLevelSource ||
|
||||||
|
generator instanceof FlatLevelSource)) {
|
||||||
|
MC.sendChatMessage("\u00A74\u00A7l\u00A7uWARNING: Distant Horizons: Unknown Chunk Generator Detected! Distant Generation May Fail!");
|
||||||
|
MC.sendChatMessage("\u00A7eIf it does crash, set Distant Generation to OFF or Generation Mode to None.");
|
||||||
|
ApiShared.LOGGER.warn("Unknown Chunk Generator detected: {}", generator.getClass());
|
||||||
|
}
|
||||||
|
params = new GlobalParameters((ServerLevel) ((WorldWrapper) serverlevel).getWorld(), lodBuilder, lodDim);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
public static ChunkAccess loadOrMakeChunk(ChunkPos chunkPos, ServerLevel level, LevelLightEngine lightEngine)
|
||||||
|
{
|
||||||
|
CompoundTag chunkData = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
chunkData = level.getChunkSource().chunkMap.readChunk(chunkPos);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
ApiShared.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
|
||||||
|
}
|
||||||
|
if (chunkData == null)
|
||||||
|
{
|
||||||
|
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return ChunkLoader.read(level, lightEngine, chunkPos, chunkData);
|
||||||
|
} catch (Exception e) {
|
||||||
|
ApiShared.LOGGER.error("DistantHorizons: Couldn't load chunk {}", chunkPos, e);
|
||||||
|
return new ProtoChunk(chunkPos, UpgradeData.EMPTY, level, level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY), null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateLodFromList(GenerationEvent e)
|
||||||
|
{
|
||||||
|
if (ENABLE_EVENT_LOGGING)
|
||||||
|
ApiShared.LOGGER.info("Lod Generate Event: " + e.pos);
|
||||||
|
e.pEvent.beginNano = System.nanoTime();
|
||||||
|
ArrayGridList<ChunkAccess> referencedChunks;
|
||||||
|
ArrayGridList<ChunkAccess> genChunks;
|
||||||
|
DistanceGenerationMode generationMode;
|
||||||
|
LightedWorldGenRegion region;
|
||||||
|
WorldGenLevelLightEngine lightEngine;
|
||||||
|
LightGetterAdaptor adaptor;
|
||||||
|
int refRange = e.range + RANGE_TO_RANGE_EMPTY_EXTENSION;
|
||||||
|
int refOffsetX = e.pos.x - refRange;
|
||||||
|
int refOffsetZ = e.pos.z - refRange;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
adaptor = new LightGetterAdaptor(params.level);
|
||||||
|
lightEngine = new WorldGenLevelLightEngine(adaptor);
|
||||||
|
|
||||||
|
@SuppressWarnings("resource")
|
||||||
|
EmptyChunkGenerator generator = (int x, int z) ->
|
||||||
|
{
|
||||||
|
ChunkPos chunkPos = new ChunkPos(x, z);
|
||||||
|
ChunkAccess target = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
target = loadOrMakeChunk(chunkPos, params.level, lightEngine);
|
||||||
|
}
|
||||||
|
catch (RuntimeException e2)
|
||||||
|
{
|
||||||
|
// Continue...
|
||||||
|
}
|
||||||
|
if (target == null)
|
||||||
|
target = new ProtoChunk(chunkPos, UpgradeData.EMPTY, params.level,
|
||||||
|
params.biomes, null);
|
||||||
|
return target;
|
||||||
|
};
|
||||||
|
|
||||||
|
referencedChunks = new ArrayGridList<>(refRange*2+1,
|
||||||
|
(x,z) -> generator.generate(x + refOffsetX,z + refOffsetZ)
|
||||||
|
);
|
||||||
|
e.pEvent.emptyNano = System.nanoTime();
|
||||||
|
e.refreshTimeout();
|
||||||
|
region = new LightedWorldGenRegion(params.level, lightEngine, referencedChunks,
|
||||||
|
ChunkStatus.STRUCTURE_STARTS, refRange, e.lightMode, generator);
|
||||||
|
adaptor.setRegion(region);
|
||||||
|
e.tParam.makeStructFeat(region);
|
||||||
|
genChunks = new ArrayGridList<>(referencedChunks, RANGE_TO_RANGE_EMPTY_EXTENSION,
|
||||||
|
referencedChunks.gridSize - RANGE_TO_RANGE_EMPTY_EXTENSION);
|
||||||
|
generateDirect(e, genChunks, e.target, region);
|
||||||
|
}
|
||||||
|
catch (StepStructureStart.StructStartCorruptedException f)
|
||||||
|
{
|
||||||
|
e.tParam.markAsInvalid();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (e.target)
|
||||||
|
{
|
||||||
|
case Empty:
|
||||||
|
case StructureStart:
|
||||||
|
case StructureReference:
|
||||||
|
generationMode = DistanceGenerationMode.NONE;
|
||||||
|
break;
|
||||||
|
case Biomes:
|
||||||
|
generationMode = DistanceGenerationMode.BIOME_ONLY;
|
||||||
|
case Noise:
|
||||||
|
generationMode = DistanceGenerationMode.BIOME_ONLY_SIMULATE_HEIGHT;
|
||||||
|
break;
|
||||||
|
case Surface:
|
||||||
|
case Carvers:
|
||||||
|
generationMode = DistanceGenerationMode.SURFACE;
|
||||||
|
break;
|
||||||
|
case Features:
|
||||||
|
generationMode = DistanceGenerationMode.FEATURES;
|
||||||
|
break;
|
||||||
|
case Light:
|
||||||
|
case LiquidCarvers:
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int oy = 0; oy < genChunks.gridSize; oy++)
|
||||||
|
{
|
||||||
|
for (int ox = 0; ox < genChunks.gridSize; ox++)
|
||||||
|
{
|
||||||
|
ChunkAccess target = genChunks.get(ox, oy);
|
||||||
|
ChunkWrapper wrappedChunk = new ChunkWrapper(target, region);
|
||||||
|
if (!wrappedChunk.isLightCorrect()) {
|
||||||
|
throw new RuntimeException("The generated chunk somehow has isLightCorrect() returning false");
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isFull = target.getStatus() == ChunkStatus.FULL || target instanceof LevelChunk;
|
||||||
|
boolean isPartial = target.isOldNoiseGeneration();
|
||||||
|
if (isFull)
|
||||||
|
{
|
||||||
|
if (ENABLE_LOAD_EVENT_LOGGING)
|
||||||
|
ApiShared.LOGGER.info("Detected full existing chunk at {}", target.getPos());
|
||||||
|
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||||
|
new LodBuilderConfig(DistanceGenerationMode.FULL), true, e.genAllDetails);
|
||||||
|
}
|
||||||
|
else if (isPartial)
|
||||||
|
{
|
||||||
|
if (ENABLE_LOAD_EVENT_LOGGING)
|
||||||
|
ApiShared.LOGGER.info("Detected old existing chunk at {}", target.getPos());
|
||||||
|
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||||
|
new LodBuilderConfig(generationMode), true, e.genAllDetails);
|
||||||
|
}
|
||||||
|
else if (target.getStatus() == ChunkStatus.EMPTY && generationMode == DistanceGenerationMode.NONE)
|
||||||
|
{
|
||||||
|
params.lodBuilder.generateLodNodeFromChunk(params.lodDim,wrappedChunk,
|
||||||
|
LodBuilderConfig.getFillVoidConfig(), true, e.genAllDetails);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
params.lodBuilder.generateLodNodeFromChunk(params.lodDim, wrappedChunk,
|
||||||
|
new LodBuilderConfig(generationMode), true, e.genAllDetails);
|
||||||
|
}
|
||||||
|
if (e.lightMode == LightGenerationMode.FANCY || isFull)
|
||||||
|
{
|
||||||
|
lightEngine.retainData(target.getPos(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
e.pEvent.endNano = System.nanoTime();
|
||||||
|
e.refreshTimeout();
|
||||||
|
if (ENABLE_PERF_LOGGING)
|
||||||
|
{
|
||||||
|
e.tParam.perf.recordEvent(e.pEvent);
|
||||||
|
ApiShared.LOGGER.info(e.tParam.perf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateDirect(GenerationEvent e, ArrayGridList<ChunkAccess> subRange, Steps step,
|
||||||
|
LightedWorldGenRegion region)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
subRange.forEach((chunk) ->
|
||||||
|
{
|
||||||
|
if (chunk instanceof ProtoChunk)
|
||||||
|
{
|
||||||
|
((ProtoChunk) chunk).setLightEngine(region.getLightEngine());
|
||||||
|
region.getLightEngine().retainData(chunk.getPos(), true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (step == Steps.Empty)
|
||||||
|
return;
|
||||||
|
stepStructureStart.generateGroup(e.tParam, region, subRange);
|
||||||
|
e.pEvent.structStartNano = System.nanoTime();
|
||||||
|
e.refreshTimeout();
|
||||||
|
if (step == Steps.StructureStart)
|
||||||
|
return;
|
||||||
|
stepStructureReference.generateGroup(e.tParam, region, subRange);
|
||||||
|
e.pEvent.structRefNano = System.nanoTime();
|
||||||
|
e.refreshTimeout();
|
||||||
|
if (step == Steps.StructureReference)
|
||||||
|
return;
|
||||||
|
stepBiomes.generateGroup(e.tParam, region, subRange);
|
||||||
|
e.pEvent.biomeNano = System.nanoTime();
|
||||||
|
e.refreshTimeout();
|
||||||
|
if (step == Steps.Biomes)
|
||||||
|
return;
|
||||||
|
stepNoise.generateGroup(e.tParam, region, subRange);
|
||||||
|
e.pEvent.noiseNano = System.nanoTime();
|
||||||
|
e.refreshTimeout();
|
||||||
|
if (step == Steps.Noise)
|
||||||
|
return;
|
||||||
|
stepSurface.generateGroup(e.tParam, region, subRange);
|
||||||
|
e.pEvent.surfaceNano = System.nanoTime();
|
||||||
|
e.refreshTimeout();
|
||||||
|
if (step == Steps.Surface)
|
||||||
|
return;
|
||||||
|
if (step == Steps.Carvers)
|
||||||
|
return;
|
||||||
|
stepFeatures.generateGroup(e.tParam, region, subRange);
|
||||||
|
e.pEvent.featureNano = System.nanoTime();
|
||||||
|
e.refreshTimeout();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
switch (region.lightMode)
|
||||||
|
{
|
||||||
|
case FANCY:
|
||||||
|
stepLight.generateGroup(region.getLightEngine(), subRange);
|
||||||
|
break;
|
||||||
|
case FAST:
|
||||||
|
subRange.forEach((p) ->
|
||||||
|
{
|
||||||
|
if (p instanceof ProtoChunk)
|
||||||
|
((ProtoChunk) p).setLightCorrect(true);
|
||||||
|
if (p instanceof LevelChunk) {
|
||||||
|
((LevelChunk) p).setLightCorrect(true);
|
||||||
|
((LevelChunk) p).setClientLightReady(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
e.pEvent.lightNano = System.nanoTime();
|
||||||
|
e.refreshTimeout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface EmptyChunkGenerator
|
||||||
|
{
|
||||||
|
ChunkAccess generate(int x, int z);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getEventCount() {
|
||||||
|
return events.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void stop(boolean blocking) {
|
||||||
|
ApiShared.LOGGER.info("Batch Chunk Generator shutting down...");
|
||||||
|
executors.shutdownNow();
|
||||||
|
if (blocking) try {
|
||||||
|
if (!executors.awaitTermination(10, TimeUnit.SECONDS)) {
|
||||||
|
ApiShared.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...");
|
||||||
|
}
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
ApiShared.LOGGER.error("Batch Chunk Generator shutdown failed! Ignoring child threads...", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+111
@@ -0,0 +1,111 @@
|
|||||||
|
|
||||||
|
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PrefEvent;
|
||||||
|
import com.seibel.lod.core.api.ApiShared;
|
||||||
|
import com.seibel.lod.core.enums.config.LightGenerationMode;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.util.LodUtil;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.worldGeneration.AbstractBatchGenerationEnvionmentWrapper.Steps;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
|
||||||
|
//======================= Main Event class======================
|
||||||
|
public final class GenerationEvent
|
||||||
|
{
|
||||||
|
static private final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||||
|
|
||||||
|
private static int generationFutureDebugIDs = 0;
|
||||||
|
final ThreadedParameters tParam;
|
||||||
|
final ChunkPos pos;
|
||||||
|
final int range;
|
||||||
|
final Future<?> future;
|
||||||
|
long nanotime;
|
||||||
|
final int id;
|
||||||
|
final Steps target;
|
||||||
|
final LightGenerationMode lightMode;
|
||||||
|
final PrefEvent pEvent = new PrefEvent();
|
||||||
|
final boolean genAllDetails;
|
||||||
|
|
||||||
|
public GenerationEvent(ChunkPos pos, int range, BatchGenerationEnvironment generationGroup, Steps target, boolean genAllDetails)
|
||||||
|
{
|
||||||
|
nanotime = System.nanoTime();
|
||||||
|
this.pos = pos;
|
||||||
|
this.range = range;
|
||||||
|
id = generationFutureDebugIDs++;
|
||||||
|
this.target = target;
|
||||||
|
this.tParam = ThreadedParameters.getOrMake(generationGroup.params);
|
||||||
|
LightGenerationMode mode = CONFIG.client().worldGenerator().getLightGenerationMode();
|
||||||
|
|
||||||
|
this.lightMode = mode;
|
||||||
|
this.genAllDetails = genAllDetails;
|
||||||
|
|
||||||
|
future = generationGroup.executors.submit(() ->
|
||||||
|
{
|
||||||
|
BatchGenerationEnvironment.isDistantGeneratorThread.set(true);
|
||||||
|
try {
|
||||||
|
generationGroup.generateLodFromList(this);
|
||||||
|
} finally {
|
||||||
|
BatchGenerationEnvironment.isDistantGeneratorThread.remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCompleted()
|
||||||
|
{
|
||||||
|
return future.isDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasTimeout(int duration, TimeUnit unit)
|
||||||
|
{
|
||||||
|
long currentTime = System.nanoTime();
|
||||||
|
long delta = currentTime - nanotime;
|
||||||
|
return (delta > TimeUnit.NANOSECONDS.convert(duration, unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean terminate()
|
||||||
|
{
|
||||||
|
ApiShared.LOGGER.info("======================DUMPING ALL THREADS FOR WORLD GEN=======================");
|
||||||
|
BatchGenerationEnvironment.threadFactory.dumpAllThreadStacks();
|
||||||
|
future.cancel(true);
|
||||||
|
return future.isCancelled();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void join()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
future.get();
|
||||||
|
}
|
||||||
|
catch (InterruptedException | ExecutionException e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e.getCause()==null? e : e.getCause());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean tooClose(int cx, int cz, int cr)
|
||||||
|
{
|
||||||
|
int distX = Math.abs(cx - pos.x);
|
||||||
|
int distZ = Math.abs(cz - pos.z);
|
||||||
|
int minRange = cr + range + 1; // Need one to account for the center
|
||||||
|
minRange += 1 + 1; // Account for required empty chunks
|
||||||
|
return distX < minRange && distZ < minRange;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void refreshTimeout()
|
||||||
|
{
|
||||||
|
nanotime = System.nanoTime();
|
||||||
|
LodUtil.checkInterruptsUnchecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return id + ":" + range + "@" + pos + "(" + target + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
+59
@@ -0,0 +1,59 @@
|
|||||||
|
|
||||||
|
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||||
|
|
||||||
|
import com.mojang.datafixers.DataFixer;
|
||||||
|
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||||
|
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.RegistryAccess;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.biome.BiomeManager;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||||
|
import net.minecraft.world.level.chunk.storage.ChunkScanAccess;
|
||||||
|
import net.minecraft.world.level.levelgen.DebugLevelSource;
|
||||||
|
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||||
|
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||||
|
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureManager;
|
||||||
|
import net.minecraft.world.level.storage.WorldData;
|
||||||
|
|
||||||
|
public final class GlobalParameters
|
||||||
|
{
|
||||||
|
public final ChunkGenerator generator;
|
||||||
|
public final StructureManager structures;
|
||||||
|
public final BiomeManager biomeManager;
|
||||||
|
public final WorldGenSettings worldGenSettings;
|
||||||
|
public final ThreadedLevelLightEngine lightEngine;
|
||||||
|
public final LodBuilder lodBuilder;
|
||||||
|
public final LodDimension lodDim;
|
||||||
|
public final Registry<Biome> biomes;
|
||||||
|
public final RegistryAccess registry;
|
||||||
|
public final long worldSeed;
|
||||||
|
public final ChunkScanAccess chunkScanner;
|
||||||
|
public final ServerLevel level; // TODO: Figure out a way to remove this. Maybe ClientLevel also works?
|
||||||
|
public final DataFixer fixerUpper;
|
||||||
|
|
||||||
|
public GlobalParameters(ServerLevel level, LodBuilder lodBuilder, LodDimension lodDim)
|
||||||
|
{
|
||||||
|
this.lodBuilder = lodBuilder;
|
||||||
|
this.lodDim = lodDim;
|
||||||
|
this.level = level;
|
||||||
|
lightEngine = (ThreadedLevelLightEngine) level.getLightEngine();
|
||||||
|
MinecraftServer server = level.getServer();
|
||||||
|
WorldData worldData = server.getWorldData();
|
||||||
|
worldGenSettings = worldData.worldGenSettings();
|
||||||
|
registry = server.registryAccess();
|
||||||
|
biomes = registry.registryOrThrow(Registry.BIOME_REGISTRY);
|
||||||
|
worldSeed = worldGenSettings.seed();
|
||||||
|
biomeManager = new BiomeManager(level, BiomeManager.obfuscateSeed(worldSeed));
|
||||||
|
structures = server.getStructureManager();
|
||||||
|
generator = level.getChunkSource().getGenerator();
|
||||||
|
chunkScanner = level.getChunkSource().chunkScanner();
|
||||||
|
fixerUpper = server.getFixerUpper();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
|
||||||
|
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||||
|
|
||||||
|
//FIXME: Move this outside the WorldGenerationStep thingy
|
||||||
|
public class Rolling
|
||||||
|
{
|
||||||
|
|
||||||
|
private final int size;
|
||||||
|
private double total = 0d;
|
||||||
|
private int index = 0;
|
||||||
|
private final double[] samples;
|
||||||
|
|
||||||
|
public Rolling(int size)
|
||||||
|
{
|
||||||
|
this.size = size;
|
||||||
|
samples = new double[size];
|
||||||
|
for (int i = 0; i < size; i++)
|
||||||
|
samples[i] = 0d;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(double x)
|
||||||
|
{
|
||||||
|
total -= samples[index];
|
||||||
|
samples[index] = x;
|
||||||
|
total += x;
|
||||||
|
if (++index == size)
|
||||||
|
index = 0; // cheaper than modulus
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getAverage()
|
||||||
|
{
|
||||||
|
return total / size;
|
||||||
|
}
|
||||||
|
}
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
package com.seibel.lod.common.wrappers.worldGeneration;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.PerfCalculator;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenStructFeatManager;
|
||||||
|
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.world.level.WorldGenLevel;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.StructureCheck;
|
||||||
|
|
||||||
|
public final class ThreadedParameters
|
||||||
|
{
|
||||||
|
private static final ThreadLocal<ThreadedParameters> localParam = new ThreadLocal<ThreadedParameters>();
|
||||||
|
final ServerLevel level;
|
||||||
|
public final WorldGenStructFeatManager structFeat;
|
||||||
|
public final StructureCheck structCheck;
|
||||||
|
boolean isValid = true;
|
||||||
|
public final PerfCalculator perf = new PerfCalculator();
|
||||||
|
|
||||||
|
public static ThreadedParameters getOrMake(GlobalParameters param)
|
||||||
|
{
|
||||||
|
ThreadedParameters tParam = localParam.get();
|
||||||
|
if (tParam != null && tParam.isValid && tParam.level == param.level)
|
||||||
|
return tParam;
|
||||||
|
tParam = new ThreadedParameters(param);
|
||||||
|
localParam.set(tParam);
|
||||||
|
return tParam;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void markAsInvalid()
|
||||||
|
{
|
||||||
|
isValid = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ThreadedParameters(GlobalParameters param)
|
||||||
|
{
|
||||||
|
level = param.level;
|
||||||
|
structCheck = new StructureCheck(param.chunkScanner, param.registry, param.structures,
|
||||||
|
param.level.dimension(), param.generator, level, param.generator.getBiomeSource(), param.worldSeed,
|
||||||
|
param.fixerUpper);
|
||||||
|
structFeat = new WorldGenStructFeatManager(level, param.worldGenSettings, null, structCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void makeStructFeat(WorldGenLevel genLevel)
|
||||||
|
{
|
||||||
|
structFeat.setGenLevel(genLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
+323
@@ -0,0 +1,323 @@
|
|||||||
|
|
||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.Dynamic;
|
||||||
|
import com.seibel.lod.core.api.ApiShared;
|
||||||
|
import com.seibel.lod.core.api.ClientApi;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
#if MC_VERSION_1_18_2
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
import net.minecraft.core.RegistryAccess;
|
||||||
|
import net.minecraft.world.level.levelgen.feature.ConfiguredStructureFeature;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.NbtOps;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
import net.minecraft.world.level.WorldGenLevel;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.biome.Biomes;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.DataLayer;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
|
import net.minecraft.world.level.chunk.PalettedContainer;
|
||||||
|
import net.minecraft.world.level.chunk.UpgradeData;
|
||||||
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
|
import net.minecraft.world.level.levelgen.blending.BlendingData;
|
||||||
|
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.pieces.StructurePieceSerializationContext;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
import net.minecraft.world.level.material.Fluid;
|
||||||
|
import net.minecraft.world.ticks.LevelChunkTicks;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
|
public class ChunkLoader
|
||||||
|
{
|
||||||
|
private static final Codec<PalettedContainer<BlockState>> BLOCK_STATE_CODEC = PalettedContainer.codec(Block.BLOCK_STATE_REGISTRY, BlockState.CODEC, PalettedContainer.Strategy.SECTION_STATES, Blocks.AIR.defaultBlockState());
|
||||||
|
private static final Logger LOGGER = ApiShared.LOGGER;
|
||||||
|
private static final String TAG_UPGRADE_DATA = "UpgradeData";
|
||||||
|
private static final String BLOCK_TICKS_TAG = "block_ticks";
|
||||||
|
private static final String FLUID_TICKS_TAG = "fluid_ticks";
|
||||||
|
|
||||||
|
private static BlendingData readBlendingData(CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
BlendingData blendingData = null;
|
||||||
|
if (chunkData.contains("blending_data", 10))
|
||||||
|
{
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
Dynamic<CompoundTag> blendingDataTag = new Dynamic(NbtOps.INSTANCE, chunkData.getCompound("blending_data"));
|
||||||
|
blendingData = BlendingData.CODEC.parse(blendingDataTag).resultOrPartial(LOGGER::error).orElse(null);
|
||||||
|
}
|
||||||
|
return blendingData;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static LevelChunkSection[] readSections(LevelAccessor level, LevelLightEngine lightEngine, ChunkPos chunkPos, CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
Registry<Biome> biomes = level.registryAccess().registryOrThrow(Registry.BIOME_REGISTRY);
|
||||||
|
#if MC_VERSION_1_18_1
|
||||||
|
Codec<PalettedContainer<Biome>> biomeCodec = PalettedContainer.codec(
|
||||||
|
biomes, biomes.byNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getOrThrow(Biomes.PLAINS));
|
||||||
|
#elif MC_VERSION_1_18_2
|
||||||
|
Codec<PalettedContainer<Holder<Biome>>> biomeCodec = PalettedContainer.codec(
|
||||||
|
biomes.asHolderIdMap(), biomes.holderByNameCodec(), PalettedContainer.Strategy.SECTION_BIOMES, biomes.getHolderOrThrow(Biomes.PLAINS));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int i = level.getSectionsCount();
|
||||||
|
LevelChunkSection[] chunkSections = new LevelChunkSection[i];
|
||||||
|
|
||||||
|
boolean isLightOn = chunkData.getBoolean("isLightOn");
|
||||||
|
boolean hasSkyLight = level.dimensionType().hasSkyLight();
|
||||||
|
ListTag tagSections = chunkData.getList("sections", 10);
|
||||||
|
|
||||||
|
for (int j = 0; j < tagSections.size(); ++j)
|
||||||
|
{
|
||||||
|
CompoundTag tagSection = tagSections.getCompound(j);
|
||||||
|
byte sectionYPos = tagSection.getByte("Y");
|
||||||
|
int sectionId = level.getSectionIndexFromSectionY(sectionYPos);
|
||||||
|
if (sectionId >= 0 && sectionId < chunkSections.length)
|
||||||
|
{
|
||||||
|
PalettedContainer<BlockState> blockStateContainer;
|
||||||
|
#if MC_VERSION_1_18_1
|
||||||
|
PalettedContainer<Biome> biomeContainer;
|
||||||
|
#elif MC_VERSION_1_18_2
|
||||||
|
PalettedContainer<Holder<Biome>> biomeContainer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
blockStateContainer = tagSection.contains("block_states", 10)
|
||||||
|
? BLOCK_STATE_CODEC.parse(NbtOps.INSTANCE, tagSection.getCompound("block_states")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error)
|
||||||
|
: new PalettedContainer<BlockState>(Block.BLOCK_STATE_REGISTRY, Blocks.AIR.defaultBlockState(), PalettedContainer.Strategy.SECTION_STATES);
|
||||||
|
|
||||||
|
#if MC_VERSION_1_18_1
|
||||||
|
biomeContainer = tagSection.contains("biomes", 10)
|
||||||
|
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, sectionYPos, string)).getOrThrow(false, LOGGER::error)
|
||||||
|
: new PalettedContainer<Biome>(biomes, biomes.getOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||||
|
#elif MC_VERSION_1_18_2
|
||||||
|
biomeContainer = tagSection.contains("biomes", 10)
|
||||||
|
? biomeCodec.parse(NbtOps.INSTANCE, tagSection.getCompound("biomes")).promotePartial(string -> logErrors(chunkPos, i, (String) string)).getOrThrow(false, LOGGER::error)
|
||||||
|
: new PalettedContainer<Holder<Biome>>(biomes.asHolderIdMap(), biomes.getHolderOrThrow(Biomes.PLAINS), PalettedContainer.Strategy.SECTION_BIOMES);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
chunkSections[sectionId] = new LevelChunkSection(sectionYPos, blockStateContainer, biomeContainer);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isLightOn)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (tagSection.contains("BlockLight", 7))
|
||||||
|
lightEngine.queueSectionData(LightLayer.BLOCK, SectionPos.of(chunkPos, sectionYPos), new DataLayer(tagSection.getByteArray("BlockLight")), true);
|
||||||
|
if (hasSkyLight && tagSection.contains("SkyLight", 7))
|
||||||
|
lightEngine.queueSectionData(LightLayer.SKY, SectionPos.of(chunkPos, sectionYPos), new DataLayer(tagSection.getByteArray("SkyLight")), true);
|
||||||
|
}
|
||||||
|
return chunkSections;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void readHeightmaps(LevelChunk chunk, CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
CompoundTag tagHeightmaps = chunkData.getCompound("Heightmaps");
|
||||||
|
for (Heightmap.Types type : ChunkStatus.FULL.heightmapsAfter())
|
||||||
|
{
|
||||||
|
String heightmap = type.getSerializationKey();
|
||||||
|
if (tagHeightmaps.contains(heightmap, 12))
|
||||||
|
chunk.setHeightmap(type, tagHeightmaps.getLongArray(heightmap));
|
||||||
|
}
|
||||||
|
Heightmap.primeHeightmaps(chunk, ChunkStatus.FULL.heightmapsAfter());
|
||||||
|
}
|
||||||
|
|
||||||
|
#if MC_VERSION_1_18_1
|
||||||
|
private static Map<StructureFeature<?>, StructureStart<?>> unpackStructureStart(StructurePieceSerializationContext structurePieceSerializationContext, CompoundTag compoundTag, long l)
|
||||||
|
{
|
||||||
|
HashMap<StructureFeature<?>, StructureStart<?>> map = Maps.newHashMap();
|
||||||
|
CompoundTag compoundTag2 = compoundTag.getCompound("starts");
|
||||||
|
for (String string : compoundTag2.getAllKeys())
|
||||||
|
{
|
||||||
|
String string2 = string.toLowerCase(Locale.ROOT);
|
||||||
|
StructureFeature<?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
|
||||||
|
if (structureFeature == null)
|
||||||
|
{
|
||||||
|
LOGGER.error("Unknown structure start: {}", (Object) string2);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
StructureStart<?> structureStart = StructureFeature.loadStaticStart(structurePieceSerializationContext, compoundTag2.getCompound(string), l);
|
||||||
|
if (structureStart == null)
|
||||||
|
continue;
|
||||||
|
map.put(structureFeature, structureStart);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<StructureFeature<?>, LongSet> unpackStructureReferences(ChunkPos chunkPos, CompoundTag compoundTag)
|
||||||
|
{
|
||||||
|
HashMap<StructureFeature<?>, LongSet> map = Maps.newHashMap();
|
||||||
|
CompoundTag compoundTag2 = compoundTag.getCompound("References");
|
||||||
|
for (String string : compoundTag2.getAllKeys())
|
||||||
|
{
|
||||||
|
String string2 = string.toLowerCase(Locale.ROOT);
|
||||||
|
StructureFeature<?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
|
||||||
|
if (structureFeature == null)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", (Object) string2, (Object) chunkPos);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
map.put(structureFeature, new LongOpenHashSet(Arrays.stream(compoundTag2.getLongArray(string)).filter(l ->
|
||||||
|
{
|
||||||
|
ChunkPos chunkPos2 = new ChunkPos(l);
|
||||||
|
if (chunkPos2.getChessboardDistance(chunkPos) > 8)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Found invalid structure reference [ {} @ {} ] for chunk {}.", (Object) string2, (Object) chunkPos2, (Object) chunkPos);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}).toArray()));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
#elif MC_VERSION_1_18_2
|
||||||
|
private static Map<ConfiguredStructureFeature<?, ?>, StructureStart> unpackStructureStart(StructurePieceSerializationContext structurePieceSerializationContext, CompoundTag compoundTag, long l) {
|
||||||
|
Map<ConfiguredStructureFeature<?, ?>, StructureStart> map = Maps.newHashMap();
|
||||||
|
Registry<ConfiguredStructureFeature<?, ?>> structStartRegistry = structurePieceSerializationContext.registryAccess().registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
|
||||||
|
CompoundTag compoundTag2 = compoundTag.getCompound("starts");
|
||||||
|
for (String string : compoundTag2.getAllKeys()) {
|
||||||
|
ResourceLocation resourceLocation = ResourceLocation.tryParse(string);
|
||||||
|
ConfiguredStructureFeature<?, ?> structureFeature = structStartRegistry.get(resourceLocation);
|
||||||
|
// String string2 = string.toLowerCase(Locale.ROOT);
|
||||||
|
// ConfiguredStructureFeature<?, ?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
|
||||||
|
if (structureFeature == null) {
|
||||||
|
LOGGER.error("Unknown structure start: {}", resourceLocation);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
StructureStart structureStart = StructureFeature.loadStaticStart(structurePieceSerializationContext, compoundTag2.getCompound(string), l);
|
||||||
|
if (structureStart == null)
|
||||||
|
continue;
|
||||||
|
map.put(structureFeature, structureStart);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<ConfiguredStructureFeature<?, ?>, LongSet> unpackStructureReferences(RegistryAccess registryAccess, ChunkPos chunkPos, CompoundTag compoundTag)
|
||||||
|
{
|
||||||
|
Map<ConfiguredStructureFeature<?, ?>, LongSet> map = Maps.newHashMap();
|
||||||
|
Registry<ConfiguredStructureFeature<?, ?>> structRegistry = registryAccess.registryOrThrow(Registry.CONFIGURED_STRUCTURE_FEATURE_REGISTRY);
|
||||||
|
CompoundTag compoundTag2 = compoundTag.getCompound("References");
|
||||||
|
for (String string : compoundTag2.getAllKeys())
|
||||||
|
{
|
||||||
|
ResourceLocation resourceLocation = ResourceLocation.tryParse(string);
|
||||||
|
ConfiguredStructureFeature<?, ?> structureFeature = structRegistry.get(resourceLocation);
|
||||||
|
// String string2 = string.toLowerCase(Locale.ROOT);
|
||||||
|
// ConfiguredStructureFeature<?, ?> structureFeature = StructureFeature.STRUCTURES_REGISTRY.get(string2);
|
||||||
|
if (structureFeature == null)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Found reference to unknown structure '{}' in chunk {}, discarding", resourceLocation, chunkPos);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
map.put(structureFeature, new LongOpenHashSet(Arrays.stream(compoundTag2.getLongArray(string)).filter(l ->
|
||||||
|
{
|
||||||
|
ChunkPos chunkPos2 = new ChunkPos(l);
|
||||||
|
if (chunkPos2.getChessboardDistance(chunkPos) > 8)
|
||||||
|
{
|
||||||
|
LOGGER.warn("Found invalid structure reference [ {} @ {} ] for chunk {}.", resourceLocation, chunkPos2, chunkPos);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}).toArray()));
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
private static void readStructures(WorldGenLevel level, LevelChunk chunk, CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
CompoundTag tagStructures = chunkData.getCompound("structures");
|
||||||
|
chunk.setAllStarts(
|
||||||
|
unpackStructureStart(StructurePieceSerializationContext.fromLevel(level.getLevel()), tagStructures, level.getSeed()));
|
||||||
|
chunk.setAllReferences(unpackStructureReferences(#if MC_VERSION_1_18_2 level.registryAccess() ,#endif chunk.getPos(), tagStructures));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void readPostPocessings(LevelChunk chunk, CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
ListTag tagPostProcessings = chunkData.getList("PostProcessing", 9);
|
||||||
|
for (int n = 0; n < tagPostProcessings.size(); ++n)
|
||||||
|
{
|
||||||
|
ListTag listTag3 = tagPostProcessings.getList(n);
|
||||||
|
for (int o = 0; o < listTag3.size(); ++o)
|
||||||
|
{
|
||||||
|
chunk.addPackedPostProcess(listTag3.getShort(o), n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ChunkStatus.ChunkType readChunkType(CompoundTag compoundTag)
|
||||||
|
{
|
||||||
|
return ChunkStatus.byName(compoundTag.getString("Status")).getChunkType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LevelChunk read(WorldGenLevel level, LevelLightEngine lightEngine, ChunkPos chunkPos, CompoundTag chunkData)
|
||||||
|
{
|
||||||
|
|
||||||
|
ChunkPos actualPos = new ChunkPos(chunkData.getInt("xPos"), chunkData.getInt("zPos"));
|
||||||
|
if (!Objects.equals(chunkPos, actualPos))
|
||||||
|
{
|
||||||
|
LOGGER.error("Distant Horizons: Chunk file at {} is in the wrong location; Ignoring. (Expected {}, got {})", (Object) chunkPos, (Object) chunkPos, (Object) actualPos);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
ChunkStatus.ChunkType chunkType = readChunkType(chunkData);
|
||||||
|
BlendingData blendingData = readBlendingData(chunkData);
|
||||||
|
if (chunkType == ChunkStatus.ChunkType.PROTOCHUNK && (blendingData == null || !blendingData.oldNoise()))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// Prepare the light engine
|
||||||
|
boolean isLightOn = chunkData.getBoolean("isLightOn");
|
||||||
|
if (isLightOn)
|
||||||
|
level.getLightEngine().retainData(chunkPos, true);
|
||||||
|
|
||||||
|
// Read params for making the LevelChunk
|
||||||
|
UpgradeData upgradeData = chunkData.contains(TAG_UPGRADE_DATA, 10)
|
||||||
|
? new UpgradeData(chunkData.getCompound(TAG_UPGRADE_DATA), level)
|
||||||
|
: UpgradeData.EMPTY;
|
||||||
|
LevelChunkTicks<Block> blockTicks = LevelChunkTicks.load(chunkData.getList(BLOCK_TICKS_TAG, 10),
|
||||||
|
string -> Registry.BLOCK.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||||
|
LevelChunkTicks<Fluid> fluidTicks = LevelChunkTicks.load(chunkData.getList(FLUID_TICKS_TAG, 10),
|
||||||
|
string -> Registry.FLUID.getOptional(ResourceLocation.tryParse(string)), chunkPos);
|
||||||
|
long inhabitedTime = chunkData.getLong("InhabitedTime");
|
||||||
|
LevelChunkSection[] chunkSections = readSections(level, lightEngine, actualPos, chunkData);
|
||||||
|
|
||||||
|
// Make chunk
|
||||||
|
LevelChunk chunk = new LevelChunk((Level) level, chunkPos, upgradeData, blockTicks, fluidTicks, inhabitedTime, chunkSections, null, blendingData);
|
||||||
|
|
||||||
|
// Set some states after object creation
|
||||||
|
chunk.setLightCorrect(isLightOn);
|
||||||
|
readHeightmaps(chunk, chunkData);
|
||||||
|
readStructures(level, chunk, chunkData);
|
||||||
|
readPostPocessings(chunk, chunkData);
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void logErrors(ChunkPos chunkPos, int i, String string)
|
||||||
|
{
|
||||||
|
LOGGER.error("Distant Horizons: Recoverable errors when loading section [" + chunkPos.x + ", " + i + ", " + chunkPos.z + "]: " + string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
|
||||||
|
|
||||||
|
import net.minecraft.world.level.BlockGetter;
|
||||||
|
import net.minecraft.world.level.LevelHeightAccessor;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.LightChunkGetter;
|
||||||
|
|
||||||
|
public class LightGetterAdaptor implements LightChunkGetter {
|
||||||
|
private final BlockGetter heightGetter;
|
||||||
|
public LightedWorldGenRegion genRegion = null;
|
||||||
|
final boolean shouldReturnNull;
|
||||||
|
|
||||||
|
public LightGetterAdaptor(BlockGetter heightAccessor) {
|
||||||
|
this.heightGetter = heightAccessor;
|
||||||
|
shouldReturnNull = ModAccessorHandler.get(IStarlightAccessor.class) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRegion(LightedWorldGenRegion region) {
|
||||||
|
genRegion = region;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockGetter getChunkForLighting(int chunkX, int chunkZ) {
|
||||||
|
if (genRegion == null)
|
||||||
|
throw new IllegalStateException("World Gen region has not been set!");
|
||||||
|
// May be null
|
||||||
|
return genRegion.getChunk(chunkX, chunkZ, ChunkStatus.EMPTY, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public BlockGetter getLevel() {
|
||||||
|
return shouldReturnNull ? null : (genRegion != null ? genRegion : heightGetter);
|
||||||
|
}
|
||||||
|
public LevelHeightAccessor getLevelHeightAccessor() {
|
||||||
|
return heightGetter;
|
||||||
|
}
|
||||||
|
}
|
||||||
+281
@@ -0,0 +1,281 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.api.ApiShared;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment.EmptyChunkGenerator;
|
||||||
|
import com.seibel.lod.core.api.ClientApi;
|
||||||
|
import com.seibel.lod.core.enums.config.LightGenerationMode;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap;
|
||||||
|
import net.minecraft.Util;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.color.block.BlockTintCache;
|
||||||
|
import net.minecraft.client.renderer.BiomeColors;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.Cursor3D;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.ColorResolver;
|
||||||
|
import net.minecraft.world.level.LevelHeightAccessor;
|
||||||
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
import net.minecraft.world.level.StructureFeatureManager;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.block.Blocks;
|
||||||
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.ImposterProtoChunk;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.levelgen.Heightmap;
|
||||||
|
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
|
||||||
|
public class LightedWorldGenRegion extends WorldGenRegion {
|
||||||
|
public final WorldGenLevelLightEngine light;
|
||||||
|
public final LightGenerationMode lightMode;
|
||||||
|
public final EmptyChunkGenerator generator;
|
||||||
|
public final int writeRadius;
|
||||||
|
public final int size;
|
||||||
|
private final ChunkPos firstPos;
|
||||||
|
private final List<ChunkAccess> cache;
|
||||||
|
Long2ObjectOpenHashMap<ChunkAccess> chunkMap = new Long2ObjectOpenHashMap<ChunkAccess>();
|
||||||
|
|
||||||
|
public LightedWorldGenRegion(ServerLevel serverLevel, WorldGenLevelLightEngine lightEngine,
|
||||||
|
List<ChunkAccess> list, ChunkStatus chunkStatus, int i,
|
||||||
|
LightGenerationMode lightMode, EmptyChunkGenerator generator) {
|
||||||
|
super(serverLevel, list, chunkStatus, i);
|
||||||
|
this.lightMode = lightMode;
|
||||||
|
this.firstPos = list.get(0).getPos();
|
||||||
|
this.generator = generator;
|
||||||
|
light = lightEngine;
|
||||||
|
writeRadius = i;
|
||||||
|
cache = list;
|
||||||
|
size = Mth.floor(Math.sqrt(list.size()));
|
||||||
|
|
||||||
|
this.tintCaches = Util.make(new Object2ObjectArrayMap(3), object2ObjectArrayMap -> {
|
||||||
|
object2ObjectArrayMap.put(BiomeColors.GRASS_COLOR_RESOLVER, new BlockTintCache((pos) -> {return calculateBlockTint(pos, BiomeColors.GRASS_COLOR_RESOLVER);}));
|
||||||
|
object2ObjectArrayMap.put(BiomeColors.FOLIAGE_COLOR_RESOLVER, new BlockTintCache((pos) -> {return calculateBlockTint(pos, BiomeColors.FOLIAGE_COLOR_RESOLVER);}));
|
||||||
|
object2ObjectArrayMap.put(BiomeColors.WATER_COLOR_RESOLVER, new BlockTintCache((pos) -> {return calculateBlockTint(pos, BiomeColors.WATER_COLOR_RESOLVER);}));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bypass BCLib mixin overrides.
|
||||||
|
@Override
|
||||||
|
public boolean ensureCanWrite(BlockPos blockPos) {
|
||||||
|
int i = SectionPos.blockToSectionCoord(blockPos.getX());
|
||||||
|
int j = SectionPos.blockToSectionCoord(blockPos.getZ());
|
||||||
|
ChunkPos chunkPos = this.getCenter();
|
||||||
|
ChunkAccess center = this.getChunk(chunkPos.x, chunkPos.z);
|
||||||
|
int k = Math.abs(chunkPos.x - i);
|
||||||
|
int l = Math.abs(chunkPos.z - j);
|
||||||
|
if (k > this.writeRadius || l > this.writeRadius) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (center.isUpgrading()) {
|
||||||
|
LevelHeightAccessor levelHeightAccessor = center.getHeightAccessorForGeneration();
|
||||||
|
if (blockPos.getY() < levelHeightAccessor.getMinBuildHeight() || blockPos.getY() >= levelHeightAccessor.getMaxBuildHeight()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Check this
|
||||||
|
// @Override
|
||||||
|
// public List<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
|
||||||
|
// StructureFeature<?> structureFeature) {
|
||||||
|
// return structFeat.startsForFeature(sectionPos, structureFeature);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Skip updating the related tile entities
|
||||||
|
@Override
|
||||||
|
public boolean setBlock(BlockPos blockPos, BlockState blockState, int i, int j) {
|
||||||
|
ChunkAccess chunkAccess = this.getChunk(blockPos);
|
||||||
|
if (chunkAccess instanceof LevelChunk)
|
||||||
|
return true;
|
||||||
|
chunkAccess.setBlockState(blockPos, blockState, false);
|
||||||
|
// This is for post ticking for water on gen and stuff like that. Not enabled
|
||||||
|
// for now.
|
||||||
|
// if (blockState.hasPostProcess(this, blockPos))
|
||||||
|
// this.getChunk(blockPos).markPosForPostprocessing(blockPos);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip Dropping the item on destroy
|
||||||
|
@Override
|
||||||
|
public boolean destroyBlock(BlockPos blockPos, boolean bl, @Nullable Entity entity, int i) {
|
||||||
|
BlockState blockState = this.getBlockState(blockPos);
|
||||||
|
if (blockState.isAir()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return this.setBlock(blockPos, Blocks.AIR.defaultBlockState(), 3, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip BlockEntity stuff. It aren't really needed
|
||||||
|
@Override
|
||||||
|
public BlockEntity getBlockEntity(BlockPos blockPos) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip BlockEntity stuff. It aren't really needed
|
||||||
|
@Override
|
||||||
|
public boolean addFreshEntity(Entity entity) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allays have empty chunks even if it's outside the worldGenRegion
|
||||||
|
// @Override
|
||||||
|
// public boolean hasChunk(int i, int j) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Override to ensure no other mod mixins cause skipping the overrided
|
||||||
|
// getChunk(...)
|
||||||
|
@Override
|
||||||
|
public ChunkAccess getChunk(int i, int j) {
|
||||||
|
return this.getChunk(i, j, ChunkStatus.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override to ensure no other mod mixins cause skipping the overrided
|
||||||
|
// getChunk(...)
|
||||||
|
@Override
|
||||||
|
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus) {
|
||||||
|
return this.getChunk(i, j, chunkStatus, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use this instead of super.getChunk() to bypass C2ME concurrency checks
|
||||||
|
private ChunkAccess superGetChunk(int x, int z, ChunkStatus cs) {
|
||||||
|
int k = x - firstPos.x;
|
||||||
|
int l = z - firstPos.z;
|
||||||
|
return cache.get(k + l * size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use this instead of super.hasChunk() to bypass C2ME concurrency checks
|
||||||
|
private boolean superHasChunk(int x, int z) {
|
||||||
|
int k = x - firstPos.x;
|
||||||
|
int l = z - firstPos.z;
|
||||||
|
return l >= 0 && l < size && k >= 0 && k < size;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow creating empty chunks even if it's outside the worldGenRegion
|
||||||
|
@Override
|
||||||
|
@Nullable
|
||||||
|
public ChunkAccess getChunk(int i, int j, ChunkStatus chunkStatus, boolean bl) {
|
||||||
|
ChunkAccess chunk = getChunkAccess(i, j, chunkStatus, bl);
|
||||||
|
if (chunk instanceof LevelChunk) {
|
||||||
|
chunk = new ImposterProtoChunk((LevelChunk) chunk, true);
|
||||||
|
}
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ChunkStatus debugTriggeredForStatus = null;
|
||||||
|
|
||||||
|
private ChunkAccess getChunkAccess(int i, int j, ChunkStatus chunkStatus, boolean bl) {
|
||||||
|
ChunkAccess chunk = superHasChunk(i, j) ? superGetChunk(i, j, ChunkStatus.EMPTY) : null;
|
||||||
|
if (chunk != null && chunk.getStatus().isOrAfter(chunkStatus)) {
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
if (!bl)
|
||||||
|
return null;
|
||||||
|
if (chunk == null) {
|
||||||
|
chunk = chunkMap.get(ChunkPos.asLong(i, j));
|
||||||
|
if (chunk == null) {
|
||||||
|
chunk = generator.generate(i, j);
|
||||||
|
if (chunk == null)
|
||||||
|
throw new NullPointerException("The provided generator should not return null!");
|
||||||
|
chunkMap.put(ChunkPos.asLong(i, j), chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chunkStatus != ChunkStatus.EMPTY && chunkStatus != debugTriggeredForStatus) {
|
||||||
|
ApiShared.LOGGER.info("WorldGen requiring " + chunkStatus
|
||||||
|
+ " outside expected range detected. Force passing EMPTY chunk and seeing if it works.");
|
||||||
|
debugTriggeredForStatus = chunkStatus;
|
||||||
|
}
|
||||||
|
return chunk;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override force use of my own light engine
|
||||||
|
@Override
|
||||||
|
public LevelLightEngine getLightEngine() {
|
||||||
|
return light;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override force use of my own light engine
|
||||||
|
@Override
|
||||||
|
public int getBrightness(LightLayer lightLayer, BlockPos blockPos) {
|
||||||
|
if (lightMode != LightGenerationMode.FAST) {
|
||||||
|
return light.getLayerListener(lightLayer).getLightValue(blockPos);
|
||||||
|
}
|
||||||
|
if (lightLayer == LightLayer.BLOCK)
|
||||||
|
return 0;
|
||||||
|
BlockPos p = super.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockPos);
|
||||||
|
return (p.getY() <= blockPos.getY()) ? getMaxLightLevel() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override force use of my own light engine
|
||||||
|
@Override
|
||||||
|
public int getRawBrightness(BlockPos blockPos, int i) {
|
||||||
|
if (lightMode != LightGenerationMode.FAST) {
|
||||||
|
return light.getRawBrightness(blockPos, i);
|
||||||
|
}
|
||||||
|
BlockPos p = super.getHeightmapPos(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES, blockPos);
|
||||||
|
return (p.getY() <= blockPos.getY()) ? getMaxLightLevel() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Override force use of my own light engine
|
||||||
|
@Override
|
||||||
|
public boolean canSeeSky(BlockPos blockPos) {
|
||||||
|
return (getBrightness(LightLayer.SKY, blockPos) >= getMaxLightLevel());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private final Object2ObjectArrayMap<ColorResolver, BlockTintCache> tintCaches;
|
||||||
|
|
||||||
|
public int getBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
||||||
|
{
|
||||||
|
BlockTintCache blockTintCache = (BlockTintCache) this.tintCaches.get(colorResolver);
|
||||||
|
return blockTintCache.getColor(blockPos);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Biome _getBiome(BlockPos pos) {
|
||||||
|
#if MC_VERSION_1_18_2
|
||||||
|
return getBiome(pos).value();
|
||||||
|
#elif MC_VERSION_1_18_1
|
||||||
|
return getBiome(pos);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public int calculateBlockTint(BlockPos blockPos, ColorResolver colorResolver)
|
||||||
|
{
|
||||||
|
int i = (Minecraft.getInstance()).options.biomeBlendRadius;
|
||||||
|
if (i == 0)
|
||||||
|
return colorResolver.getColor((Biome) _getBiome(blockPos), blockPos.getX(), blockPos.getZ());
|
||||||
|
int j = (i * 2 + 1) * (i * 2 + 1);
|
||||||
|
int k = 0;
|
||||||
|
int l = 0;
|
||||||
|
int m = 0;
|
||||||
|
Cursor3D cursor3D = new Cursor3D(blockPos.getX() - i, blockPos.getY(), blockPos.getZ() - i, blockPos.getX() + i, blockPos.getY(), blockPos.getZ() + i);
|
||||||
|
BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
|
||||||
|
while (cursor3D.advance())
|
||||||
|
{
|
||||||
|
mutableBlockPos.set(cursor3D.nextX(), cursor3D.nextY(), cursor3D.nextZ());
|
||||||
|
int n = colorResolver.getColor((Biome) _getBiome((BlockPos) mutableBlockPos), mutableBlockPos.getX(), mutableBlockPos.getZ());
|
||||||
|
k += (n & 0xFF0000) >> 16;
|
||||||
|
l += (n & 0xFF00) >> 8;
|
||||||
|
m += n & 0xFF;
|
||||||
|
}
|
||||||
|
return (k / j & 0xFF) << 16 | (l / j & 0xFF) << 8 | m / j & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+176
@@ -0,0 +1,176 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.LevelHeightAccessor;
|
||||||
|
import net.minecraft.world.level.LightLayer;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.DataLayer;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
|
import net.minecraft.world.level.lighting.BlockLightEngine;
|
||||||
|
import net.minecraft.world.level.lighting.LayerLightEventListener;
|
||||||
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
||||||
|
import net.minecraft.world.level.lighting.SkyLightEngine;
|
||||||
|
|
||||||
|
public class WorldGenLevelLightEngine extends LevelLightEngine {
|
||||||
|
public static final int MAX_SOURCE_LEVEL = 15;
|
||||||
|
public static final int LIGHT_SECTION_PADDING = 1;
|
||||||
|
protected final LevelHeightAccessor levelHeightAccessor;
|
||||||
|
@Nullable
|
||||||
|
public final BlockLightEngine blockEngine;
|
||||||
|
@Nullable
|
||||||
|
public final SkyLightEngine skyEngine;
|
||||||
|
|
||||||
|
public WorldGenLevelLightEngine(LightGetterAdaptor genRegion) {
|
||||||
|
super(genRegion, false, false);
|
||||||
|
this.levelHeightAccessor = genRegion.getLevelHeightAccessor();
|
||||||
|
this.blockEngine = new BlockLightEngine(genRegion);
|
||||||
|
this.skyEngine = new SkyLightEngine(genRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void checkBlock(BlockPos blockPos) {
|
||||||
|
if (this.blockEngine != null) {
|
||||||
|
this.blockEngine.checkBlock(blockPos);
|
||||||
|
}
|
||||||
|
if (this.skyEngine != null) {
|
||||||
|
this.skyEngine.checkBlock(blockPos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBlockEmissionIncrease(BlockPos blockPos, int i) {
|
||||||
|
if (this.blockEngine != null) {
|
||||||
|
this.blockEngine.onBlockEmissionIncrease(blockPos, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasLightWork() {
|
||||||
|
if (this.skyEngine != null && this.skyEngine.hasLightWork()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return this.blockEngine != null && this.blockEngine.hasLightWork();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int runUpdates(int i, boolean bl, boolean bl2) {
|
||||||
|
if (this.blockEngine != null && this.skyEngine != null) {
|
||||||
|
int j = i / 2;
|
||||||
|
int k = this.blockEngine.runUpdates(j, bl, bl2);
|
||||||
|
int l = i - j + k;
|
||||||
|
int m = this.skyEngine.runUpdates(l, bl, bl2);
|
||||||
|
if (k == 0 && m > 0) {
|
||||||
|
return this.blockEngine.runUpdates(m, bl, bl2);
|
||||||
|
}
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
if (this.blockEngine != null) {
|
||||||
|
return this.blockEngine.runUpdates(i, bl, bl2);
|
||||||
|
}
|
||||||
|
if (this.skyEngine != null) {
|
||||||
|
return this.skyEngine.runUpdates(i, bl, bl2);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateSectionStatus(SectionPos sectionPos, boolean bl) {
|
||||||
|
if (this.blockEngine != null) {
|
||||||
|
this.blockEngine.updateSectionStatus(sectionPos, bl);
|
||||||
|
}
|
||||||
|
if (this.skyEngine != null) {
|
||||||
|
this.skyEngine.updateSectionStatus(sectionPos, bl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void enableLightSources(ChunkPos chunkPos, boolean bl) {
|
||||||
|
if (this.blockEngine != null) {
|
||||||
|
this.blockEngine.enableLightSources(chunkPos, bl);
|
||||||
|
}
|
||||||
|
if (this.skyEngine != null) {
|
||||||
|
this.skyEngine.enableLightSources(chunkPos, bl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LayerLightEventListener getLayerListener(LightLayer lightLayer) {
|
||||||
|
if (lightLayer == LightLayer.BLOCK) {
|
||||||
|
if (this.blockEngine == null) {
|
||||||
|
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
|
||||||
|
}
|
||||||
|
return this.blockEngine;
|
||||||
|
}
|
||||||
|
if (this.skyEngine == null) {
|
||||||
|
return LayerLightEventListener.DummyLightLayerEventListener.INSTANCE;
|
||||||
|
}
|
||||||
|
return this.skyEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getRawBrightness(BlockPos blockPos, int i) {
|
||||||
|
int j = this.skyEngine == null ? 0 : this.skyEngine.getLightValue(blockPos) - i;
|
||||||
|
int k = this.blockEngine == null ? 0 : this.blockEngine.getLightValue(blockPos);
|
||||||
|
return Math.max(k, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void lightChunk(ChunkAccess chunkAccess, boolean needLightBlockUpdate) {
|
||||||
|
ChunkPos chunkPos = chunkAccess.getPos();
|
||||||
|
chunkAccess.setLightCorrect(false);
|
||||||
|
|
||||||
|
LevelChunkSection[] levelChunkSections = chunkAccess.getSections();
|
||||||
|
for (int i = 0; i < chunkAccess.getSectionsCount(); ++i) {
|
||||||
|
LevelChunkSection levelChunkSection = levelChunkSections[i];
|
||||||
|
if (levelChunkSection.hasOnlyAir()) continue;
|
||||||
|
int j = this.levelHeightAccessor.getSectionYFromSectionIndex(i);
|
||||||
|
updateSectionStatus(SectionPos.of(chunkPos, j), false);
|
||||||
|
}
|
||||||
|
enableLightSources(chunkPos, true);
|
||||||
|
if (needLightBlockUpdate) {
|
||||||
|
chunkAccess.getLights().forEach(blockPos ->
|
||||||
|
onBlockEmissionIncrease(blockPos, chunkAccess.getLightEmission(blockPos)));
|
||||||
|
}
|
||||||
|
|
||||||
|
chunkAccess.setLightCorrect(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDebugData(LightLayer lightLayer, SectionPos sectionPos) {
|
||||||
|
throw new UnsupportedOperationException("This should never be used!");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void queueSectionData(LightLayer lightLayer, SectionPos sectionPos, @Nullable DataLayer dataLayer, boolean bl) {
|
||||||
|
if (lightLayer == LightLayer.BLOCK) {
|
||||||
|
if (this.blockEngine != null) {
|
||||||
|
this.blockEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
|
||||||
|
}
|
||||||
|
} else if (this.skyEngine != null) {
|
||||||
|
this.skyEngine.queueSectionData(sectionPos.asLong(), dataLayer, bl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void retainData(ChunkPos chunkPos, boolean bl) {
|
||||||
|
if (this.blockEngine != null) {
|
||||||
|
this.blockEngine.retainData(chunkPos, bl);
|
||||||
|
}
|
||||||
|
if (this.skyEngine != null) {
|
||||||
|
this.skyEngine.retainData(chunkPos, bl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getLightSectionCount() {
|
||||||
|
throw new UnsupportedOperationException("This should never be used!");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getMinLightSection() {
|
||||||
|
throw new UnsupportedOperationException("This should never be used!");
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public int getMaxLightSection() {
|
||||||
|
throw new UnsupportedOperationException("This should never be used!");
|
||||||
|
}
|
||||||
|
}
|
||||||
+82
@@ -0,0 +1,82 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.mimicObject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||||
|
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.StructureFeatureManager;
|
||||||
|
import net.minecraft.world.level.WorldGenLevel;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.levelgen.WorldGenSettings;
|
||||||
|
import net.minecraft.world.level.levelgen.feature.StructureFeature;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.StructureCheck;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||||
|
|
||||||
|
public class WorldGenStructFeatManager extends StructureFeatureManager {
|
||||||
|
WorldGenLevel genLevel;
|
||||||
|
WorldGenSettings worldGenSettings;
|
||||||
|
StructureCheck structureCheck;
|
||||||
|
public WorldGenStructFeatManager(LevelAccessor levelAccessor, WorldGenSettings worldGenSettings,
|
||||||
|
WorldGenLevel genLevel, StructureCheck structureCheck) {
|
||||||
|
super(levelAccessor, worldGenSettings, structureCheck);
|
||||||
|
this.genLevel = genLevel;
|
||||||
|
this.worldGenSettings = worldGenSettings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGenLevel(WorldGenLevel genLevel) {
|
||||||
|
this.genLevel = genLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WorldGenStructFeatManager forWorldGenRegion(WorldGenRegion worldGenRegion) {
|
||||||
|
if (worldGenRegion == genLevel)
|
||||||
|
return this;
|
||||||
|
return new WorldGenStructFeatManager(worldGenRegion, worldGenSettings, worldGenRegion, structureCheck);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasAnyStructureAt(BlockPos blockPos) {
|
||||||
|
SectionPos sectionPos = SectionPos.of(blockPos);
|
||||||
|
ChunkAccess chunk = genLevel.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES,
|
||||||
|
false);
|
||||||
|
if (chunk == null) return false;
|
||||||
|
return chunk.hasAnyStructureReferences();
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Check this
|
||||||
|
/*
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||||
|
public List<? extends StructureStart<?>> startsForFeature(SectionPos sectionPos,
|
||||||
|
StructureFeature<?> structureFeature) {
|
||||||
|
if (genLevel == null)
|
||||||
|
return List.of();
|
||||||
|
ChunkAccess chunk = genLevel.getChunk(sectionPos.x(), sectionPos.z(), ChunkStatus.STRUCTURE_REFERENCES,
|
||||||
|
false);
|
||||||
|
if (chunk == null)
|
||||||
|
return List.of();
|
||||||
|
LongSet longSet = chunk.getReferencesForFeature(structureFeature);
|
||||||
|
ImmutableList.Builder builder = ImmutableList.builder();
|
||||||
|
LongIterator longIterator = longSet.iterator();
|
||||||
|
while (longIterator.hasNext()) {
|
||||||
|
long l = (Long)longIterator.next();
|
||||||
|
SectionPos sectPos = SectionPos.of(new ChunkPos(l), genLevel.getMinSection());
|
||||||
|
ChunkAccess startChunk = genLevel.getChunk(sectPos.x(), sectPos.z(), ChunkStatus.STRUCTURE_STARTS, false);
|
||||||
|
if (startChunk == null) continue;
|
||||||
|
StructureStart<?> structureStart = this.getStartForFeature(sectPos, structureFeature, startChunk);
|
||||||
|
if (structureStart == null || !structureStart.isValid()) continue;
|
||||||
|
builder.add(structureStart);
|
||||||
|
}
|
||||||
|
return builder.build();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||||
|
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
|
import net.minecraft.world.level.StructureFeatureManager;
|
||||||
|
import net.minecraft.world.level.biome.Biome;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkGenerator;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
import net.minecraft.world.level.levelgen.DebugLevelSource;
|
||||||
|
import net.minecraft.world.level.levelgen.FlatLevelSource;
|
||||||
|
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||||
|
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||||
|
|
||||||
|
public final class StepBiomes {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private final BatchGenerationEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param batchGenerationEnvironment
|
||||||
|
*/
|
||||||
|
public StepBiomes(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||||
|
{
|
||||||
|
environment = batchGenerationEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ChunkStatus STATUS = ChunkStatus.BIOMES;
|
||||||
|
|
||||||
|
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||||
|
List<ChunkAccess> chunks) {
|
||||||
|
|
||||||
|
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunks) {
|
||||||
|
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||||
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
chunksToDo.add(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunksToDo) {
|
||||||
|
// System.out.println("StepBiomes: "+chunk.getPos());
|
||||||
|
chunk = environment.joinSync(environment.params.generator.createBiomes(environment.params.biomes, Runnable::run, Blender.of(worldGenRegion),
|
||||||
|
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||||
|
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||||
|
|
||||||
|
import net.minecraft.ReportedException;
|
||||||
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||||
|
|
||||||
|
public final class StepFeatures {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private final BatchGenerationEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param batchGenerationEnvironment
|
||||||
|
*/
|
||||||
|
public StepFeatures(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||||
|
{
|
||||||
|
environment = batchGenerationEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ChunkStatus STATUS = ChunkStatus.FEATURES;
|
||||||
|
|
||||||
|
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||||
|
ArrayGridList<ChunkAccess> chunks) {
|
||||||
|
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunks) {
|
||||||
|
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||||
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
chunksToDo.add(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunksToDo) {
|
||||||
|
try {
|
||||||
|
environment.params.generator.applyBiomeDecoration(worldGenRegion, chunk,
|
||||||
|
tParams.structFeat.forWorldGenRegion(worldGenRegion));
|
||||||
|
Blender.generateBorderTicks(worldGenRegion, chunk);
|
||||||
|
} catch (ReportedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
// FIXME: Features concurrent modification issue. Something about cocobeans just
|
||||||
|
// aren't happy
|
||||||
|
// For now just retry.
|
||||||
|
}
|
||||||
|
}/*
|
||||||
|
for (ChunkAccess chunk : chunks) {
|
||||||
|
Heightmap.primeHeightmaps(chunk,
|
||||||
|
EnumSet.of(Heightmap.Types.MOTION_BLOCKING, Heightmap.Types.MOTION_BLOCKING_NO_LEAVES,
|
||||||
|
Heightmap.Types.OCEAN_FLOOR, Heightmap.Types.WORLD_SURFACE));
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.mimicObject.WorldGenLevelLightEngine;
|
||||||
|
import com.seibel.lod.core.util.gridList.ArrayGridList;
|
||||||
|
|
||||||
|
import net.minecraft.server.level.ThreadedLevelLightEngine;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
import net.minecraft.world.level.lighting.LightEventListener;
|
||||||
|
|
||||||
|
public final class StepLight {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private final BatchGenerationEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param batchGenerationEnvironment
|
||||||
|
*/
|
||||||
|
public StepLight(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||||
|
{
|
||||||
|
environment = batchGenerationEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ChunkStatus STATUS = ChunkStatus.LIGHT;
|
||||||
|
|
||||||
|
public void generateGroup(LightEventListener lightEngine,
|
||||||
|
ArrayGridList<ChunkAccess> chunks) {
|
||||||
|
//ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunks) {
|
||||||
|
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||||
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunks) {
|
||||||
|
boolean hasCorrectBlockLight = (chunk instanceof LevelChunk && chunk.isLightCorrect());
|
||||||
|
try {
|
||||||
|
if (lightEngine == null) {
|
||||||
|
// Do nothing
|
||||||
|
} else if (lightEngine instanceof WorldGenLevelLightEngine) {
|
||||||
|
((WorldGenLevelLightEngine)lightEngine).lightChunk(chunk, !hasCorrectBlockLight);
|
||||||
|
} else if (lightEngine instanceof ThreadedLevelLightEngine) {
|
||||||
|
((ThreadedLevelLightEngine) lightEngine).lightChunk(chunk, !hasCorrectBlockLight).join();
|
||||||
|
} else {
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
if (chunk instanceof LevelChunk) ((LevelChunk)chunk).setClientLightReady(true);
|
||||||
|
chunk.setLightCorrect(true);
|
||||||
|
}
|
||||||
|
lightEngine.runUpdates(Integer.MAX_VALUE, true, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||||
|
|
||||||
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.world.level.LevelHeightAccessor;
|
||||||
|
import net.minecraft.world.level.StructureFeatureManager;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||||
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
import net.minecraft.world.level.levelgen.NoiseBasedChunkGenerator;
|
||||||
|
import net.minecraft.world.level.levelgen.NoiseSettings;
|
||||||
|
import net.minecraft.world.level.levelgen.blending.Blender;
|
||||||
|
|
||||||
|
public final class StepNoise {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private final BatchGenerationEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param batchGenerationEnvironment
|
||||||
|
*/
|
||||||
|
public StepNoise(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||||
|
{
|
||||||
|
environment = batchGenerationEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ChunkStatus STATUS = ChunkStatus.NOISE;
|
||||||
|
|
||||||
|
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||||
|
List<ChunkAccess> chunks) {
|
||||||
|
|
||||||
|
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunks) {
|
||||||
|
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||||
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
chunksToDo.add(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunksToDo) {
|
||||||
|
// System.out.println("StepNoise: "+chunk.getPos());
|
||||||
|
chunk = environment.joinSync(environment.params.generator.fillFromNoise(Runnable::run, Blender.of(worldGenRegion),
|
||||||
|
tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+54
@@ -0,0 +1,54 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||||
|
|
||||||
|
import net.minecraft.CrashReport;
|
||||||
|
import net.minecraft.CrashReportCategory;
|
||||||
|
import net.minecraft.ReportedException;
|
||||||
|
import net.minecraft.core.Registry;
|
||||||
|
import net.minecraft.core.SectionPos;
|
||||||
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
|
import net.minecraft.world.level.ChunkPos;
|
||||||
|
import net.minecraft.world.level.StructureFeatureManager;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
import net.minecraft.world.level.levelgen.structure.StructureStart;
|
||||||
|
|
||||||
|
public final class StepStructureReference {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private final BatchGenerationEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param batchGenerationEnvironment
|
||||||
|
*/
|
||||||
|
public StepStructureReference(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||||
|
{
|
||||||
|
environment = batchGenerationEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_REFERENCES;
|
||||||
|
|
||||||
|
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||||
|
List<ChunkAccess> chunks) {
|
||||||
|
|
||||||
|
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunks) {
|
||||||
|
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||||
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
chunksToDo.add(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunksToDo) {
|
||||||
|
// System.out.println("StepStructureReference: "+chunk.getPos());
|
||||||
|
environment.params.generator.createReferences(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion), chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+67
@@ -0,0 +1,67 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||||
|
|
||||||
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
|
||||||
|
public final class StepStructureStart {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private final BatchGenerationEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param batchGenerationEnvironment
|
||||||
|
*/
|
||||||
|
public StepStructureStart(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||||
|
{
|
||||||
|
environment = batchGenerationEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ChunkStatus STATUS = ChunkStatus.STRUCTURE_STARTS;
|
||||||
|
|
||||||
|
public static class StructStartCorruptedException extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = -8987434342051563358L;
|
||||||
|
|
||||||
|
public StructStartCorruptedException(ArrayIndexOutOfBoundsException e) {
|
||||||
|
super("StructStartCorruptedException");
|
||||||
|
super.initCause(e);
|
||||||
|
fillInStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||||
|
List<ChunkAccess> chunks) {
|
||||||
|
|
||||||
|
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunks) {
|
||||||
|
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||||
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
chunksToDo.add(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (environment.params.worldGenSettings.generateFeatures()) {
|
||||||
|
for (ChunkAccess chunk : chunksToDo) {
|
||||||
|
// System.out.println("StepStructureStart: "+chunk.getPos());
|
||||||
|
environment.params.generator.createStructures(environment.params.registry, tParams.structFeat, chunk, environment.params.structures,
|
||||||
|
environment.params.worldSeed);
|
||||||
|
try {
|
||||||
|
tParams.structCheck.onStructureLoad(chunk.getPos(), chunk.getAllStarts());
|
||||||
|
} catch (ArrayIndexOutOfBoundsException e) {
|
||||||
|
// There's a rare issue with StructStart where it throws ArrayIndexOutOfBounds
|
||||||
|
// This means the structFeat is corrupted (For some reason) and I need to reset it.
|
||||||
|
// TODO: Figure out in the future why this happens even though I am using new structFeat
|
||||||
|
throw new StepStructureStart.StructStartCorruptedException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+46
@@ -0,0 +1,46 @@
|
|||||||
|
package com.seibel.lod.common.wrappers.worldGeneration.step;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.ThreadedParameters;
|
||||||
|
|
||||||
|
import net.minecraft.server.level.WorldGenRegion;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkAccess;
|
||||||
|
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||||
|
import net.minecraft.world.level.chunk.ProtoChunk;
|
||||||
|
|
||||||
|
public final class StepSurface {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private final BatchGenerationEnvironment environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param batchGenerationEnvironment
|
||||||
|
*/
|
||||||
|
public StepSurface(BatchGenerationEnvironment batchGenerationEnvironment)
|
||||||
|
{
|
||||||
|
environment = batchGenerationEnvironment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final ChunkStatus STATUS = ChunkStatus.SURFACE;
|
||||||
|
|
||||||
|
public void generateGroup(ThreadedParameters tParams, WorldGenRegion worldGenRegion,
|
||||||
|
List<ChunkAccess> chunks) {
|
||||||
|
ArrayList<ChunkAccess> chunksToDo = new ArrayList<ChunkAccess>();
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunks) {
|
||||||
|
if (chunk.getStatus().isOrAfter(STATUS)) continue;
|
||||||
|
((ProtoChunk) chunk).setStatus(STATUS);
|
||||||
|
chunksToDo.add(chunk);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (ChunkAccess chunk : chunksToDo) {
|
||||||
|
// System.out.println("StepSurface: "+chunk.getPos());
|
||||||
|
environment.params.generator.buildSurface(worldGenRegion, tParams.structFeat.forWorldGenRegion(worldGenRegion),
|
||||||
|
chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
accessWidener v1 named
|
||||||
|
|
||||||
|
# used when determining where to save files to
|
||||||
|
accessible field net/minecraft/world/level/storage/DimensionDataStorage dataFolder Ljava/io/File;
|
||||||
|
|
||||||
|
# used when rendering
|
||||||
|
accessible field com/mojang/blaze3d/vertex/VertexBuffer indexCount I
|
||||||
|
accessible field com/mojang/blaze3d/vertex/VertexBuffer vertextBufferId I
|
||||||
|
accessible method net/minecraft/client/renderer/GameRenderer getFov (Lnet/minecraft/client/Camera;FZ)D
|
||||||
|
|
||||||
|
# used for grabbing vanilla rendered chunks
|
||||||
|
accessible field net/minecraft/client/renderer/LevelRenderer renderChunkStorage Ljava/util/concurrent/atomic/AtomicReference;
|
||||||
|
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkStorage
|
||||||
|
accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo
|
||||||
|
accessible field net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo chunk Lnet/minecraft/client/renderer/chunk/ChunkRenderDispatcher$RenderChunk;
|
||||||
|
|
||||||
|
# lighting
|
||||||
|
accessible field net/minecraft/client/renderer/LightTexture lightPixels Lcom/mojang/blaze3d/platform/NativeImage;
|
||||||
|
accessible field net/minecraft/world/level/lighting/LevelLightEngine blockEngine Lnet/minecraft/world/level/lighting/LayerLightEngine;
|
||||||
|
accessible field net/minecraft/world/level/lighting/LevelLightEngine skyEngine Lnet/minecraft/world/level/lighting/LayerLightEngine;
|
||||||
|
|
||||||
|
# world generation
|
||||||
|
accessible method net/minecraft/world/level/levelgen/Heightmap setHeight (III)V
|
||||||
|
accessible field net/minecraft/world/level/biome/Biome generationSettings Lnet/minecraft/world/level/biome/BiomeGenerationSettings;
|
||||||
|
accessible field net/minecraft/world/level/biome/Biome biomeCategory Lnet/minecraft/world/level/biome/Biome$BiomeCategory;
|
||||||
|
# accessible field net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator settings Lnet/minecraft/core/Holder;
|
||||||
|
accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doFill (Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;II)Lnet/minecraft/world/level/chunk/ChunkAccess;
|
||||||
|
#accessible method net/minecraft/world/level/levelgen/NoiseBasedChunkGenerator doCreateBiomes (Lnet/minecraft/core/Registry;Lnet/minecraft/world/level/levelgen/blending/Blender;Lnet/minecraft/world/level/StructureFeatureManager;Lnet/minecraft/world/level/chunk/ChunkAccess;)V
|
||||||
|
accessible method net/minecraft/world/level/lighting/LayerLightEngine queueSectionData (JLnet/minecraft/world/level/chunk/DataLayer;Z)V
|
||||||
|
|
||||||
|
# lod generation from save file
|
||||||
|
accessible field net/minecraft/server/level/ChunkMap mainThreadExecutor Lnet/minecraft/util/thread/BlockableEventLoop;
|
||||||
|
accessible method net/minecraft/server/level/ChunkMap readChunk (Lnet/minecraft/world/level/ChunkPos;)Lnet/minecraft/nbt/CompoundTag;
|
||||||
|
|
||||||
|
|
||||||
|
# grabbing textures
|
||||||
|
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite animatedTexture Lnet/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture;
|
||||||
|
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite width I
|
||||||
|
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite height I
|
||||||
|
accessible field net/minecraft/client/renderer/texture/TextureAtlasSprite mainImage [Lcom/mojang/blaze3d/platform/NativeImage;
|
||||||
|
accessible class net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture
|
||||||
|
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameX (I)I
|
||||||
|
accessible method net/minecraft/client/renderer/texture/TextureAtlasSprite$AnimatedTexture getFrameY (I)I
|
||||||
|
extendable class com/mojang/math/Matrix4f
|
||||||
|
|
||||||
|
# hacky stuff
|
||||||
|
accessible field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
|
||||||
|
mutable field net/minecraft/util/ThreadingDetector lock Ljava/util/concurrent/Semaphore;
|
||||||
Submodule
+1
Submodule core added at 6cd0281d0e
@@ -0,0 +1,169 @@
|
|||||||
|
plugins {
|
||||||
|
id "com.github.johnrengelman.shadow" version "7.1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
version = rootProject.mod_version+"-"+rootProject.minecraft_version+"-"+new Date().format("yyyy_MM_dd_HH_mm")
|
||||||
|
|
||||||
|
loom {
|
||||||
|
accessWidenerPath.set(project(":common").file("src/main/resources/lod.accesswidener"))
|
||||||
|
}
|
||||||
|
|
||||||
|
architectury {
|
||||||
|
platformSetupLoomIde()
|
||||||
|
fabric()
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
compileClasspath.extendsFrom common
|
||||||
|
runtimeClasspath.extendsFrom common
|
||||||
|
developmentFabric.extendsFrom common
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
// Required for ModMenu
|
||||||
|
maven { url "https://maven.terraformersmc.com/" }
|
||||||
|
}
|
||||||
|
|
||||||
|
def addMod(path, enabled) {
|
||||||
|
if (enabled == "2")
|
||||||
|
dependencies { modImplementation(path) }
|
||||||
|
else if (enabled == "1")
|
||||||
|
dependencies { modCompileOnly(path) }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Fabric loader
|
||||||
|
modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
|
||||||
|
|
||||||
|
// Fabric API
|
||||||
|
modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
|
||||||
|
|
||||||
|
// Mod Menu
|
||||||
|
modImplementation("com.terraformersmc:modmenu:${rootProject.modmenu_version}") {
|
||||||
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Starlight
|
||||||
|
addMod("curse.maven:starlight-521783:${rootProject.starlight_version_fabric}", rootProject.enable_starlight)
|
||||||
|
|
||||||
|
// Sodium
|
||||||
|
addMod("curse.maven:sodium-394468:${rootProject.sodium_version}", rootProject.enable_sodium)
|
||||||
|
implementation "org.joml:joml:1.10.2"
|
||||||
|
|
||||||
|
// Lithium
|
||||||
|
addMod("maven.modrinth:lithium:${rootProject.lithium_version}", rootProject.enable_lithium)
|
||||||
|
|
||||||
|
// Iris
|
||||||
|
addMod("maven.modrinth:iris:${rootProject.iris_version}", rootProject.enable_iris)
|
||||||
|
|
||||||
|
// BCLib
|
||||||
|
addMod("com.github.paulevsGitch:BCLib:${rootProject.bclib_version}", rootProject.enable_bclib)
|
||||||
|
|
||||||
|
// Immersive Portals
|
||||||
|
/*
|
||||||
|
modImplementation("com.github.qouteall.ImmersivePortalsMod:build:${rootProject.immersive_portals_version}") {
|
||||||
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
|
transitive(false)
|
||||||
|
}
|
||||||
|
modImplementation("com.github.qouteall.ImmersivePortalsMod:imm_ptl_core:${rootProject.immersive_portals_version}") {
|
||||||
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
|
transitive(false)
|
||||||
|
}
|
||||||
|
modImplementation("com.github.qouteall.ImmersivePortalsMod:q_misc_util:${rootProject.immersive_portals_version}") {
|
||||||
|
exclude(group: "net.fabricmc.fabric-api")
|
||||||
|
transitive(false)
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Toml
|
||||||
|
shadowMe("com.electronwill.night-config:toml:${rootProject.toml_version}") {}
|
||||||
|
|
||||||
|
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||||
|
shadowMe(project(path: ":common", configuration: "transformProductionFabric")) { transitive false }
|
||||||
|
|
||||||
|
// Compression
|
||||||
|
common 'org.tukaani:xz:1.9'
|
||||||
|
common 'org.apache.commons:commons-compress:1.21'
|
||||||
|
shadowMe 'org.tukaani:xz:1.9'
|
||||||
|
shadowMe 'org.apache.commons:commons-compress:1.21'
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method copies the access wideners from the common project to the fabric project. And it was generated by Github Copilot
|
||||||
|
task copyAccessWidener(type: Copy) {
|
||||||
|
from project(":common").file("src/main/resources/lod.accesswidener")
|
||||||
|
into file("src/generated/resources")
|
||||||
|
}
|
||||||
|
|
||||||
|
task copyCoreResources(type: Copy) {
|
||||||
|
from fileTree(project(":core").file("src/main/resources"))
|
||||||
|
into file("build/resources/main")
|
||||||
|
}
|
||||||
|
|
||||||
|
task deleteResources(type: Delete) {
|
||||||
|
delete file("build/resources/main")
|
||||||
|
}
|
||||||
|
|
||||||
|
task copyCommonResources(type: Copy) {
|
||||||
|
from fileTree(project(":common").file("src/main/resources"))
|
||||||
|
into file("build/resources/main")
|
||||||
|
}
|
||||||
|
|
||||||
|
runClient {
|
||||||
|
dependsOn(copyCoreResources)
|
||||||
|
dependsOn(copyCommonResources)
|
||||||
|
jvmArgs "-XX:-OmitStackTraceInFastThrow"
|
||||||
|
finalizedBy(deleteResources)
|
||||||
|
}
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
dependsOn(copyAccessWidener)
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
configurations = [project.configurations.shadowMe]
|
||||||
|
relocate 'org.tukaani', 'shaded.tukaani'
|
||||||
|
relocate 'org.apache.commons.compress', 'shaded.apache.commons.compress'
|
||||||
|
relocate 'com.electronwill.nightconfig', 'shaded.electronwill.nightconfig'
|
||||||
|
|
||||||
|
relocate 'com.seibel.lod.common', 'fabric.com.seibel.lod.common'
|
||||||
|
|
||||||
|
classifier "dev-shadow"
|
||||||
|
}
|
||||||
|
|
||||||
|
remapJar {
|
||||||
|
input.set shadowJar.archiveFile
|
||||||
|
dependsOn shadowJar
|
||||||
|
classifier null
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
classifier "dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
sourcesJar {
|
||||||
|
def commonSources = project(":common").sourcesJar
|
||||||
|
dependsOn commonSources
|
||||||
|
from commonSources.archiveFile.map { zipTree(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
components.java {
|
||||||
|
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
||||||
|
skip()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
mavenFabric(MavenPublication) {
|
||||||
|
artifactId = rootProject.archives_base_name + "-" + project.name
|
||||||
|
from components.java
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
||||||
|
repositories {
|
||||||
|
// Add repositories to publish to here.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,194 @@
|
|||||||
|
/*
|
||||||
|
* 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.fabric;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.worldGeneration.BatchGenerationEnvironment;
|
||||||
|
import com.seibel.lod.core.api.ClientApi;
|
||||||
|
import com.seibel.lod.core.api.EventApi;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.mojang.blaze3d.platform.InputConstants;
|
||||||
|
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.world.DimensionTypeWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||||
|
|
||||||
|
import com.seibel.lod.fabric.mixins.MixinUtilBackgroudThread;
|
||||||
|
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents;
|
||||||
|
import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
|
||||||
|
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerWorldEvents;
|
||||||
|
import net.minecraft.client.KeyMapping;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.server.MinecraftServer;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
|
import net.minecraft.world.level.LevelAccessor;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This handles all events sent to the client,
|
||||||
|
* and is the starting point for most of the mod.
|
||||||
|
*
|
||||||
|
* @author coolGi2007
|
||||||
|
* @author Ran
|
||||||
|
* @version 11-23-2021
|
||||||
|
*/
|
||||||
|
public class ClientProxy
|
||||||
|
{
|
||||||
|
private final EventApi eventApi = EventApi.INSTANCE;
|
||||||
|
private final ClientApi clientApi = ClientApi.INSTANCE;
|
||||||
|
|
||||||
|
public static Supplier<Boolean> isGenerationThreadChecker = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers Fabric Events
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
public void registerEvents() {
|
||||||
|
/* Registor the mod accessor*/
|
||||||
|
|
||||||
|
/* World Events */
|
||||||
|
//ServerTickEvents.START_SERVER_TICK.register(this::serverTickEvent);
|
||||||
|
ServerTickEvents.END_SERVER_TICK.register(this::serverTickEvent);
|
||||||
|
|
||||||
|
/* World Events */
|
||||||
|
//ServerChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
|
||||||
|
//ClientChunkEvents.CHUNK_LOAD.register(this::chunkLoadEvent);
|
||||||
|
|
||||||
|
/* World Events */
|
||||||
|
ServerWorldEvents.LOAD.register((server, level) -> this.worldLoadEvent(level));
|
||||||
|
ServerWorldEvents.UNLOAD.register((server, level) -> this.worldUnloadEvent(level));
|
||||||
|
|
||||||
|
/* The Client World Events are in the mixins
|
||||||
|
Client world load event is in MixinClientLevel
|
||||||
|
Client world unload event is in MixinMinecraft */
|
||||||
|
/* The save events are in MixinServerLevel */
|
||||||
|
|
||||||
|
/* Keyboard Events */
|
||||||
|
ClientTickEvents.END_CLIENT_TICK.register(client -> {
|
||||||
|
if (client.player != null) onKeyInput();
|
||||||
|
});
|
||||||
|
isGenerationThreadChecker = BatchGenerationEnvironment::isCurrentThreadDistantGeneratorThread;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void serverTickEvent(MinecraftServer server)
|
||||||
|
{
|
||||||
|
eventApi.serverTickEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void chunkLoadEvent(LevelAccessor level, LevelChunk chunk)
|
||||||
|
{
|
||||||
|
clientApi.clientChunkLoadEvent(new ChunkWrapper(chunk, level),
|
||||||
|
WorldWrapper.getWorldWrapper(level));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void worldSaveEvent()
|
||||||
|
{
|
||||||
|
eventApi.worldSaveEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** This is also called when a new dimension loads */
|
||||||
|
public void worldLoadEvent(Level level)
|
||||||
|
{
|
||||||
|
if (level != null) {
|
||||||
|
eventApi.worldLoadEvent(WorldWrapper.getWorldWrapper(level));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void worldUnloadEvent(Level level)
|
||||||
|
{
|
||||||
|
if (level != null) {
|
||||||
|
eventApi.worldUnloadEvent(WorldWrapper.getWorldWrapper(level));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Can someone tell me how to make this better
|
||||||
|
* @author Ran
|
||||||
|
*
|
||||||
|
* public void blockChangeEvent(BlockEventData event) {
|
||||||
|
* // we only care about certain block events
|
||||||
|
* if (event.getClass() == BlockEventData.BreakEvent.class ||
|
||||||
|
* event.getClass() == BlockEventData.EntityPlaceEvent.class ||
|
||||||
|
* event.getClass() == BlockEventData.EntityMultiPlaceEvent.class ||
|
||||||
|
* event.getClass() == BlockEventData.FluidPlaceBlockEvent.class ||
|
||||||
|
* event.getClass() == BlockEventData.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);
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
public void blockChangeEvent(LevelAccessor world, BlockPos pos) {
|
||||||
|
IChunkWrapper chunk = new ChunkWrapper(world.getChunk(pos), world);
|
||||||
|
DimensionTypeWrapper dimType = DimensionTypeWrapper.getDimensionTypeWrapper(world.dimensionType());
|
||||||
|
|
||||||
|
// recreate the LOD where the blocks were changed
|
||||||
|
eventApi.blockChangeEvent(chunk, dimType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final List<Integer> KEY_TO_CHECK_FOR = List.of(GLFW.GLFW_KEY_F6, GLFW.GLFW_KEY_F8);
|
||||||
|
|
||||||
|
HashSet<Integer> previousKeyDown = new HashSet<Integer>();
|
||||||
|
|
||||||
|
public void onKeyInput() {
|
||||||
|
ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||||
|
if (CONFIG.client().advanced().debugging().getDebugKeybindingsEnabled())
|
||||||
|
{
|
||||||
|
HashSet<Integer> currectKeyDown = new HashSet<Integer>();
|
||||||
|
|
||||||
|
// Note: Minecraft's InputConstants is same as GLFW Key values
|
||||||
|
//TODO: Use mixin to hook directly into the GLFW Keyboard event in minecraft KeyboardHandler
|
||||||
|
// Check all keys we need
|
||||||
|
for (int i = InputConstants.KEY_A; i <= InputConstants.KEY_Z; i++) {
|
||||||
|
if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), i)) {
|
||||||
|
currectKeyDown.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i : KEY_TO_CHECK_FOR) {
|
||||||
|
if (InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), i)) {
|
||||||
|
currectKeyDown.add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Diff and trigger events
|
||||||
|
for (int c : currectKeyDown) {
|
||||||
|
if (!previousKeyDown.contains(c)) {
|
||||||
|
ClientApi.INSTANCE.keyPressedEvent(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the set
|
||||||
|
previousKeyDown = currectKeyDown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* 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.fabric;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.LodCommonMain;
|
||||||
|
import com.seibel.lod.core.ModInfo;
|
||||||
|
import com.seibel.lod.core.api.ApiShared;
|
||||||
|
import com.seibel.lod.core.api.ClientApi;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
|
||||||
|
import com.seibel.lod.fabric.networking.NetworkHandler;
|
||||||
|
import com.seibel.lod.fabric.wrappers.modAccessor.ModChecker;
|
||||||
|
import com.seibel.lod.fabric.wrappers.modAccessor.OptifineAccessor;
|
||||||
|
import com.seibel.lod.fabric.wrappers.modAccessor.SodiumAccessor;
|
||||||
|
import com.seibel.lod.fabric.wrappers.modAccessor.StarlightAccessor;
|
||||||
|
import com.seibel.lod.fabric.wrappers.FabricDependencySetup;
|
||||||
|
|
||||||
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize and setup the Mod. <br>
|
||||||
|
* If you are looking for the real start of the mod
|
||||||
|
* check out the ClientProxy.
|
||||||
|
*
|
||||||
|
* @author coolGi2007
|
||||||
|
* @author Ran
|
||||||
|
* @version 12-1-2021
|
||||||
|
*/
|
||||||
|
public class Main implements ClientModInitializer
|
||||||
|
{
|
||||||
|
// This is a client mod so it should implement ClientModInitializer and in fabric.mod.json it should have "environment": "client"
|
||||||
|
// Once it works on servers change the implement to ModInitializer and in fabric.mod.json it should be "environment": "*"
|
||||||
|
|
||||||
|
public static ClientProxy client_proxy;
|
||||||
|
|
||||||
|
|
||||||
|
// Do if implements ClientModInitializer
|
||||||
|
// This loads the mod before minecraft loads which causes a lot of issues
|
||||||
|
@Override
|
||||||
|
public void onInitializeClient() {
|
||||||
|
// no.
|
||||||
|
}
|
||||||
|
|
||||||
|
// This loads the mod after minecraft loads which doesn't causes a lot of issues
|
||||||
|
public static void init() {
|
||||||
|
LodCommonMain.initConfig();
|
||||||
|
LodCommonMain.startup(null, false, new NetworkHandler());
|
||||||
|
FabricDependencySetup.createInitialBindings();
|
||||||
|
FabricDependencySetup.finishBinding();
|
||||||
|
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
|
||||||
|
|
||||||
|
// Check if this works
|
||||||
|
client_proxy = new ClientProxy();
|
||||||
|
client_proxy.registerEvents();
|
||||||
|
if (SingletonHandler.get(IModChecker.class).isModLoaded("sodium")) {
|
||||||
|
ModAccessorHandler.bind(ISodiumAccessor.class, new SodiumAccessor());
|
||||||
|
}
|
||||||
|
if (SingletonHandler.get(IModChecker.class).isModLoaded("starlight")) {
|
||||||
|
ModAccessorHandler.bind(IStarlightAccessor.class, new StarlightAccessor());
|
||||||
|
}
|
||||||
|
if (SingletonHandler.get(IModChecker.class).isModLoaded("optifine")) {
|
||||||
|
ModAccessorHandler.bind(IOptifineAccessor.class, new OptifineAccessor());
|
||||||
|
}
|
||||||
|
|
||||||
|
ModAccessorHandler.finishBinding();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void initServer() {
|
||||||
|
LodCommonMain.initConfig();
|
||||||
|
LodCommonMain.startup(null, true, new NetworkHandler());
|
||||||
|
FabricDependencySetup.createInitialBindings();
|
||||||
|
FabricDependencySetup.finishBinding();
|
||||||
|
ApiShared.LOGGER.info(ModInfo.READABLE_NAME + ", Version: " + ModInfo.VERSION);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.seibel.lod.fabric.mixins;
|
||||||
|
|
||||||
|
import com.seibel.lod.fabric.Main;
|
||||||
|
import net.minecraft.server.dedicated.DedicatedServer;
|
||||||
|
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.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
@Mixin(DedicatedServer.class)
|
||||||
|
public class MixinDedicatedServer {
|
||||||
|
@Inject(method = "initServer", at = @At("TAIL"))
|
||||||
|
public void initServer(CallbackInfoReturnable<Boolean> cir) {
|
||||||
|
Main.initServer();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package com.seibel.lod.fabric.mixins;
|
||||||
|
|
||||||
|
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.systems.RenderSystem;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||||
|
|
||||||
|
import net.minecraft.client.Camera;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer;
|
||||||
|
import net.minecraft.client.renderer.FogRenderer.FogMode;
|
||||||
|
import net.minecraft.world.effect.MobEffects;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
import net.minecraft.world.level.material.FogType;
|
||||||
|
|
||||||
|
@Mixin(FogRenderer.class)
|
||||||
|
public class MixinFogRenderer {
|
||||||
|
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||||
|
|
||||||
|
// Using this instead of Float.MAX_VALUE because Sodium don't like it.
|
||||||
|
private static final float A_REALLY_REALLY_BIG_VALUE = 420694206942069.F;
|
||||||
|
private static final float A_EVEN_LARGER_VALUE = 42069420694206942069.F;
|
||||||
|
|
||||||
|
@Inject(at = @At("RETURN"), method = "setupFog(Lnet/minecraft/client/Camera;Lnet/minecraft/client/renderer/FogRenderer$FogMode;FZ)V")
|
||||||
|
private static void disableSetupFog(Camera camera, FogMode fogMode, float f, boolean bl, CallbackInfo callback) {
|
||||||
|
FogType fogTypes = camera.getFluidInCamera();
|
||||||
|
Entity entity = camera.getEntity();
|
||||||
|
boolean isUnderWater = (entity instanceof LivingEntity) && ((LivingEntity)entity).hasEffect(MobEffects.BLINDNESS);
|
||||||
|
if (!isUnderWater) {
|
||||||
|
if (fogMode == FogMode.FOG_TERRAIN && fogTypes == FogType.NONE && CONFIG.client().graphics().fogQuality().getDisableVanillaFog()) {
|
||||||
|
RenderSystem.setShaderFogStart(A_REALLY_REALLY_BIG_VALUE);
|
||||||
|
RenderSystem.setShaderFogEnd(A_EVEN_LARGER_VALUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.seibel.lod.fabric.mixins;
|
||||||
|
|
||||||
|
import com.seibel.lod.fabric.Main;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.main.GameConfig;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the mod after minecraft loads.
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
@Mixin(value = Minecraft.class)
|
||||||
|
public class MixinMinecraft {
|
||||||
|
@Inject(method = "<init>", at = @At("TAIL"))
|
||||||
|
private void startMod(GameConfig gameConfig, CallbackInfo ci) {
|
||||||
|
Main.init();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
package com.seibel.lod.fabric.mixins;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.config.ConfigGui;
|
||||||
|
import com.seibel.lod.common.wrappers.config.TexturedButtonWidget;
|
||||||
|
import com.seibel.lod.core.ModInfo;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||||
|
import net.minecraft.client.gui.screens.OptionsScreen;
|
||||||
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.network.chat.TranslatableComponent;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
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 java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a button to the menu to goto the config
|
||||||
|
*
|
||||||
|
* @author coolGi2007
|
||||||
|
* @version 12-02-2021
|
||||||
|
*/
|
||||||
|
@Mixin(OptionsScreen.class)
|
||||||
|
public class MixinOptionsScreen extends Screen {
|
||||||
|
// Get the texture for the button
|
||||||
|
private static final ResourceLocation ICON_TEXTURE = new ResourceLocation(ModInfo.ID,"textures/gui/button.png");
|
||||||
|
protected MixinOptionsScreen(Component title) {
|
||||||
|
super(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(at = @At("HEAD"),method = "init")
|
||||||
|
private void lodconfig$init(CallbackInfo ci) {
|
||||||
|
if (SingletonHandler.get(ILodConfigWrapperSingleton.class).client().getOptionsButton())
|
||||||
|
this.addRenderableWidget(new TexturedButtonWidget(
|
||||||
|
// Where the button is on the screen
|
||||||
|
this.width / 2 - 180, this.height / 6 - 12,
|
||||||
|
// Width and height of the button
|
||||||
|
20, 20,
|
||||||
|
// Offset
|
||||||
|
0, 0,
|
||||||
|
// Some textuary stuff
|
||||||
|
20, ICON_TEXTURE, 20, 40,
|
||||||
|
// Create the button and tell it where to go
|
||||||
|
// For now it goes to the client option by default
|
||||||
|
(buttonWidget) -> Objects.requireNonNull(minecraft).setScreen(ConfigGui.getScreen(this, "client")),
|
||||||
|
// Add a title to the screen
|
||||||
|
new TranslatableComponent("text.autoconfig." + ModInfo.ID + ".title")));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package com.seibel.lod.fabric.mixins;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import com.seibel.lod.fabric.ClientProxy;
|
||||||
|
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.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.util.DummyRunExecutorService;
|
||||||
|
|
||||||
|
import net.minecraft.Util;
|
||||||
|
|
||||||
|
@Mixin(Util.class)
|
||||||
|
public class MixinUtilBackgroudThread
|
||||||
|
{
|
||||||
|
|
||||||
|
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/lang/Runnable;)Ljava/lang/Runnable;",
|
||||||
|
at = @At("HEAD"), cancellable = true)
|
||||||
|
private static void overrideUtil$wrapThreadWithTaskName(String string, Runnable r, CallbackInfoReturnable<Runnable> ci)
|
||||||
|
{
|
||||||
|
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
|
||||||
|
{
|
||||||
|
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Runnable) triggered");
|
||||||
|
ci.setReturnValue(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Inject(method = "wrapThreadWithTaskName(Ljava/lang/String;Ljava/util/function/Supplier;)Ljava/util/function/Supplier;",
|
||||||
|
at = @At("HEAD"), cancellable = true)
|
||||||
|
private static void overrideUtil$wrapThreadWithTaskNameForSupplier(String string, Supplier<?> r, CallbackInfoReturnable<Supplier<?>> ci)
|
||||||
|
{
|
||||||
|
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
|
||||||
|
{
|
||||||
|
//ApiShared.LOGGER.info("util wrapThreadWithTaskName(Supplier) triggered");
|
||||||
|
ci.setReturnValue(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "backgroundExecutor", at = @At("HEAD"), cancellable = true)
|
||||||
|
private static void overrideUtil$backgroundExecutor(CallbackInfoReturnable<ExecutorService> ci)
|
||||||
|
{
|
||||||
|
if (ClientProxy.isGenerationThreadChecker != null && ClientProxy.isGenerationThreadChecker.get())
|
||||||
|
{
|
||||||
|
//ApiShared.LOGGER.info("util backgroundExecutor triggered");
|
||||||
|
ci.setReturnValue(new DummyRunExecutorService());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* 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.fabric.mixins;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.vertex.PoseStack;
|
||||||
|
import com.mojang.math.Matrix4f;
|
||||||
|
import com.seibel.lod.common.wrappers.McObjectConverter;
|
||||||
|
import com.seibel.lod.core.api.ClientApi;
|
||||||
|
import com.seibel.lod.core.objects.math.Mat4f;
|
||||||
|
import net.minecraft.client.Camera;
|
||||||
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
|
import net.minecraft.client.renderer.RenderType;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
* This is also the mixin for rendering the clouds
|
||||||
|
*
|
||||||
|
* @author coolGi2007
|
||||||
|
* @author James Seibel
|
||||||
|
* @version 12-31-2021
|
||||||
|
*/
|
||||||
|
@Mixin(LevelRenderer.class)
|
||||||
|
public class MixinWorldRenderer
|
||||||
|
{
|
||||||
|
private static float previousPartialTicks = 0;
|
||||||
|
|
||||||
|
public MixinWorldRenderer() {
|
||||||
|
throw new NullPointerException("Null cannot be cast to non-null type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "renderClouds", at = @At("HEAD"), cancellable = true)
|
||||||
|
public void renderClouds(PoseStack poseStack, Matrix4f projectionMatrix, float tickDelta, double cameraX, double cameraY, double cameraZ, CallbackInfo ci) {
|
||||||
|
// get the partial ticks since renderChunkLayer doesn't
|
||||||
|
// have access to them
|
||||||
|
previousPartialTicks = tickDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HEAD or RETURN
|
||||||
|
@Inject(at = @At("RETURN"),
|
||||||
|
method = "renderSky",
|
||||||
|
cancellable = true)
|
||||||
|
private void renderLod(PoseStack modelViewMatrixStack, Matrix4f projectionMatrix, float f,
|
||||||
|
#if MC_VERSION_1_18_2 Camera camera, boolean bl,#endif Runnable r, CallbackInfo callback) {
|
||||||
|
|
||||||
|
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||||
|
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
|
|
||||||
|
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
// HEAD or RETURN
|
||||||
|
@Inject(at = @At("HEAD"),
|
||||||
|
method = "renderChunkLayer(Lnet/minecraft/client/renderer/RenderType;Lcom/mojang/blaze3d/vertex/PoseStack;DDDLcom/mojang/math/Matrix4f;)V",
|
||||||
|
cancellable = true)
|
||||||
|
private void renderChunkLayer(RenderType renderType, PoseStack modelViewMatrixStack, double cameraXBlockPos, double cameraYBlockPos, double cameraZBlockPos, Matrix4f projectionMatrix, CallbackInfo callback)
|
||||||
|
{
|
||||||
|
// only render before solid blocks
|
||||||
|
if (renderType.equals(RenderType.solid()))
|
||||||
|
{
|
||||||
|
Mat4f mcModelViewMatrix = McObjectConverter.Convert(modelViewMatrixStack.last().pose());
|
||||||
|
Mat4f mcProjectionMatrix = McObjectConverter.Convert(projectionMatrix);
|
||||||
|
|
||||||
|
ClientApi.INSTANCE.renderLods(mcModelViewMatrix, mcProjectionMatrix, previousPartialTicks);
|
||||||
|
}
|
||||||
|
//callback.cancel();
|
||||||
|
}*/
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package com.seibel.lod.fabric.mixins.events;
|
||||||
|
|
||||||
|
import com.seibel.lod.fabric.Main;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
|
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||||
|
import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If someone has a better way to do this then please let me know.
|
||||||
|
*
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
@Mixin(ClientboundBlockUpdatePacket.class)
|
||||||
|
public abstract class MixinBlockUpdate {
|
||||||
|
@Shadow public abstract BlockPos getPos();
|
||||||
|
|
||||||
|
@Inject(method = "handle(Lnet/minecraft/network/protocol/game/ClientGamePacketListener;)V", at = @At("TAIL"))
|
||||||
|
private void onBlockUpdate(ClientGamePacketListener clientGamePacketListener, CallbackInfo ci) {
|
||||||
|
Main.client_proxy.blockChangeEvent(Minecraft.getInstance().player.clientLevel, this.getPos());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
package com.seibel.lod.fabric.mixins.events;
|
||||||
|
|
||||||
|
import com.seibel.lod.fabric.Main;
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
|
import net.minecraft.client.renderer.LevelRenderer;
|
||||||
|
#if MC_VERSION_1_18_2
|
||||||
|
import net.minecraft.core.Holder;
|
||||||
|
#endif
|
||||||
|
import net.minecraft.resources.ResourceKey;
|
||||||
|
import net.minecraft.world.level.chunk.LevelChunk;
|
||||||
|
import net.minecraft.world.level.dimension.DimensionType;
|
||||||
|
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 java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used for world loading events
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Mixin(ClientLevel.class)
|
||||||
|
public class MixinClientLevel {
|
||||||
|
#if MC_VERSION_1_18_2
|
||||||
|
@Inject(method = "<init>", at = @At("TAIL"))
|
||||||
|
private void loadWorldEvent(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey resourceKey, Holder holder, int i, int j, Supplier supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) {
|
||||||
|
Main.client_proxy.worldLoadEvent((ClientLevel) (Object) this);
|
||||||
|
}
|
||||||
|
#elif MC_VERSION_1_18_1
|
||||||
|
@Inject(method = "<init>", at = @At("TAIL"))
|
||||||
|
private void loadWorldEvent(ClientPacketListener clientPacketListener, ClientLevel.ClientLevelData clientLevelData, ResourceKey resourceKey, DimensionType dimensionType, int i, int j, Supplier supplier, LevelRenderer levelRenderer, boolean bl, long l, CallbackInfo ci) {
|
||||||
|
Main.client_proxy.worldLoadEvent((ClientLevel) (Object) this);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@Inject(method = "setLightReady", at = @At("HEAD"))
|
||||||
|
private void onChunkLightReady(int x, int z, CallbackInfo ci) {
|
||||||
|
ClientLevel l = (ClientLevel) (Object) this;
|
||||||
|
LevelChunk chunk = l.getChunkSource().getChunk(x, z, false);
|
||||||
|
if (chunk!=null && !chunk.isClientLightReady())
|
||||||
|
Main.client_proxy.chunkLoadEvent(l, chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.seibel.lod.fabric.mixins.events;
|
||||||
|
|
||||||
|
import com.seibel.lod.fabric.Main;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.screens.Screen;
|
||||||
|
import net.minecraft.client.multiplayer.ClientLevel;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used for world unloading events
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
@Mixin(Minecraft.class)
|
||||||
|
public class MixinMinecraft {
|
||||||
|
@Shadow @Nullable public ClientLevel level;
|
||||||
|
|
||||||
|
@Inject(method = "setLevel", at = @At("HEAD"))
|
||||||
|
private void unloadWorldEvent_sL(ClientLevel clientLevel, CallbackInfo ci) {
|
||||||
|
if (level != null) Main.client_proxy.worldUnloadEvent(level);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At("HEAD"))
|
||||||
|
private void unloadWorldEvent_cL(Screen screen, CallbackInfo ci) {
|
||||||
|
if (this.level != null) Main.client_proxy.worldUnloadEvent(this.level);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.seibel.lod.fabric.mixins.events;
|
||||||
|
|
||||||
|
import com.seibel.lod.fabric.Main;
|
||||||
|
import net.minecraft.server.level.ServerLevel;
|
||||||
|
import net.minecraft.util.ProgressListener;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used for world saving events
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
@Mixin(ServerLevel.class)
|
||||||
|
public class MixinServerLevel {
|
||||||
|
@Inject(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;saveAll()V", shift = At.Shift.AFTER))
|
||||||
|
private void saveWorldEvent_sA(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) {
|
||||||
|
Main.client_proxy.worldSaveEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "save", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/level/entity/PersistentEntitySectionManager;autoSave()V", shift = At.Shift.AFTER))
|
||||||
|
private void saveWorldEvent_aS(ProgressListener progressListener, boolean bl, boolean bl2, CallbackInfo ci) {
|
||||||
|
Main.client_proxy.worldSaveEvent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.seibel.lod.fabric.mixins.unsafe;
|
||||||
|
|
||||||
|
import net.minecraft.util.ThreadingDetector;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import java.util.concurrent.Semaphore;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Why does this exist? But okay! (Will be probably removed when the experimental generator is done)
|
||||||
|
*/
|
||||||
|
@Mixin(ThreadingDetector.class)
|
||||||
|
public class MixinThreadingDectector {
|
||||||
|
@Mutable
|
||||||
|
@Shadow
|
||||||
|
private Semaphore lock;
|
||||||
|
|
||||||
|
@Inject(method = "<init>", at = @At("RETURN"))
|
||||||
|
private void setSemaphore(CallbackInfo ci) {
|
||||||
|
this.lock = new Semaphore(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.seibel.lod.fabric.networking;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.networking.NetworkInterface;
|
||||||
|
import com.seibel.lod.common.networking.Networking;
|
||||||
|
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
|
||||||
|
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Ran
|
||||||
|
*/
|
||||||
|
public class NetworkHandler implements NetworkInterface {
|
||||||
|
@Override
|
||||||
|
public void register_Client() {
|
||||||
|
ClientPlayNetworking.registerGlobalReceiver(Networking.resourceLocation_meow, (client, handler, buf, responseSender) -> {
|
||||||
|
com.seibel.lod.common.networking.NetworkHandler.receivePacketClient(client, handler, buf);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void register_Server() {
|
||||||
|
ServerPlayNetworking.registerGlobalReceiver(Networking.resourceLocation_meow, (server, player, handler, buf, responseSender) -> {
|
||||||
|
com.seibel.lod.common.networking.NetworkHandler.receivePacketServer(server, player, handler, buf);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.seibel.lod.fabric.wrappers;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||||
|
import com.seibel.lod.common.wrappers.config.LodConfigWrapperSingleton;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||||
|
import com.seibel.lod.fabric.wrappers.modAccessor.ModChecker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @author Ran
|
||||||
|
* @version 3-5-2022
|
||||||
|
*/
|
||||||
|
public class FabricDependencySetup
|
||||||
|
{
|
||||||
|
public static void createInitialBindings()
|
||||||
|
{
|
||||||
|
SingletonHandler.bind(IModChecker.class, ModChecker.INSTANCE);
|
||||||
|
|
||||||
|
SingletonHandler.bind(ILodConfigWrapperSingleton.class, LodConfigWrapperSingleton.INSTANCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void finishBinding() {
|
||||||
|
SingletonHandler.finishBinding();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.seibel.lod.fabric.wrappers.config;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.config.ConfigGui;
|
||||||
|
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
|
||||||
|
import com.terraformersmc.modmenu.api.ModMenuApi;
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For making the config show up in modmenu
|
||||||
|
*/
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
public class ModMenuIntegration implements ModMenuApi {
|
||||||
|
// For the custom config code
|
||||||
|
@Override
|
||||||
|
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
||||||
|
return parent -> ConfigGui.getScreen(parent, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package com.seibel.lod.fabric.wrappers.modAccessor;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||||
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
|
|
||||||
|
public class ModChecker implements IModChecker {
|
||||||
|
public static final ModChecker INSTANCE = new ModChecker();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isModLoaded(String modid) {
|
||||||
|
return FabricLoader.getInstance().isModLoaded(modid);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.seibel.lod.fabric.wrappers.modAccessor;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||||
|
|
||||||
|
public class OptifineAccessor implements IOptifineAccessor
|
||||||
|
{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModName()
|
||||||
|
{
|
||||||
|
return "Optifine-Fabric-1.18.X";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashSet<AbstractChunkPosWrapper> getNormalRenderedChunks()
|
||||||
|
{
|
||||||
|
// TODO: Impl proper methods here
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.seibel.lod.fabric.wrappers.modAccessor;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||||
|
|
||||||
|
import me.jellysquid.mods.sodium.client.render.SodiumWorldRenderer;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.world.level.LevelHeightAccessor;
|
||||||
|
|
||||||
|
public class SodiumAccessor implements ISodiumAccessor {
|
||||||
|
IWrapperFactory factory = SingletonHandler.get(IWrapperFactory.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModName() {
|
||||||
|
return "Sodium-Fabric-1.18.X";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public HashSet<AbstractChunkPosWrapper> getNormalRenderedChunks() {
|
||||||
|
SodiumWorldRenderer renderer = SodiumWorldRenderer.instance();
|
||||||
|
LevelHeightAccessor height = Minecraft.getInstance().level;
|
||||||
|
// 0b11 = Lighted chunk & loaded chunk
|
||||||
|
return renderer.getChunkTracker().getChunks(0b00).filter(
|
||||||
|
(long l) -> {
|
||||||
|
return true;
|
||||||
|
//for (int i = height.getMinSection(); i<height.getMaxSection(); i++) {
|
||||||
|
// SectionPos p = SectionPos.of(new ChunkPos(l), i);
|
||||||
|
// if (renderer.isBoxVisible(p.minBlockX()+1, p.minBlockY()+1, p.minBlockZ()+1,
|
||||||
|
// p.maxBlockX()-1, p.maxBlockY()-1, p.maxBlockZ()-1)) return true;
|
||||||
|
//}
|
||||||
|
//return false;
|
||||||
|
}).mapToObj((long l) -> {
|
||||||
|
return (AbstractChunkPosWrapper)factory.createChunkPos(l);
|
||||||
|
}).collect(Collectors.toCollection(HashSet::new));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
package com.seibel.lod.fabric.wrappers.modAccessor;
|
||||||
|
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IStarlightAccessor;
|
||||||
|
|
||||||
|
|
||||||
|
public class StarlightAccessor implements IStarlightAccessor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getModName() {
|
||||||
|
return "Starlight-Fabric-1.18.X";
|
||||||
|
}
|
||||||
|
|
||||||
|
public StarlightAccessor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,458 @@
|
|||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
Version 2.1, February 1999
|
||||||
|
|
||||||
|
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
[This is the first released version of the Lesser GPL. It also counts
|
||||||
|
as the successor of the GNU Library Public License, version 2, hence
|
||||||
|
the version number 2.1.]
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
Licenses are intended to guarantee your freedom to share and change
|
||||||
|
free software--to make sure the software is free for all its users.
|
||||||
|
|
||||||
|
This license, the Lesser General Public License, applies to some
|
||||||
|
specially designated software packages--typically libraries--of the
|
||||||
|
Free Software Foundation and other authors who decide to use it. You
|
||||||
|
can use it too, but we suggest you first think carefully about whether
|
||||||
|
this license or the ordinary General Public License is the better
|
||||||
|
strategy to use in any particular case, based on the explanations below.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom of use,
|
||||||
|
not price. Our General Public Licenses are designed to make sure that
|
||||||
|
you have the freedom to distribute copies of free software (and charge
|
||||||
|
for this service if you wish); that you receive source code or can get
|
||||||
|
it if you want it; that you can change the software and use pieces of
|
||||||
|
it in new free programs; and that you are informed that you can do
|
||||||
|
these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
distributors to deny you these rights or to ask you to surrender these
|
||||||
|
rights. These restrictions translate to certain responsibilities for
|
||||||
|
you if you distribute copies of the library or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of the library, whether gratis
|
||||||
|
or for a fee, you must give the recipients all the rights that we gave
|
||||||
|
you. You must make sure that they, too, receive or can get the source
|
||||||
|
code. If you link other code with the library, you must provide
|
||||||
|
complete object files to the recipients, so that they can relink them
|
||||||
|
with the library after making changes to the library and recompiling
|
||||||
|
it. And you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with a two-step method: (1) we copyright the
|
||||||
|
library, and (2) we offer you this license, which gives you legal
|
||||||
|
permission to copy, distribute and/or modify the library.
|
||||||
|
|
||||||
|
To protect each distributor, we want to make it very clear that
|
||||||
|
there is no warranty for the free library. Also, if the library is
|
||||||
|
modified by someone else and passed on, the recipients should know
|
||||||
|
that what they have is not the original version, so that the original
|
||||||
|
author's reputation will not be affected by problems that might be
|
||||||
|
introduced by others.
|
||||||
|
|
||||||
|
Finally, software patents pose a constant threat to the existence of
|
||||||
|
any free program. We wish to make sure that a company cannot
|
||||||
|
effectively restrict the users of a free program by obtaining a
|
||||||
|
restrictive license from a patent holder. Therefore, we insist that
|
||||||
|
any patent license obtained for a version of the library must be
|
||||||
|
consistent with the full freedom of use specified in this license.
|
||||||
|
|
||||||
|
Most GNU software, including some libraries, is covered by the
|
||||||
|
ordinary GNU General Public License. This license, the GNU Lesser
|
||||||
|
General Public License, applies to certain designated libraries, and
|
||||||
|
is quite different from the ordinary General Public License. We use
|
||||||
|
this license for certain libraries in order to permit linking those
|
||||||
|
libraries into non-free programs.
|
||||||
|
|
||||||
|
When a program is linked with a library, whether statically or using
|
||||||
|
a shared library, the combination of the two is legally speaking a
|
||||||
|
combined work, a derivative of the original library. The ordinary
|
||||||
|
General Public License therefore permits such linking only if the
|
||||||
|
entire combination fits its criteria of freedom. The Lesser General
|
||||||
|
Public License permits more lax criteria for linking other code with
|
||||||
|
the library.
|
||||||
|
|
||||||
|
We call this license the "Lesser" General Public License because it
|
||||||
|
does Less to protect the user's freedom than the ordinary General
|
||||||
|
Public License. It also provides other free software developers Less
|
||||||
|
of an advantage over competing non-free programs. These disadvantages
|
||||||
|
are the reason we use the ordinary General Public License for many
|
||||||
|
libraries. However, the Lesser license provides advantages in certain
|
||||||
|
special circumstances.
|
||||||
|
|
||||||
|
For example, on rare occasions, there may be a special need to
|
||||||
|
encourage the widest possible use of a certain library, so that it becomes
|
||||||
|
a de-facto standard. To achieve this, non-free programs must be
|
||||||
|
allowed to use the library. A more frequent case is that a free
|
||||||
|
library does the same job as widely used non-free libraries. In this
|
||||||
|
case, there is little to gain by limiting the free library to free
|
||||||
|
software only, so we use the Lesser General Public License.
|
||||||
|
|
||||||
|
In other cases, permission to use a particular library in non-free
|
||||||
|
programs enables a greater number of people to use a large body of
|
||||||
|
free software. For example, permission to use the GNU C Library in
|
||||||
|
non-free programs enables many more people to use the whole GNU
|
||||||
|
operating system, as well as its variant, the GNU/Linux operating
|
||||||
|
system.
|
||||||
|
|
||||||
|
Although the Lesser General Public License is Less protective of the
|
||||||
|
users' freedom, it does ensure that the user of a program that is
|
||||||
|
linked with the Library has the freedom and the wherewithal to run
|
||||||
|
that program using a modified version of the Library.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow. Pay close attention to the difference between a
|
||||||
|
"work based on the library" and a "work that uses the library". The
|
||||||
|
former contains code derived from the library, whereas the latter must
|
||||||
|
be combined with the library in order to run.
|
||||||
|
|
||||||
|
GNU LESSER GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License Agreement applies to any software library or other
|
||||||
|
program which contains a notice placed by the copyright holder or
|
||||||
|
other authorized party saying it may be distributed under the terms of
|
||||||
|
this Lesser General Public License (also called "this License").
|
||||||
|
Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
A "library" means a collection of software functions and/or data
|
||||||
|
prepared so as to be conveniently linked with application programs
|
||||||
|
(which use some of those functions and data) to form executables.
|
||||||
|
|
||||||
|
The "Library", below, refers to any such software library or work
|
||||||
|
which has been distributed under these terms. A "work based on the
|
||||||
|
Library" means either the Library or any derivative work under
|
||||||
|
copyright law: that is to say, a work containing the Library or a
|
||||||
|
portion of it, either verbatim or with modifications and/or translated
|
||||||
|
straightforwardly into another language. (Hereinafter, translation is
|
||||||
|
included without limitation in the term "modification".)
|
||||||
|
|
||||||
|
"Source code" for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For a library, complete source code means
|
||||||
|
all the source code for all modules it contains, plus any associated
|
||||||
|
interface definition files, plus the scripts used to control compilation
|
||||||
|
and installation of the library.
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running a program using the Library is not restricted, and output from
|
||||||
|
such a program is covered only if its contents constitute a work based
|
||||||
|
on the Library (independent of the use of the Library in a tool for
|
||||||
|
writing it). Whether that is true depends on what the Library does
|
||||||
|
and what the program that uses the Library does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Library's
|
||||||
|
complete source code as you receive it, in any medium, provided that
|
||||||
|
you conspicuously and appropriately publish on each copy an
|
||||||
|
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||||
|
all the notices that refer to this License and to the absence of any
|
||||||
|
warranty; and distribute a copy of this License along with the
|
||||||
|
Library.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy,
|
||||||
|
and you may at your option offer warranty protection in exchange for a
|
||||||
|
fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Library or any portion
|
||||||
|
of it, thus forming a work based on the Library, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The modified work must itself be a software library.
|
||||||
|
|
||||||
|
b) You must cause the files modified to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
c) You must cause the whole of the work to be licensed at no
|
||||||
|
charge to all third parties under the terms of this License.
|
||||||
|
|
||||||
|
d) If a facility in the modified Library refers to a function or a
|
||||||
|
table of data to be supplied by an application program that uses
|
||||||
|
the facility, other than as an argument passed when the facility
|
||||||
|
is invoked, then you must make a good faith effort to ensure that,
|
||||||
|
in the event an application does not supply such function or
|
||||||
|
table, the facility still operates, and performs whatever part of
|
||||||
|
its purpose remains meaningful.
|
||||||
|
|
||||||
|
(For example, a function in a library to compute square roots has
|
||||||
|
a purpose that is entirely well-defined independent of the
|
||||||
|
application. Therefore, Subsection 2d requires that any
|
||||||
|
application-supplied function or table used by this function must
|
||||||
|
be optional: if the application does not supply it, the square
|
||||||
|
root function must still compute square roots.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Library,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Library, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Library.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Library
|
||||||
|
with the Library (or with a work based on the Library) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||||
|
License instead of this License to a given copy of the Library. To do
|
||||||
|
this, you must alter all the notices that refer to this License, so
|
||||||
|
that they refer to the ordinary GNU General Public License, version 2,
|
||||||
|
instead of to this License. (If a newer version than version 2 of the
|
||||||
|
ordinary GNU General Public License has appeared, then you can specify
|
||||||
|
that version instead if you wish.) Do not make any other change in
|
||||||
|
these notices.
|
||||||
|
|
||||||
|
Once this change is made in a given copy, it is irreversible for
|
||||||
|
that copy, so the ordinary GNU General Public License applies to all
|
||||||
|
subsequent copies and derivative works made from that copy.
|
||||||
|
|
||||||
|
This option is useful when you wish to copy part of the code of
|
||||||
|
the Library into a program that is not a library.
|
||||||
|
|
||||||
|
4. You may copy and distribute the Library (or a portion or
|
||||||
|
derivative of it, under Section 2) in object code or executable form
|
||||||
|
under the terms of Sections 1 and 2 above provided that you accompany
|
||||||
|
it with the complete corresponding machine-readable source code, which
|
||||||
|
must be distributed under the terms of Sections 1 and 2 above on a
|
||||||
|
medium customarily used for software interchange.
|
||||||
|
|
||||||
|
If distribution of object code is made by offering access to copy
|
||||||
|
from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place satisfies the requirement to
|
||||||
|
distribute the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
5. A program that contains no derivative of any portion of the
|
||||||
|
Library, but is designed to work with the Library by being compiled or
|
||||||
|
linked with it, is called a "work that uses the Library". Such a
|
||||||
|
work, in isolation, is not a derivative work of the Library, and
|
||||||
|
therefore falls outside the scope of this License.
|
||||||
|
|
||||||
|
However, linking a "work that uses the Library" with the Library
|
||||||
|
creates an executable that is a derivative of the Library (because it
|
||||||
|
contains portions of the Library), rather than a "work that uses the
|
||||||
|
library". The executable is therefore covered by this License.
|
||||||
|
Section 6 states terms for distribution of such executables.
|
||||||
|
|
||||||
|
When a "work that uses the Library" uses material from a header file
|
||||||
|
that is part of the Library, the object code for the work may be a
|
||||||
|
derivative work of the Library even though the source code is not.
|
||||||
|
Whether this is true is especially significant if the work can be
|
||||||
|
linked without the Library, or if the work is itself a library. The
|
||||||
|
threshold for this to be true is not precisely defined by law.
|
||||||
|
|
||||||
|
If such an object file uses only numerical parameters, data
|
||||||
|
structure layouts and accessors, and small macros and small inline
|
||||||
|
functions (ten lines or less in length), then the use of the object
|
||||||
|
file is unrestricted, regardless of whether it is legally a derivative
|
||||||
|
work. (Executables containing this object code plus portions of the
|
||||||
|
Library will still fall under Section 6.)
|
||||||
|
|
||||||
|
Otherwise, if the work is a derivative of the Library, you may
|
||||||
|
distribute the object code for the work under the terms of Section 6.
|
||||||
|
Any executables containing that work also fall under Section 6,
|
||||||
|
whether or not they are linked directly with the Library itself.
|
||||||
|
|
||||||
|
6. As an exception to the Sections above, you may also combine or
|
||||||
|
link a "work that uses the Library" with the Library to produce a
|
||||||
|
work containing portions of the Library, and distribute that work
|
||||||
|
under terms of your choice, provided that the terms permit
|
||||||
|
modification of the work for the customer's own use and reverse
|
||||||
|
engineering for debugging such modifications.
|
||||||
|
|
||||||
|
You must give prominent notice with each copy of the work that the
|
||||||
|
Library is used in it and that the Library and its use are covered by
|
||||||
|
this License. You must supply a copy of this License. If the work
|
||||||
|
during execution displays copyright notices, you must include the
|
||||||
|
copyright notice for the Library among them, as well as a reference
|
||||||
|
directing the user to the copy of this License. Also, you must do one
|
||||||
|
of these things:
|
||||||
|
|
||||||
|
a) Accompany the work with the complete corresponding
|
||||||
|
machine-readable source code for the Library including whatever
|
||||||
|
changes were used in the work (which must be distributed under
|
||||||
|
Sections 1 and 2 above); and, if the work is an executable linked
|
||||||
|
with the Library, with the complete machine-readable "work that
|
||||||
|
uses the Library", as object code and/or source code, so that the
|
||||||
|
user can modify the Library and then relink to produce a modified
|
||||||
|
executable containing the modified Library. (It is understood
|
||||||
|
that the user who changes the contents of definitions files in the
|
||||||
|
Library will not necessarily be able to recompile the application
|
||||||
|
to use the modified definitions.)
|
||||||
|
|
||||||
|
b) Use a suitable shared library mechanism for linking with the
|
||||||
|
Library. A suitable mechanism is one that (1) uses at run time a
|
||||||
|
copy of the library already present on the user's computer system,
|
||||||
|
rather than copying library functions into the executable, and (2)
|
||||||
|
will operate properly with a modified version of the library, if
|
||||||
|
the user installs one, as long as the modified version is
|
||||||
|
interface-compatible with the version that the work was made with.
|
||||||
|
|
||||||
|
c) Accompany the work with a written offer, valid for at
|
||||||
|
least three years, to give the same user the materials
|
||||||
|
specified in Subsection 6a, above, for a charge no more
|
||||||
|
than the cost of performing this distribution.
|
||||||
|
|
||||||
|
d) If distribution of the work is made by offering access to copy
|
||||||
|
from a designated place, offer equivalent access to copy the above
|
||||||
|
specified materials from the same place.
|
||||||
|
|
||||||
|
e) Verify that the user has already received a copy of these
|
||||||
|
materials or that you have already sent this user a copy.
|
||||||
|
|
||||||
|
For an executable, the required form of the "work that uses the
|
||||||
|
Library" must include any data and utility programs needed for
|
||||||
|
reproducing the executable from it. However, as a special exception,
|
||||||
|
the materials to be distributed need not include anything that is
|
||||||
|
normally distributed (in either source or binary form) with the major
|
||||||
|
components (compiler, kernel, and so on) of the operating system on
|
||||||
|
which the executable runs, unless that component itself accompanies
|
||||||
|
the executable.
|
||||||
|
|
||||||
|
It may happen that this requirement contradicts the license
|
||||||
|
restrictions of other proprietary libraries that do not normally
|
||||||
|
accompany the operating system. Such a contradiction means you cannot
|
||||||
|
use both them and the Library together in an executable that you
|
||||||
|
distribute.
|
||||||
|
|
||||||
|
7. You may place library facilities that are a work based on the
|
||||||
|
Library side-by-side in a single library together with other library
|
||||||
|
facilities not covered by this License, and distribute such a combined
|
||||||
|
library, provided that the separate distribution of the work based on
|
||||||
|
the Library and of the other library facilities is otherwise
|
||||||
|
permitted, and provided that you do these two things:
|
||||||
|
|
||||||
|
a) Accompany the combined library with a copy of the same work
|
||||||
|
based on the Library, uncombined with any other library
|
||||||
|
facilities. This must be distributed under the terms of the
|
||||||
|
Sections above.
|
||||||
|
|
||||||
|
b) Give prominent notice with the combined library of the fact
|
||||||
|
that part of it is a work based on the Library, and explaining
|
||||||
|
where to find the accompanying uncombined form of the same work.
|
||||||
|
|
||||||
|
8. You may not copy, modify, sublicense, link with, or distribute
|
||||||
|
the Library except as expressly provided under this License. Any
|
||||||
|
attempt otherwise to copy, modify, sublicense, link with, or
|
||||||
|
distribute the Library is void, and will automatically terminate your
|
||||||
|
rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses
|
||||||
|
terminated so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
9. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Library or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Library (or any work based on the
|
||||||
|
Library), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Library or works based on it.
|
||||||
|
|
||||||
|
10. Each time you redistribute the Library (or any work based on the
|
||||||
|
Library), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute, link with or modify the Library
|
||||||
|
subject to these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties with
|
||||||
|
this License.
|
||||||
|
|
||||||
|
11. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Library at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Library by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Library.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply,
|
||||||
|
and the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
12. If the distribution and/or use of the Library is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Library under this License may add
|
||||||
|
an explicit geographical distribution limitation excluding those countries,
|
||||||
|
so that distribution is permitted only in or among countries not thus
|
||||||
|
excluded. In such case, this License incorporates the limitation as if
|
||||||
|
written in the body of this License.
|
||||||
|
|
||||||
|
13. The Free Software Foundation may publish revised and/or new
|
||||||
|
versions of the Lesser General Public License from time to time.
|
||||||
|
Such new versions will be similar in spirit to the present version,
|
||||||
|
but may differ in detail to address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Library
|
||||||
|
specifies a version number of this License which applies to it and
|
||||||
|
"any later version", you have the option of following the terms and
|
||||||
|
conditions either of that version or of any later version published by
|
||||||
|
the Free Software Foundation. If the Library does not specify a
|
||||||
|
license version number, you may choose any version ever published by
|
||||||
|
the Free Software Foundation.
|
||||||
|
|
||||||
|
14. If you wish to incorporate parts of the Library into other free
|
||||||
|
programs whose distribution conditions are incompatible with these,
|
||||||
|
write to the author to ask for permission. For software which is
|
||||||
|
copyrighted by the Free Software Foundation, write to the Free
|
||||||
|
Software Foundation; we sometimes make exceptions for this. Our
|
||||||
|
decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing
|
||||||
|
and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||||
|
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||||
|
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||||
|
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||||
|
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||||
|
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||||
|
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||||
|
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||||
|
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||||
|
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||||
|
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||||
|
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||||
|
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||||
|
DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"required": true,
|
||||||
|
"minVersion": "0.8",
|
||||||
|
"package": "com.seibel.lod.fabric.mixins",
|
||||||
|
"compatibilityLevel": "JAVA_17",
|
||||||
|
"mixins": [
|
||||||
|
"unsafe.MixinThreadingDectector",
|
||||||
|
"MixinUtilBackgroudThread",
|
||||||
|
"events.MixinServerLevel"
|
||||||
|
],
|
||||||
|
"client": [
|
||||||
|
"MixinMinecraft",
|
||||||
|
"MixinOptionsScreen",
|
||||||
|
"MixinWorldRenderer",
|
||||||
|
"MixinFogRenderer",
|
||||||
|
"events.MixinClientLevel",
|
||||||
|
"events.MixinMinecraft",
|
||||||
|
"events.MixinBlockUpdate"
|
||||||
|
],
|
||||||
|
"server": [
|
||||||
|
"MixinDedicatedServer"
|
||||||
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
{
|
||||||
|
"schemaVersion": 1,
|
||||||
|
"id": "lod",
|
||||||
|
"version": "${version}",
|
||||||
|
|
||||||
|
"name": "${mod_name}",
|
||||||
|
"description": "${description}",
|
||||||
|
"authors": ["${authors}"],
|
||||||
|
|
||||||
|
"contact": {
|
||||||
|
"homepage": "${homepage}",
|
||||||
|
"sources": "${source}",
|
||||||
|
"issues": "${issues}"
|
||||||
|
},
|
||||||
|
|
||||||
|
"license": "CC0-1.0",
|
||||||
|
"icon": "icon.png",
|
||||||
|
|
||||||
|
"environment": "client",
|
||||||
|
"entrypoints": {
|
||||||
|
"client": [
|
||||||
|
"com.seibel.lod.fabric.Main"
|
||||||
|
],
|
||||||
|
"modmenu": [
|
||||||
|
"com.seibel.lod.fabric.wrappers.config.ModMenuIntegration"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
"mixins": [
|
||||||
|
"fabric.lod.mixins.json"
|
||||||
|
],
|
||||||
|
|
||||||
|
"accessWidener" : "lod.accesswidener",
|
||||||
|
"depends": {
|
||||||
|
"fabricloader": "*",
|
||||||
|
"fabric": "*",
|
||||||
|
"minecraft": "${minecraft_version}",
|
||||||
|
"java": ">=${java_version}"
|
||||||
|
},
|
||||||
|
"suggests": {
|
||||||
|
"another-mod": "*"
|
||||||
|
},
|
||||||
|
|
||||||
|
"custom": {
|
||||||
|
"modmenu": {
|
||||||
|
"links": {
|
||||||
|
"modmenu.discord": "https://discord.gg/xAB8G4cENx"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
plugins {
|
||||||
|
id "com.github.johnrengelman.shadow" version "7.1.0"
|
||||||
|
}
|
||||||
|
|
||||||
|
version = rootProject.mod_version+"-"+rootProject.minecraft_version+"-"+new Date().format("yyyy_MM_dd_HH_mm")
|
||||||
|
|
||||||
|
loom {
|
||||||
|
accessWidenerPath.set(project(":common").file("src/main/resources/lod.accesswidener"))
|
||||||
|
|
||||||
|
forge {
|
||||||
|
convertAccessWideners.set(true)
|
||||||
|
extraAccessWideners.add("lod.accesswidener")
|
||||||
|
mixinConfigs("lod.mixins.json")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
architectury {
|
||||||
|
platformSetupLoomIde()
|
||||||
|
forge()
|
||||||
|
}
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
compileClasspath.extendsFrom common
|
||||||
|
runtimeClasspath.extendsFrom common
|
||||||
|
developmentForge.extendsFrom common
|
||||||
|
}
|
||||||
|
|
||||||
|
def addMod(path, enabled) {
|
||||||
|
if (enabled == "2")
|
||||||
|
dependencies { modImplementation(path) }
|
||||||
|
else if (enabled == "1")
|
||||||
|
dependencies { modCompileOnly(path) }
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Forge loader
|
||||||
|
forge "net.minecraftforge:forge:${rootProject.minecraft_version}-${rootProject.forge_version}"
|
||||||
|
|
||||||
|
// Starlight
|
||||||
|
addMod("curse.maven:starlight-forge-526854:${rootProject.starlight_version_forge}", rootProject.enable_starlight_forge)
|
||||||
|
annotationProcessor "org.spongepowered:mixin:0.8.4:processor"
|
||||||
|
|
||||||
|
common(project(path: ":common", configuration: "namedElements")) { transitive false }
|
||||||
|
shadowMe(project(path: ":common", configuration: "transformProductionForge")) { transitive = false }
|
||||||
|
|
||||||
|
// forgeDependencies(project(":core")) { transitive false }
|
||||||
|
|
||||||
|
|
||||||
|
// Toml
|
||||||
|
shadowMe("com.electronwill.night-config:toml:${rootProject.toml_version}") {}
|
||||||
|
|
||||||
|
// Compression
|
||||||
|
forgeDependencies('org.tukaani:xz:1.9')
|
||||||
|
forgeDependencies('org.apache.commons:commons-compress:1.21')
|
||||||
|
shadowMe 'org.tukaani:xz:1.9'
|
||||||
|
shadowMe 'org.apache.commons:commons-compress:1.21'
|
||||||
|
}
|
||||||
|
|
||||||
|
task copyCoreResources(type: Copy) {
|
||||||
|
from fileTree(project(":core").file("src/main/resources"))
|
||||||
|
into file("build/resources/main")
|
||||||
|
}
|
||||||
|
|
||||||
|
task copyCommonResources(type: Copy) {
|
||||||
|
from fileTree(project(":common").file("src/main/resources"))
|
||||||
|
into file("build/resources/main")
|
||||||
|
}
|
||||||
|
|
||||||
|
processResources {
|
||||||
|
dependsOn(copyCoreResources)
|
||||||
|
dependsOn(copyCommonResources)
|
||||||
|
}
|
||||||
|
|
||||||
|
shadowJar {
|
||||||
|
dependencies {
|
||||||
|
exclude(dependency("net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"))
|
||||||
|
}
|
||||||
|
exclude "fabric.mod.json"
|
||||||
|
configurations = [project.configurations.shadowMe]
|
||||||
|
relocate 'org.tukaani', 'shaded.tukaani'
|
||||||
|
relocate 'org.apache.commons.compress', 'shaded.apache.commons.compress'
|
||||||
|
relocate 'com.electronwill.nightconfig', 'shaded.electronwill.nightconfig' // This is already included with forge
|
||||||
|
|
||||||
|
relocate 'com.seibel.lod.common', 'forge.com.seibel.lod.common'
|
||||||
|
|
||||||
|
classifier "dev-shadow"
|
||||||
|
}
|
||||||
|
|
||||||
|
remapJar {
|
||||||
|
input.set shadowJar.archiveFile
|
||||||
|
dependsOn shadowJar
|
||||||
|
classifier null
|
||||||
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
classifier "dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
sourcesJar {
|
||||||
|
def commonSources = project(":common").sourcesJar
|
||||||
|
dependsOn commonSources
|
||||||
|
from commonSources.archiveFile.map { zipTree(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
components.java {
|
||||||
|
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
|
||||||
|
skip()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
mavenForge(MavenPublication) {
|
||||||
|
artifactId = rootProject.archives_base_name + "-" + project.name
|
||||||
|
from components.java
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
|
||||||
|
repositories {
|
||||||
|
// Add repositories to publish to here.
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
loom.platform=forge
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* 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.ClientApi;
|
||||||
|
import com.seibel.lod.core.api.EventApi;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||||
|
|
||||||
|
import org.lwjgl.glfw.GLFW;
|
||||||
|
|
||||||
|
import com.seibel.lod.common.wrappers.chunk.ChunkWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.world.DimensionTypeWrapper;
|
||||||
|
import com.seibel.lod.common.wrappers.world.WorldWrapper;
|
||||||
|
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
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;
|
||||||
|
private final ClientApi clientApi = ClientApi.INSTANCE;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void serverTickEvent(TickEvent.ServerTickEvent event)
|
||||||
|
{
|
||||||
|
if (event.phase != TickEvent.Phase.START) return;
|
||||||
|
eventApi.serverTickEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void chunkLoadEvent(ChunkEvent.Load event)
|
||||||
|
{
|
||||||
|
clientApi.clientChunkLoadEvent(new ChunkWrapper(event.getChunk(), event.getWorld()), WorldWrapper.getWorldWrapper(event.getWorld()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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)
|
||||||
|
{
|
||||||
|
if (event.getWorld() != null) {
|
||||||
|
eventApi.worldLoadEvent(WorldWrapper.getWorldWrapper(event.getWorld()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SubscribeEvent
|
||||||
|
public void worldUnloadEvent(WorldEvent.Unload event)
|
||||||
|
{
|
||||||
|
eventApi.worldUnloadEvent(WorldWrapper.getWorldWrapper(event.getWorld()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@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()), event.getWorld());
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (Minecraft.getInstance().player == null) return;
|
||||||
|
if (event.getAction() != GLFW.GLFW_PRESS) return;
|
||||||
|
clientApi.keyPressedEvent(event.getKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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.common.LodCommonMain;
|
||||||
|
import com.seibel.lod.common.forge.LodForgeMethodCaller;
|
||||||
|
import com.seibel.lod.common.wrappers.config.ConfigGui;
|
||||||
|
import com.seibel.lod.common.wrappers.minecraft.MinecraftClientWrapper;
|
||||||
|
import com.seibel.lod.core.ModInfo;
|
||||||
|
import com.seibel.lod.core.api.ApiShared;
|
||||||
|
import com.seibel.lod.core.handlers.ReflectionHandler;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.ModAccessorHandler;
|
||||||
|
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IModChecker;
|
||||||
|
import com.seibel.lod.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
|
||||||
|
import com.seibel.lod.forge.networking.NetworkHandler;
|
||||||
|
import com.seibel.lod.forge.wrappers.ForgeDependencySetup;
|
||||||
|
|
||||||
|
import com.seibel.lod.forge.wrappers.modAccessor.ModChecker;
|
||||||
|
import com.seibel.lod.forge.wrappers.modAccessor.OptifineAccessor;
|
||||||
|
|
||||||
|
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||||
|
import net.minecraft.core.Direction;
|
||||||
|
import net.minecraft.world.level.block.Block;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
|
import net.minecraftforge.client.model.data.ModelDataMap;
|
||||||
|
import net.minecraftforge.client.ConfigGuiHandler;
|
||||||
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
|
import net.minecraftforge.fml.ModLoadingContext;
|
||||||
|
import net.minecraftforge.fml.common.Mod;
|
||||||
|
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
|
||||||
|
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
|
||||||
|
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||||
|
import net.minecraftforge.fml.loading.FMLLoader;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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-21-2021
|
||||||
|
*/
|
||||||
|
@Mod(ModInfo.ID)
|
||||||
|
public class ForgeMain implements LodForgeMethodCaller
|
||||||
|
{
|
||||||
|
public static ForgeClientProxy forgeClientProxy;
|
||||||
|
|
||||||
|
private void init(final FMLCommonSetupEvent event)
|
||||||
|
{
|
||||||
|
// make sure the dependencies are set up before the mod needs them
|
||||||
|
LodCommonMain.initConfig();
|
||||||
|
LodCommonMain.startup(this, !FMLLoader.getDist().isClient(), new NetworkHandler());
|
||||||
|
ForgeDependencySetup.createInitialBindings();
|
||||||
|
ForgeDependencySetup.finishBinding();
|
||||||
|
ApiShared.LOGGER.info("Distant Horizons initializing...");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForgeMain()
|
||||||
|
{
|
||||||
|
// Register the methods for server and other game events we are interested in
|
||||||
|
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::init);
|
||||||
|
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::onClientStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClientStart(final FMLClientSetupEvent event)
|
||||||
|
{
|
||||||
|
if (ReflectionHandler.instance.optifinePresent()) {
|
||||||
|
ModAccessorHandler.bind(IOptifineAccessor.class, new OptifineAccessor());
|
||||||
|
}
|
||||||
|
|
||||||
|
ModAccessorHandler.finishBinding();
|
||||||
|
|
||||||
|
ModLoadingContext.get().registerExtensionPoint(ConfigGuiHandler.ConfigGuiFactory.class,
|
||||||
|
() -> new ConfigGuiHandler.ConfigGuiFactory((client, parent) -> ConfigGui.getScreen(parent, "")));
|
||||||
|
forgeClientProxy = new ForgeClientProxy();
|
||||||
|
MinecraftForge.EVENT_BUS.register(forgeClientProxy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final ModelDataMap dataMap = new ModelDataMap.Builder().build();
|
||||||
|
@Override
|
||||||
|
public List<BakedQuad> getQuads(MinecraftClientWrapper mc, Block block, BlockState blockState, Direction direction, Random random) {
|
||||||
|
return mc.getModelManager().getBlockModelShaper().getBlockModel(block.defaultBlockState()).getQuads(blockState, direction, random, dataMap);
|
||||||
|
}
|
||||||
|
}
|
||||||
+72
@@ -0,0 +1,72 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||||
|
import com.seibel.lod.forge.fabric.api.event.EventFactory;
|
||||||
|
import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offers access to events related to the indication of a connected server's ability to receive packets in certain channels.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public final class C2SPlayChannelEvents {
|
||||||
|
/**
|
||||||
|
* An event for the client play network handler receiving an update indicating the connected server's ability to receive packets in certain channels.
|
||||||
|
* This event may be invoked at any time after login and up to disconnection.
|
||||||
|
*/
|
||||||
|
public static final Event<Register> REGISTER = EventFactory.createArrayBacked(Register.class, callbacks -> (handler, sender, client, channels) -> {
|
||||||
|
for (Register callback : callbacks) {
|
||||||
|
callback.onChannelRegister(handler, sender, client, channels);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event for the client play network handler receiving an update indicating the connected server's lack of ability to receive packets in certain channels.
|
||||||
|
* This event may be invoked at any time after login and up to disconnection.
|
||||||
|
*/
|
||||||
|
public static final Event<Unregister> UNREGISTER = EventFactory.createArrayBacked(Unregister.class, callbacks -> (handler, sender, client, channels) -> {
|
||||||
|
for (Unregister callback : callbacks) {
|
||||||
|
callback.onChannelUnregister(handler, sender, client, channels);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private C2SPlayChannelEvents() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see C2SPlayChannelEvents#REGISTER
|
||||||
|
*/
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Register {
|
||||||
|
void onChannelRegister(ClientPacketListener handler, PacketSender sender, Minecraft client, List<ResourceLocation> channels);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see C2SPlayChannelEvents#UNREGISTER
|
||||||
|
*/
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Unregister {
|
||||||
|
void onChannelUnregister(ClientPacketListener handler, PacketSender sender, Minecraft client, List<ResourceLocation> channels);
|
||||||
|
}
|
||||||
|
}
|
||||||
+103
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||||
|
|
||||||
|
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||||
|
import com.seibel.lod.forge.fabric.api.event.EventFactory;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offers access to events related to the connection to a server on the client while the server is processing the client's login request.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public final class ClientLoginConnectionEvents {
|
||||||
|
/**
|
||||||
|
* Event indicating a connection entered the LOGIN state, ready for registering query request handlers.
|
||||||
|
* This event may be used by mods to prepare their client side state.
|
||||||
|
* This event does not guarantee that a login attempt will be successful.
|
||||||
|
*
|
||||||
|
* @see ClientLoginNetworking#registerReceiver(ResourceLocation, ClientLoginNetworking.LoginQueryRequestHandler)
|
||||||
|
*/
|
||||||
|
public static final Event<Init> INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, client) -> {
|
||||||
|
for (Init callback : callbacks) {
|
||||||
|
callback.onLoginStart(handler, client);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event for when the client has started receiving login queries.
|
||||||
|
* A client can only start receiving login queries when a server has sent the first login query.
|
||||||
|
* Vanilla servers will typically never make the client enter this login phase, but it is not a guarantee that the
|
||||||
|
* connected server is a vanilla server since a modded server or proxy may have no login queries to send to the client
|
||||||
|
* and therefore bypass the login query phase.
|
||||||
|
* If this event is fired then it is a sign that a server is not a vanilla server or the server is behind a proxy which
|
||||||
|
* is capable of handling login queries.
|
||||||
|
*
|
||||||
|
* <p>This event may be used to {@link ClientLoginNetworking.LoginQueryRequestHandler register login query handlers}
|
||||||
|
* which may be used to send a response to a server.
|
||||||
|
*
|
||||||
|
* <p>No packets should be sent when this event is invoked.
|
||||||
|
*/
|
||||||
|
public static final Event<QueryStart> QUERY_START = EventFactory.createArrayBacked(QueryStart.class, callbacks -> (handler, client) -> {
|
||||||
|
for (QueryStart callback : callbacks) {
|
||||||
|
callback.onLoginQueryStart(handler, client);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event for when the client's login process has ended due to disconnection.
|
||||||
|
*
|
||||||
|
* <p>No packets should be sent when this event is invoked.
|
||||||
|
*/
|
||||||
|
public static final Event<Disconnect> DISCONNECT = EventFactory.createArrayBacked(Disconnect.class, callbacks -> (handler, client) -> {
|
||||||
|
for (Disconnect callback : callbacks) {
|
||||||
|
callback.onLoginDisconnect(handler, client);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private ClientLoginConnectionEvents() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ClientLoginConnectionEvents#INIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Init {
|
||||||
|
void onLoginStart(ClientHandshakePacketListenerImpl handler, Minecraft client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ClientLoginConnectionEvents#QUERY_START
|
||||||
|
*/
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface QueryStart {
|
||||||
|
void onLoginQueryStart(ClientHandshakePacketListenerImpl handler, Minecraft client);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ClientLoginConnectionEvents#DISCONNECT
|
||||||
|
*/
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Disconnect {
|
||||||
|
void onLoginDisconnect(ClientHandshakePacketListenerImpl handler, Minecraft client);
|
||||||
|
}
|
||||||
|
}
|
||||||
+161
@@ -0,0 +1,161 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
import io.netty.util.concurrent.Future;
|
||||||
|
import io.netty.util.concurrent.GenericFutureListener;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import com.seibel.lod.forge.fabric.api.networking.v1.ServerLoginNetworking;
|
||||||
|
import com.seibel.lod.forge.fabric.impl.networking.client.ClientNetworkingImpl;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientHandshakePacketListenerImpl;
|
||||||
|
import net.minecraft.network.Connection;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.network.PacketListener;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offers access to login stage client-side networking functionalities.
|
||||||
|
*
|
||||||
|
* <p>The Minecraft login protocol only allows the client to respond to a server's request, but not initiate one of its own.
|
||||||
|
*
|
||||||
|
* @see ClientPlayNetworking
|
||||||
|
* @see ServerLoginNetworking
|
||||||
|
*/
|
||||||
|
|
||||||
|
public final class ClientLoginNetworking {
|
||||||
|
/**
|
||||||
|
* Registers a handler to a query request channel.
|
||||||
|
* A global receiver is registered to all connections, in the present and future.
|
||||||
|
*
|
||||||
|
* <p>If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made.
|
||||||
|
* Use {@link #unregisterGlobalReceiver(ResourceLocation)} to unregister the existing handler.
|
||||||
|
*
|
||||||
|
* @param channelName the id of the channel
|
||||||
|
* @param queryHandler the handler
|
||||||
|
* @return false if a handler is already registered to the channel
|
||||||
|
* @see ClientLoginNetworking#unregisterGlobalReceiver(ResourceLocation)
|
||||||
|
* @see ClientLoginNetworking#registerReceiver(ResourceLocation, LoginQueryRequestHandler)
|
||||||
|
*/
|
||||||
|
public static boolean registerGlobalReceiver(ResourceLocation channelName, LoginQueryRequestHandler queryHandler) {
|
||||||
|
return ClientNetworkingImpl.LOGIN.registerGlobalReceiver(channelName, queryHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the handler of a query request channel.
|
||||||
|
* A global receiver is registered to all connections, in the present and future.
|
||||||
|
*
|
||||||
|
* <p>The {@code channel} is guaranteed not to have a handler after this call.
|
||||||
|
*
|
||||||
|
* @param channelName the id of the channel
|
||||||
|
* @return the previous handler, or {@code null} if no handler was bound to the channel
|
||||||
|
* @see ClientLoginNetworking#registerGlobalReceiver(ResourceLocation, LoginQueryRequestHandler)
|
||||||
|
* @see ClientLoginNetworking#unregisterReceiver(ResourceLocation)
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static ClientLoginNetworking.LoginQueryRequestHandler unregisterGlobalReceiver(ResourceLocation channelName) {
|
||||||
|
return ClientNetworkingImpl.LOGIN.unregisterGlobalReceiver(channelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all query request channel names which global receivers are registered for.
|
||||||
|
* A global receiver is registered to all connections, in the present and future.
|
||||||
|
*
|
||||||
|
* @return all channel names which global receivers are registered for.
|
||||||
|
*/
|
||||||
|
public static Set<ResourceLocation> getGlobalReceivers() {
|
||||||
|
return ClientNetworkingImpl.LOGIN.getChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a handler to a query request channel.
|
||||||
|
*
|
||||||
|
* <p>If a handler is already registered to the {@code channelName}, this method will return {@code false}, and no change will be made.
|
||||||
|
* Use {@link #unregisterReceiver(ResourceLocation)} to unregister the existing handler.
|
||||||
|
*
|
||||||
|
* @param channelName the id of the channel
|
||||||
|
* @param queryHandler the handler
|
||||||
|
* @return false if a handler is already registered to the channel name
|
||||||
|
* @throws IllegalStateException if the client is not logging in
|
||||||
|
*/
|
||||||
|
public static boolean registerReceiver(ResourceLocation channelName, LoginQueryRequestHandler queryHandler) throws IllegalStateException {
|
||||||
|
final Connection connection = ClientNetworkingImpl.getLoginConnection();
|
||||||
|
|
||||||
|
if (connection != null) {
|
||||||
|
final PacketListener packetListener = connection.getPacketListener();
|
||||||
|
|
||||||
|
if (packetListener instanceof ClientHandshakePacketListenerImpl) {
|
||||||
|
return ClientNetworkingImpl.getAddon(((ClientHandshakePacketListenerImpl) packetListener)).registerChannel(channelName, queryHandler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Cannot register receiver while client is not logging in!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the handler of a query request channel.
|
||||||
|
*
|
||||||
|
* <p>The {@code channelName} is guaranteed not to have a handler after this call.
|
||||||
|
*
|
||||||
|
* @param channelName the id of the channel
|
||||||
|
* @return the previous handler, or {@code null} if no handler was bound to the channel name
|
||||||
|
* @throws IllegalStateException if the client is not logging in
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static LoginQueryRequestHandler unregisterReceiver(ResourceLocation channelName) throws IllegalStateException {
|
||||||
|
final Connection connection = ClientNetworkingImpl.getLoginConnection();
|
||||||
|
|
||||||
|
if (connection != null) {
|
||||||
|
final PacketListener packetListener = connection.getPacketListener();
|
||||||
|
|
||||||
|
if (packetListener instanceof ClientHandshakePacketListenerImpl) {
|
||||||
|
return ClientNetworkingImpl.getAddon(((ClientHandshakePacketListenerImpl) packetListener)).unregisterChannel(channelName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Cannot unregister receiver while client is not logging in!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClientLoginNetworking() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface LoginQueryRequestHandler {
|
||||||
|
/**
|
||||||
|
* Handles an incoming query request from a server.
|
||||||
|
*
|
||||||
|
* <p>This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}.
|
||||||
|
* Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft client instance.
|
||||||
|
*
|
||||||
|
* <p>The return value of this method is a completable future that may be used to delay the login process to the server until a task {@link CompletableFuture#isDone() is done}.
|
||||||
|
* The future should complete in reasonably time to prevent disconnection by the server.
|
||||||
|
* If your request processes instantly, you may use {@link CompletableFuture#completedFuture(Object)} to wrap your response for immediate sending.
|
||||||
|
*
|
||||||
|
* @param client the client
|
||||||
|
* @param handler the network handler that received this packet
|
||||||
|
* @param buf the payload of the packet
|
||||||
|
* @param listenerAdder listeners to be called when the response packet is sent to the server
|
||||||
|
* @return a completable future which contains the payload to respond to the server with.
|
||||||
|
* If the future contains {@code null}, then the server will be notified that the client did not understand the query.
|
||||||
|
*/
|
||||||
|
CompletableFuture<@Nullable FriendlyByteBuf> receive(Minecraft client, ClientHandshakePacketListenerImpl handler, FriendlyByteBuf buf, Consumer<GenericFutureListener<? extends Future<? super Void>>> listenerAdder);
|
||||||
|
}
|
||||||
|
}
|
||||||
+85
@@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||||
|
|
||||||
|
import com.seibel.lod.forge.fabric.api.event.Event;
|
||||||
|
import com.seibel.lod.forge.fabric.api.event.EventFactory;
|
||||||
|
import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offers access to events related to the connection to a server on a logical client.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public final class ClientPlayConnectionEvents {
|
||||||
|
/**
|
||||||
|
* Event indicating a connection entered the PLAY state, ready for registering channel handlers.
|
||||||
|
*
|
||||||
|
* @see ClientPlayNetworking#registerReceiver(ResourceLocation, ClientPlayNetworking.PlayChannelHandler)
|
||||||
|
*/
|
||||||
|
public static final Event<Init> INIT = EventFactory.createArrayBacked(Init.class, callbacks -> (handler, client) -> {
|
||||||
|
for (Init callback : callbacks) {
|
||||||
|
callback.onPlayInit(handler, client);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event for notification when the client play network handler is ready to send packets to the server.
|
||||||
|
*
|
||||||
|
* <p>At this stage, the network handler is ready to send packets to the server.
|
||||||
|
* Since the client's local state has been setup.
|
||||||
|
*/
|
||||||
|
public static final Event<Join> JOIN = EventFactory.createArrayBacked(Join.class, callbacks -> (handler, sender, client) -> {
|
||||||
|
for (Join callback : callbacks) {
|
||||||
|
callback.onPlayReady(handler, sender, client);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An event for the disconnection of the client play network handler.
|
||||||
|
*
|
||||||
|
* <p>No packets should be sent when this event is invoked.
|
||||||
|
*/
|
||||||
|
public static final Event<Disconnect> DISCONNECT = EventFactory.createArrayBacked(Disconnect.class, callbacks -> (handler, client) -> {
|
||||||
|
for (Disconnect callback : callbacks) {
|
||||||
|
callback.onPlayDisconnect(handler, client);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
private ClientPlayConnectionEvents() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Init {
|
||||||
|
void onPlayInit(ClientPacketListener handler, Minecraft client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Join {
|
||||||
|
void onPlayReady(ClientPacketListener handler, PacketSender sender, Minecraft client);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface Disconnect {
|
||||||
|
void onPlayDisconnect(ClientPacketListener handler, Minecraft client);
|
||||||
|
}
|
||||||
|
}
|
||||||
+256
@@ -0,0 +1,256 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import com.seibel.lod.forge.fabric.api.networking.v1.PacketSender;
|
||||||
|
import com.seibel.lod.forge.fabric.api.networking.v1.ServerPlayNetworking;
|
||||||
|
import com.seibel.lod.forge.fabric.impl.networking.client.ClientNetworkingImpl;
|
||||||
|
import com.seibel.lod.forge.fabric.impl.networking.client.ClientPlayNetworkAddon;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.multiplayer.ClientPacketListener;
|
||||||
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
|
import net.minecraft.network.protocol.Packet;
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Offers access to play stage client-side networking functionalities.
|
||||||
|
*
|
||||||
|
* <p>Client-side networking functionalities include receiving clientbound packets,
|
||||||
|
* sending serverbound packets, and events related to client-side network handlers.
|
||||||
|
*
|
||||||
|
* <p>This class should be only used on the physical client and for the logical client.
|
||||||
|
*
|
||||||
|
* @see ClientLoginNetworking
|
||||||
|
* @see ServerPlayNetworking
|
||||||
|
*/
|
||||||
|
|
||||||
|
public final class ClientPlayNetworking {
|
||||||
|
/**
|
||||||
|
* Registers a handler to a channel.
|
||||||
|
* A global receiver is registered to all connections, in the present and future.
|
||||||
|
*
|
||||||
|
* <p>If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made.
|
||||||
|
* Use {@link #unregisterGlobalReceiver(ResourceLocation)} to unregister the existing handler.
|
||||||
|
*
|
||||||
|
* @param channelName the id of the channel
|
||||||
|
* @param channelHandler the handler
|
||||||
|
* @return false if a handler is already registered to the channel
|
||||||
|
* @see ClientPlayNetworking#unregisterGlobalReceiver(ResourceLocation)
|
||||||
|
* @see ClientPlayNetworking#registerReceiver(ResourceLocation, PlayChannelHandler)
|
||||||
|
*/
|
||||||
|
public static boolean registerGlobalReceiver(ResourceLocation channelName, PlayChannelHandler channelHandler) {
|
||||||
|
return ClientNetworkingImpl.PLAY.registerGlobalReceiver(channelName, channelHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the handler of a channel.
|
||||||
|
* A global receiver is registered to all connections, in the present and future.
|
||||||
|
*
|
||||||
|
* <p>The {@code channel} is guaranteed not to have a handler after this call.
|
||||||
|
*
|
||||||
|
* @param channelName the id of the channel
|
||||||
|
* @return the previous handler, or {@code null} if no handler was bound to the channel
|
||||||
|
* @see ClientPlayNetworking#registerGlobalReceiver(ResourceLocation, PlayChannelHandler)
|
||||||
|
* @see ClientPlayNetworking#unregisterReceiver(ResourceLocation)
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static PlayChannelHandler unregisterGlobalReceiver(ResourceLocation channelName) {
|
||||||
|
return ClientNetworkingImpl.PLAY.unregisterGlobalReceiver(channelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all channel names which global receivers are registered for.
|
||||||
|
* A global receiver is registered to all connections, in the present and future.
|
||||||
|
*
|
||||||
|
* @return all channel names which global receivers are registered for.
|
||||||
|
*/
|
||||||
|
public static Set<ResourceLocation> getGlobalReceivers() {
|
||||||
|
return ClientNetworkingImpl.PLAY.getChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a handler to a channel.
|
||||||
|
*
|
||||||
|
* <p>If a handler is already registered to the {@code channel}, this method will return {@code false}, and no change will be made.
|
||||||
|
* Use {@link #unregisterReceiver(ResourceLocation)} to unregister the existing handler.
|
||||||
|
*
|
||||||
|
* <p>For example, if you only register a receiver using this method when a {@linkplain ClientLoginNetworking#registerGlobalReceiver(ResourceLocation, ClientLoginNetworking.LoginQueryRequestHandler)}
|
||||||
|
* login query has been received, you should use {@link ClientPlayConnectionEvents#INIT} to register the channel handler.
|
||||||
|
*
|
||||||
|
* @param channelName the id of the channel
|
||||||
|
* @return false if a handler is already registered to the channel
|
||||||
|
* @throws IllegalStateException if the client is not connected to a server
|
||||||
|
* @see ClientPlayConnectionEvents#INIT
|
||||||
|
*/
|
||||||
|
public static boolean registerReceiver(ResourceLocation channelName, PlayChannelHandler channelHandler) {
|
||||||
|
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
|
||||||
|
|
||||||
|
if (addon != null) {
|
||||||
|
return addon.registerChannel(channelName, channelHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Cannot register receiver while not in game!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the handler of a channel.
|
||||||
|
*
|
||||||
|
* <p>The {@code channelName} is guaranteed not to have a handler after this call.
|
||||||
|
*
|
||||||
|
* @param channelName the id of the channel
|
||||||
|
* @return the previous handler, or {@code null} if no handler was bound to the channel
|
||||||
|
* @throws IllegalStateException if the client is not connected to a server
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
public static PlayChannelHandler unregisterReceiver(ResourceLocation channelName) throws IllegalStateException {
|
||||||
|
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
|
||||||
|
|
||||||
|
if (addon != null) {
|
||||||
|
return addon.unregisterChannel(channelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Cannot unregister receiver while not in game!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all the channel names that the client can receive packets on.
|
||||||
|
*
|
||||||
|
* @return All the channel names that the client can receive packets on
|
||||||
|
* @throws IllegalStateException if the client is not connected to a server
|
||||||
|
*/
|
||||||
|
public static Set<ResourceLocation> getReceived() throws IllegalStateException {
|
||||||
|
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
|
||||||
|
|
||||||
|
if (addon != null) {
|
||||||
|
return addon.getReceivableChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Cannot get a list of channels the client can receive packets on while not in game!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all channel names that the connected server declared the ability to receive a packets on.
|
||||||
|
*
|
||||||
|
* @return All the channel names the connected server declared the ability to receive a packets on
|
||||||
|
* @throws IllegalStateException if the client is not connected to a server
|
||||||
|
*/
|
||||||
|
public static Set<ResourceLocation> getSendable() throws IllegalStateException {
|
||||||
|
final ClientPlayNetworkAddon addon = ClientNetworkingImpl.getClientPlayAddon();
|
||||||
|
|
||||||
|
if (addon != null) {
|
||||||
|
return addon.getSendableChannels();
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Cannot get a list of channels the server can receive packets on while not in game!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the connected server declared the ability to receive a packet on a specified channel name.
|
||||||
|
*
|
||||||
|
* @param channelName the channel name
|
||||||
|
* @return True if the connected server has declared the ability to receive a packet on the specified channel.
|
||||||
|
* False if the client is not in game.
|
||||||
|
*/
|
||||||
|
public static boolean canSend(ResourceLocation channelName) throws IllegalArgumentException {
|
||||||
|
// You cant send without a client player, so this is fine
|
||||||
|
if (Minecraft.getInstance().getConnection() != null) {
|
||||||
|
return ClientNetworkingImpl.getAddon(Minecraft.getInstance().getConnection()).getSendableChannels().contains(channelName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a packet which may be sent to a the connected server.
|
||||||
|
*
|
||||||
|
* @param channelName the channel name
|
||||||
|
* @param buf the packet byte buf which represents the payload of the packet
|
||||||
|
* @return a new packet
|
||||||
|
*/
|
||||||
|
public static Packet<?> createC2SPacket(ResourceLocation channelName, FriendlyByteBuf buf) {
|
||||||
|
Objects.requireNonNull(channelName, "Channel name cannot be null");
|
||||||
|
Objects.requireNonNull(buf, "Buf cannot be null");
|
||||||
|
|
||||||
|
return ClientNetworkingImpl.createPlayC2SPacket(channelName, buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the packet sender which sends packets to the connected server.
|
||||||
|
*
|
||||||
|
* @return the client's packet sender
|
||||||
|
* @throws IllegalStateException if the client is not connected to a server
|
||||||
|
*/
|
||||||
|
public static PacketSender getSender() throws IllegalStateException {
|
||||||
|
// You cant send without a client player, so this is fine
|
||||||
|
if (Minecraft.getInstance().getConnection() != null) {
|
||||||
|
return ClientNetworkingImpl.getAddon(Minecraft.getInstance().getConnection());
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Cannot get packet sender when not in game!");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a packet to the connected server.
|
||||||
|
*
|
||||||
|
* @param channelName the channel of the packet
|
||||||
|
* @param buf the payload of the packet
|
||||||
|
* @throws IllegalStateException if the client is not connected to a server
|
||||||
|
*/
|
||||||
|
public static void send(ResourceLocation channelName, FriendlyByteBuf buf) throws IllegalStateException {
|
||||||
|
// You cant send without a client player, so this is fine
|
||||||
|
if (Minecraft.getInstance().getConnection() != null) {
|
||||||
|
Minecraft.getInstance().getConnection().send(createC2SPacket(channelName, buf));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Cannot send packets when not in game!");
|
||||||
|
}
|
||||||
|
|
||||||
|
private ClientPlayNetworking() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface PlayChannelHandler {
|
||||||
|
/**
|
||||||
|
* Handles an incoming packet.
|
||||||
|
*
|
||||||
|
* <p>This method is executed on {@linkplain io.netty.channel.EventLoop netty's event loops}.
|
||||||
|
* Modification to the game should be {@linkplain net.minecraft.util.thread.BlockableEventLoop#submit(Runnable) scheduled} using the provided Minecraft client instance.
|
||||||
|
*
|
||||||
|
* <p>An example usage of this is to display an overlay message:
|
||||||
|
* <pre>{@code
|
||||||
|
* ClientPlayNetworking.registerReceiver(new Identifier("mymod", "overlay"), (client, handler, buf, responseSender) -&rt; {
|
||||||
|
* String message = buf.readString(32767);
|
||||||
|
*
|
||||||
|
* // All operations on the server or world must be executed on the server thread
|
||||||
|
* client.execute(() -&rt; {
|
||||||
|
* client.inGameHud.setOverlayMessage(message, true);
|
||||||
|
* });
|
||||||
|
* });
|
||||||
|
* }</pre>
|
||||||
|
* @param client the client
|
||||||
|
* @param handler the network handler that received this packet
|
||||||
|
* @param buf the payload of the packet
|
||||||
|
* @param responseSender the packet sender
|
||||||
|
*/
|
||||||
|
void receive(Minecraft client, ClientPacketListener handler, FriendlyByteBuf buf, PacketSender responseSender);
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Networking API (client side), version 1.
|
||||||
|
*
|
||||||
|
* <p>For login stage networking see {@link net.fabricmc.fabric.api.client.networking.v1.ClientLoginNetworking}.
|
||||||
|
* For play stage networking see {@link net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking}.
|
||||||
|
*
|
||||||
|
* <p>For events related to connection to a server see {@link net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents} for login stage
|
||||||
|
* or {@link net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents} for play stage.
|
||||||
|
*
|
||||||
|
* <p>For events related to the ability of a server to receive packets on a channel of a specific name see {@link net.fabricmc.fabric.api.client.networking.v1.C2SPlayChannelEvents}.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.seibel.lod.forge.fabric.api.client.networking.v1;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user