mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-05-20 08:40:26 +00:00
Compare commits
775 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e6300df185 | |||
| 65eb66c3ca | |||
| aa3fe18339 | |||
| 6a6a3928cd | |||
| ac1258d233 | |||
| b6d42fdcc1 | |||
| a9251fa228 | |||
| 38a1571941 | |||
| b9af66848a | |||
| e9d30b8794 | |||
| 53dafa4a2c | |||
| df46c617f2 | |||
| e706ef89fc | |||
| a66c2a0749 | |||
| a5fe4d7928 | |||
| 966bcab370 | |||
| eae5a60cf9 | |||
| 9357b18964 | |||
| 86bb4d5a1a | |||
| 47bdd66fe7 | |||
| eb6b3704d0 | |||
| 8eb5a70d4d | |||
| 5dc9f419ac | |||
| 2215ea8336 | |||
| 998b6478f3 | |||
| efa4bf5bb4 | |||
| 2ad05cbbb6 | |||
| 1bbedf51b5 | |||
| bdcd93f164 | |||
| c4a366112e | |||
| cb08401536 | |||
| 9a16336f53 | |||
| 16705057e0 | |||
| d52cd0d7cf | |||
| 7d3382e623 | |||
| 87e437f889 | |||
| 292be6bcec | |||
| f03f39f1d7 | |||
| 8bfff6b010 | |||
| e5d30183ef | |||
| 3777fda641 | |||
| f684c60039 | |||
| ef088dd3f7 | |||
| 4f672dfb7b | |||
| b851b2f881 | |||
| 9c64353111 | |||
| c537605880 | |||
| c6eb2f49f3 | |||
| 6929de7b61 | |||
| a159debe3e | |||
| 99e2907b2d | |||
| ac71b3ec0c | |||
| e184937743 | |||
| 8c155c78eb | |||
| fc779e1120 | |||
| be964da4fa | |||
| 6ca401413b | |||
| e556e2bca1 | |||
| 1fc97a480a | |||
| bba55f2669 | |||
| 97b4ea6d94 | |||
| cf4f7822e2 | |||
| d6285a5901 | |||
| 8b933b0d5c | |||
| f9a5dfbfce | |||
| 24bca3ed98 | |||
| f8f6b0b4bc | |||
| dd2f0365b0 | |||
| ae2d801be0 | |||
| 8578bba7b9 | |||
| d262831107 | |||
| ddc8cc7db5 | |||
| 12f1b3f8fc | |||
| dc7c57d1a3 | |||
| 309fb5af96 | |||
| 9d747aed71 | |||
| 3cf11a9ad4 | |||
| 9f766b0647 | |||
| 8fa3978dc8 | |||
| c282e55f90 | |||
| 8b62badbdb | |||
| 8bceb255c0 | |||
| ad80769d67 | |||
| 9d0fa0a7c4 | |||
| 8c532ede8e | |||
| c3d26527a7 | |||
| 1fe56335c8 | |||
| 3b377d91ee | |||
| 0144200ec9 | |||
| d1ad3d04e1 | |||
| d640b49ded | |||
| ecbfd1740c | |||
| dc5952add7 | |||
| 1b6ebeb05f | |||
| 234ff3e49c | |||
| 243c523b57 | |||
| 1700650753 | |||
| 12d2221d49 | |||
| 42e1adfc3a | |||
| 4ff91c9fea | |||
| 81bc51f5a1 | |||
| ac98726f81 | |||
| 1d2c6d4294 | |||
| 9ca7014344 | |||
| 8d153998fa | |||
| 2b09ed8fd9 | |||
| 96493ede15 | |||
| 48586eb523 | |||
| a80b94ad45 | |||
| 089850d633 | |||
| 42f3c56b71 | |||
| 874ef56025 | |||
| 06f04005ea | |||
| 774d076f77 | |||
| e4561bd48f | |||
| 550a037661 | |||
| 3b25e82a73 | |||
| 9b3a105672 | |||
| 10558b5446 | |||
| 326300bcce | |||
| a7826dec49 | |||
| fd3d1ce830 | |||
| 84a6cd0c26 | |||
| d1faac8b96 | |||
| de4656d01f | |||
| 6dba2e9394 | |||
| 8a8db4a9b8 | |||
| c1a00ca5c7 | |||
| 2b5d613aef | |||
| 8bea1d23e0 | |||
| fb5e597a11 | |||
| 0990df0620 | |||
| 451683aff5 | |||
| 41e9c2f55f | |||
| 4873b321cb | |||
| 64546bb154 | |||
| d97478d2c4 | |||
| 359b4826bc | |||
| 4b218a65f6 | |||
| b88712e569 | |||
| af509ebc3b | |||
| a5c3733568 | |||
| 3ef60f4b33 | |||
| b7864bb6fb | |||
| 757ed6ad4d | |||
| 1ef12fdec0 | |||
| 4e890f96e4 | |||
| 4e70ee99c9 | |||
| b149497c60 | |||
| d9f591bdb4 | |||
| a4b74e2e7f | |||
| b53d475f42 | |||
| 4ddb741d0d | |||
| 852f5aa610 | |||
| 953895a8d4 | |||
| 8788eab839 | |||
| 2b62473372 | |||
| b9187248c3 | |||
| 2d42810ba3 | |||
| 9f546370cd | |||
| 428bf341ef | |||
| 8a61571ceb | |||
| b669f87b79 | |||
| e507675ef6 | |||
| 0fc2105ee6 | |||
| 77b077dd47 | |||
| f38fcd03b0 | |||
| af1e9de474 | |||
| 3322a16f09 | |||
| 78707468c5 | |||
| c658d1a81b | |||
| 56a7234494 | |||
| 217b708177 | |||
| 7d86a41f65 | |||
| 753574fc9b | |||
| 95f89ed2b6 | |||
| cb8aefe8d2 | |||
| cd8d6f0da3 | |||
| d33b75b77b | |||
| 79f9488380 | |||
| 4c2ce65cdc | |||
| 70c448dd0d | |||
| 3ad0ef8501 | |||
| 060bda2ec1 | |||
| 6b60246694 | |||
| 1a1f461550 | |||
| da20e282ce | |||
| 9b14b0ee96 | |||
| 89cbab071f | |||
| 71953c90a2 | |||
| 923cb08b37 | |||
| 21ef8c0dc4 | |||
| 77b1960757 | |||
| a06c6fd980 | |||
| 46f533ca9d | |||
| 9a61334f5a | |||
| 118aeb872f | |||
| 5446b729f9 | |||
| d71c6bb25f | |||
| d8524603c6 | |||
| 85234ddc39 | |||
| 78162eaafe | |||
| 7a041d8a63 | |||
| 8cfa2e1467 | |||
| 5f367c0f2c | |||
| f4db7fc507 | |||
| ad9d16f48c | |||
| 85b6dcc891 | |||
| 29691dfb4d | |||
| 81eab13ce1 | |||
| a79a347765 | |||
| 46e603d681 | |||
| 3f77b4a975 | |||
| 16755fa049 | |||
| 68d5b22ca4 | |||
| 40b8c85c75 | |||
| 63367e5f03 | |||
| 1d95e7a87d | |||
| a25e3cd5a5 | |||
| b2e21d8b70 | |||
| 4041239b03 | |||
| 280699bbce | |||
| c4dfdafce8 | |||
| 3fe79338db | |||
| 6984dc29d0 | |||
| bd253ea5d2 | |||
| d743d7d1df | |||
| 238a7954a7 | |||
| c2319ca4ab | |||
| 95172bfa7e | |||
| 124dbc8836 | |||
| 8706340584 | |||
| 9a9f90aa0d | |||
| 20a5bfdd0f | |||
| 4fee8cdb24 | |||
| 70de38ffcb | |||
| 6722d22f72 | |||
| c5526c86a2 | |||
| 84fa72f96c | |||
| cc5258ce73 | |||
| 7f324bd72b | |||
| 748e027282 | |||
| bf6612edd0 | |||
| 4eace9e7fb | |||
| d90a4200fe | |||
| 39ae1fdf93 | |||
| af9fb211a8 | |||
| e9d1add6af | |||
| e4395cec83 | |||
| 94d135c66c | |||
| 1881051191 | |||
| 28132e0f13 | |||
| 1ef34469cb | |||
| e79ea4ab82 | |||
| 4450a56ef0 | |||
| a061660e46 | |||
| abdff16a0a | |||
| c08e973e3e | |||
| b12fe77f32 | |||
| bab8923f1e | |||
| 28d93d158e | |||
| 118dc32d64 | |||
| b4068e6c59 | |||
| b143c72d0e | |||
| 5f5e70970b | |||
| ec812ef5fb | |||
| 85826071cb | |||
| d9a4d64b17 | |||
| 56a1feb708 | |||
| c4f093210a | |||
| 858adfe866 | |||
| f14d22b264 | |||
| bdd80d7832 | |||
| adfdb8d63c | |||
| ef10081bcd | |||
| dc8492a6cb | |||
| 5e1c9d8ebe | |||
| 5dff25670c | |||
| 089b25dea4 | |||
| 1dd59c378e | |||
| d97fb4ff7b | |||
| 016961c19c | |||
| 9f3e225b62 | |||
| 761a014ea5 | |||
| 9749eecd87 | |||
| 32cc4976c8 | |||
| e2e0e292b7 | |||
| 227bfe7b29 | |||
| c95df25d30 | |||
| 0adca3c227 | |||
| 782b300d1f | |||
| 967a4a0b2b | |||
| d3df5e56c3 | |||
| dabc2359b3 | |||
| 1d658bd52d | |||
| 52dc690243 | |||
| d33d4af296 | |||
| fb0dbda296 | |||
| 4c860ca4ae | |||
| b6e4543625 | |||
| 0921dfb204 | |||
| 4bef2f5a7f | |||
| 18cb08b622 | |||
| 1b15694878 | |||
| 267994427e | |||
| 248eb174d8 | |||
| 0a93b0fac3 | |||
| 03124cb008 | |||
| 14a07602ee | |||
| 167a712c0e | |||
| 83bc2c9022 | |||
| 06a60b3db4 | |||
| 1b4824c5db | |||
| 5892464a1d | |||
| 8366a5288b | |||
| d2b7384639 | |||
| 49c6e70037 | |||
| c36b12e657 | |||
| 8ffb09db36 | |||
| 9906771fbc | |||
| e0a26046a0 | |||
| 8bad33ef22 | |||
| f278ae7ab5 | |||
| a61c6b8a97 | |||
| 830ede9272 | |||
| 8e544a68d4 | |||
| e8e9f69fac | |||
| 3a7d1a69d0 | |||
| 7b29d25847 | |||
| 810d10ac0a | |||
| aecc003f23 | |||
| d0bc006faa | |||
| 98aadc816b | |||
| 992ae592fd | |||
| 7711e67999 | |||
| 35bdc99873 | |||
| 5ba5d6efdd | |||
| c848c33bc0 | |||
| ff153ddc21 | |||
| cb2841ed4f | |||
| 4f668adb67 | |||
| 1d8a208d10 | |||
| 6279638363 | |||
| 23b846eca9 | |||
| d1f881ca2c | |||
| b4ab3769b0 | |||
| d5ab3e23f5 | |||
| 3a28551e97 | |||
| ac66fc7d69 | |||
| bfc1c32d46 | |||
| fa6e0e0ae4 | |||
| f953c5085d | |||
| 7288373dbc | |||
| 983cb1f012 | |||
| 944c04b9b8 | |||
| 73a2c70794 | |||
| 088523222d | |||
| 6badce6bc7 | |||
| 92a5134458 | |||
| 4222eef531 | |||
| 9b6a503f31 | |||
| 82a9ecf736 | |||
| eec4db43b2 | |||
| 1d3c380784 | |||
| 65e4c9a149 | |||
| d4549643fc | |||
| a87ad8c966 | |||
| 153f6e5a87 | |||
| a385a43250 | |||
| 3cd6aead64 | |||
| 4f33b11828 | |||
| f5bbaa3c3a | |||
| 4fd84a3f2d | |||
| bed67c211d | |||
| 2c8d3416ab | |||
| 5e43f0afef | |||
| ecbca608a5 | |||
| 02fdcee705 | |||
| b4ab88a02e | |||
| ef1c9c125f | |||
| 4165224c51 | |||
| e665e187c1 | |||
| bd28d8170c | |||
| 710bbc33c9 | |||
| 1929239015 | |||
| 3ca90808f0 | |||
| 9d91440997 | |||
| f98062d417 | |||
| 8df3a4dd02 | |||
| afd2c81b19 | |||
| 4432ae4867 | |||
| 16c951838b | |||
| 8de4f1198a | |||
| d91e531fa5 | |||
| 2a40f4af1e | |||
| 144c932703 | |||
| e56b8856fa | |||
| d088d2f5a8 | |||
| 3d66386f99 | |||
| 1912d8e34c | |||
| d48b610b39 | |||
| 04f6d18198 | |||
| 640645b96b | |||
| a70738eda5 | |||
| 62756d2784 | |||
| 32f8907cb1 | |||
| b75e9c152e | |||
| c190485dbe | |||
| e756953828 | |||
| 071f9d39af | |||
| d2107fd258 | |||
| df3e623530 | |||
| f0d03d4538 | |||
| 84fe8792d6 | |||
| 67fc2ba4dc | |||
| 8d63c40e2f | |||
| b0bc37c34d | |||
| f2c5c15650 | |||
| f5de88215c | |||
| 8a6ad95947 | |||
| cc14c716bf | |||
| ece5213a87 | |||
| a01f700653 | |||
| 0ca7171bae | |||
| 6261f0849c | |||
| 4fc24f022f | |||
| 61ed302137 | |||
| 053ec39b7b | |||
| 0a952cff4c | |||
| 12faae8fd5 | |||
| 1496f2c929 | |||
| 40a938be19 | |||
| dc6cfb4187 | |||
| 4be2390294 | |||
| cd2421bb49 | |||
| da16f65ea2 | |||
| 65d026a130 | |||
| d45256b2f7 | |||
| 16d8e8f29d | |||
| a58b2a5193 | |||
| 1e5a1e20c2 | |||
| 592788450c | |||
| 060cbfd0c4 | |||
| b9c2f4e63b | |||
| 87674aa0ba | |||
| 40ccf80c7f | |||
| 6946755e31 | |||
| 3b9962662e | |||
| 7ca61f82b2 | |||
| 6851999926 | |||
| 585967157d | |||
| 305255511d | |||
| 819be16d83 | |||
| 8a028b193a | |||
| d31679e6be | |||
| 9d328b12b3 | |||
| a743e9c015 | |||
| 43d52e4bc1 | |||
| accc07fa07 | |||
| c1d3155ddd | |||
| 9a01a6c6a0 | |||
| 3033fbbf29 | |||
| c78a984a11 | |||
| 1ae0d1f867 | |||
| be7e10c30c | |||
| 2ccf8a8805 | |||
| 197cb12be2 | |||
| adb43dcaa8 | |||
| b03d128913 | |||
| 725fa88466 | |||
| a82dcd579c | |||
| 370b2e0122 | |||
| 331075e54d | |||
| a20d2c1f60 | |||
| 973590f5fd | |||
| 1a5ab6b505 | |||
| 14732328cd | |||
| 6c7974c302 | |||
| 1204b7a8c1 | |||
| fbe1c76e26 | |||
| add7803e65 | |||
| 4393a16b2f | |||
| b4fa635455 | |||
| 9f425c6159 | |||
| 158ffba2a5 | |||
| f5f3725dba | |||
| a7a7354c40 | |||
| 42dcc9d9bd | |||
| b7326c0ff6 | |||
| f70a83aec3 | |||
| 589cf83c38 | |||
| 581651e83b | |||
| a95a1284a4 | |||
| c95b3c09a8 | |||
| c374c2d5ef | |||
| 13782bb51e | |||
| 1aa3ef813c | |||
| 6cc53beecb | |||
| 2c45ba91aa | |||
| 6244ffca63 | |||
| 59d943b3ea | |||
| f605ee1937 | |||
| f87b7c07d9 | |||
| f1124aae6b | |||
| 9c8298fe53 | |||
| d69b0dba90 | |||
| 42166d5239 | |||
| d6772f51ea | |||
| f469193909 | |||
| 10d723372d | |||
| 1d05f95f74 | |||
| bd73427072 | |||
| 017b4608bc | |||
| 5f340f8ffd | |||
| 5b35eb041b | |||
| 699d5d1d62 | |||
| 07e3d0058d | |||
| b1ad820e1c | |||
| 3644ee7fca | |||
| b14b355c6f | |||
| 2df2755631 | |||
| ddb131d413 | |||
| 6042f1c036 | |||
| af2ac64cd4 | |||
| 06457bf3ce | |||
| b63f5f4a8f | |||
| 4bad8f702c | |||
| 76f12e0cb8 | |||
| 2e145ccd0a | |||
| 8cf766e77b | |||
| 0731d781d5 | |||
| 5bc73dec37 | |||
| a23d624ab9 | |||
| 15a298304e | |||
| 664d1a3191 | |||
| 73047284c8 | |||
| ce9fb53df4 | |||
| 1f01b99d29 | |||
| 18a24562ec | |||
| 2f2d43e1b8 | |||
| 6c8a7da254 | |||
| ca4461ba2a | |||
| c6df3c302b | |||
| 328ebf5aa9 | |||
| 2c476a25d9 | |||
| b432a4e01d | |||
| f73eadda76 | |||
| 1acdad5c6b | |||
| 732a894945 | |||
| bbf0915bc9 | |||
| 5f70ecb943 | |||
| 2e709dace6 | |||
| 3bef7d8572 | |||
| 08df5fc278 | |||
| c97f25cb95 | |||
| 28c689d16f | |||
| a34946cece | |||
| 922cd35e84 | |||
| 4acd0de6fa | |||
| 44d23573b3 | |||
| 2443fff0a4 | |||
| cd767a648c | |||
| e7cc275340 | |||
| fddc9a52b9 | |||
| 0758e13bc7 | |||
| d490324bfc | |||
| 5fa7007d45 | |||
| 2d0e4a83b0 | |||
| e68f928e38 | |||
| 4a3678cea9 | |||
| d810cad8d0 | |||
| 4e7de501c0 | |||
| 6ff0903d83 | |||
| 133df45968 | |||
| 1f937a2ae0 | |||
| d861d3e849 | |||
| 3d4aec4abb | |||
| 62e589870d | |||
| 2b125414c9 | |||
| 59d7632927 | |||
| d81f886e8c | |||
| b29ba2db70 | |||
| 02a7363f01 | |||
| 9e60db4b0d | |||
| 4536767794 | |||
| 3fa4b21247 | |||
| 17acde09a3 | |||
| dd272bce64 | |||
| c20b1eaf10 | |||
| 72f761678a | |||
| 62317a2f3f | |||
| 823afd592b | |||
| ff03b38b81 | |||
| 35246d65b9 | |||
| 41652d29df | |||
| 142d364682 | |||
| 01e011a9ed | |||
| b848ddabda | |||
| 94949c9120 | |||
| c52ad56ccc | |||
| 7214053b9e | |||
| da5d0c52f2 | |||
| f3476c5cc8 | |||
| cd69c7e77d | |||
| 56dd15c9aa | |||
| 2f470a3720 | |||
| 5350917412 | |||
| 45528acac8 | |||
| 921212ccb5 | |||
| 37641d43d6 | |||
| 9c181f7ee1 | |||
| 87ea5ce9e7 | |||
| 77f766b8bb | |||
| ecbba57b0a | |||
| 839835afd7 | |||
| 56941c237c | |||
| 179a304cd2 | |||
| 4970bf5720 | |||
| f877f861cf | |||
| d5f0b69bc7 | |||
| b10fd84e00 | |||
| 271e7f3c69 | |||
| 3e04bae828 | |||
| 6681bdfbf2 | |||
| ab60f14ff1 | |||
| d8ba9e1016 | |||
| 3622003a39 | |||
| 84cd96ecf7 | |||
| 82334cfe9e | |||
| 8afda7424c | |||
| 50ba1c6eab | |||
| da4ab8b71c | |||
| 3745c3e947 | |||
| fd20837b55 | |||
| 27a967f3a6 | |||
| 4c71355535 | |||
| e83b70b5ae | |||
| 56b428d501 | |||
| 7ca24faad3 | |||
| 9d200565d7 | |||
| f6c2795eaf | |||
| 6f03746e41 | |||
| 47c8cb3168 | |||
| a9f973cae9 | |||
| 033181d7c8 | |||
| e11a235386 | |||
| db1e924246 | |||
| c86faa44ec | |||
| de91a6facb | |||
| d4a328eb38 | |||
| b039629b2d | |||
| d48fa96ec7 | |||
| 8dd1f49b88 | |||
| 81528915a8 | |||
| 5979254808 | |||
| 0091e5b785 | |||
| 41045ae8aa | |||
| 4a83f01c1f | |||
| fc764a0fb3 | |||
| 22c46f2f80 | |||
| f408faaa80 | |||
| 0ad7ee4f9f | |||
| 1e55074cfa | |||
| 2a92d76276 | |||
| 687ad5db59 | |||
| f9c9789016 | |||
| 3142c2a4f0 | |||
| b5532b7679 | |||
| 8af299d09c | |||
| 5cf8a5061d | |||
| 017876475e | |||
| d88e4f1f9b | |||
| 17eac505a0 | |||
| 8043814138 | |||
| 554887ab54 | |||
| 2f46a01adc | |||
| a1db0574e9 | |||
| fd6decc706 | |||
| 0ba0d472e6 | |||
| 11b03eb93d | |||
| 46ca45cb1d | |||
| 4e5b066b91 | |||
| db8df9741f | |||
| 80c52870f5 | |||
| 5048bc8ede | |||
| fc0d7374e4 | |||
| e4c3affb9f | |||
| e160cae3d8 | |||
| cb9aa4f167 | |||
| b612d1c7aa | |||
| e4df8dce1d | |||
| 601d174720 | |||
| 3339d08e11 | |||
| bc65015af0 | |||
| 913637b0a5 | |||
| 86f2356cc8 | |||
| 55d09818f7 | |||
| c0aaf6c6e8 | |||
| aecdcd578c | |||
| 382069b094 | |||
| 734d4bfb94 | |||
| c82e015559 | |||
| 1ab3233cba | |||
| 59ea5a69d8 | |||
| 4ba71e9c27 | |||
| 5c7441241c | |||
| ffb1198da2 | |||
| 2c211f0aa6 | |||
| 3aef977384 | |||
| 6060ceae57 | |||
| 0efb0916e6 | |||
| 82fbf796da | |||
| 94bf67d09d | |||
| e499ddebd4 | |||
| f86d4bae32 | |||
| c7cecaebe6 | |||
| 866d527d35 | |||
| 4f706f5502 | |||
| fe954a7b2b | |||
| 15e72bae35 | |||
| 513c2df9f9 | |||
| aec00d9169 | |||
| 540552d301 | |||
| 4dfe2054e9 | |||
| 16e61098d9 | |||
| 8aecf6b97f | |||
| 4788483139 | |||
| 9e8aefe7f7 | |||
| 272556ed81 | |||
| fd0c4df04c | |||
| 1c3ee86376 | |||
| defd775f13 | |||
| a73fda7d04 | |||
| b8586135b8 | |||
| 4065cfea53 | |||
| a117db40be | |||
| 72e0974cc5 | |||
| d8938c5519 | |||
| acf79f5c53 | |||
| 839bc23a5a | |||
| 852cf0321b | |||
| 89d497d500 | |||
| 0df940d688 | |||
| dd7bebb27f | |||
| 72649d5cf7 | |||
| 7cf87de463 | |||
| 020033f839 | |||
| b3ef4ac79c | |||
| 3f9f2bdce4 | |||
| 0ab463f34f | |||
| 0b1d67b533 | |||
| c4f665ffc5 | |||
| c00753b0fc | |||
| 77812545df | |||
| ad9bc7f67c | |||
| 81a96d6b76 | |||
| d696e4fd24 | |||
| c98d39c5d7 | |||
| a6fe268f79 | |||
| 648da95e7d | |||
| 5829112a74 | |||
| c41bf55b7b | |||
| 5d12a560f1 | |||
| 6f08908bb4 | |||
| 9292d3de17 | |||
| 0149a29b04 | |||
| cd8605850f | |||
| 148b8dfe35 | |||
| 3f485b1825 | |||
| cb6ecff113 | |||
| e30bcbf1ba | |||
| 70b1c3bbf3 | |||
| e9b145b6c3 | |||
| 99d848b394 | |||
| 4828d51da4 |
+7
-7
@@ -8,7 +8,7 @@ indent_style = space
|
||||
insert_final_newline = false
|
||||
max_line_length = 140
|
||||
tab_width = 4
|
||||
ij_continuation_indent_size = 8
|
||||
ij_continuation_indent_size = 4
|
||||
ij_formatter_off_tag = @formatter:off
|
||||
ij_formatter_on_tag = @formatter:on
|
||||
ij_formatter_tags_enabled = false
|
||||
@@ -25,12 +25,12 @@ ij_java_align_multiline_annotation_parameters = true
|
||||
ij_java_align_multiline_array_initializer_expression = true
|
||||
ij_java_align_multiline_assignment = true
|
||||
ij_java_align_multiline_binary_operation = true
|
||||
ij_java_align_multiline_chained_methods = true
|
||||
ij_java_align_multiline_chained_methods = false
|
||||
ij_java_align_multiline_extends_list = true
|
||||
ij_java_align_multiline_for = true
|
||||
ij_java_align_multiline_method_parentheses = true
|
||||
ij_java_align_multiline_method_parentheses = false
|
||||
ij_java_align_multiline_parameters = true
|
||||
ij_java_align_multiline_parameters_in_calls = true
|
||||
ij_java_align_multiline_parameters_in_calls = false
|
||||
ij_java_align_multiline_parenthesized_expression = true
|
||||
ij_java_align_multiline_records = true
|
||||
ij_java_align_multiline_resources = true
|
||||
@@ -127,7 +127,7 @@ ij_java_keep_blank_lines_in_declarations = 2
|
||||
ij_java_keep_builder_methods_indents = true
|
||||
ij_java_keep_control_statement_in_one_line = true
|
||||
ij_java_keep_first_column_comment = false
|
||||
ij_java_keep_indents_on_empty_lines = true
|
||||
ij_java_keep_indents_on_empty_lines = false
|
||||
ij_java_keep_line_breaks = true
|
||||
ij_java_keep_multiple_expressions_in_one_line = false
|
||||
ij_java_keep_simple_blocks_in_one_line = true
|
||||
@@ -577,14 +577,14 @@ ij_properties_keep_blank_lines = false
|
||||
ij_properties_key_value_delimiter = equals
|
||||
ij_properties_spaces_around_key_value_delimiter = false
|
||||
|
||||
[{*.yaml, *.yml}]
|
||||
[{*.yml, *.yaml}]
|
||||
indent_size = 2
|
||||
ij_visual_guides = none
|
||||
ij_yaml_align_values_properties = do_not_align
|
||||
ij_yaml_autoinsert_sequence_marker = true
|
||||
ij_yaml_block_mapping_on_new_line = false
|
||||
ij_yaml_indent_sequence_value = true
|
||||
ij_yaml_keep_indents_on_empty_lines = true
|
||||
ij_yaml_keep_indents_on_empty_lines = false
|
||||
ij_yaml_keep_line_breaks = true
|
||||
ij_yaml_sequence_on_new_line = false
|
||||
ij_yaml_space_before_colon = false
|
||||
|
||||
+7
-12
@@ -1,19 +1,14 @@
|
||||
# Global owners, automatically request review when pull request is submitted
|
||||
* @dfsek @solonovamax
|
||||
* @dfsek @solonovamax @duplexsystem @astrsh @justaureus
|
||||
|
||||
# Platforms
|
||||
## dfsek wrote the majority of the platform impls
|
||||
/platforms/bukkit/ @dfsek
|
||||
/platforms/fabric/ @dfsek
|
||||
/platforms/forge/ @dfsek
|
||||
/platforms/sponge/ @dfsek
|
||||
## solonovamax is working on the region generator (unless duplexsystem takes it over)
|
||||
/platforms/region/ @solonovamax
|
||||
/platforms/ @dfsek @solonovamax @duplexsystem @justaureus
|
||||
/platforms/bukkit @dfsek @solonovamax @duplexsystem @justaureus @OakLoaf
|
||||
|
||||
# Common
|
||||
/common/ @dfsek @solonovamax
|
||||
/common/ @dfsek @solonovamax @duplexsystem @astrsh
|
||||
|
||||
# Gradle Stuff
|
||||
## Most gradle stuff was written by solonovamax
|
||||
/buildSrc/ @solonovamax
|
||||
*.gradle.kts @solonovamax
|
||||
/buildSrc/ @dfsek @solonovamax @duplexsystem
|
||||
*.gradle.kts @dfsek @solonovamax @duplexsystem
|
||||
/gradle/ @dfsek @solonovamax @duplexsystem
|
||||
|
||||
@@ -51,13 +51,13 @@ assignees: ""
|
||||
|
||||
<!-- You can fill out the different items by putting the correct value beside each cell. -->
|
||||
|
||||
| Name | Value |
|
||||
|------------------------------|-------|
|
||||
| Terra Version | <!-- Put your Terra version here. (remove the comment) -->
|
||||
| Platform / Platform Version | <!-- Put your platform and platform version here. (remove the comment) (eg. Spigot, Fabric, Paper, etc.) (If you are using the Region generator, put that here instead) -->
|
||||
| Any External Plugins or Mods | <!-- Put a list of all the plugins or mods you have installed here. (remove the comment) (Make sure to NOT include any new lines) -->
|
||||
| Terra Packs In Use | <!-- Put a list of all the Terra packs you have installed here. (remove the comment) (Make sure to NOT include any new lines) (/te packs may be used to get a list) -->
|
||||
| Terra Addons In Use | <!-- Put a list of all the Terra addons you have installed here. (remove the comment) (Make sure to NOT include any new lines) (/te addons may be used to get a list) -->
|
||||
| Name | Value |
|
||||
|------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Terra Version | <!-- Put your Terra version here. (remove the comment) -->
|
||||
| Platform / Platform Version | <!-- Put your platform and platform version here. (remove the comment) (eg. Spigot, Fabric, Paper, etc.) (If you are using the Region generator, put that here instead) -->
|
||||
| Any External Plugins or Mods | <!-- Put a list of all the plugins or mods you have installed here. (remove the comment) (Make sure to NOT include any new lines) -->
|
||||
| Terra Packs In Use | <!-- Put a list of all the Terra packs you have installed here. (remove the comment) (Make sure to NOT include any new lines) (/te packs may be used to get a list) -->
|
||||
| Terra Addons In Use | <!-- Put a list of all the Terra addons you have installed here. (remove the comment) (Make sure to NOT include any new lines) (/te addons may be used to get a list) -->
|
||||
|
||||
## Issue Description
|
||||
|
||||
|
||||
@@ -1,58 +1,19 @@
|
||||
# Pull Request
|
||||
|
||||
## Brief description.
|
||||
## Description
|
||||
|
||||
<!-- Please provide a brief description of the goals of your PR -->
|
||||
<!-- Include a description of the PR here -->
|
||||
|
||||
<!--
|
||||
###########################################################################
|
||||
## WARNING! ##
|
||||
## IGNORING THE FOLLOWING TEMPLATE WILL RESULT IN YOUR PR BEING CLOSED ##
|
||||
###########################################################################
|
||||
-->
|
||||
<!--
|
||||
Please go through this checklist item by item and make sure you have successfully completed each of these steps.
|
||||
- Your pull request MUST be either on the latest version of Terra, or on a branch for a future release.
|
||||
- Make sure that there are no already existing PRs that fix this. If so, it will be closed as a duplicate.
|
||||
- Make sure that this change is actually within the scope of Terra and is something a terrain generator should be doing.
|
||||
- Make sure that this is not an issue with a specific Terra *pack*, and instead applies to all of Terra.
|
||||
- Make sure that you have filled out all the required information and given descriptions of everything.
|
||||
-->
|
||||
<!-- You can erase any parts of this template not applicable to your Pull Request. -->
|
||||
|
||||
### What Issues Does This Fix?
|
||||
|
||||
<!--
|
||||
Put Fix #XXXX or Closes #XXXX here if there are any open issues that this PR fixes.
|
||||
This is to automatically close the relevant issues.
|
||||
You may remove this if there is no issue for this PR.
|
||||
But unless this is a very small change, you should make an issue for it.
|
||||
If applicable, include 'Fixes #XXXX' or 'Closes #XXXX' for any related open issues.
|
||||
This helps us relate, track, and close the relevant issues.
|
||||
-->
|
||||
|
||||
## Licensing
|
||||
|
||||
<!-- In order to be accepted, your changes must be under the GPLv3 license. Please check one of the following: -->
|
||||
|
||||
- [ ] I am the original author of this code, and I am willing to release it
|
||||
under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html).
|
||||
- [ ] I am not the original author of this code, but it is in public domain or
|
||||
released under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html) or a
|
||||
compatible license.
|
||||
<!--
|
||||
Please provide reliable evidence of this.
|
||||
NOTE: for compatible licenses, you must make sure to add the included license somewhere in the program, if so required.
|
||||
(And even if it's not required, it's still nice to do it. Also add attribution somewhere.)
|
||||
-->
|
||||
|
||||
## Goal of the PR
|
||||
### Changelog
|
||||
|
||||
<!--
|
||||
What is the goal of the PR?
|
||||
Put a checklist here of what has been done
|
||||
(and what *hasn't*, but you plan to do),
|
||||
so we can easily know what was changed.
|
||||
Note: this is only required for PRs that add new features.
|
||||
If your PR is not adding new features, only fixing bugs or adding translations, then you may delete this section.
|
||||
Fill out a changelog below of what has been done, and what might be planned to be done.
|
||||
You may delete this if your PR is not adding new features, only fixing bugs or adding translations.
|
||||
-->
|
||||
|
||||
- [ ] <!-- First thing -->
|
||||
@@ -61,47 +22,58 @@
|
||||
- [ ] <!-- Second thing -->
|
||||
- [ ] <!-- etc. -->
|
||||
|
||||
## Affects of the PR
|
||||
## Checklist
|
||||
|
||||
<!---
|
||||
What types of changes does your code introduce? (Select any that apply. You may select multiple.)
|
||||
You must put an x in all the boxes that it applies to. (Like this: [x])
|
||||
<!--
|
||||
Select the options below that apply.
|
||||
You must put an x in all the boxes that it applies to. (Like this: [x])
|
||||
-->
|
||||
|
||||
#### Mandatory checks
|
||||
|
||||
- [ ] The base branch of this PR is an unreleased version branch (that has a `ver/` prefix)
|
||||
or is a branch that is intended to be merged into a version branch.
|
||||
<!--
|
||||
This is not applicable if the PR is a version branch itself.
|
||||
PRs for new versions should use the `master` branch instead.
|
||||
-->
|
||||
- [ ] There are no already existing PRs that provide the same changes.
|
||||
<!-- If this is not applicable, the PR will be removed as a duplicate. -->
|
||||
- [ ] The PR is within the scope of Terra (i.e. is something a configurable terrain generator should be doing).
|
||||
- [ ] Changes follow the code style for this project.
|
||||
<!-- There is an included `.editorconfig` file in the base of the repo. Please use a plugin for your IDE of choice that follows those settings. -->
|
||||
- [ ] I have read the [`CONTRIBUTING.md`](https://github.com/PolyhedralDev/Terra/blob/master/CONTRIBUTING.md)
|
||||
document in the root of the git repository.
|
||||
|
||||
#### Types of changes
|
||||
|
||||
- [ ] Bug Fix <!-- Anything which fixes an issue in Terra. -->
|
||||
- [ ] Build system <!-- Anything which pretain to the build system. -->
|
||||
- [ ] Documentation <!-- Anything which adds or improves documentation for existing features. -->
|
||||
- [ ] New Feature <!-- Anything which adds new functionality to Terra. -->
|
||||
- [ ] Performance <!-- Anything which is imrpoves the performance of Terra. -->
|
||||
- [ ] Refactoring <!-- Anything which does not add any new code, only moves code around. -->
|
||||
- [ ] Repository <!-- Anything which affects the repository. Eg. changes to the `README.md` file. -->
|
||||
- [ ] Revert <!-- Anything which reverts previous commits. -->
|
||||
- [ ] Style <!-- Anything which updates style. -->
|
||||
- [ ] Tests <!-- Anything which adds or updates tests. -->
|
||||
- [ ] Translation <!-- Anything which is internationalizing the Terra program to other languages. -->
|
||||
- [ ] Bug Fix <!-- Changes include bug fixes. -->
|
||||
- [ ] Build system <!-- Changes the build system. -->
|
||||
- [ ] Documentation <!-- Changes add to or improve documentation. -->
|
||||
- [ ] New Feature <!-- Changes add new functionality to Terra. -->
|
||||
- [ ] Performance <!-- Changes improve the performance of Terra. -->
|
||||
- [ ] Refactoring <!-- Changes do not add any new code, only moves code around. -->
|
||||
- [ ] Repository <!-- Changes affect the repository. E.g. changes to the `README.md` file. -->
|
||||
- [ ] Revert <!-- Changes revert previous commits. -->
|
||||
- [ ] Style <!-- Changes update style, namely the .editorconfig file. -->
|
||||
- [ ] Tests <!-- Changes add or update tests. -->
|
||||
- [ ] Translation <!-- Changes include translations to other languages for Terra. -->
|
||||
|
||||
#### Compatiblity
|
||||
#### Compatibility
|
||||
|
||||
- [ ] Breaking
|
||||
change <!-- A fix, or a feature, that breaks some previous functionality to Terra. -->
|
||||
- [ ] Non-Breaking change.
|
||||
<!--
|
||||
A change which does not break *any* previous functionality of Terra.
|
||||
(ie. is backwards compatible and will work with *any* previously existing supported features.
|
||||
Note: if a feature is annotated with @Incubating, @Preview, @Experimental,
|
||||
or is in a package called something similar to the previous annotations,
|
||||
then you may push breaking changes to only THOSE parts of Terra.)
|
||||
-->
|
||||
<!-- The following options determine if the PR pertains to a major, minor, or patch version bump -->
|
||||
|
||||
#### Contribution Guidelines.
|
||||
|
||||
- [ ] I have read
|
||||
the [`CONTRIBUTING.md`](https://github.com/PolyhedralDev/Terra/blob/master/CONTRIBUTING.md)
|
||||
document in the root of the git repository.
|
||||
- [ ] My code follows the code style for this
|
||||
project. <!-- There is an included `.editorconfig` file in the base of the repo. Please use a plugin for your IDE of choice that follows those settings. -->
|
||||
- [ ] Introduces a breaking change
|
||||
<!--
|
||||
Breaking changes are any fix or feature that breaks some previous functionality to Terra / is not backwards compatible.
|
||||
Breaking changes do not include:
|
||||
- changes that are backwards compatible and will work with *any* previously existing supported features.
|
||||
- changes to code marked as in a pre-release
|
||||
state (annotated with @Incubating, @Preview, @Experimental
|
||||
or in a package called something similar to the previous annotations)
|
||||
-->
|
||||
- [ ] Introduces new functionality in a backwards compatible way.
|
||||
- [ ] Introduces bug fixes
|
||||
|
||||
#### Documentation
|
||||
|
||||
@@ -112,7 +84,21 @@
|
||||
|
||||
- [ ] I have added tests to cover my changes.
|
||||
- [ ] All new and existing tests passed.
|
||||
<!--
|
||||
If it only introduces small changes, you don't need to add tests.
|
||||
But if you add big changes, you should probably at least write *some* testing, where applicable.
|
||||
-->
|
||||
<!--
|
||||
Tests are typically not necessary for small changes.
|
||||
Including *some* testing is recommended for large changes where applicable.
|
||||
-->
|
||||
|
||||
#### Licensing
|
||||
|
||||
<!-- In order to be accepted, your changes must be under the GPLv3 license. Please check one of the following: -->
|
||||
|
||||
- [ ] I am the original author of this code, and I am willing to
|
||||
release it under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html).
|
||||
- [ ] I am not the original author of this code, but it is in public domain or
|
||||
released under [GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html) or a compatible license.
|
||||
<!--
|
||||
Please provide reliable evidence of this.
|
||||
NOTE: for compatible licenses, you must make sure to add the included license somewhere in the program, if so required.
|
||||
(And even if it's not required, it's still nice to do it. Also add attribution somewhere.)
|
||||
-->
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
# This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created
|
||||
# For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle
|
||||
|
||||
name: Gradle Build
|
||||
|
||||
on: [ pull_request ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4.7.1
|
||||
with:
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
server-id: github # Value of the distributionManagement/repository/id field of the pom.xml
|
||||
settings-path: ${{ github.workspace }} # location for the settings.xml file
|
||||
|
||||
- uses: burrunan/gradle-cache-action@v3.0.1
|
||||
name: Build Terra
|
||||
with:
|
||||
# Specifies arguments for Gradle execution
|
||||
# If arguments is missing or empty, then Gradle is not executed
|
||||
arguments: build
|
||||
# arguments can be multi-line for better readability
|
||||
# arguments: |
|
||||
# --no-paralell
|
||||
# build
|
||||
# -x test
|
||||
# Gradle version to use for execution:
|
||||
# wrapper (default), current, rc, nightly, release-nightly, or
|
||||
# versions like 6.6 (see https://services.gradle.org/versions/all)
|
||||
gradle-version: wrapper
|
||||
# Properties are passed as -Pname=value
|
||||
properties: |
|
||||
kotlin.js.compiler=ir
|
||||
kotlin.parallel.tasks.in.project=true
|
||||
@@ -249,3 +249,5 @@ nbdist/
|
||||
|
||||
platforms/**/run/**
|
||||
|
||||
#Vale Config File
|
||||
**/.vale.ini
|
||||
|
||||
Vendored
+149
@@ -0,0 +1,149 @@
|
||||
pipeline {
|
||||
agent any
|
||||
|
||||
tools {
|
||||
jdk "Temurin Java 21"
|
||||
}
|
||||
|
||||
triggers {
|
||||
githubPush()
|
||||
}
|
||||
|
||||
environment {
|
||||
DISCORD_WEBHOOK_URL = credentials('polydev-discord-webhook-url')
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Checkout') {
|
||||
steps {
|
||||
scmSkip(deleteBuild: true)
|
||||
}
|
||||
}
|
||||
|
||||
stage('Setup Gradle') {
|
||||
steps {
|
||||
sh 'chmod +x gradlew'
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build') {
|
||||
steps {
|
||||
withGradle {
|
||||
sh './gradlew build --rerun-tasks -x check'
|
||||
sh './gradlew javadoc'
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
success {
|
||||
archiveArtifacts artifacts: 'platforms/fabric/build/libs/Terra-fabric*.jar,platforms/bukkit/build/libs/Terra-bukkit*-shaded.jar,platforms/allay/build/libs/Terra-allay*.jar,platforms/minestom/build/libs/Terra-minestom*.jar', fingerprint: true, onlyIfSuccessful: true
|
||||
|
||||
javadoc javadocDir: 'common/api/build/docs/javadoc', keepAll: true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Tests') {
|
||||
steps {
|
||||
withGradle {
|
||||
sh './gradlew test --rerun-tasks'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stage('Deploy to snapshots repositories') {
|
||||
// when {
|
||||
// allOf {
|
||||
// not { buildingTag() }
|
||||
// not { expression { env.TAG_NAME != null && env.TAG_NAME.matches('v\\d+\\.\\d+\\.\\d+') } }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// steps {
|
||||
// withCredentials([
|
||||
// string(credentialsId: 'maven-signing-key', variable: 'ORG_GRADLE_PROJECT_signingKey'),
|
||||
// string(credentialsId: 'maven-signing-key-password', variable: 'ORG_GRADLE_PROJECT_signingPassword'),
|
||||
// usernamePassword(
|
||||
// credentialsId: 'solo-studios-maven',
|
||||
// passwordVariable: 'ORG_GRADLE_PROJECT_SoloStudiosSnapshotsPassword',
|
||||
// usernameVariable: 'ORG_GRADLE_PROJECT_SoloStudiosSnapshotsUsername'
|
||||
// )
|
||||
// ]) {
|
||||
// withGradle {
|
||||
// sh './gradlew publishAllPublicationsToSoloStudiosSnapshotsRepository'
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
stage('Deploy to releases repositories') {
|
||||
// when {
|
||||
// allOf {
|
||||
// buildingTag()
|
||||
// expression { env.TAG_NAME != null && env.TAG_NAME.matches('v\\d+\\.\\d+\\.\\d+') }
|
||||
// }
|
||||
// }
|
||||
|
||||
steps {
|
||||
withCredentials([
|
||||
string(credentialsId: 'maven-signing-key', variable: 'ORG_GRADLE_PROJECT_signingKey'),
|
||||
string(credentialsId: 'maven-signing-key-password', variable: 'ORG_GRADLE_PROJECT_signingPassword'),
|
||||
usernamePassword(
|
||||
credentialsId: 'solo-studios-maven',
|
||||
passwordVariable: 'ORG_GRADLE_PROJECT_SoloStudiosReleasesPassword',
|
||||
usernameVariable: 'ORG_GRADLE_PROJECT_SoloStudiosReleasesUsername'
|
||||
),
|
||||
// TODO: does not yet exist (uncomment once added)
|
||||
// usernamePassword(
|
||||
// credentialsId: 'sonatype-maven-credentials',
|
||||
// passwordVariable: 'ORG_GRADLE_PROJECT_SonatypePassword',
|
||||
// usernameVariable: 'ORG_GRADLE_PROJECT_SonatypeUsername'
|
||||
// ),
|
||||
// usernamePassword(
|
||||
// credentialsId: 'codemc-maven-credentials',
|
||||
// passwordVariable: 'ORG_GRADLE_PROJECT_CodeMCPassword',
|
||||
// usernameVariable: 'ORG_GRADLE_PROJECT_CodeMCUsername'
|
||||
// )
|
||||
]) {
|
||||
withGradle {
|
||||
sh './gradlew publish'
|
||||
//sh './gradlew publishAllPublicationsToSoloStudiosReleasesRepository'
|
||||
// sh './gradlew publishAllPublicationsToSonatypeRepository'
|
||||
// sh './gradlew publishAllPublicationsToCodeMCRepository'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
post {
|
||||
always {
|
||||
discoverReferenceBuild()
|
||||
|
||||
// junit testResults: '**/build/test-results/*/TEST-*.xml'
|
||||
|
||||
recordIssues(
|
||||
aggregatingResults: true,
|
||||
enabledForFailure: true,
|
||||
minimumSeverity: 'ERROR',
|
||||
sourceCodeEncoding: 'UTF-8',
|
||||
checksAnnotationScope: 'ALL',
|
||||
sourceCodeRetention: 'LAST_BUILD',
|
||||
tools: [java(), javaDoc()]
|
||||
)
|
||||
|
||||
discordSend(
|
||||
title: env.JOB_NAME + ' ' + env.BUILD_DISPLAY_NAME,
|
||||
showChangeset: true,
|
||||
enableArtifactsList: true,
|
||||
link: env.BUILD_URL,
|
||||
result: currentBuild.currentResult,
|
||||
customAvatarUrl: 'https://github.com/PolyhedralDev.png',
|
||||
customUsername: 'Solo Studios Jenkins',
|
||||
webhookURL: env.DISCORD_WEBHOOK_URL,
|
||||
)
|
||||
|
||||
cleanWs()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020-2021 Polyhedral Development
|
||||
Copyright (c) 2020-2025 Polyhedral Development
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
+15
-13
@@ -1,38 +1,39 @@
|
||||
preRelease(true)
|
||||
|
||||
versionProjects(":common:api", version("6.4.0"))
|
||||
versionProjects(":common:implementation", version("6.4.0"))
|
||||
versionProjects(":platforms", version("6.4.0"))
|
||||
versionProjects(":common:api", version("7.0.0"))
|
||||
versionProjects(":common:implementation", version("7.0.0"))
|
||||
versionProjects(":platforms", version("7.0.0"))
|
||||
|
||||
|
||||
allprojects {
|
||||
group = "com.dfsek.terra"
|
||||
|
||||
|
||||
configureCompilation()
|
||||
configureDependencies()
|
||||
configurePublishing()
|
||||
|
||||
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.isFork = true
|
||||
options.isIncremental = true
|
||||
options.release.set(21)
|
||||
}
|
||||
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
useJUnitPlatform()
|
||||
|
||||
|
||||
maxHeapSize = "2G"
|
||||
ignoreFailures = false
|
||||
failFast = true
|
||||
maxParallelForks = (Runtime.getRuntime().availableProcessors() - 1).takeIf { it > 0 } ?: 1
|
||||
|
||||
|
||||
reports.html.required.set(false)
|
||||
reports.junitXml.required.set(false)
|
||||
}
|
||||
|
||||
|
||||
tasks.withType<Copy>().configureEach {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
|
||||
|
||||
tasks.withType<Jar>().configureEach {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
@@ -43,13 +44,14 @@ afterEvaluate {
|
||||
configureDistribution()
|
||||
}
|
||||
project(":platforms:bukkit:common").configureDistribution()
|
||||
project(":platforms:minestom:example").configureDistribution()
|
||||
forSubProjects(":common:addons") {
|
||||
apply(plugin = "com.github.johnrengelman.shadow")
|
||||
|
||||
apply(plugin = "com.gradleup.shadow")
|
||||
|
||||
tasks.named("build") {
|
||||
finalizedBy(tasks.named("shadowJar"))
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
"compileOnly"(project(":common:api"))
|
||||
"testImplementation"(project(":common:api"))
|
||||
|
||||
@@ -6,21 +6,27 @@ plugins {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven("https://maven.solo-studios.ca/releases") {
|
||||
name = "Solo Studios"
|
||||
}
|
||||
maven("https://maven.solo-studios.ca/snapshots") {
|
||||
name = "Solo Studios"
|
||||
}
|
||||
maven("https://repo.codemc.org/repository/maven-public") {
|
||||
name = "CodeMC"
|
||||
}
|
||||
maven("https://papermc.io/repo/repository/maven-public/") {
|
||||
maven("https://repo.papermc.io/repository/maven-public/") {
|
||||
name = "PaperMC"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
//TODO Allow pulling from Versions.kt
|
||||
implementation("com.github.johnrengelman", "shadow", "8.1.1")
|
||||
implementation("io.papermc.paperweight.userdev", "io.papermc.paperweight.userdev.gradle.plugin","1.5.6")
|
||||
|
||||
implementation("org.ow2.asm", "asm", "9.5")
|
||||
implementation("org.ow2.asm", "asm-tree", "9.5")
|
||||
implementation("com.dfsek.tectonic", "common", "4.2.0")
|
||||
implementation("org.yaml", "snakeyaml", "2.2")
|
||||
implementation("com.gradleup.shadow", "shadow-gradle-plugin", "8.3.9")
|
||||
|
||||
implementation("io.papermc.paperweight.userdev", "io.papermc.paperweight.userdev.gradle.plugin", "2.0.0-beta.18")
|
||||
implementation("org.ow2.asm", "asm", "9.9")
|
||||
implementation("org.ow2.asm", "asm-tree", "9.9")
|
||||
implementation("com.dfsek.tectonic", "common", "4.3.1")
|
||||
implementation("org.yaml", "snakeyaml", "2.5")
|
||||
}
|
||||
@@ -18,7 +18,7 @@ fun Project.addonDir(dir: File, task: Task) {
|
||||
matchingAddons(dir) {
|
||||
it.name.startsWith("Terra-") // Assume everything that starts with Terra- is a core addon.
|
||||
}.forEach {
|
||||
println("Deleting old addon: " + it.absolutePath)
|
||||
logger.info("Deleting old addon: " + it.absolutePath)
|
||||
it.delete()
|
||||
}
|
||||
forSubProjects(":common:addons") {
|
||||
@@ -29,7 +29,7 @@ fun Project.addonDir(dir: File, task: Task) {
|
||||
|
||||
val base = "${jar.archiveBaseName.get()}-${version}"
|
||||
|
||||
println("Copying addon ${jar.archiveFileName.get()} to ${target.absolutePath}. Base name: $base")
|
||||
logger.info("Copying addon ${jar.archiveFileName.get()} to ${target.absolutePath}. Base name: $base")
|
||||
|
||||
jar.archiveFile.orNull?.asFile?.copyTo(target)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.gradle.kotlin.dsl.getByName
|
||||
import org.gradle.kotlin.dsl.register
|
||||
import org.gradle.kotlin.dsl.withType
|
||||
import org.gradle.language.jvm.tasks.ProcessResources
|
||||
import org.gradle.plugins.ide.idea.model.IdeaModel
|
||||
|
||||
fun Project.configureCompilation() {
|
||||
apply(plugin = "maven-publish")
|
||||
@@ -21,9 +22,16 @@ fun Project.configureCompilation() {
|
||||
apply(plugin = "idea")
|
||||
apply<TectonicDocPlugin>()
|
||||
|
||||
configure<IdeaModel> {
|
||||
module {
|
||||
isDownloadJavadoc = true
|
||||
isDownloadSources = true
|
||||
}
|
||||
}
|
||||
|
||||
configure<JavaPluginExtension> {
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = JavaVersion.VERSION_21
|
||||
targetCompatibility = JavaVersion.VERSION_21
|
||||
}
|
||||
|
||||
tasks.withType<JavaCompile> {
|
||||
|
||||
@@ -30,13 +30,19 @@ fun Project.configureDependencies() {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
maven("https://maven.solo-studios.ca/releases") {
|
||||
name = "Solo Studios"
|
||||
}
|
||||
maven("https://maven.solo-studios.ca/snapshots") {
|
||||
name = "Solo Studios"
|
||||
}
|
||||
maven("https://maven.fabricmc.net/") {
|
||||
name = "FabricMC"
|
||||
}
|
||||
maven("https://repo.codemc.org/repository/maven-public") {
|
||||
name = "CodeMC"
|
||||
}
|
||||
maven("https://papermc.io/repo/repository/maven-public/") {
|
||||
maven("https://repo.papermc.io/repository/maven-public/") {
|
||||
name = "PaperMC"
|
||||
}
|
||||
maven("https://files.minecraftforge.net/maven/") {
|
||||
@@ -48,17 +54,20 @@ fun Project.configureDependencies() {
|
||||
maven("https://jitpack.io") {
|
||||
name = "JitPack"
|
||||
}
|
||||
maven("https://nexuslite.gcnt.net/repos/other/") {
|
||||
name = "GCNT"
|
||||
maven("https://s01.oss.sonatype.org/content/repositories/snapshots/") {
|
||||
name = "Sonatype Snapshots"
|
||||
}
|
||||
maven("https://repo.onarandombox.com/multiverse-releases") {
|
||||
name = "onarandombox"
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.7.0")
|
||||
testImplementation("org.junit.jupiter:junit-jupiter-engine:5.7.0")
|
||||
compileOnly("org.jetbrains:annotations:23.0.0")
|
||||
testImplementation("org.junit.jupiter", "junit-jupiter", Versions.Libraries.Internal.junit)
|
||||
"testRuntimeOnly"("org.junit.platform", "junit-platform-launcher")
|
||||
compileOnly("org.jetbrains", "annotations", Versions.Libraries.Internal.jetBrainsAnnotations)
|
||||
|
||||
compileOnly("com.google.guava:guava:30.0-jre")
|
||||
testImplementation("com.google.guava:guava:30.0-jre")
|
||||
compileOnly("com.google.guava", "guava", Versions.Libraries.Internal.guava)
|
||||
testImplementation("com.google.guava", "guava", Versions.Libraries.Internal.guava)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import io.papermc.paperweight.util.path
|
||||
import java.io.File
|
||||
import java.io.FileWriter
|
||||
import java.net.URI
|
||||
import java.net.URL
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.StandardCopyOption
|
||||
import java.nio.file.Path
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.BasePluginExtension
|
||||
import org.gradle.kotlin.dsl.TaskContainerScope
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.apply
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
@@ -17,17 +16,54 @@ import org.gradle.kotlin.dsl.get
|
||||
import org.gradle.kotlin.dsl.named
|
||||
import org.yaml.snakeyaml.DumperOptions
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import kotlin.io.path.copyTo
|
||||
import kotlin.io.path.createDirectories
|
||||
import kotlin.io.path.createFile
|
||||
import kotlin.io.path.exists
|
||||
|
||||
private fun Project.installAddonsInto(dest: Path) {
|
||||
FileSystems.newFileSystem(dest, mapOf("create" to "false"), null).use { fs ->
|
||||
forSubProjects(":common:addons") {
|
||||
val jar = getJarTask()
|
||||
|
||||
logger.info("Packaging addon ${jar.archiveFileName.get()} to $dest. size: ${jar.archiveFile.get().asFile.length() / 1024}KB")
|
||||
|
||||
val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else ""
|
||||
val addonPath = fs.getPath("/addons/$boot${jar.archiveFileName.get()}")
|
||||
|
||||
if (!addonPath.exists()) {
|
||||
addonPath.parent.createDirectories()
|
||||
addonPath.createFile()
|
||||
jar.archiveFile.get().asFile.toPath().copyTo(addonPath, overwrite = true)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.configureDistribution() {
|
||||
apply(plugin = "com.github.johnrengelman.shadow")
|
||||
apply(plugin = "com.gradleup.shadow")
|
||||
|
||||
val downloadDefaultPacks = tasks.create("downloadDefaultPacks") {
|
||||
group = "terra"
|
||||
doFirst {
|
||||
file("${buildDir}/resources/main/packs/").deleteRecursively()
|
||||
val defaultPackUrl = URL("https://github.com/PolyhedralDev/TerraOverworldConfig/releases/download/latest/default.zip")
|
||||
downloadPack(defaultPackUrl, project)
|
||||
try {
|
||||
file("${buildDir}/resources/main/packs/").deleteRecursively()
|
||||
file("${buildDir}/resources/main/metapacks/").deleteRecursively()
|
||||
val overworldPackUrl =
|
||||
URL("https://github.com/PolyhedralDev/TerraOverworldConfig/releases/download/" + Versions.Terra.overworldConfig + "/Overworld.zip")
|
||||
val reimagENDPackUrl =
|
||||
URL("https://github.com/PolyhedralDev/ReimagEND/releases/download/" + Versions.Terra.reimagENDConfig + "/ReimagEND.zip")
|
||||
val tartarusPackUrl =
|
||||
URL("https://github.com/PolyhedralDev/Tartarus/releases/download/" + Versions.Terra.tartarusConfig + "/Tartarus.zip")
|
||||
val defaultPackUrl =
|
||||
URL("https://github.com/PolyhedralDev/DefaultMetapack/releases/download/" + Versions.Terra.defaultConfig + "/default.zip")
|
||||
downloadPack(overworldPackUrl, project)
|
||||
downloadPack(reimagENDPackUrl, project)
|
||||
downloadPack(tartarusPackUrl, project)
|
||||
downloadPack(defaultPackUrl, project, true)
|
||||
} catch (_: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,25 +81,18 @@ fun Project.configureDistribution() {
|
||||
|
||||
doLast {
|
||||
// https://github.com/johnrengelman/shadow/issues/111
|
||||
val dest = URI.create("jar:" + tasks.named<ShadowJar>("shadowJar").get().archiveFile.get().asFile.toURI())
|
||||
|
||||
FileSystems.newFileSystem(dest, mapOf("create" to "false"), null).use { fs ->
|
||||
forSubProjects(":common:addons") {
|
||||
val jar = getJarTask()
|
||||
|
||||
println("Packaging addon ${jar.archiveFileName.get()} to $dest. size: ${jar.archiveFile.get().asFile.length() / 1024}KB")
|
||||
|
||||
val boot = if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "bootstrap/" else ""
|
||||
val addonPath = fs.getPath("/addons/$boot${jar.archiveFileName.get()}")
|
||||
|
||||
if (!Files.exists(addonPath)) {
|
||||
Files.createDirectories(addonPath.parent)
|
||||
Files.createFile(addonPath)
|
||||
Files.copy(jar.archiveFile.get().asFile.toPath(), addonPath, StandardCopyOption.REPLACE_EXISTING)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
val dest = tasks.named<ShadowJar>("shadowJar").get().archiveFile.get().path
|
||||
installAddonsInto(dest)
|
||||
}
|
||||
}
|
||||
|
||||
tasks.create("installAddonsIntoDefaultJar") {
|
||||
group = "terra"
|
||||
dependsOn(compileAddons)
|
||||
|
||||
doLast {
|
||||
val dest = tasks.named<Jar>("jar").get().archiveFile.get().path
|
||||
installAddonsInto(dest)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,6 +107,13 @@ fun Project.configureDistribution() {
|
||||
resources.computeIfAbsent("packs") { ArrayList() }.add(it.name)
|
||||
}
|
||||
|
||||
val metaPacksDir = File("${project.buildDir}/resources/main/metapacks/")
|
||||
|
||||
metaPacksDir.walkTopDown().forEach {
|
||||
if (it.isDirectory || !it.name.endsWith(".zip")) return@forEach
|
||||
resources.computeIfAbsent("metapacks") { ArrayList() }.add(it.name)
|
||||
}
|
||||
|
||||
val langDir = File("${project(":common:implementation").buildDir}/resources/main/lang/")
|
||||
|
||||
langDir.walkTopDown().forEach {
|
||||
@@ -89,7 +125,8 @@ fun Project.configureDistribution() {
|
||||
val jar = getJarTask().archiveFileName.get()
|
||||
resources.computeIfAbsent(
|
||||
if (extra.has("bootstrap") && extra.get("bootstrap") as Boolean) "addons/bootstrap"
|
||||
else "addons") { ArrayList() }.add(jar)
|
||||
else "addons"
|
||||
) { ArrayList() }.add(jar)
|
||||
}
|
||||
|
||||
val options = DumperOptions()
|
||||
@@ -110,7 +147,7 @@ fun Project.configureDistribution() {
|
||||
FileWriter(manifest).use {
|
||||
yaml.dump(resources, it)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,10 +163,9 @@ fun Project.configureDistribution() {
|
||||
dependsOn(downloadDefaultPacks)
|
||||
configurations = listOf(project.configurations["shaded"])
|
||||
archiveClassifier.set("shaded")
|
||||
setVersion(project.version)
|
||||
version = project.version
|
||||
relocate("org.apache.commons", "com.dfsek.terra.lib.commons")
|
||||
relocate("org.objectweb.asm", "com.dfsek.terra.lib.asm")
|
||||
relocate("com.dfsek.paralithic", "com.dfsek.terra.lib.paralithic")
|
||||
relocate("org.json", "com.dfsek.terra.lib.json")
|
||||
relocate("org.yaml", "com.dfsek.terra.lib.yaml")
|
||||
|
||||
@@ -145,9 +181,10 @@ fun Project.configureDistribution() {
|
||||
}
|
||||
}
|
||||
|
||||
fun downloadPack(packUrl: URL, project: Project) {
|
||||
fun downloadPack(packUrl: URL, project: Project, metapack: Boolean = false) {
|
||||
val fileName = packUrl.file.substring(packUrl.file.lastIndexOf("/"))
|
||||
val file = File("${project.buildDir}/resources/main/packs/${fileName}")
|
||||
val resourceType = if (metapack) "metapacks" else "packs"
|
||||
val file = File("${project.buildDir}/resources/main/${resourceType}/${fileName}")
|
||||
file.parentFile.mkdirs()
|
||||
file.outputStream().write(packUrl.readBytes())
|
||||
}
|
||||
|
||||
@@ -16,16 +16,17 @@ fun Project.configurePublishing() {
|
||||
}
|
||||
|
||||
repositories {
|
||||
val mavenUrl = "https://repo.codemc.io/repository/maven-releases/"
|
||||
val mavenUrl = "https://maven.solo-studios.ca/releases/"
|
||||
//val mavenSnapshotUrl = "https://repo.codemc.io/repository/maven-snapshots/"
|
||||
|
||||
maven(mavenUrl) {
|
||||
val mavenUsername: String? by project
|
||||
val mavenPassword: String? by project
|
||||
if (mavenUsername != null && mavenPassword != null) {
|
||||
val SoloStudiosReleasesUsername: String? by project
|
||||
val SoloStudiosReleasesPassword: String? by project
|
||||
|
||||
if (SoloStudiosReleasesUsername != null && SoloStudiosReleasesPassword != null) {
|
||||
credentials {
|
||||
username = mavenUsername
|
||||
password = mavenPassword
|
||||
username = SoloStudiosReleasesUsername
|
||||
password = SoloStudiosReleasesPassword
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,10 +42,10 @@ fun preRelease(preRelease: Boolean) {
|
||||
fun Project.versionProjects(project: String, version: String) {
|
||||
forSubProjects(project) {
|
||||
this.version = version
|
||||
println("Setting version of $path to $version")
|
||||
logger.info("Setting version of $path to $version")
|
||||
}
|
||||
project(project).version = version
|
||||
println("Setting version of $project to $version")
|
||||
logger.info("Setting version of $project to $version")
|
||||
}
|
||||
|
||||
fun Project.version(version: String): String {
|
||||
|
||||
@@ -1,27 +1,39 @@
|
||||
object Versions {
|
||||
object Terra {
|
||||
const val overworldConfig = "latest"
|
||||
const val reimagENDConfig = "latest"
|
||||
const val tartarusConfig = "latest"
|
||||
const val defaultConfig = "latest"
|
||||
}
|
||||
|
||||
object Libraries {
|
||||
const val tectonic = "4.2.1"
|
||||
const val paralithic = "0.7.1"
|
||||
const val tectonic = "4.3.1"
|
||||
const val paralithic = "2.0.1"
|
||||
const val strata = "1.3.2"
|
||||
const val seismic = "2.5.7"
|
||||
|
||||
const val cloud = "1.8.4"
|
||||
const val cloud = "2.0.0"
|
||||
|
||||
const val slf4j = "2.0.9"
|
||||
const val log4j_slf4j_impl = "2.20.0"
|
||||
const val caffeine = "3.2.2"
|
||||
|
||||
const val slf4j = "2.0.17"
|
||||
|
||||
object Internal {
|
||||
const val shadow = "8.1.1"
|
||||
const val apacheText = "1.10.0"
|
||||
const val jafama = "2.3.2"
|
||||
const val apacheIO = "2.14.0"
|
||||
const val guava = "32.1.3-jre"
|
||||
const val asm = "9.5"
|
||||
const val snakeYml = "2.2"
|
||||
const val shadow = "8.3.9"
|
||||
const val apacheText = "1.14.0"
|
||||
const val apacheIO = "2.20.0"
|
||||
const val guava = "33.5.0-jre"
|
||||
const val asm = "9.9"
|
||||
const val snakeYml = "2.5"
|
||||
const val jetBrainsAnnotations = "26.0.2-1"
|
||||
const val junit = "6.0.0"
|
||||
const val nbt = "6.1"
|
||||
}
|
||||
}
|
||||
|
||||
object Fabric {
|
||||
const val fabricAPI = "0.90.0+${Mod.minecraft}"
|
||||
const val fabricAPI = "0.134.1+${Mod.minecraft}"
|
||||
const val cloud = "2.0.0-beta.13"
|
||||
}
|
||||
//
|
||||
// object Quilt {
|
||||
@@ -30,33 +42,37 @@ object Versions {
|
||||
// }
|
||||
|
||||
object Mod {
|
||||
const val mixin = "0.12.5+mixin.0.8.5"
|
||||
const val mixin = "0.16.4+mixin.0.8.7"
|
||||
const val mixinExtras = "0.5.0"
|
||||
|
||||
const val minecraft = "1.20.2"
|
||||
const val yarn = "$minecraft+build.4"
|
||||
const val fabricLoader = "0.14.23"
|
||||
const val minecraft = "1.21.10"
|
||||
const val yarn = "$minecraft+build.1"
|
||||
const val fabricLoader = "0.18.2"
|
||||
|
||||
const val architecuryLoom = "1.3.357"
|
||||
const val architecturyPlugin = "3.4.146"
|
||||
|
||||
const val loomVineflower = "1.11.0"
|
||||
}
|
||||
|
||||
object Forge {
|
||||
const val forge = "${Mod.minecraft}-48.0.13"
|
||||
const val burningwave = "12.63.0"
|
||||
const val architecuryLoom = "1.11.451"
|
||||
const val architecturyPlugin = "3.4.162"
|
||||
|
||||
}
|
||||
//
|
||||
// object Forge {
|
||||
// const val forge = "${Mod.minecraft}-48.0.13"
|
||||
// const val burningwave = "12.63.0"
|
||||
// }
|
||||
|
||||
object Bukkit {
|
||||
const val paper = "1.18.2-R0.1-SNAPSHOT"
|
||||
const val paperLib = "1.0.5"
|
||||
const val foliaLib = "0.2.5"
|
||||
const val minecraft = "1.20.2"
|
||||
const val reflectionRemapper = "0.1.0-SNAPSHOT"
|
||||
const val paperDevBundle = "1.20.2-R0.1-SNAPSHOT"
|
||||
const val runPaper = "2.2.0"
|
||||
const val paperWeight = "1.5.6"
|
||||
const val minecraft = "1.21.10"
|
||||
const val nms = "$minecraft-R0.1"
|
||||
const val paperBuild = "$nms-20251012.013929-7"
|
||||
const val paper = paperBuild
|
||||
const val paperLib = "1.0.8"
|
||||
const val reflectionRemapper = "0.1.3"
|
||||
const val paperDevBundle = paperBuild
|
||||
const val runPaper = "2.3.1"
|
||||
const val paperWeight = "2.0.0-beta.19"
|
||||
const val cloud = "2.0.0-beta.12"
|
||||
const val multiverse = "5.3.0"
|
||||
}
|
||||
|
||||
//
|
||||
// object Sponge {
|
||||
// const val sponge = "9.0.0-SNAPSHOT"
|
||||
@@ -65,7 +81,21 @@ object Versions {
|
||||
// }
|
||||
//
|
||||
object CLI {
|
||||
const val nbt = "6.1"
|
||||
const val logback = "1.4.11"
|
||||
const val logback = "1.5.19"
|
||||
const val picocli = "4.7.7"
|
||||
}
|
||||
}
|
||||
|
||||
object Allay {
|
||||
const val api = "0.13.0"
|
||||
const val gson = "2.13.2"
|
||||
|
||||
const val mappings = "15398c1"
|
||||
const val mappingsGenerator = "8fa6058"
|
||||
|
||||
const val mcmeta = "e85a17c"
|
||||
}
|
||||
|
||||
object Minestom {
|
||||
const val minestom = "2025.10.04-1.21.8"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ abstract class GenerateDocsTask : DefaultTask() {
|
||||
}
|
||||
|
||||
template.add(keyName.toString(), description.toString().ifBlank {
|
||||
println("No description provided for field " + field.name + " in class " + name)
|
||||
logger.info("No description provided for field " + field.name + " in class " + name)
|
||||
"*No description provided.*"
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020-2021 Polyhedral Development
|
||||
Copyright (c) 2020-2025 Polyhedral Development
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
+4
-4
@@ -8,17 +8,17 @@ import com.dfsek.terra.api.addon.BaseAddon;
|
||||
public class ApiAddon implements BaseAddon {
|
||||
private final Version version;
|
||||
private final String id;
|
||||
|
||||
|
||||
public ApiAddon(Version version, String id) {
|
||||
this.version = version;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Version getVersion() {
|
||||
public Version version() {
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
@@ -15,7 +15,7 @@ public class ApiAddonClassLoader extends URLClassLoader {
|
||||
static {
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
}
|
||||
|
||||
|
||||
public ApiAddonClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super(urls, parent);
|
||||
}
|
||||
+6
-6
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
@@ -20,20 +20,20 @@ import com.dfsek.terra.api.addon.bootstrap.BootstrapBaseAddon;
|
||||
|
||||
public class ApiAddonLoader implements BootstrapBaseAddon<BaseAddon> {
|
||||
private static final Version VERSION = Versions.getVersion(1, 0, 0);
|
||||
|
||||
|
||||
@Override
|
||||
public Iterable<BaseAddon> loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent) {
|
||||
|
||||
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return "API";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Version getVersion() {
|
||||
public Version version() {
|
||||
return VERSION;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020-2021 Polyhedral Development
|
||||
Copyright (c) 2020-2025 Polyhedral Development
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
version = version("1.0.0")
|
||||
|
||||
dependencies {
|
||||
api("commons-io:commons-io:2.7")
|
||||
implementation("com.dfsek.tectonic:yaml:${Versions.Libraries.tectonic}")
|
||||
api("commons-io", "commons-io", Versions.Libraries.Internal.apacheIO)
|
||||
implementation("com.dfsek.tectonic", "yaml", Versions.Libraries.tectonic)
|
||||
}
|
||||
|
||||
tasks.withType<Jar> {
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
+13
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
@@ -29,34 +29,34 @@ public class ManifestAddon implements BaseAddon {
|
||||
private final List<AddonInitializer> initializers;
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
|
||||
public ManifestAddon(AddonManifest manifest, List<AddonInitializer> initializers) {
|
||||
this.manifest = manifest;
|
||||
this.initializers = initializers;
|
||||
}
|
||||
|
||||
|
||||
public AddonManifest getManifest() {
|
||||
return manifest;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return manifest.getID();
|
||||
}
|
||||
|
||||
|
||||
public void initialize() {
|
||||
Injector<BaseAddon> addonInjector = Injector.get(this);
|
||||
addonInjector.addExplicitTarget(BaseAddon.class);
|
||||
|
||||
|
||||
Injector<Platform> platformInjector = Injector.get(platform);
|
||||
platformInjector.addExplicitTarget(Platform.class);
|
||||
|
||||
|
||||
logger.debug("Initializing addon {}", getID());
|
||||
|
||||
|
||||
initializers.forEach(initializer -> {
|
||||
Injector<Logger> loggerInjector = Injector.get(LoggerFactory.getLogger(initializer.getClass()));
|
||||
loggerInjector.addExplicitTarget(Logger.class);
|
||||
|
||||
|
||||
logger.debug("Invoking entry point {}", initializer.getClass());
|
||||
addonInjector.inject(initializer);
|
||||
platformInjector.inject(initializer);
|
||||
@@ -64,14 +64,14 @@ public class ManifestAddon implements BaseAddon {
|
||||
initializer.initialize();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<String, VersionRange> getDependencies() {
|
||||
public Map<String, VersionRange> dependencies() {
|
||||
return manifest.getDependencies();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Version getVersion() {
|
||||
public Version version() {
|
||||
return manifest.getVersion();
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
@@ -15,7 +15,7 @@ public class ManifestAddonClassLoader extends URLClassLoader {
|
||||
static {
|
||||
ClassLoader.registerAsParallelCapable();
|
||||
}
|
||||
|
||||
|
||||
public ManifestAddonClassLoader(URL[] urls, ClassLoader parent) {
|
||||
super(urls, parent);
|
||||
}
|
||||
+30
-30
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
@@ -44,34 +44,34 @@ import com.dfsek.terra.api.addon.bootstrap.BootstrapBaseAddon;
|
||||
public class ManifestAddonLoader implements BootstrapBaseAddon<ManifestAddon> {
|
||||
private static final Logger logger = LoggerFactory.getLogger(ManifestAddonLoader.class);
|
||||
private static final Version VERSION = Versions.getVersion(1, 0, 0);
|
||||
|
||||
|
||||
private final ConfigLoader manifestLoader = new ConfigLoader()
|
||||
.registerLoader(Version.class, new VersionLoader())
|
||||
.registerLoader(VersionRange.class, new VersionRangeLoader())
|
||||
.registerLoader(WebsiteConfig.class, WebsiteConfig::new);
|
||||
|
||||
.registerLoader(Version.class, new VersionLoader())
|
||||
.registerLoader(VersionRange.class, new VersionRangeLoader())
|
||||
.registerLoader(WebsiteConfig.class, WebsiteConfig::new);
|
||||
|
||||
public ManifestAddon loadAddon(Path addonPath, ClassLoader loader) {
|
||||
try(JarFile jar = new JarFile(addonPath.toFile())) {
|
||||
logger.debug("Loading addon from JAR {}", addonPath);
|
||||
|
||||
|
||||
JarEntry manifestEntry = jar.getJarEntry("terra.addon.yml");
|
||||
if(manifestEntry == null) {
|
||||
throw new ManifestNotPresentException("Addon " + addonPath + " does not contain addon manifest.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//noinspection NestedTryStatement
|
||||
try {
|
||||
AddonManifest manifest = manifestLoader.load(new AddonManifest(),
|
||||
new YamlConfiguration(jar.getInputStream(manifestEntry),
|
||||
"terra.addon.yml"));
|
||||
|
||||
new YamlConfiguration(jar.getInputStream(manifestEntry),
|
||||
"terra.addon.yml"));
|
||||
|
||||
logger.debug("Loading addon {}@{}", manifest.getID(), manifest.getVersion().getFormatted());
|
||||
|
||||
|
||||
if(manifest.getSchemaVersion() != 1) {
|
||||
throw new AddonException("Addon " + manifest.getID() + " has unknown schema version: " + manifest.getSchemaVersion());
|
||||
}
|
||||
|
||||
|
||||
List<AddonInitializer> initializers = manifest.getEntryPoints().stream().map(entryPoint -> {
|
||||
try {
|
||||
Object in = loader.loadClass(entryPoint).getConstructor().newInstance();
|
||||
@@ -87,9 +87,9 @@ public class ManifestAddonLoader implements BootstrapBaseAddon<ManifestAddon> {
|
||||
throw new AddonException(String.format("Entry point %s not found in JAR.", entryPoint), e);
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
|
||||
return new ManifestAddon(manifest, initializers);
|
||||
|
||||
|
||||
} catch(LoadException e) {
|
||||
throw new ManifestException("Failed to load addon manifest", e);
|
||||
}
|
||||
@@ -97,19 +97,19 @@ public class ManifestAddonLoader implements BootstrapBaseAddon<ManifestAddon> {
|
||||
throw new AddonException("Failed to load addon from JAR " + addonPath, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterable<ManifestAddon> loadAddons(Path addonsFolder, BootstrapAddonClassLoader parent) {
|
||||
logger.debug("Loading addons...");
|
||||
|
||||
|
||||
try(Stream<Path> files = Files.walk(addonsFolder, 1, FileVisitOption.FOLLOW_LINKS)) {
|
||||
List<Path> addons = files
|
||||
.filter(path -> path.toFile().isFile())
|
||||
.filter(path -> path.toFile().canRead())
|
||||
.filter(path -> !path.getFileName().startsWith(".")) // ignore hidden files.
|
||||
.filter(path -> path.toString().endsWith(".jar"))
|
||||
.toList();
|
||||
|
||||
.filter(path -> path.toFile().isFile())
|
||||
.filter(path -> path.toFile().canRead())
|
||||
.filter(path -> !path.getFileName().startsWith(".")) // ignore hidden files.
|
||||
.filter(path -> path.toString().endsWith(".jar"))
|
||||
.toList();
|
||||
|
||||
addons.stream().map(path -> {
|
||||
try {
|
||||
return path.toUri().toURL();
|
||||
@@ -117,22 +117,22 @@ public class ManifestAddonLoader implements BootstrapBaseAddon<ManifestAddon> {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}).forEach(parent::addURL);
|
||||
|
||||
|
||||
return addons.stream()
|
||||
.map(jar -> loadAddon(jar, parent))
|
||||
.collect(Collectors.toList());
|
||||
.map(jar -> loadAddon(jar, parent))
|
||||
.collect(Collectors.toList());
|
||||
} catch(IOException e) {
|
||||
throw new UncheckedIOException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return "MANIFEST";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Version getVersion() {
|
||||
public Version version() {
|
||||
return VERSION;
|
||||
}
|
||||
}
|
||||
+16
-16
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
@@ -24,60 +24,60 @@ import com.dfsek.terra.api.registry.key.StringIdentifiable;
|
||||
public class AddonManifest implements ConfigTemplate, StringIdentifiable {
|
||||
@Value("schema-version")
|
||||
private int schemaVersion;
|
||||
|
||||
|
||||
@Value("id")
|
||||
private String id;
|
||||
|
||||
|
||||
@Value("version")
|
||||
private Version version;
|
||||
|
||||
|
||||
@Value("license")
|
||||
private String license;
|
||||
|
||||
|
||||
@Value("contributors")
|
||||
@Default
|
||||
private List<String> contributors = Collections.emptyList();
|
||||
|
||||
|
||||
@Value("entrypoints")
|
||||
private List<String> entryPoints;
|
||||
|
||||
|
||||
@Value("depends")
|
||||
@Default
|
||||
private Map<String, VersionRange> dependencies = Collections.emptyMap();
|
||||
|
||||
|
||||
@Value("website")
|
||||
@Default
|
||||
private WebsiteConfig website;
|
||||
|
||||
|
||||
@Override
|
||||
public String getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
|
||||
public int getSchemaVersion() {
|
||||
return schemaVersion;
|
||||
}
|
||||
|
||||
|
||||
public Version getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
public List<String> getContributors() {
|
||||
return contributors;
|
||||
}
|
||||
|
||||
|
||||
public List<String> getEntryPoints() {
|
||||
return entryPoints;
|
||||
}
|
||||
|
||||
|
||||
public String getLicense() {
|
||||
return license;
|
||||
}
|
||||
|
||||
|
||||
public WebsiteConfig getWebsite() {
|
||||
return website;
|
||||
}
|
||||
|
||||
|
||||
public Map<String, VersionRange> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
@@ -14,25 +14,25 @@ import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
public class WebsiteConfig implements ObjectTemplate<WebsiteConfig> {
|
||||
@Value("issues")
|
||||
private String issues;
|
||||
|
||||
|
||||
@Value("source")
|
||||
private String source;
|
||||
|
||||
|
||||
@Value("docs")
|
||||
private String docs;
|
||||
|
||||
|
||||
public String getDocs() {
|
||||
return docs;
|
||||
}
|
||||
|
||||
|
||||
public String getIssues() {
|
||||
return issues;
|
||||
}
|
||||
|
||||
|
||||
public String getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public WebsiteConfig get() {
|
||||
return this;
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
@@ -13,11 +13,11 @@ import java.io.Serial;
|
||||
public class AddonException extends RuntimeException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -4201912399458420090L;
|
||||
|
||||
|
||||
public AddonException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public AddonException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
@@ -13,11 +13,11 @@ import java.io.Serial;
|
||||
public class ManifestException extends AddonException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -2458077663176544645L;
|
||||
|
||||
|
||||
public ManifestException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public ManifestException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2020-2021 Polyhedral Development
|
||||
* Copyright (c) 2020-2025 Polyhedral Development
|
||||
*
|
||||
* The Terra Core Addons are licensed under the terms of the MIT License. For more details,
|
||||
* reference the LICENSE file in this module's root directory.
|
||||
@@ -13,11 +13,11 @@ import java.io.Serial;
|
||||
public class ManifestNotPresentException extends ManifestException {
|
||||
@Serial
|
||||
private static final long serialVersionUID = -2116663180747013810L;
|
||||
|
||||
|
||||
public ManifestNotPresentException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
|
||||
public ManifestNotPresentException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
version = version("1.0.0")
|
||||
|
||||
dependencies {
|
||||
compileOnlyApi(project(":common:addons:addon-loader-manifest"))
|
||||
}
|
||||
+18
-18
@@ -21,26 +21,26 @@ public class BiomeQueryAPIAddon implements AddonInitializer {
|
||||
private Platform platform;
|
||||
@Inject
|
||||
private BaseAddon addon;
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
|
||||
|
||||
platform.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPostLoadEvent.class)
|
||||
.then(event -> {
|
||||
Collection<Biome> biomes = event
|
||||
.getPack()
|
||||
.getRegistry(Biome.class)
|
||||
.entries();
|
||||
|
||||
BiomeTagFlattener flattener = new BiomeTagFlattener(biomes
|
||||
.stream()
|
||||
.flatMap(biome -> biome.getTags().stream())
|
||||
.toList());
|
||||
|
||||
biomes.forEach(biome -> biome.getContext().put(BIOME_TAG_KEY, new BiomeTagHolder(biome, flattener)));
|
||||
})
|
||||
.global();
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPostLoadEvent.class)
|
||||
.then(event -> {
|
||||
Collection<Biome> biomes = event
|
||||
.getPack()
|
||||
.getRegistry(Biome.class)
|
||||
.entries();
|
||||
|
||||
BiomeTagFlattener flattener = new BiomeTagFlattener(biomes
|
||||
.stream()
|
||||
.flatMap(biome -> biome.getTags().stream())
|
||||
.toList());
|
||||
|
||||
biomes.forEach(biome -> biome.getContext().put(BIOME_TAG_KEY, new BiomeTagHolder(biome, flattener)));
|
||||
})
|
||||
.global();
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -10,7 +10,7 @@ public final class BiomeQueries {
|
||||
private BiomeQueries() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static Predicate<Biome> has(String tag) {
|
||||
return new SingleTagQuery(tag);
|
||||
}
|
||||
+3
-3
@@ -5,15 +5,15 @@ import java.util.List;
|
||||
|
||||
public class BiomeTagFlattener {
|
||||
private final List<String> tags;
|
||||
|
||||
|
||||
public BiomeTagFlattener(List<String> tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
|
||||
public int index(String tag) {
|
||||
return tags.indexOf(tag);
|
||||
}
|
||||
|
||||
|
||||
public int size() {
|
||||
return tags.size();
|
||||
}
|
||||
+3
-3
@@ -7,7 +7,7 @@ import com.dfsek.terra.api.world.biome.Biome;
|
||||
public class BiomeTagHolder implements Properties {
|
||||
private final boolean[] tags;
|
||||
private final BiomeTagFlattener flattener;
|
||||
|
||||
|
||||
public BiomeTagHolder(Biome biome, BiomeTagFlattener flattener) {
|
||||
this.tags = new boolean[flattener.size()];
|
||||
this.flattener = flattener;
|
||||
@@ -15,11 +15,11 @@ public class BiomeTagHolder implements Properties {
|
||||
tags[flattener.index(tag)] = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
boolean get(int index) {
|
||||
return tags[index];
|
||||
}
|
||||
|
||||
|
||||
public BiomeTagFlattener getFlattener() {
|
||||
return flattener;
|
||||
}
|
||||
+9
-9
@@ -9,23 +9,23 @@ import com.dfsek.terra.api.world.biome.Biome;
|
||||
public class SingleTagQuery implements Predicate<Biome> {
|
||||
private final String tag;
|
||||
private int tagIndex = -1;
|
||||
|
||||
|
||||
public SingleTagQuery(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean test(Biome biome) {
|
||||
if(tagIndex < 0) {
|
||||
tagIndex = biome
|
||||
.getContext()
|
||||
.get(BiomeQueryAPIAddon.BIOME_TAG_KEY)
|
||||
.getFlattener()
|
||||
.index(tag);
|
||||
}
|
||||
return biome
|
||||
.getContext()
|
||||
.get(BiomeQueryAPIAddon.BIOME_TAG_KEY)
|
||||
.get(tagIndex);
|
||||
.getFlattener()
|
||||
.index(tag);
|
||||
}
|
||||
return biome
|
||||
.getContext()
|
||||
.get(BiomeQueryAPIAddon.BIOME_TAG_KEY)
|
||||
.get(tagIndex);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
schema-version: 1
|
||||
contributors:
|
||||
- Terra contributors
|
||||
id: biome-query-api
|
||||
id: api-biome-query
|
||||
version: @VERSION@
|
||||
entrypoints:
|
||||
- "com.dfsek.terra.addons.biome.query.BiomeQueryAPIAddon"
|
||||
@@ -0,0 +1,7 @@
|
||||
version = version("1.1.0")
|
||||
|
||||
dependencies {
|
||||
compileOnlyApi(project(":common:addons:addon-loader-manifest"))
|
||||
|
||||
|
||||
}
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
package com.dfsek.terra.addons.image;
|
||||
|
||||
import com.dfsek.seismic.type.sampler.Sampler;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
|
||||
import com.dfsek.terra.addons.image.config.ColorLoader;
|
||||
import com.dfsek.terra.addons.image.config.ColorLoader.ColorString;
|
||||
import com.dfsek.terra.addons.image.config.ImageLibraryPackConfigTemplate;
|
||||
import com.dfsek.terra.addons.image.config.colorsampler.ConstantColorSamplerTemplate;
|
||||
import com.dfsek.terra.addons.image.config.colorsampler.image.SingleImageColorSamplerTemplate;
|
||||
import com.dfsek.terra.addons.image.config.colorsampler.image.TileImageColorSamplerTemplate;
|
||||
import com.dfsek.terra.addons.image.config.colorsampler.mutate.RotateColorSamplerTemplate;
|
||||
import com.dfsek.terra.addons.image.config.colorsampler.mutate.TranslateColorSamplerTemplate;
|
||||
import com.dfsek.terra.addons.image.config.image.ImageTemplate;
|
||||
import com.dfsek.terra.addons.image.config.image.StitchedImageTemplate;
|
||||
import com.dfsek.terra.addons.image.config.sampler.ChannelSamplerTemplate;
|
||||
import com.dfsek.terra.addons.image.config.sampler.DistanceTransformSamplerTemplate;
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
import com.dfsek.terra.addons.image.operator.DistanceTransform;
|
||||
import com.dfsek.terra.addons.manifest.api.AddonInitializer;
|
||||
import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.addon.BaseAddon;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.event.events.config.pack.ConfigPackPreLoadEvent;
|
||||
import com.dfsek.terra.api.event.functional.FunctionalEventHandler;
|
||||
import com.dfsek.terra.api.inject.annotations.Inject;
|
||||
import com.dfsek.terra.api.registry.CheckedRegistry;
|
||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
||||
|
||||
|
||||
public class ImageLibraryAddon implements AddonInitializer {
|
||||
|
||||
public static final TypeKey<Supplier<ObjectTemplate<Image>>> IMAGE_REGISTRY_KEY = new TypeKey<>() {
|
||||
};
|
||||
|
||||
public static final TypeKey<Supplier<ObjectTemplate<ColorSampler>>> COLOR_PICKER_REGISTRY_KEY = new TypeKey<>() {
|
||||
};
|
||||
|
||||
public static final TypeKey<Supplier<ObjectTemplate<Sampler>>> NOISE_SAMPLER_TOKEN = new TypeKey<>() {
|
||||
};
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
@Inject
|
||||
private BaseAddon addon;
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
platform.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPreLoadEvent.class)
|
||||
.priority(10)
|
||||
.then(event -> {
|
||||
ImageLibraryPackConfigTemplate config = event.loadTemplate(new ImageLibraryPackConfigTemplate());
|
||||
event.getPack().getContext().put(config);
|
||||
})
|
||||
.then(event -> {
|
||||
ConfigPack pack = event.getPack();
|
||||
CheckedRegistry<Supplier<ObjectTemplate<Image>>> imageRegistry = pack.getOrCreateRegistry(IMAGE_REGISTRY_KEY);
|
||||
imageRegistry.register(addon.key("BITMAP"), () -> new ImageTemplate(pack));
|
||||
imageRegistry.register(addon.key("STITCHED_BITMAP"), () -> new StitchedImageTemplate(pack));
|
||||
})
|
||||
.then(event -> {
|
||||
event.getPack()
|
||||
.applyLoader(DistanceTransform.CostFunction.class,
|
||||
(type, o, loader, depthTracker) -> DistanceTransform.CostFunction.valueOf((String) o))
|
||||
.applyLoader(DistanceTransform.Normalization.class,
|
||||
(type, o, loader, depthTracker) -> DistanceTransform.Normalization.valueOf((String) o))
|
||||
.applyLoader(ColorString.class, new ColorLoader());
|
||||
|
||||
CheckedRegistry<Supplier<ObjectTemplate<Sampler>>> noiseRegistry = event.getPack().getOrCreateRegistry(
|
||||
NOISE_SAMPLER_TOKEN);
|
||||
noiseRegistry.register(addon.key("DISTANCE_TRANSFORM"), DistanceTransformSamplerTemplate::new);
|
||||
noiseRegistry.register(addon.key("CHANNEL"), ChannelSamplerTemplate::new);
|
||||
})
|
||||
.then(event -> {
|
||||
CheckedRegistry<Supplier<ObjectTemplate<ColorSampler>>> colorSamplerRegistry = event.getPack().getOrCreateRegistry(
|
||||
COLOR_PICKER_REGISTRY_KEY);
|
||||
colorSamplerRegistry.register(addon.key("SINGLE_IMAGE"), SingleImageColorSamplerTemplate::new);
|
||||
colorSamplerRegistry.register(addon.key("TILED_IMAGE"), TileImageColorSamplerTemplate::new);
|
||||
colorSamplerRegistry.register(addon.key("COLOR"), ConstantColorSamplerTemplate::new);
|
||||
colorSamplerRegistry.register(addon.key("ROTATE"), RotateColorSamplerTemplate::new);
|
||||
colorSamplerRegistry.register(addon.key("TRANSLATE"), TranslateColorSamplerTemplate::new);
|
||||
});
|
||||
}
|
||||
}
|
||||
+2
-1
@@ -2,10 +2,11 @@ package com.dfsek.terra.addons.image.colorsampler;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface ColorSampler {
|
||||
|
||||
|
||||
/**
|
||||
* @param x World x coordinate
|
||||
* @param z World z coordinate
|
||||
*
|
||||
* @return Integer representing a web color
|
||||
*/
|
||||
int apply(int x, int z);
|
||||
+6
-6
@@ -1,24 +1,24 @@
|
||||
package com.dfsek.terra.addons.image.colorsampler.image;
|
||||
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
|
||||
import com.dfsek.terra.addons.image.colorsampler.image.transform.ImageTransformation;
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
|
||||
|
||||
public class SingleImageColorSampler implements ColorSampler {
|
||||
|
||||
|
||||
private final Image image;
|
||||
|
||||
|
||||
private final ColorSampler fallback;
|
||||
|
||||
|
||||
private final ImageTransformation transformation;
|
||||
|
||||
|
||||
public SingleImageColorSampler(Image image, ColorSampler fallback, ImageTransformation transformation) {
|
||||
this.image = image;
|
||||
this.fallback = fallback;
|
||||
this.transformation = transformation;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int apply(int x, int z) {
|
||||
var nx = transformation.transformX(image, x);
|
||||
+6
-8
@@ -1,27 +1,25 @@
|
||||
package com.dfsek.terra.addons.image.colorsampler.image;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
|
||||
import com.dfsek.terra.addons.image.colorsampler.image.transform.ImageTransformation;
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
|
||||
|
||||
public class TileImageColorSampler implements ColorSampler {
|
||||
|
||||
|
||||
private final Image image;
|
||||
|
||||
|
||||
private final ImageTransformation transformation;
|
||||
|
||||
|
||||
public TileImageColorSampler(Image image, ImageTransformation transformation) {
|
||||
this.image = image;
|
||||
this.transformation = transformation;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int apply(int x, int z) {
|
||||
x = transformation.transformX(image, x);
|
||||
z = transformation.transformZ(image, z);
|
||||
return image.getRGB(FastMath.floorMod(x, image.getWidth()), FastMath.floorMod(z, image.getHeight()));
|
||||
return image.getRGB(Math.floorMod(x, image.getWidth()), Math.floorMod(z, image.getHeight()));
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -4,13 +4,13 @@ import com.dfsek.terra.addons.image.image.Image;
|
||||
|
||||
|
||||
public enum Alignment implements ImageTransformation {
|
||||
|
||||
|
||||
NONE() {
|
||||
@Override
|
||||
public int transformX(Image image, int x) {
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int transformZ(Image image, int z) {
|
||||
return z;
|
||||
@@ -21,7 +21,7 @@ public enum Alignment implements ImageTransformation {
|
||||
public int transformX(Image image, int x) {
|
||||
return x + image.getWidth() / 2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int transformZ(Image image, int z) {
|
||||
return z + image.getHeight() / 2;
|
||||
+2
-2
@@ -4,8 +4,8 @@ import com.dfsek.terra.addons.image.image.Image;
|
||||
|
||||
|
||||
public interface ImageTransformation {
|
||||
|
||||
|
||||
int transformX(Image image, int x);
|
||||
|
||||
|
||||
int transformZ(Image image, int z);
|
||||
}
|
||||
+19
-18
@@ -1,37 +1,38 @@
|
||||
package com.dfsek.terra.addons.image.colorsampler.mutate;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
import com.dfsek.seismic.math.trigonometry.TrigonometryFunctions;
|
||||
|
||||
import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
|
||||
|
||||
|
||||
public class RotateColorSampler implements ColorSampler {
|
||||
|
||||
|
||||
private final ColorSampler sampler;
|
||||
|
||||
|
||||
private final double radians;
|
||||
|
||||
|
||||
private final RotationMethod rotationMethod;
|
||||
|
||||
|
||||
public RotateColorSampler(ColorSampler sampler, double degrees) {
|
||||
this.sampler = sampler;
|
||||
|
||||
|
||||
double normalizedDegrees = degrees % 360.0;
|
||||
if (normalizedDegrees < 0) normalizedDegrees += 360.0;
|
||||
|
||||
if (normalizedDegrees == 0.0)
|
||||
if(normalizedDegrees < 0) normalizedDegrees += 360.0;
|
||||
|
||||
if(normalizedDegrees == 0.0)
|
||||
rotationMethod = RotationMethod.DEG_0;
|
||||
else if (normalizedDegrees == 90.0)
|
||||
else if(normalizedDegrees == 90.0)
|
||||
rotationMethod = RotationMethod.DEG_90;
|
||||
else if (normalizedDegrees == 180.0)
|
||||
else if(normalizedDegrees == 180.0)
|
||||
rotationMethod = RotationMethod.DEG_180;
|
||||
else if (normalizedDegrees == 270.0)
|
||||
else if(normalizedDegrees == 270.0)
|
||||
rotationMethod = RotationMethod.DEG_270;
|
||||
else
|
||||
rotationMethod = RotationMethod.RAD_ANY;
|
||||
|
||||
this.radians = FastMath.toRadians(degrees);
|
||||
|
||||
this.radians = Math.toRadians(degrees);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int apply(int x, int z) {
|
||||
int rx = switch(rotationMethod) {
|
||||
@@ -39,18 +40,18 @@ public class RotateColorSampler implements ColorSampler {
|
||||
case DEG_90 -> -z;
|
||||
case DEG_180 -> -x;
|
||||
case DEG_270 -> z;
|
||||
case RAD_ANY -> (int) (x * FastMath.cos(radians) - z * FastMath.sin(radians));
|
||||
case RAD_ANY -> (int) (x * TrigonometryFunctions.cos(radians) - z * TrigonometryFunctions.sin(radians));
|
||||
};
|
||||
int rz = switch(rotationMethod) {
|
||||
case DEG_0 -> z;
|
||||
case DEG_90 -> x;
|
||||
case DEG_180 -> -z;
|
||||
case DEG_270 -> -x;
|
||||
case RAD_ANY -> (int) (z * FastMath.cos(radians) + x * FastMath.sin(radians));
|
||||
case RAD_ANY -> (int) (z * TrigonometryFunctions.cos(radians) + x * TrigonometryFunctions.sin(radians));
|
||||
};
|
||||
return sampler.apply(rx, rz);
|
||||
}
|
||||
|
||||
|
||||
private enum RotationMethod {
|
||||
DEG_0,
|
||||
DEG_90,
|
||||
+3
-3
@@ -4,16 +4,16 @@ import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
|
||||
|
||||
|
||||
public class TranslateColorSampler implements ColorSampler {
|
||||
|
||||
|
||||
private final ColorSampler sampler;
|
||||
private final int translateX, translateZ;
|
||||
|
||||
|
||||
public TranslateColorSampler(ColorSampler sampler, int translateX, int translateZ) {
|
||||
this.sampler = sampler;
|
||||
this.translateX = translateX;
|
||||
this.translateZ = translateZ;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int apply(int x, int z) {
|
||||
return sampler.apply(x - translateX, z - translateZ);
|
||||
+26
-26
@@ -13,80 +13,80 @@ import com.dfsek.terra.addons.image.util.ColorUtil;
|
||||
|
||||
|
||||
public class ColorLoader implements TypeLoader<ColorString> {
|
||||
|
||||
|
||||
@Override
|
||||
public ColorString load(@NotNull AnnotatedType annotatedType, @NotNull Object o, @NotNull ConfigLoader configLoader,
|
||||
DepthTracker depthTracker) throws LoadException {
|
||||
return new ColorString((String) o);
|
||||
}
|
||||
|
||||
|
||||
public static class ColorString {
|
||||
|
||||
|
||||
private final int argb;
|
||||
|
||||
|
||||
public ColorString(String string) throws IllegalArgumentException {
|
||||
this.argb = parse(string);
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return argb;
|
||||
}
|
||||
|
||||
|
||||
private static int parse(String string) throws IllegalArgumentException {
|
||||
if (string.length() == 0)
|
||||
if(string.length() == 0)
|
||||
throw new IllegalArgumentException("Empty string cannot be parsed as a valid color");
|
||||
|
||||
|
||||
String[] split = string.split(",");
|
||||
|
||||
if (split.length == 1)
|
||||
|
||||
if(split.length == 1)
|
||||
return parseHex(string);
|
||||
else if (split.length == 3)
|
||||
else if(split.length == 3)
|
||||
return parseChannels("255", split[0], split[1], split[2]);
|
||||
else if (split.length == 4)
|
||||
else if(split.length == 4)
|
||||
return parseChannels(split[0], split[1], split[2], split[3]);
|
||||
else
|
||||
throw new IllegalArgumentException("Invalid channels provided, required format RED,GREEN,BLUE or ALPHA,RED,GREEN,BLUE");
|
||||
}
|
||||
|
||||
|
||||
private static int parseHex(String hex) throws IllegalArgumentException {
|
||||
if (hex.startsWith("#"))
|
||||
if(hex.startsWith("#"))
|
||||
hex = hex.substring(1);
|
||||
|
||||
|
||||
int alpha = 255;
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
|
||||
|
||||
try {
|
||||
if(hex.length() == 8) {
|
||||
alpha = Integer.parseInt(hex.substring(0, 2), 16);
|
||||
hex = hex.substring(2);
|
||||
}
|
||||
|
||||
|
||||
if(hex.length() != 6)
|
||||
throw new IllegalArgumentException("Invalid color channels, required format AARRGGBB or RRGGBB");
|
||||
|
||||
|
||||
red = Integer.parseInt(hex.substring(0, 2), 16);
|
||||
green = Integer.parseInt(hex.substring(2, 4), 16);
|
||||
blue = Integer.parseInt(hex.substring(4, 6), 16);
|
||||
|
||||
|
||||
return ColorUtil.argbValidated(alpha, red, green, blue);
|
||||
} catch (NumberFormatException e) {
|
||||
} catch(NumberFormatException e) {
|
||||
throw new IllegalArgumentException("Failed to parse hex color", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static int parseChannels(String alpha, String red, String green, String blue) throws IllegalArgumentException {
|
||||
try {
|
||||
int a = Integer.decode(alpha);
|
||||
int r = Integer.decode(red);
|
||||
int g = Integer.decode(green);
|
||||
int b = Integer.decode(blue);
|
||||
|
||||
|
||||
return ColorUtil.argbValidated(a, r, g, b);
|
||||
} catch (NumberFormatException e) {
|
||||
} catch(NumberFormatException e) {
|
||||
throw new IllegalArgumentException("Invalid channel value", e);
|
||||
}
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return argb;
|
||||
}
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package com.dfsek.terra.addons.image.config;
|
||||
|
||||
import com.dfsek.tectonic.api.config.template.ConfigTemplate;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Description;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
|
||||
|
||||
public class ImageLibraryPackConfigTemplate implements ConfigTemplate, Properties {
|
||||
// TODO - These would be better as plugin wide config parameters in config.yml
|
||||
|
||||
@Value("images.cache.load-on-use")
|
||||
@Description("If set to true, images will load into memory upon use rather than on pack load.")
|
||||
@Default
|
||||
private boolean loadOnUse = false;
|
||||
|
||||
@Value("images.cache.timeout")
|
||||
@Description("How many seconds to keep images loaded in the image cache for. " +
|
||||
"If set to a number greater than 0, images will be removed from memory if not used after the timeout, otherwise images " +
|
||||
"will stay loaded in memory. " +
|
||||
"Setting the timeout to greater than 0 will trade decreased memory consumption when not performing any image reads for a" +
|
||||
" period of time for extra processing time required to perform cache lookups.")
|
||||
@Default
|
||||
private int cacheTimeout = 0;
|
||||
|
||||
public boolean loadOnUse() {
|
||||
return loadOnUse;
|
||||
}
|
||||
|
||||
public boolean unloadOnTimeout() {
|
||||
return cacheTimeout > 0;
|
||||
}
|
||||
|
||||
public int getCacheTimeout() {
|
||||
return cacheTimeout;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -8,10 +8,10 @@ import com.dfsek.terra.addons.image.config.ColorLoader.ColorString;
|
||||
|
||||
|
||||
public class ConstantColorSamplerTemplate implements ObjectTemplate<ColorSampler> {
|
||||
|
||||
|
||||
@Value("color")
|
||||
private ColorString color;
|
||||
|
||||
|
||||
@Override
|
||||
public ColorSampler get() {
|
||||
return ((x, z) -> color.getColor());
|
||||
+4
-4
@@ -4,18 +4,18 @@ import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
|
||||
import com.dfsek.terra.addons.image.colorsampler.image.transform.Alignment;
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
|
||||
|
||||
public abstract class ImageColorSamplerTemplate implements ObjectTemplate<ColorSampler> {
|
||||
|
||||
|
||||
@Value("image")
|
||||
protected Image image;
|
||||
|
||||
|
||||
@Value("align")
|
||||
@Default
|
||||
protected Alignment alignment = Alignment.NONE;
|
||||
|
||||
|
||||
}
|
||||
+1
-1
@@ -7,7 +7,7 @@ import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
|
||||
|
||||
|
||||
public abstract class MutateColorSamplerTemplate implements ObjectTemplate<ColorSampler> {
|
||||
|
||||
|
||||
@Value("color-sampler")
|
||||
protected ColorSampler sampler;
|
||||
}
|
||||
+2
-2
@@ -7,10 +7,10 @@ import com.dfsek.terra.addons.image.colorsampler.mutate.RotateColorSampler;
|
||||
|
||||
|
||||
public class RotateColorSamplerTemplate extends MutateColorSamplerTemplate {
|
||||
|
||||
|
||||
@Value("angle")
|
||||
private double degrees;
|
||||
|
||||
|
||||
@Override
|
||||
public ColorSampler get() {
|
||||
return new RotateColorSampler(sampler, degrees);
|
||||
+4
-4
@@ -7,15 +7,15 @@ import com.dfsek.terra.addons.image.colorsampler.mutate.TranslateColorSampler;
|
||||
|
||||
|
||||
public class TranslateColorSamplerTemplate extends MutateColorSamplerTemplate {
|
||||
|
||||
|
||||
@Value("x")
|
||||
private int translateX;
|
||||
|
||||
|
||||
@Value("z")
|
||||
private int translateZ;
|
||||
|
||||
|
||||
@Override
|
||||
public ColorSampler get() {
|
||||
return new TranslateColorSampler(sampler, translateX, translateZ);
|
||||
return new TranslateColorSampler(sampler, translateX, translateZ);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -6,9 +6,9 @@ import com.dfsek.terra.addons.image.converter.mapping.ColorMapping;
|
||||
|
||||
|
||||
public abstract class ClosestColorConverterTemplate<T> implements ColorConverterTemplate<T> {
|
||||
|
||||
|
||||
protected abstract ColorMapping<T> getMapping();
|
||||
|
||||
|
||||
@Override
|
||||
public ColorConverter<T> get() {
|
||||
return new ClosestMatchColorConverter<T>(getMapping().get());
|
||||
+4
-4
@@ -6,13 +6,13 @@ import com.dfsek.terra.addons.image.converter.mapping.ColorMapping;
|
||||
|
||||
|
||||
public abstract class ExactColorConverterTemplate<T> implements ColorConverterTemplate<T> {
|
||||
|
||||
|
||||
protected abstract ColorMapping<T> getMapping();
|
||||
|
||||
|
||||
protected abstract T getFallback();
|
||||
|
||||
|
||||
protected abstract boolean ignoreAlpha();
|
||||
|
||||
|
||||
@Override
|
||||
public ColorConverter<T> get() {
|
||||
return new ExactColorConverter<T>(getMapping().get(), getFallback(), ignoreAlpha());
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
package com.dfsek.terra.addons.image.config.image;
|
||||
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
import com.github.benmanes.caffeine.cache.LoadingCache;
|
||||
import com.github.benmanes.caffeine.cache.Scheduler;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.dfsek.terra.addons.image.config.ImageLibraryPackConfigTemplate;
|
||||
import com.dfsek.terra.addons.image.image.BufferedImageWrapper;
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
import com.dfsek.terra.addons.image.image.SuppliedImage;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.properties.Properties;
|
||||
import com.dfsek.terra.api.util.generic.Memo;
|
||||
|
||||
import static com.dfsek.terra.api.util.cache.CacheUtils.CACHE_EXECUTOR;
|
||||
|
||||
|
||||
/*
|
||||
* Cache prevents configs from loading the same image multiple times into memory
|
||||
*/
|
||||
record ImageCache(LoadingCache<String, Image> cache) implements Properties {
|
||||
public static Image load(String path, ConfigPack pack) throws IOException {
|
||||
ImageLibraryPackConfigTemplate config = pack.getContext().get(ImageLibraryPackConfigTemplate.class);
|
||||
ImageCache images;
|
||||
if(!pack.getContext().has(ImageCache.class)) {
|
||||
var cacheBuilder = Caffeine.newBuilder().executor(CACHE_EXECUTOR).scheduler(Scheduler.systemScheduler());
|
||||
if(config.unloadOnTimeout()) cacheBuilder.expireAfterAccess(config.getCacheTimeout(), TimeUnit.SECONDS);
|
||||
images = new ImageCache(cacheBuilder.build(s -> loadImage(s, pack.getRootPath())));
|
||||
pack.getContext().put(images);
|
||||
} else images = pack.getContext().get(ImageCache.class);
|
||||
|
||||
if(config.loadOnUse()) {
|
||||
if(config.unloadOnTimeout()) { // Grab directly from cache if images are to unload on timeout
|
||||
return new SuppliedImage(() -> images.cache.get(path));
|
||||
} else {
|
||||
// If images do not time out, image can be lazily loaded once instead of performing cache lookups for each image operation
|
||||
Memo<Image> lazyImage = Memo.lazy(() -> images.cache.get(path));
|
||||
return new SuppliedImage(lazyImage::value);
|
||||
}
|
||||
}
|
||||
|
||||
return images.cache.get(path);
|
||||
}
|
||||
|
||||
private static Image loadImage(String path, Path directory) throws IOException {
|
||||
InputStream is = Files.newInputStream(directory.resolve(path));
|
||||
return new BufferedImageWrapper(ImageIO.read(is));
|
||||
}
|
||||
}
|
||||
+6
-11
@@ -7,27 +7,22 @@ import java.io.IOException;
|
||||
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.config.Loader;
|
||||
|
||||
|
||||
public class ImageTemplate implements ObjectTemplate<Image> {
|
||||
|
||||
|
||||
private final ConfigPack pack;
|
||||
@Value("path")
|
||||
private String path;
|
||||
|
||||
private final Loader files;
|
||||
|
||||
private final ConfigPack pack;
|
||||
|
||||
public ImageTemplate(Loader files, ConfigPack pack) {
|
||||
this.files = files;
|
||||
|
||||
public ImageTemplate(ConfigPack pack) {
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Image get() {
|
||||
try {
|
||||
return ImageCache.load(path, pack, files);
|
||||
return ImageCache.load(path, pack);
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
+6
-14
@@ -11,40 +11,32 @@ import java.io.IOException;
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
import com.dfsek.terra.addons.image.image.StitchedImage;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.config.Loader;
|
||||
|
||||
|
||||
public class StitchedImageTemplate implements ObjectTemplate<Image>, ValidatedConfigTemplate {
|
||||
|
||||
private final ConfigPack pack;
|
||||
@Value("path-format")
|
||||
private String path;
|
||||
|
||||
@Value("rows")
|
||||
private int rows;
|
||||
|
||||
@Value("columns")
|
||||
private int cols;
|
||||
|
||||
@Value("zero-indexed")
|
||||
@Default
|
||||
private boolean zeroIndexed = false;
|
||||
|
||||
private final Loader files;
|
||||
|
||||
private final ConfigPack pack;
|
||||
|
||||
public StitchedImageTemplate(Loader files, ConfigPack pack) {
|
||||
this.files = files;
|
||||
public StitchedImageTemplate(ConfigPack pack) {
|
||||
this.pack = pack;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Image get() {
|
||||
Image[][] grid = new Image[rows][cols];
|
||||
for(int i = 0; i < rows; i++) {
|
||||
for(int j = 0; j < cols; j++) {
|
||||
try {
|
||||
grid[i][j] = ImageCache.load(getFormattedPath(i, j), pack, files);
|
||||
grid[i][j] = ImageCache.load(getFormattedPath(i, j), pack);
|
||||
} catch(IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@@ -52,9 +44,9 @@ public class StitchedImageTemplate implements ObjectTemplate<Image>, ValidatedCo
|
||||
}
|
||||
return new StitchedImage(grid, zeroIndexed);
|
||||
}
|
||||
|
||||
|
||||
private String getFormattedPath(int row, int column) {
|
||||
if (!zeroIndexed) {
|
||||
if(!zeroIndexed) {
|
||||
row++;
|
||||
column++;
|
||||
}
|
||||
+11
-11
@@ -1,30 +1,30 @@
|
||||
package com.dfsek.terra.addons.image.config.noisesampler;
|
||||
package com.dfsek.terra.addons.image.config.sampler;
|
||||
|
||||
import com.dfsek.seismic.type.sampler.Sampler;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
|
||||
import com.dfsek.terra.addons.image.noisesampler.ChannelNoiseSampler;
|
||||
import com.dfsek.terra.addons.image.sampler.ChannelSampler;
|
||||
import com.dfsek.terra.addons.image.util.ColorUtil.Channel;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
|
||||
public class ChannelNoiseSamplerTemplate implements ObjectTemplate<NoiseSampler> {
|
||||
|
||||
public class ChannelSamplerTemplate implements ObjectTemplate<Sampler> {
|
||||
|
||||
@Value("color-sampler")
|
||||
private ColorSampler colorSampler;
|
||||
|
||||
|
||||
@Value("channel")
|
||||
private Channel channel;
|
||||
|
||||
|
||||
/*
|
||||
* If the channel should be normalized to range [-1, 1] or not
|
||||
*/
|
||||
@Value("normalize")
|
||||
@Default
|
||||
private boolean normalize = true;
|
||||
|
||||
|
||||
/*
|
||||
* Whether to multiply color channels by the alpha channel or not. If users
|
||||
* are expecting pixel transparency to reduce the output value then this should
|
||||
@@ -33,9 +33,9 @@ public class ChannelNoiseSamplerTemplate implements ObjectTemplate<NoiseSampler>
|
||||
@Value("premultiply")
|
||||
@Default
|
||||
private boolean premultiply = false;
|
||||
|
||||
|
||||
@Override
|
||||
public NoiseSampler get() {
|
||||
return new ChannelNoiseSampler(colorSampler, channel, normalize, premultiply);
|
||||
public Sampler get() {
|
||||
return new ChannelSampler(colorSampler, channel, normalize, premultiply);
|
||||
}
|
||||
}
|
||||
+14
-13
@@ -1,5 +1,6 @@
|
||||
package com.dfsek.terra.addons.image.config.noisesampler;
|
||||
package com.dfsek.terra.addons.image.config.sampler;
|
||||
|
||||
import com.dfsek.seismic.type.sampler.Sampler;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Default;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
@@ -9,14 +10,13 @@ import com.dfsek.terra.addons.image.operator.DistanceTransform;
|
||||
import com.dfsek.terra.addons.image.operator.DistanceTransform.CostFunction;
|
||||
import com.dfsek.terra.addons.image.operator.DistanceTransform.Normalization;
|
||||
import com.dfsek.terra.addons.image.util.ColorUtil.Channel;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
|
||||
public class DistanceTransformNoiseSamplerTemplate implements ObjectTemplate<NoiseSampler> {
|
||||
|
||||
public class DistanceTransformSamplerTemplate implements ObjectTemplate<Sampler> {
|
||||
|
||||
@Value("image")
|
||||
private Image image;
|
||||
|
||||
|
||||
/**
|
||||
* The threshold value applied to the channel specified in the 'channel' parameter that splits
|
||||
* the image into a binary image. This parameter is only used for cost functions that utilize
|
||||
@@ -25,7 +25,7 @@ public class DistanceTransformNoiseSamplerTemplate implements ObjectTemplate<Noi
|
||||
@Value("threshold")
|
||||
@Default
|
||||
private int threshold = 127;
|
||||
|
||||
|
||||
/**
|
||||
* If set to true, distances calculated will be clamped to stay above the largest
|
||||
* distance calculated on the edges of the image. This ensures output values do not
|
||||
@@ -37,14 +37,14 @@ public class DistanceTransformNoiseSamplerTemplate implements ObjectTemplate<Noi
|
||||
@Value("clamp-to-max-edge")
|
||||
@Default
|
||||
private boolean clampToEdge = false;
|
||||
|
||||
|
||||
/**
|
||||
* The target channel to run distance calculations on.
|
||||
*/
|
||||
@Value("channel")
|
||||
@Default
|
||||
private Channel channel = Channel.GRAYSCALE;
|
||||
|
||||
|
||||
/**
|
||||
* The method of image processing applied to the specified image prior to calculating
|
||||
* distances.
|
||||
@@ -52,23 +52,24 @@ public class DistanceTransformNoiseSamplerTemplate implements ObjectTemplate<Noi
|
||||
@Value("cost-function")
|
||||
@Default
|
||||
private CostFunction costFunction = CostFunction.Channel;
|
||||
|
||||
|
||||
/**
|
||||
* Inverts the resulting binary image that may be used as a cost function.
|
||||
*/
|
||||
@Value("invert-threshold")
|
||||
@Default
|
||||
private boolean invertThreshold = false;
|
||||
|
||||
|
||||
/**
|
||||
* How the final distance calculation should be redistributed.
|
||||
*/
|
||||
@Value("normalization")
|
||||
@Default
|
||||
private Normalization normalization = Normalization.None;
|
||||
|
||||
|
||||
@Override
|
||||
public NoiseSampler get() {
|
||||
return new DistanceTransform.Noise(new DistanceTransform(image, channel, threshold, clampToEdge, costFunction, invertThreshold), normalization);
|
||||
public Sampler get() {
|
||||
return new DistanceTransform.Noise(new DistanceTransform(image, channel, threshold, clampToEdge, costFunction, invertThreshold),
|
||||
normalization);
|
||||
}
|
||||
}
|
||||
+1
@@ -4,6 +4,7 @@ import java.util.Map;
|
||||
|
||||
import com.dfsek.terra.addons.image.util.ColorUtil;
|
||||
|
||||
|
||||
public class ClosestMatchColorConverter<T> implements ColorConverter<T> {
|
||||
|
||||
private final Map<Integer, T> map;
|
||||
+2
-2
@@ -1,8 +1,8 @@
|
||||
package com.dfsek.terra.addons.image.converter;
|
||||
|
||||
public interface ColorConverter<T> {
|
||||
|
||||
|
||||
T apply(int color);
|
||||
|
||||
|
||||
Iterable<T> getEntries();
|
||||
}
|
||||
+7
-7
@@ -10,29 +10,29 @@ import com.dfsek.terra.addons.image.util.MapUtil;
|
||||
|
||||
public class ExactColorConverter<T> implements ColorConverter<T> {
|
||||
private final Map<Integer, T> map;
|
||||
|
||||
|
||||
private final T fallback;
|
||||
|
||||
|
||||
private final boolean ignoreAlpha;
|
||||
|
||||
|
||||
public ExactColorConverter(Map<Integer, T> map, T fallback, boolean ignoreAlpha) {
|
||||
if (ignoreAlpha) {
|
||||
if(ignoreAlpha) {
|
||||
map = MapUtil.mapKeys(map, ColorUtil::zeroAlpha);
|
||||
}
|
||||
this.map = map;
|
||||
this.fallback = fallback;
|
||||
this.ignoreAlpha = ignoreAlpha;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public T apply(int color) {
|
||||
if (ignoreAlpha) {
|
||||
if(ignoreAlpha) {
|
||||
color = ColorUtil.zeroAlpha(color);
|
||||
}
|
||||
T lookup = map.get(color);
|
||||
return lookup != null ? lookup : fallback;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterable<T> getEntries() {
|
||||
Set<T> entries = new HashSet<>(map.values());
|
||||
+6
-5
@@ -12,16 +12,16 @@ import com.dfsek.terra.api.world.biome.Biome;
|
||||
|
||||
|
||||
public class BiomeDefinedColorMapping<T> implements ColorMapping<T> {
|
||||
|
||||
|
||||
Registry<Biome> biomeRegistry;
|
||||
|
||||
|
||||
Function<Biome, T> converter;
|
||||
|
||||
|
||||
public BiomeDefinedColorMapping(Registry<Biome> biomeRegistry, Function<Biome, T> converter) {
|
||||
this.biomeRegistry = biomeRegistry;
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Map<Integer, T> get() {
|
||||
Map<Biome, Integer> colorMap = new HashSet<>(biomeRegistry.entries()).stream().collect(Collectors.toMap(b -> b, Biome::getColor));
|
||||
@@ -30,7 +30,8 @@ public class BiomeDefinedColorMapping<T> implements ColorMapping<T> {
|
||||
if(!output.containsKey(color)) {
|
||||
output.put(color, biome);
|
||||
} else {
|
||||
throw new IllegalArgumentException(String.format("Biome %s has same color as %s: %x", biome.getID(), output.get(color).getID(), color));
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Biome %s has same color as %s: %x", biome.getID(), output.get(color).getID(), color));
|
||||
}
|
||||
}));
|
||||
return output.entrySet().stream().collect(Collectors.toMap(Entry::getKey, e -> converter.apply(e.getValue())));
|
||||
+5
-5
@@ -4,23 +4,23 @@ import java.awt.image.BufferedImage;
|
||||
|
||||
|
||||
public class BufferedImageWrapper implements Image {
|
||||
|
||||
|
||||
private final BufferedImage image;
|
||||
|
||||
|
||||
public BufferedImageWrapper(BufferedImage image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getRGB(int x, int y) {
|
||||
return image.getRGB(x, y);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return image.getWidth();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return image.getHeight();
|
||||
+2
-2
@@ -2,8 +2,8 @@ package com.dfsek.terra.addons.image.image;
|
||||
|
||||
public interface Image {
|
||||
int getRGB(int x, int y);
|
||||
|
||||
|
||||
int getWidth();
|
||||
|
||||
|
||||
int getHeight();
|
||||
}
|
||||
+13
-13
@@ -1,13 +1,13 @@
|
||||
package com.dfsek.terra.addons.image.image;
|
||||
|
||||
public class StitchedImage implements Image {
|
||||
|
||||
|
||||
private final Image[][] images;
|
||||
|
||||
|
||||
private final int[] rowOffsets, columnOffsets;
|
||||
|
||||
|
||||
private final int width, height;
|
||||
|
||||
|
||||
public StitchedImage(Image[][] images, boolean zeroIndexed) throws IllegalArgumentException {
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
@@ -33,40 +33,40 @@ public class StitchedImage implements Image {
|
||||
throw new IllegalArgumentException("Image widths in column " + (i + (zeroIndexed ? 0 : 1)) + " do not match");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.images = images;
|
||||
}
|
||||
|
||||
|
||||
private int getColumn(int x) {
|
||||
for(int i = columnOffsets.length-1; i > 0; i--) {
|
||||
for(int i = columnOffsets.length - 1; i > 0; i--) {
|
||||
if(x >= columnOffsets[i])
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
private int getRow(int y) {
|
||||
for(int i = rowOffsets.length-1; i > 0; i--) {
|
||||
for(int i = rowOffsets.length - 1; i > 0; i--) {
|
||||
if(y >= rowOffsets[i])
|
||||
return i;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getRGB(int x, int y) {
|
||||
int row = getRow(y);
|
||||
int column = getColumn(x);
|
||||
return images[row][column].getRGB(x-columnOffsets[column], y-rowOffsets[row]);
|
||||
return images[row][column].getRGB(x - columnOffsets[column], y - rowOffsets[row]);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return width;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return height;
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
package com.dfsek.terra.addons.image.image;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
|
||||
public class SuppliedImage implements Image {
|
||||
|
||||
private final Supplier<Image> imageSupplier;
|
||||
|
||||
public SuppliedImage(Supplier<Image> imageSupplier) {
|
||||
this.imageSupplier = imageSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRGB(int x, int y) {
|
||||
return imageSupplier.get().getRGB(x, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getWidth() {
|
||||
return imageSupplier.get().getWidth();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return imageSupplier.get().getHeight();
|
||||
}
|
||||
}
|
||||
+58
-55
@@ -1,11 +1,11 @@
|
||||
package com.dfsek.terra.addons.image.operator;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
import com.dfsek.seismic.math.floatingpoint.FloatingPointFunctions;
|
||||
import com.dfsek.seismic.type.sampler.Sampler;
|
||||
|
||||
import com.dfsek.terra.addons.image.image.Image;
|
||||
import com.dfsek.terra.addons.image.util.ColorUtil;
|
||||
import com.dfsek.terra.addons.image.util.ColorUtil.Channel;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
import static com.dfsek.terra.addons.image.util.MathUtil.lerp;
|
||||
|
||||
@@ -17,22 +17,21 @@ import static com.dfsek.terra.addons.image.util.MathUtil.lerp;
|
||||
* by Pedro F. Felzenszwalb and Daniel P. Huttenlocher.
|
||||
*/
|
||||
public class DistanceTransform {
|
||||
|
||||
|
||||
private static final double MAX_DISTANCE_CAP = 10_000_000; // Arbitrarily large value, doubtful someone would
|
||||
private final double[][] distances;
|
||||
|
||||
/**
|
||||
* Size bounds matching the provided image.
|
||||
*/
|
||||
private final int width, height;
|
||||
|
||||
/**
|
||||
* Min and max distances of the distance computation. These may change after {@link #normalize(Normalization)} calls.
|
||||
*/
|
||||
private double minDistance, maxDistance;
|
||||
|
||||
private static final double MAX_DISTANCE_CAP = 10_000_000; // Arbitrarily large value, doubtful someone would
|
||||
// ever use an image large enough to exceed this.
|
||||
public DistanceTransform(Image image, Channel channel, int threshold, boolean clampToMaxEdgeDistance, CostFunction costFunction, boolean invertThreshold) {
|
||||
|
||||
// ever use an image large enough to exceed this.
|
||||
public DistanceTransform(Image image, Channel channel, int threshold, boolean clampToMaxEdgeDistance, CostFunction costFunction,
|
||||
boolean invertThreshold) {
|
||||
// Construct binary image based on threshold value
|
||||
boolean[][] binaryImage = new boolean[image.getWidth()][image.getHeight()];
|
||||
for(int x = 0; x < image.getWidth(); x++) {
|
||||
@@ -40,7 +39,7 @@ public class DistanceTransform {
|
||||
binaryImage[x][y] = ColorUtil.getChannel(image.getRGB(x, y), channel) > threshold ^ invertThreshold;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Get edges of binary image
|
||||
boolean[][] binaryImageEdge = new boolean[image.getWidth()][image.getHeight()];
|
||||
for(int x = 0; x < image.getWidth(); x++) {
|
||||
@@ -49,26 +48,26 @@ public class DistanceTransform {
|
||||
binaryImageEdge[x][y] = false;
|
||||
else
|
||||
// If cell borders any false cell
|
||||
binaryImageEdge[x][y] = x > 0 && !binaryImage[x-1][y] ||
|
||||
y > 0 && !binaryImage[x][y-1] ||
|
||||
x < image.getWidth ()-1 && !binaryImage[x+1][y] ||
|
||||
y < image.getHeight()-1 && !binaryImage[x][y+1];
|
||||
binaryImageEdge[x][y] = x > 0 && !binaryImage[x - 1][y] ||
|
||||
y > 0 && !binaryImage[x][y - 1] ||
|
||||
x < image.getWidth() - 1 && !binaryImage[x + 1][y] ||
|
||||
y < image.getHeight() - 1 && !binaryImage[x][y + 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double[][] function = new double[image.getWidth()][image.getHeight()];
|
||||
for(int x = 0; x < image.getWidth(); x++) {
|
||||
for(int y = 0; y < image.getHeight(); y++) {
|
||||
function[x][y] = switch (costFunction) {
|
||||
function[x][y] = switch(costFunction) {
|
||||
case Channel -> ColorUtil.getChannel(image.getRGB(x, y), channel);
|
||||
case Threshold -> binaryImage[x][y] ? MAX_DISTANCE_CAP : 0;
|
||||
case ThresholdEdge, ThresholdEdgeSigned -> binaryImageEdge[x][y] ? 0 : MAX_DISTANCE_CAP;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
distances = calculateDistance2D(function);
|
||||
|
||||
|
||||
if(costFunction == CostFunction.ThresholdEdgeSigned) {
|
||||
for(int x = 0; x < image.getWidth(); x++) {
|
||||
for(int y = 0; y < image.getHeight(); y++) {
|
||||
@@ -76,17 +75,17 @@ public class DistanceTransform {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(clampToMaxEdgeDistance) {
|
||||
// Find largest value on the edge of the image
|
||||
// Find the largest value on the edge of the image
|
||||
double max = Double.NEGATIVE_INFINITY;
|
||||
for(int x = 0; x < image.getWidth(); x++) {
|
||||
max = Math.max(max, distances[x][0]);
|
||||
max = Math.max(max, distances[x][image.getHeight()-1]);
|
||||
max = Math.max(max, distances[x][image.getHeight() - 1]);
|
||||
}
|
||||
for(int y = 0; y < image.getHeight(); y++) {
|
||||
max = Math.max(max, distances[0][y]);
|
||||
max = Math.max(max, distances[image.getWidth()-1][y]);
|
||||
max = Math.max(max, distances[image.getWidth() - 1][y]);
|
||||
}
|
||||
// Clamp to that largest value
|
||||
for(int x = 0; x < image.getWidth(); x++) {
|
||||
@@ -98,10 +97,10 @@ public class DistanceTransform {
|
||||
|
||||
this.width = image.getWidth();
|
||||
this.height = image.getHeight();
|
||||
|
||||
|
||||
setOutputRange();
|
||||
}
|
||||
|
||||
|
||||
private double[][] calculateDistance2D(double[][] f) {
|
||||
double[][] d = new double[f.length][f[0].length];
|
||||
// Distance pass for each column
|
||||
@@ -115,41 +114,43 @@ public class DistanceTransform {
|
||||
row[x] = d[x][y];
|
||||
row = calculateDistance1D(row);
|
||||
for(int x = 0; x < f[0].length; x++) {
|
||||
d[x][y] = FastMath.sqrt(row[x]);
|
||||
d[x][y] = Math.sqrt(row[x]);
|
||||
}
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
private double[] calculateDistance1D(double[] f) {
|
||||
double[] d = new double[f.length];
|
||||
int[] v = new int[f.length];
|
||||
double[] z = new double[f.length+1];
|
||||
double[] z = new double[f.length + 1];
|
||||
int k = 0;
|
||||
v[0] = 0;
|
||||
z[0] = Integer.MIN_VALUE;
|
||||
z[1] = Integer.MAX_VALUE;
|
||||
for(int q = 1; q <= f.length-1; q++) {
|
||||
double s = ((f[q]+FastMath.pow2(q))-(f[v[k]]+FastMath.pow2(v[k])))/(2*q-2*v[k]);
|
||||
while (s <= z[k]) {
|
||||
for(int q = 1; q <= f.length - 1; q++) {
|
||||
double fqPlusQ2 = (f[q] + Math.pow(q, 2));
|
||||
double twoQ = 2 * q;
|
||||
double s = (fqPlusQ2 - (f[v[k]] + Math.pow(v[k], 2))) / (twoQ - 2 * v[k]);
|
||||
while(s <= z[k]) {
|
||||
k--;
|
||||
s = ((f[q]+FastMath.pow2(q))-(f[v[k]]+FastMath.pow2(v[k])))/(2*q-2*v[k]);
|
||||
s = (fqPlusQ2 - (f[v[k]] + Math.pow(v[k], 2))) / (twoQ - 2 * v[k]);
|
||||
}
|
||||
k++;
|
||||
v[k] = q;
|
||||
z[k] = s;
|
||||
z[k+1] = Integer.MAX_VALUE;
|
||||
z[k + 1] = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
|
||||
k = 0;
|
||||
for(int q = 0; q <= f.length-1; q++) {
|
||||
while(z[k+1] < q)
|
||||
for(int q = 0; q <= f.length - 1; q++) {
|
||||
while(z[k + 1] < q)
|
||||
k++;
|
||||
d[q] = FastMath.pow2(q-v[k]) + f[v[k]];
|
||||
d[q] = Math.pow(q - v[k], 2) + f[v[k]];
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Redistributes the stored distance computation according to the provided {@link Normalization} method.
|
||||
*/
|
||||
@@ -166,9 +167,9 @@ public class DistanceTransform {
|
||||
yield lerp(distances[x][y], minDistance, -1, maxDistance, 1);
|
||||
} else {
|
||||
if(d > 0) {
|
||||
yield FastMath.pow2(d/maxDistance);
|
||||
yield Math.pow(d / maxDistance, 2);
|
||||
} else if(d < 0) {
|
||||
yield -FastMath.pow2(d/minDistance);
|
||||
yield -Math.pow(d / minDistance, 2);
|
||||
} else {
|
||||
yield 0;
|
||||
}
|
||||
@@ -179,7 +180,7 @@ public class DistanceTransform {
|
||||
}
|
||||
setOutputRange();
|
||||
}
|
||||
|
||||
|
||||
private void setOutputRange() {
|
||||
double minDistance = Double.POSITIVE_INFINITY;
|
||||
double maxDistance = Double.NEGATIVE_INFINITY;
|
||||
@@ -192,25 +193,26 @@ public class DistanceTransform {
|
||||
this.minDistance = minDistance;
|
||||
this.maxDistance = maxDistance;
|
||||
}
|
||||
|
||||
|
||||
public enum CostFunction {
|
||||
Channel,
|
||||
Threshold,
|
||||
ThresholdEdge,
|
||||
ThresholdEdgeSigned,
|
||||
}
|
||||
|
||||
|
||||
|
||||
public enum Normalization {
|
||||
/**
|
||||
* Return the raw calculated distances.
|
||||
*/
|
||||
None,
|
||||
|
||||
|
||||
/**
|
||||
* Redistribute the output values to fit in the range [-1, 1]
|
||||
*/
|
||||
Linear,
|
||||
|
||||
|
||||
/**
|
||||
* Redistributes smoothly to the range [-1, 1], such that areas where distance = 0 stay 0.
|
||||
* This is only really applicable to signed distance calculations, and will fall back to linear
|
||||
@@ -218,25 +220,26 @@ public class DistanceTransform {
|
||||
*/
|
||||
SmoothPreserveZero,
|
||||
}
|
||||
|
||||
public static class Noise implements NoiseSampler {
|
||||
|
||||
|
||||
|
||||
public static class Noise implements Sampler {
|
||||
|
||||
private final DistanceTransform transform;
|
||||
|
||||
|
||||
public Noise(DistanceTransform transform, Normalization normalization) {
|
||||
this.transform = transform;
|
||||
transform.normalize(normalization);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double noise(long seed, double x, double y) {
|
||||
if(x<0 || y<0 || x>=transform.width || y>=transform.height) return transform.minDistance;
|
||||
return transform.distances[FastMath.floorToInt(x)][FastMath.floorToInt(y)];
|
||||
public double getSample(long seed, double x, double y) {
|
||||
if(x < 0 || y < 0 || x >= transform.width || y >= transform.height) return transform.minDistance;
|
||||
return transform.distances[FloatingPointFunctions.floor(x)][FloatingPointFunctions.floor(y)];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double noise(long seed, double x, double y, double z) {
|
||||
return noise(seed, x, z);
|
||||
public double getSample(long seed, double x, double y, double z) {
|
||||
return getSample(seed, x, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
+15
-14
@@ -1,40 +1,41 @@
|
||||
package com.dfsek.terra.addons.image.noisesampler;
|
||||
package com.dfsek.terra.addons.image.sampler;
|
||||
|
||||
import com.dfsek.seismic.type.sampler.Sampler;
|
||||
|
||||
import com.dfsek.terra.addons.image.colorsampler.ColorSampler;
|
||||
import com.dfsek.terra.addons.image.util.ColorUtil;
|
||||
import com.dfsek.terra.addons.image.util.ColorUtil.Channel;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
|
||||
import static com.dfsek.terra.addons.image.util.MathUtil.lerp;
|
||||
|
||||
|
||||
public class ChannelNoiseSampler implements NoiseSampler {
|
||||
|
||||
public class ChannelSampler implements Sampler {
|
||||
|
||||
private final ColorSampler colorSampler;
|
||||
|
||||
|
||||
private final Channel channel;
|
||||
|
||||
|
||||
private final boolean normalize;
|
||||
|
||||
|
||||
private final boolean premultiply;
|
||||
|
||||
public ChannelNoiseSampler(ColorSampler colorSampler, Channel channel, boolean normalize, boolean premultiply) {
|
||||
|
||||
public ChannelSampler(ColorSampler colorSampler, Channel channel, boolean normalize, boolean premultiply) {
|
||||
this.colorSampler = colorSampler;
|
||||
this.channel = channel;
|
||||
this.normalize = normalize;
|
||||
this.premultiply = premultiply;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double noise(long seed, double x, double y) {
|
||||
public double getSample(long seed, double x, double y) {
|
||||
int sample = colorSampler.apply((int) x, (int) y);
|
||||
int premultiplied = premultiply ? ColorUtil.premultiply(sample) : sample;
|
||||
double channelValue = channel.from(premultiplied);
|
||||
return normalize ? lerp(channelValue, 0, -1, 255, 1) : channelValue;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public double noise(long seed, double x, double y, double z) {
|
||||
return noise(seed, x, z);
|
||||
public double getSample(long seed, double x, double y, double z) {
|
||||
return getSample(seed, x, z);
|
||||
}
|
||||
}
|
||||
+71
-53
@@ -1,149 +1,159 @@
|
||||
package com.dfsek.terra.addons.image.util;
|
||||
|
||||
import net.jafama.FastMath;
|
||||
|
||||
|
||||
/**
|
||||
* Utility class for manipulating 8 bit ARGB colors
|
||||
*/
|
||||
public class ColorUtil {
|
||||
|
||||
private ColorUtil() {}
|
||||
|
||||
|
||||
private ColorUtil() { }
|
||||
|
||||
public static int distance(int a, int b) {
|
||||
return FastMath.abs(getRed(a) - getRed(b)) +
|
||||
FastMath.abs(getGreen(a) - getGreen(b)) +
|
||||
FastMath.abs(getBlue(a) - getBlue(b));
|
||||
return Math.abs(getRed(a) - getRed(b)) +
|
||||
Math.abs(getGreen(a) - getGreen(b)) +
|
||||
Math.abs(getBlue(a) - getBlue(b));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the red channel value of a given ARGB color value.
|
||||
*
|
||||
* @param argb the ARGB color value to extract the red channel value from
|
||||
*
|
||||
* @return the red channel value of the given ARGB color value, in the range 0-255
|
||||
*/
|
||||
public static int getRed(int argb) {
|
||||
return argb >> 16 & 255;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the green channel value of a given ARGB color value.
|
||||
*
|
||||
* @param argb the ARGB color value to extract the green channel value from
|
||||
*
|
||||
* @return the green channel value of the given ARGB color value, in the range 0-255
|
||||
*/
|
||||
public static int getGreen(int argb) {
|
||||
return argb >> 8 & 255;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the blue channel value of a given ARGB color value.
|
||||
*
|
||||
* @param argb the ARGB color value to extract the blue channel value from
|
||||
*
|
||||
* @return the blue channel value of the given ARGB color value, in the range 0-255
|
||||
*/
|
||||
public static int getBlue(int argb) {
|
||||
return argb & 255;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the alpha channel value of a given ARGB color value.
|
||||
*
|
||||
* @param argb the ARGB color value to extract the blue channel value from
|
||||
*
|
||||
* @return the alpha channel value of the given ARGB color value, in the range 0-255
|
||||
*/
|
||||
public static int getAlpha(int argb) {
|
||||
return argb >> 24 & 255;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the grayscale value of a given ARGB color value.
|
||||
*
|
||||
* @param argb the ARGB color value to convert to grayscale
|
||||
*
|
||||
* @return the grayscale value of the given ARGB color value, in the range 0-255
|
||||
*/
|
||||
public static int getGrayscale(int argb) {
|
||||
return (getRed(argb) + getGreen(argb) + getBlue(argb)) / 3;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value of the specified channel for a given ARGB color value.
|
||||
*
|
||||
* @param argb the ARGB color value to extract the channel value from
|
||||
* @param argb the ARGB color value to extract the channel value from
|
||||
* @param channel the channel to extract the value from
|
||||
*
|
||||
* @return the value of the specified channel for the given ARGB color value, in the range 0-255
|
||||
*/
|
||||
public static int getChannel(int argb, Channel channel) {
|
||||
return channel.from(argb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the red channel value of a given ARGB color value to zero.
|
||||
*
|
||||
* @param argb the ARGB color value to zero the red channel of
|
||||
*
|
||||
* @return the resulting ARGB color value with the red channel set to zero
|
||||
*/
|
||||
public static int zeroRed(int argb) {
|
||||
return argb & ~0x00FF0000;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the green channel value of a given ARGB color value to zero.
|
||||
*
|
||||
* @param argb the ARGB color value to zero the green channel of
|
||||
*
|
||||
* @return the resulting ARGB color value with the green channel set to zero
|
||||
*/
|
||||
public static int zeroGreen(int argb) {
|
||||
return argb & ~0x0000FF00;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the blue channel value of a given ARGB color value to zero.
|
||||
*
|
||||
* @param argb the ARGB color value to zero the blue channel of
|
||||
*
|
||||
* @return the resulting ARGB color value with the blue channel set to zero
|
||||
*/
|
||||
public static int zeroBlue(int argb) {
|
||||
return argb & ~0x000000FF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the alpha channel value of a given ARGB color value to zero.
|
||||
* This is the same as setting the color to fully transparent.
|
||||
*
|
||||
* @param argb the ARGB color value to zero the alpha channel of
|
||||
*
|
||||
* @return the resulting ARGB color value with the alpha channel set to zero
|
||||
*/
|
||||
public static int zeroAlpha(int argb) {
|
||||
return argb & ~0xFF000000;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the color channels of a given ARGB color value to zero.
|
||||
* This is the same as setting the color to black, while preserving the alpha.
|
||||
*
|
||||
* @param argb the ARGB color value to zero the color channel of
|
||||
*
|
||||
* @return the resulting ARGB color value with the color channels set to zero
|
||||
*/
|
||||
public static int zeroGrayscale(int argb) {
|
||||
return argb & ~0x00FFFFFF;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the specified channel value of a given ARGB color value to zero.
|
||||
*
|
||||
* @param argb the ARGB color value to zero the specified channel of
|
||||
* @param argb the ARGB color value to zero the specified channel of
|
||||
* @param channel the channel to zero the value of
|
||||
*
|
||||
* @return the resulting ARGB color value with the specified channel value set to zero
|
||||
*/
|
||||
public static int zeroChannel(int argb, Channel channel) {
|
||||
return channel.zero(argb);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Multiply the RGB channels of a given ARGB color value by its alpha channel value.
|
||||
*
|
||||
* @param argb the ARGB color value to premultiply the RGB channels of
|
||||
*
|
||||
* @return the resulting premultiplied ARGB color value
|
||||
*/
|
||||
public static int premultiply(int argb) {
|
||||
@@ -153,96 +163,104 @@ public class ColorUtil {
|
||||
int blue = (getBlue(argb) * alpha + 127) / 255;
|
||||
return argb(alpha, red, green, blue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an ARGB color value with the specified values for alpha, red, green, and blue channels.
|
||||
*
|
||||
* @param alpha the alpha value, between 0 and 255, to set in the ARGB color value
|
||||
* @param red the red value, between 0 and 255, to set in the ARGB color value
|
||||
* @param red the red value, between 0 and 255, to set in the ARGB color value
|
||||
* @param green the green value, between 0 and 255, to set in the ARGB color value
|
||||
* @param blue the blue value, between 0 and 255, to set in the ARGB color value
|
||||
* @param blue the blue value, between 0 and 255, to set in the ARGB color value
|
||||
*
|
||||
* @return the resulting ARGB color value with the specified values for alpha, red, green, and blue channels
|
||||
*/
|
||||
public static int argb(int alpha, int red, int green, int blue) {
|
||||
return argbAlpha(alpha) | argbRed(red) | argbGreen(green) | argbBlue(blue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns an ARGB color value with the specified values for alpha, red, green, and blue channels,
|
||||
* after validating that each channel value is in the range 0-255.
|
||||
*
|
||||
* @param alpha the alpha value, between 0 and 255, to set in the ARGB color value
|
||||
* @param red the red value, between 0 and 255, to set in the ARGB color value
|
||||
* @param red the red value, between 0 and 255, to set in the ARGB color value
|
||||
* @param green the green value, between 0 and 255, to set in the ARGB color value
|
||||
* @param blue the blue value, between 0 and 255, to set in the ARGB color value
|
||||
* @param blue the blue value, between 0 and 255, to set in the ARGB color value
|
||||
*
|
||||
* @return the resulting ARGB color value with the specified values for alpha, red, green, and blue channels
|
||||
*
|
||||
* @throws IllegalArgumentException if any channel value is outside the range 0-255
|
||||
*/
|
||||
public static int argbValidated(int alpha, int red, int green, int blue) throws IllegalArgumentException {
|
||||
if (alpha < 0 || alpha > 255 ||
|
||||
red < 0 || red > 255 ||
|
||||
green < 0 || green > 255 ||
|
||||
blue < 0 || blue > 255
|
||||
if(alpha < 0 || alpha > 255 ||
|
||||
red < 0 || red > 255 ||
|
||||
green < 0 || green > 255 ||
|
||||
blue < 0 || blue > 255
|
||||
) throw new IllegalArgumentException("Channel values must be in range 0-255");
|
||||
return argb(alpha, red, green, blue);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ARGB color value with the specified alpha channel value and zero
|
||||
* for the red, green, and blue channels.
|
||||
*
|
||||
* @param alpha the alpha channel value to set in the ARGB color value
|
||||
*
|
||||
* @return the resulting ARGB color value
|
||||
*/
|
||||
public static int argbAlpha(int alpha) { return alpha << 24; }
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ARGB color value with the specified red channel value and zero
|
||||
* for the alpha, green, and blue channels.
|
||||
*
|
||||
* @param red the red channel value to set in the ARGB color value
|
||||
*
|
||||
* @return the resulting ARGB color value
|
||||
*/
|
||||
public static int argbRed(int red) { return red << 16; }
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ARGB color value with the specified red channel value and zero
|
||||
* for the alpha, red, and blue channels.
|
||||
*
|
||||
* @param green the green channel value to set in the ARGB color value
|
||||
*
|
||||
* @return the resulting ARGB color value
|
||||
*/
|
||||
public static int argbGreen(int green) { return green << 8; }
|
||||
|
||||
|
||||
/**
|
||||
* Returns the ARGB color value with the specified blue channel value and zero
|
||||
* for the alpha, red, and green channels.
|
||||
*
|
||||
* @param blue the blue channel value to set in the ARGB color value
|
||||
*
|
||||
* @return the resulting ARGB color value
|
||||
*/
|
||||
public static int argbBlue(int blue) { return blue; }
|
||||
|
||||
|
||||
/**
|
||||
* Returns an ARGB color value with the specified grayscale value for all four channels.
|
||||
*
|
||||
* @param value the grayscale value to set in all four channels of the ARGB color value
|
||||
*
|
||||
* @return the resulting ARGB color value with the specified grayscale value for all four channels
|
||||
*/
|
||||
public static int argbGrayscale(int value) { return argb(value, value, value, value); }
|
||||
|
||||
|
||||
public enum Channel {
|
||||
RED {
|
||||
@Override
|
||||
public int from(int argb) {
|
||||
return getRed(argb);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int zero(int argb) {
|
||||
return zeroRed(argb);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argb(int value) {
|
||||
return argbRed(value);
|
||||
@@ -253,12 +271,12 @@ public class ColorUtil {
|
||||
public int from(int argb) {
|
||||
return getGreen(argb);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int zero(int argb) {
|
||||
return zeroGreen(argb);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argb(int value) {
|
||||
return argbGreen(value);
|
||||
@@ -269,12 +287,12 @@ public class ColorUtil {
|
||||
public int from(int argb) {
|
||||
return getBlue(argb);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int zero(int argb) {
|
||||
return zeroBlue(argb);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argb(int value) {
|
||||
return argbBlue(value);
|
||||
@@ -285,12 +303,12 @@ public class ColorUtil {
|
||||
public int from(int argb) {
|
||||
return getGrayscale(argb);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int zero(int argb) {
|
||||
return zeroGrayscale(argb);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argb(int value) {
|
||||
return argbAlpha(value);
|
||||
@@ -301,22 +319,22 @@ public class ColorUtil {
|
||||
public int from(int argb) {
|
||||
return getAlpha(argb);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int zero(int argb) {
|
||||
return zeroAlpha(argb);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int argb(int value) {
|
||||
return argbAlpha(value);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public abstract int from(int argb);
|
||||
|
||||
|
||||
public abstract int zero(int argb);
|
||||
|
||||
|
||||
public abstract int argb(int value);
|
||||
}
|
||||
}
|
||||
+8
-8
@@ -8,18 +8,18 @@ import java.util.stream.Collectors;
|
||||
|
||||
public class MapUtil {
|
||||
|
||||
private MapUtil() {}
|
||||
|
||||
private MapUtil() { }
|
||||
|
||||
/**
|
||||
* Utility method for applying transformations on a map's keys.
|
||||
*/
|
||||
public static <O, N, T> Map<N, T> mapKeys(Map<O, T> map, Function<O, N> mappingFunction) {
|
||||
return map
|
||||
.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(
|
||||
e -> mappingFunction.apply(e.getKey()),
|
||||
Entry::getValue
|
||||
));
|
||||
.entrySet()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(
|
||||
e -> mappingFunction.apply(e.getKey()),
|
||||
Entry::getValue
|
||||
));
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
package com.dfsek.terra.addons.image.util;
|
||||
|
||||
public class MathUtil {
|
||||
private MathUtil() {}
|
||||
|
||||
private MathUtil() { }
|
||||
|
||||
public static double lerp(double x, double x1, double y1, double x2, double y2) {
|
||||
return (((y1-y2)*(x-x1))/(x1-x2))+y1;
|
||||
return (((y1 - y2) * (x - x1)) / (x1 - x2)) + y1;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
schema-version: 1
|
||||
contributors:
|
||||
- Terra contributors
|
||||
id: library-image
|
||||
id: api-image
|
||||
version: @VERSION@
|
||||
entrypoints:
|
||||
- "com.dfsek.terra.addons.image.ImageLibraryAddon"
|
||||
@@ -1,6 +1,6 @@
|
||||
version = version("1.0.0")
|
||||
|
||||
dependencies {
|
||||
compileOnlyApi(project(":common:addons:manifest-addon-loader"))
|
||||
compileOnlyApi(project(":common:addons:biome-query-api"))
|
||||
compileOnlyApi(project(":common:addons:addon-loader-manifest"))
|
||||
compileOnlyApi(project(":common:addons:api-biome-query"))
|
||||
}
|
||||
|
||||
+8
-8
@@ -9,11 +9,11 @@ class BaseBiomeColumn implements Column<Biome> {
|
||||
private final Biome base;
|
||||
private final int min;
|
||||
private final int max;
|
||||
|
||||
|
||||
private final int x;
|
||||
private final int z;
|
||||
private final long seed;
|
||||
|
||||
|
||||
protected BaseBiomeColumn(BiomeExtrusionProvider biomeProvider, Biome base, int min, int max, int x, int z, long seed) {
|
||||
this.biomeProvider = biomeProvider;
|
||||
this.base = base;
|
||||
@@ -23,29 +23,29 @@ class BaseBiomeColumn implements Column<Biome> {
|
||||
this.z = z;
|
||||
this.seed = seed;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMinY() {
|
||||
return min;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getMaxY() {
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int getZ() {
|
||||
return z;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Biome get(int y) {
|
||||
return biomeProvider.extrude(base, x, y, z, seed);
|
||||
return biomeProvider.pipeline.extrude(base, x, y, z, seed);
|
||||
}
|
||||
}
|
||||
|
||||
+26
-26
@@ -27,41 +27,41 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
public class BiomeExtrusionAddon implements AddonInitializer {
|
||||
public static final TypeKey<Supplier<ObjectTemplate<Extrusion>>> EXTRUSION_REGISTRY_KEY = new TypeKey<>() {
|
||||
};
|
||||
|
||||
|
||||
public static final TypeKey<Supplier<ObjectTemplate<BiomeProvider>>> PROVIDER_REGISTRY_KEY = new TypeKey<>() {
|
||||
};
|
||||
|
||||
|
||||
@Inject
|
||||
private Platform platform;
|
||||
|
||||
|
||||
@Inject
|
||||
private BaseAddon addon;
|
||||
|
||||
|
||||
@Override
|
||||
public void initialize() {
|
||||
platform.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPreLoadEvent.class)
|
||||
.then(event -> {
|
||||
CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry =
|
||||
event.getPack()
|
||||
.getOrCreateRegistry(PROVIDER_REGISTRY_KEY);
|
||||
providerRegistry.register(addon.key("EXTRUSION"), BiomeExtrusionTemplate::new);
|
||||
})
|
||||
.then(event -> {
|
||||
CheckedRegistry<Supplier<ObjectTemplate<Extrusion>>> extrusionRegistry = event.getPack().getOrCreateRegistry(
|
||||
EXTRUSION_REGISTRY_KEY);
|
||||
extrusionRegistry.register(addon.key("SET"), SetExtrusionTemplate::new);
|
||||
extrusionRegistry.register(addon.key("REPLACE"), ReplaceExtrusionTemplate::new);
|
||||
})
|
||||
.failThrough();
|
||||
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPreLoadEvent.class)
|
||||
.then(event -> {
|
||||
CheckedRegistry<Supplier<ObjectTemplate<BiomeProvider>>> providerRegistry =
|
||||
event.getPack()
|
||||
.getOrCreateRegistry(PROVIDER_REGISTRY_KEY);
|
||||
providerRegistry.register(addon.key("EXTRUSION"), BiomeExtrusionTemplate::new);
|
||||
})
|
||||
.then(event -> {
|
||||
CheckedRegistry<Supplier<ObjectTemplate<Extrusion>>> extrusionRegistry = event.getPack().getOrCreateRegistry(
|
||||
EXTRUSION_REGISTRY_KEY);
|
||||
extrusionRegistry.register(addon.key("SET"), SetExtrusionTemplate::new);
|
||||
extrusionRegistry.register(addon.key("REPLACE"), ReplaceExtrusionTemplate::new);
|
||||
})
|
||||
.failThrough();
|
||||
|
||||
platform.getEventManager()
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPostLoadEvent.class)
|
||||
.then(event -> {
|
||||
Registry<Biome> biomeRegistry = event.getPack().getRegistry(Biome.class);
|
||||
event.getPack().applyLoader(ReplaceableBiome.class, new ReplaceableBiomeLoader(biomeRegistry));
|
||||
});
|
||||
.getHandler(FunctionalEventHandler.class)
|
||||
.register(addon, ConfigPackPostLoadEvent.class)
|
||||
.then(event -> {
|
||||
Registry<Biome> biomeRegistry = event.getPack().getRegistry(Biome.class);
|
||||
event.getPack().applyLoader(ReplaceableBiome.class, new ReplaceableBiomeLoader(biomeRegistry));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+19
-22
@@ -6,62 +6,59 @@ import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.dfsek.terra.addons.biome.extrusion.api.Extrusion;
|
||||
import com.dfsek.terra.addons.biome.extrusion.utils.ExtrusionPipeline;
|
||||
import com.dfsek.terra.addons.biome.extrusion.utils.ExtrusionPipelineFactory;
|
||||
import com.dfsek.terra.api.util.Column;
|
||||
import com.dfsek.terra.api.util.generic.data.types.Maybe;
|
||||
import com.dfsek.terra.api.world.biome.Biome;
|
||||
import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
|
||||
|
||||
public class BiomeExtrusionProvider implements BiomeProvider {
|
||||
public final ExtrusionPipeline pipeline;
|
||||
private final BiomeProvider delegate;
|
||||
private final Set<Biome> biomes;
|
||||
private final List<Extrusion> extrusions;
|
||||
private final int resolution;
|
||||
|
||||
|
||||
public BiomeExtrusionProvider(BiomeProvider delegate, List<Extrusion> extrusions, int resolution) {
|
||||
this.delegate = delegate;
|
||||
this.biomes = delegate.stream().collect(Collectors.toSet());
|
||||
extrusions.forEach(e -> biomes.addAll(e.getBiomes()));
|
||||
this.extrusions = extrusions;
|
||||
|
||||
this.pipeline = ExtrusionPipelineFactory.create(extrusions);
|
||||
|
||||
this.resolution = resolution;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Biome getBiome(int x, int y, int z, long seed) {
|
||||
Biome delegated = delegate.getBiome(x, y, z, seed);
|
||||
|
||||
return extrude(delegated, x, y, z, seed);
|
||||
return pipeline.extrude(delegated, x, y, z, seed);
|
||||
}
|
||||
|
||||
public Biome extrude(Biome original, int x, int y, int z, long seed) {
|
||||
for(Extrusion extrusion : extrusions) {
|
||||
original = extrusion.extrude(original, x, y, z, seed);
|
||||
}
|
||||
return original;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Column<Biome> getColumn(int x, int z, long seed, int min, int max) {
|
||||
return delegate.getBaseBiome(x, z, seed)
|
||||
.map(base -> (Column<Biome>) new BaseBiomeColumn(this, base, min, max, x, z, seed))
|
||||
.orElseGet(() -> BiomeProvider.super.getColumn(x, z, seed, min, max));
|
||||
.map(base -> (Column<Biome>) new BaseBiomeColumn(this, base, min, max, x, z, seed))
|
||||
.get(() -> BiomeProvider.super.getColumn(x, z, seed, min, max));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Optional<Biome> getBaseBiome(int x, int z, long seed) {
|
||||
public Maybe<Biome> getBaseBiome(int x, int z, long seed) {
|
||||
return delegate.getBaseBiome(x, z, seed);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Iterable<Biome> getBiomes() {
|
||||
return biomes;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int resolution() {
|
||||
return resolution;
|
||||
}
|
||||
|
||||
|
||||
public BiomeProvider getDelegate() {
|
||||
return delegate;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -7,6 +7,6 @@ import com.dfsek.terra.api.world.biome.Biome;
|
||||
|
||||
public interface Extrusion {
|
||||
Biome extrude(Biome original, int x, int y, int z, long seed);
|
||||
|
||||
|
||||
Collection<Biome> getBiomes();
|
||||
}
|
||||
|
||||
+3
-3
@@ -6,16 +6,16 @@ import com.dfsek.terra.api.world.biome.Biome;
|
||||
|
||||
final class PresentBiome implements ReplaceableBiome {
|
||||
private final Biome biome;
|
||||
|
||||
|
||||
PresentBiome(Biome biome) {
|
||||
this.biome = biome;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Biome get(Biome existing) {
|
||||
return biome;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSelf() {
|
||||
return false;
|
||||
|
||||
+4
-4
@@ -13,19 +13,19 @@ public sealed interface ReplaceableBiome permits PresentBiome, SelfBiome {
|
||||
static ReplaceableBiome of(Biome biome) {
|
||||
return new PresentBiome(biome);
|
||||
}
|
||||
|
||||
|
||||
static ReplaceableBiome self() {
|
||||
return SelfBiome.INSTANCE;
|
||||
}
|
||||
|
||||
|
||||
Biome get(Biome existing);
|
||||
|
||||
|
||||
default Biome get() {
|
||||
if(isSelf()) {
|
||||
throw new IllegalStateException("Cannot get() self biome!");
|
||||
}
|
||||
return get(null);
|
||||
}
|
||||
|
||||
|
||||
boolean isSelf();
|
||||
}
|
||||
|
||||
+2
-2
@@ -8,12 +8,12 @@ import com.dfsek.terra.api.world.biome.Biome;
|
||||
|
||||
final class SelfBiome implements ReplaceableBiome {
|
||||
public static final SelfBiome INSTANCE = new SelfBiome();
|
||||
|
||||
|
||||
@Override
|
||||
public Biome get(Biome existing) {
|
||||
return Objects.requireNonNull(existing);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isSelf() {
|
||||
return true;
|
||||
|
||||
+3
-3
@@ -15,14 +15,14 @@ import com.dfsek.terra.api.world.biome.generation.BiomeProvider;
|
||||
public class BiomeExtrusionTemplate implements ObjectTemplate<BiomeProvider> {
|
||||
@Value("provider")
|
||||
private @Meta BiomeProvider provider;
|
||||
|
||||
|
||||
@Value("resolution")
|
||||
@Default
|
||||
private @Meta int resolution = 4;
|
||||
|
||||
|
||||
@Value("extrusions")
|
||||
private @Meta List<@Meta Extrusion> extrusions;
|
||||
|
||||
|
||||
@Override
|
||||
public BiomeProvider get() {
|
||||
return new BiomeExtrusionProvider(provider, extrusions, resolution);
|
||||
|
||||
+5
-5
@@ -15,18 +15,18 @@ import com.dfsek.terra.api.world.biome.Biome;
|
||||
|
||||
public class ReplaceableBiomeLoader implements TypeLoader<ReplaceableBiome> {
|
||||
private final Registry<Biome> biomeRegistry;
|
||||
|
||||
|
||||
public ReplaceableBiomeLoader(Registry<Biome> biomeRegistry) {
|
||||
this.biomeRegistry = biomeRegistry;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public ReplaceableBiome load(@NotNull AnnotatedType t, @NotNull Object c, @NotNull ConfigLoader loader, DepthTracker depthTracker)
|
||||
throws LoadException {
|
||||
if(c.equals("SELF")) return ReplaceableBiome.self();
|
||||
return biomeRegistry
|
||||
.getByID((String) c)
|
||||
.map(ReplaceableBiome::of)
|
||||
.orElseThrow(() -> new LoadException("No such biome: " + c, depthTracker));
|
||||
.getByID((String) c)
|
||||
.map(ReplaceableBiome::of)
|
||||
.collectThrow(left -> new LoadException("No such biome: " + c + ": " + left, depthTracker));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -12,10 +12,10 @@ import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||
public class ReplaceExtrusionTemplate extends SamplerExtrusionTemplate {
|
||||
@Value("to")
|
||||
private @Meta ProbabilityCollection<@Meta ReplaceableBiome> biomes;
|
||||
|
||||
|
||||
@Value("from")
|
||||
private @Meta String fromTag;
|
||||
|
||||
|
||||
@Override
|
||||
public Extrusion get() {
|
||||
return new ReplaceExtrusion(sampler, range, biomes, fromTag);
|
||||
|
||||
+4
-4
@@ -1,18 +1,18 @@
|
||||
package com.dfsek.terra.addons.biome.extrusion.config.extrusions;
|
||||
|
||||
import com.dfsek.seismic.type.sampler.Sampler;
|
||||
import com.dfsek.tectonic.api.config.template.annotations.Value;
|
||||
import com.dfsek.tectonic.api.config.template.object.ObjectTemplate;
|
||||
|
||||
import com.dfsek.terra.addons.biome.extrusion.api.Extrusion;
|
||||
import com.dfsek.terra.api.config.meta.Meta;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.Range;
|
||||
import com.dfsek.terra.api.util.range.Range;
|
||||
|
||||
|
||||
public abstract class SamplerExtrusionTemplate implements ObjectTemplate<Extrusion> {
|
||||
@Value("sampler")
|
||||
protected @Meta NoiseSampler sampler;
|
||||
|
||||
protected @Meta Sampler sampler;
|
||||
|
||||
@Value("range")
|
||||
protected @Meta Range range;
|
||||
}
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@ import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||
public class SetExtrusionTemplate extends SamplerExtrusionTemplate {
|
||||
@Value("to")
|
||||
private @Meta ProbabilityCollection<@Meta ReplaceableBiome> biomes;
|
||||
|
||||
|
||||
@Override
|
||||
public Extrusion get() {
|
||||
return new SetExtrusion(sampler, range, biomes);
|
||||
|
||||
+35
-17
@@ -1,5 +1,7 @@
|
||||
package com.dfsek.terra.addons.biome.extrusion.extrusions;
|
||||
|
||||
import com.dfsek.seismic.type.sampler.Sampler;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -7,9 +9,9 @@ import java.util.stream.Collectors;
|
||||
import com.dfsek.terra.addons.biome.extrusion.api.Extrusion;
|
||||
import com.dfsek.terra.addons.biome.extrusion.api.ReplaceableBiome;
|
||||
import com.dfsek.terra.addons.biome.query.api.BiomeQueries;
|
||||
import com.dfsek.terra.api.noise.NoiseSampler;
|
||||
import com.dfsek.terra.api.util.Range;
|
||||
import com.dfsek.terra.api.util.collection.ProbabilityCollection;
|
||||
import com.dfsek.terra.api.util.collection.TriStateIntCache;
|
||||
import com.dfsek.terra.api.util.range.Range;
|
||||
import com.dfsek.terra.api.world.biome.Biome;
|
||||
|
||||
|
||||
@@ -17,36 +19,52 @@ import com.dfsek.terra.api.world.biome.Biome;
|
||||
* Sets biomes at locations based on a sampler.
|
||||
*/
|
||||
public class ReplaceExtrusion implements Extrusion {
|
||||
private final NoiseSampler sampler;
|
||||
|
||||
private final Sampler sampler;
|
||||
private final Range range;
|
||||
|
||||
private final ProbabilityCollection<ReplaceableBiome> biomes;
|
||||
|
||||
private final Predicate<Biome> hasTag;
|
||||
|
||||
public ReplaceExtrusion(NoiseSampler sampler, Range range, ProbabilityCollection<ReplaceableBiome> biomes, String tag) {
|
||||
private final TriStateIntCache cache;
|
||||
|
||||
public ReplaceExtrusion(Sampler sampler, Range range, ProbabilityCollection<ReplaceableBiome> biomes, String tag) {
|
||||
this.sampler = sampler;
|
||||
this.range = range;
|
||||
this.biomes = biomes;
|
||||
this.hasTag = BiomeQueries.has(tag);
|
||||
this.cache = new TriStateIntCache(Biome.INT_ID_COUNTER.get());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Biome extrude(Biome original, int x, int y, int z, long seed) {
|
||||
if(hasTag.test(original)) {
|
||||
return range.ifInRange(y, () -> biomes.get(sampler, x, y, z, seed).get(original), original);
|
||||
int id = original.getIntID();
|
||||
|
||||
long state = cache.get(id);
|
||||
boolean passes;
|
||||
|
||||
if(state == TriStateIntCache.STATE_UNSET) {
|
||||
// Only run the test if unset in cache
|
||||
passes = hasTag.test(original);
|
||||
cache.set(id, passes);
|
||||
} else {
|
||||
// Read the primitive long directly
|
||||
passes = (state == TriStateIntCache.STATE_TRUE);
|
||||
}
|
||||
|
||||
if(passes) {
|
||||
if(range.isInRange(y)) {
|
||||
return biomes.get(sampler, x, y, z, seed).get(original);
|
||||
}
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Collection<Biome> getBiomes() {
|
||||
return biomes
|
||||
.getContents()
|
||||
.stream()
|
||||
.filter(Predicate.not(ReplaceableBiome::isSelf))
|
||||
.map(ReplaceableBiome::get)
|
||||
.collect(Collectors.toSet());
|
||||
.getContents()
|
||||
.stream()
|
||||
.filter(Predicate.not(ReplaceableBiome::isSelf))
|
||||
.map(ReplaceableBiome::get)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user