diff --git a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 index 58d677f5..d80d9ce3 100644 --- a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 +++ b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 @@ -1,5 +1,5 @@ -// 1.20.1 2024-07-03T10:53:15.138751138 Create: Numismatics/Numismatics' Advancements -8f32fb49ef81058e2e660fac983dbef2f554db38 data/numismatics/advancements/root.json +// 1.20.1 2024-07-21T07:28:28.810770107 Create: Numismatics/Numismatics' Advancements +4ab84595dc44460d6d89ff3608940dd8694b93d6 data/numismatics/advancements/is_this_legal.json 645c92e6e449889ed4cf617432fd6fa87ffe355b data/numismatics/advancements/questionable_investment.json +8f32fb49ef81058e2e660fac983dbef2f554db38 data/numismatics/advancements/root.json 894790d980b33b5cc24a21937c7db72bf0af1c5a data/numismatics/advancements/money_laundering.json -4ab84595dc44460d6d89ff3608940dd8694b93d6 data/numismatics/advancements/is_this_legal.json diff --git a/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 b/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 index 36bada8a..631a847c 100644 --- a/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 +++ b/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 @@ -1,75 +1,107 @@ -// 1.20.1 2024-07-03T10:53:15.138076264 Create: Numismatics/Numismatics Standard Recipes -e16d9a5134c226db94bb389c44e55a8b393ca6c4 data/numismatics/recipes/crafting/brass_depositor.json -151c31385fcbf7283f380e25ee2c8fdacd6d5103 data/numismatics/recipes/crafting/orange_id_card.json -858305a3537cdcb5bb19b883e688ddb876f0473c data/numismatics/recipes/crafting/brown_id_card.json -f2d158116054b5f0a28e2df07be3e11e5e5e74f7 data/numismatics/advancements/recipes/misc/crafting/white_id_card.json -8c7b922c9569a4c7b2cedbe957e59427975f6abf data/numismatics/advancements/recipes/misc/crafting/green_card.json -8fd00cd399cf9329a63b6264918372ebf90ad79b data/numismatics/recipes/crafting/light_gray_id_card.json -e4e1818714e49b1dd45c596ece3ca28042381906 data/numismatics/advancements/recipes/misc/crafting/red_card.json -78c03ce1632f59f8203d7c5839e7c093b0a56ff6 data/numismatics/recipes/crafting/light_blue_card.json -9dc53a455bef89e74178737998ff8bb699974af2 data/numismatics/advancements/recipes/misc/crafting/pink_id_card.json -dcb522b8700b7e058e043573f31c4fc67551eb86 data/numismatics/recipes/crafting/andesite_depositor.json -b359f00206e8522f61fa06cc6bda43142f180e30 data/numismatics/recipes/crafting/lime_card.json -39047da0807eb1054a179e6ecf63e85676a9f0a0 data/numismatics/advancements/recipes/misc/crafting/brass_depositor.json -360f03b664bac1cf6fde98e1ec77ca6e93933c4a data/numismatics/advancements/recipes/misc/crafting/banking_guide.json -574d01d5616971ae92d1087f9a9d90bb93c3419e data/numismatics/recipes/crafting/black_id_card.json -29ba720cf8ae338eec2edbd997fcb3f6a8de7cd1 data/numismatics/advancements/recipes/misc/crafting/vendor.json -11be645cfbf1ee8721ffceb2b47d30e2923e9323 data/numismatics/advancements/recipes/misc/crafting/andesite_depositor.json -ba04c62863e2c847ad7ac240e282c3f6ecd85d62 data/numismatics/recipes/crafting/banking_guide.json -a2966bf8eb0aa54b64e4c77d1522bd6163e03a1d data/numismatics/advancements/recipes/misc/crafting/orange_id_card.json -0000b8a2cd58843eb7cf2c0b4b7b71a07baf3652 data/numismatics/advancements/recipes/misc/crafting/magenta_card.json +// 1.20.1 2024-07-21T07:28:28.808884081 Create: Numismatics/Numismatics Standard Recipes 0e1680b878cfa51c04809504b3542cb6312027a1 data/numismatics/recipes/crafting/gray_id_card.json -af8adf907389ccfa18bfa035d40108f9c5755ddd data/numismatics/recipes/crafting/white_id_card.json -5c882ba48afb491eac809ad5fef36c5d419afd1f data/numismatics/recipes/crafting/purple_card.json 61954216f844eecdbee266da7e517a983993d2f8 data/numismatics/advancements/recipes/misc/crafting/brown_card.json -8ae4c3c323f9b8ea0261f5e0d1fb9f7c15e9cf6b data/numismatics/recipes/crafting/light_gray_card.json -753e91e51246f8ac75ac67fbd3b912e663ba8ee8 data/numismatics/advancements/recipes/misc/crafting/purple_card.json -c5c615ba24d8d06bd315053984225ae34124761c data/numismatics/recipes/crafting/magenta_id_card.json -caff153f8b3751f805227c8fc20a145dae8406b6 data/numismatics/advancements/recipes/misc/crafting/light_gray_id_card.json -53a3678011a51e8d1c6419345c88d2ffa07e6d44 data/numismatics/recipes/crafting/cyan_id_card.json -f160e3f01433b3815e8734e0ae0ed7eadc19e53b data/numismatics/recipes/crafting/cyan_card.json -2c923f377d0945abea77297db5f4bf08bafb824e data/numismatics/advancements/recipes/misc/crafting/cyan_card.json -3bdee0ea570562c973144de2f27938e8018ef9b4 data/numismatics/recipes/crafting/pink_card.json -d518f47ea8446f1ebd592d7d74d96dec66755651 data/numismatics/recipes/crafting/gray_card.json +2c732f9c3bc02a29a4d86a0552f4dbbae986a34a data/numismatics/recipes/crafting/blue_authorized_card.json +e91feedee6f602a6c19d39fd6a3c10f0fd17208f data/numismatics/recipes/crafting/brown_authorized_card.json +350ce3eaa44f59f9cdf7810bdc101cb010c9dcc1 data/numismatics/advancements/recipes/misc/crafting/magenta_authorized_card.json +a87641c131fe00d2ef54caed44ec741ef0dd6dee data/numismatics/recipes/crafting/magenta_card.json ff7d6b3f21b735e3378add718c16e3c0c643f5f3 data/numismatics/recipes/crafting/pink_id_card.json -1d0c5ff8b555ba922b0699a93dceb4cb9d49c4f9 data/numismatics/advancements/recipes/misc/crafting/lime_card.json 244012381f0600ab5116066948c81398dcdbd3d4 data/numismatics/advancements/recipes/misc/crafting/bank_terminal.json +0000b8a2cd58843eb7cf2c0b4b7b71a07baf3652 data/numismatics/advancements/recipes/misc/crafting/magenta_card.json +f2d158116054b5f0a28e2df07be3e11e5e5e74f7 data/numismatics/advancements/recipes/misc/crafting/white_id_card.json +839f1ed3f0f662ca63614bdb48f70472deb6cc8e data/numismatics/recipes/crafting/gray_authorized_card.json +4f1f98fe5f1e8d59cdd6b7bc8213b439edce4634 data/numismatics/recipes/crafting/yellow_authorized_card.json adb81866fed19b22faf8aee7dff52d1294326208 data/numismatics/recipes/crafting/light_blue_id_card.json -d3d26ab5f434385090c7f3e5ba10dd874a336bdd data/numismatics/recipes/crafting/green_id_card.json -4dc98a1d5028d6a9df2d6ae8987744e409a97029 data/numismatics/advancements/recipes/misc/crafting/orange_card.json +9dc53a455bef89e74178737998ff8bb699974af2 data/numismatics/advancements/recipes/misc/crafting/pink_id_card.json +c8f1d58fc2017de5d0888b13ebcbf7802dc7678c data/numismatics/advancements/recipes/misc/crafting/light_blue_authorized_card.json +a9acb103fdf3c06e561b7252083fae594074ba40 data/numismatics/advancements/recipes/misc/crafting/white_card.json +29ba720cf8ae338eec2edbd997fcb3f6a8de7cd1 data/numismatics/advancements/recipes/misc/crafting/vendor.json +6c3d017d9438e74552384a2b391ad5b6c5bb74e0 data/numismatics/recipes/crafting/magenta_authorized_card.json +67ac012247db080a6231312a1de981724cd3f82d data/numismatics/recipes/crafting/bank_terminal.json +da540ae92c84519149c1b37ad49290814f507a8a data/numismatics/advancements/recipes/misc/crafting/white_authorized_card.json +12014c6c5ac12fdddc45d61bdb3841e2f930125d data/numismatics/recipes/crafting/red_card.json +858305a3537cdcb5bb19b883e688ddb876f0473c data/numismatics/recipes/crafting/brown_id_card.json +35d3c0460a2ba41603bea8e1453b26d662a1f2d5 data/numismatics/advancements/recipes/misc/crafting/yellow_authorized_card.json +ce32a3a7c2a5564e84b30bb1b71007ca4adc985d data/numismatics/recipes/crafting/lime_authorized_card.json +501f27ee03faeb675a05b63b0c8058f1473f02d5 data/numismatics/advancements/recipes/misc/crafting/purple_id_card.json 8d863132d01d516db98d228e9038425923b7354d data/numismatics/recipes/crafting/black_card.json -d8a8bdef01cc07e8902c89c247da5b53c6b3cda8 data/numismatics/advancements/recipes/misc/crafting/yellow_card.json +78af0a7f17e04133eae7172df3255aaa34034537 data/numismatics/advancements/recipes/misc/crafting/red_id_card.json +e16d9a5134c226db94bb389c44e55a8b393ca6c4 data/numismatics/recipes/crafting/brass_depositor.json 86ccf10cd1549f633f99674b002c543bd46aefd0 data/numismatics/recipes/crafting/yellow_card.json +1d0c5ff8b555ba922b0699a93dceb4cb9d49c4f9 data/numismatics/advancements/recipes/misc/crafting/lime_card.json +3cfbeee014050f945e5fa2299dbbcfbf120bf29a data/numismatics/recipes/crafting/red_authorized_card.json +6d90141ba018612413149776136ccb11b26add7c data/numismatics/advancements/recipes/misc/crafting/light_gray_authorized_card.json +8ae4c3c323f9b8ea0261f5e0d1fb9f7c15e9cf6b data/numismatics/recipes/crafting/light_gray_card.json +d8007d8586a071ea28f40b14ec36a37771b4c173 data/numismatics/advancements/recipes/misc/crafting/brown_authorized_card.json +8c7b922c9569a4c7b2cedbe957e59427975f6abf data/numismatics/advancements/recipes/misc/crafting/green_card.json +151c31385fcbf7283f380e25ee2c8fdacd6d5103 data/numismatics/recipes/crafting/orange_id_card.json +dca08f89788e5995829190522f0b65518ba4662a data/numismatics/recipes/crafting/orange_card.json +545cd37f988dd1904ce5929f9ca44bf782b2b8d7 data/numismatics/recipes/crafting/pink_authorized_card.json +001236743f26b5c2df8d050b4182562e84a69779 data/numismatics/advancements/recipes/misc/crafting/magenta_id_card.json +7d42bcd127bc77bc6d06d07b84a77622522d1e98 data/numismatics/recipes/crafting/light_gray_authorized_card.json +dcb522b8700b7e058e043573f31c4fc67551eb86 data/numismatics/recipes/crafting/andesite_depositor.json +6bd7bdeefcc3019e6a60fe097ae155779d34a412 data/numismatics/advancements/recipes/misc/crafting/light_gray_card.json +06323df9c938f4a44bb98ab5236c8d28af1daff8 data/numismatics/advancements/recipes/misc/crafting/green_id_card.json +0ec4f8d7fd3ef45fd3a20d995b91b327767ee122 data/numismatics/recipes/crafting/light_blue_authorized_card.json +c310626562a698c5598e5b95cc397dcf5c4c803d data/numismatics/advancements/recipes/misc/crafting/gray_card.json +4dc98a1d5028d6a9df2d6ae8987744e409a97029 data/numismatics/advancements/recipes/misc/crafting/orange_card.json +78c03ce1632f59f8203d7c5839e7c093b0a56ff6 data/numismatics/recipes/crafting/light_blue_card.json +a2966bf8eb0aa54b64e4c77d1522bd6163e03a1d data/numismatics/advancements/recipes/misc/crafting/orange_id_card.json +1dfe24cac3a8509fb4681d46998cf7e1b39e8e2c data/numismatics/advancements/recipes/misc/crafting/black_authorized_card.json 5cc24c0941d059f3beba740a0b5f80a4537781a3 data/numismatics/advancements/recipes/misc/crafting/blue_card.json -78af0a7f17e04133eae7172df3255aaa34034537 data/numismatics/advancements/recipes/misc/crafting/red_id_card.json -67ac012247db080a6231312a1de981724cd3f82d data/numismatics/recipes/crafting/bank_terminal.json +e4e1818714e49b1dd45c596ece3ca28042381906 data/numismatics/advancements/recipes/misc/crafting/red_card.json +8ebbf07d426b182d8833afb9ee3f8e3a2feb850f data/numismatics/recipes/crafting/blue_id_card.json +b33377448ad6812c10b1405051359e58172299e9 data/numismatics/advancements/recipes/misc/crafting/brown_id_card.json +2c923f377d0945abea77297db5f4bf08bafb824e data/numismatics/advancements/recipes/misc/crafting/cyan_card.json +606c6054ab3ab165654c4de002c7e93d3f7fab3b data/numismatics/recipes/crafting/green_card.json 50dae4e6bc13a1e6f914fb8de99b06e807641d2a data/numismatics/advancements/recipes/misc/crafting/pink_card.json -a9acb103fdf3c06e561b7252083fae594074ba40 data/numismatics/advancements/recipes/misc/crafting/white_card.json +574d01d5616971ae92d1087f9a9d90bb93c3419e data/numismatics/recipes/crafting/black_id_card.json +11be645cfbf1ee8721ffceb2b47d30e2923e9323 data/numismatics/advancements/recipes/misc/crafting/andesite_depositor.json +4f07744fcb39c07782b21f31584dbd041f7d172e data/numismatics/advancements/recipes/misc/crafting/light_blue_card.json +ea20b56eaa5e6c8af48b7b8c3c33cd15c0107bc1 data/numismatics/advancements/recipes/misc/crafting/gray_authorized_card.json +d7a7609aa109440f0f47b8ba7c598d9f7a667734 data/numismatics/advancements/recipes/misc/crafting/blue_id_card.json +4ef1874d44a47c50706505c00f866b9ecb6d860d data/numismatics/recipes/crafting/purple_authorized_card.json +dccd117562bb9bf28890aa0aa53273b4587504ee data/numismatics/recipes/crafting/white_card.json +cee2975b897e1c1216e301ad69dea85258902546 data/numismatics/advancements/recipes/misc/crafting/black_id_card.json +6ed249679ea9168906e4e00a7c6f85f432f9cd16 data/numismatics/advancements/recipes/misc/crafting/orange_authorized_card.json 20434910bb6e5fa2e8350f52b30c728b091a85d3 data/numismatics/recipes/crafting/brown_card.json -a2d0106c95fb00a808af0ebb2a5c0d83a3a913a4 data/numismatics/advancements/recipes/misc/crafting/light_blue_id_card.json -8ebbf07d426b182d8833afb9ee3f8e3a2feb850f data/numismatics/recipes/crafting/blue_id_card.json -c310626562a698c5598e5b95cc397dcf5c4c803d data/numismatics/advancements/recipes/misc/crafting/gray_card.json -6bd7bdeefcc3019e6a60fe097ae155779d34a412 data/numismatics/advancements/recipes/misc/crafting/light_gray_card.json +24bb0a27737622bbc1dfce601b0030372f0b6bcf data/numismatics/recipes/crafting/black_authorized_card.json +53a3678011a51e8d1c6419345c88d2ffa07e6d44 data/numismatics/recipes/crafting/cyan_id_card.json +ff911cab5fbdab250fe0cf4822e6fbd4e5c99f2a data/numismatics/advancements/recipes/misc/crafting/blue_authorized_card.json +7a4b88c35cad4209e13d11e913617fdcc525542d data/numismatics/advancements/recipes/misc/crafting/red_authorized_card.json +d3d26ab5f434385090c7f3e5ba10dd874a336bdd data/numismatics/recipes/crafting/green_id_card.json +13b984e17c52cc24968f4fd1ba67b915243a4b27 data/numismatics/recipes/crafting/vendor.json +cb356731ac23d0daa7a9ed36a0abdda104235b64 data/numismatics/advancements/recipes/misc/crafting/pink_authorized_card.json +5c882ba48afb491eac809ad5fef36c5d419afd1f data/numismatics/recipes/crafting/purple_card.json 156bac80f52563211c3e8625f308acc229640000 data/numismatics/recipes/crafting/blue_card.json -cee2975b897e1c1216e301ad69dea85258902546 data/numismatics/advancements/recipes/misc/crafting/black_id_card.json -dccd117562bb9bf28890aa0aa53273b4587504ee data/numismatics/recipes/crafting/white_card.json -501f27ee03faeb675a05b63b0c8058f1473f02d5 data/numismatics/advancements/recipes/misc/crafting/purple_id_card.json +a2d0106c95fb00a808af0ebb2a5c0d83a3a913a4 data/numismatics/advancements/recipes/misc/crafting/light_blue_id_card.json +3bdee0ea570562c973144de2f27938e8018ef9b4 data/numismatics/recipes/crafting/pink_card.json +011bfd082068cb75738cb9ea54e5f76147c0436f data/numismatics/advancements/recipes/misc/crafting/black_card.json +5bf1eddd9bf4c4d910728c812c392f88ce427012 data/numismatics/recipes/crafting/red_id_card.json +b359f00206e8522f61fa06cc6bda43142f180e30 data/numismatics/recipes/crafting/lime_card.json +386f7cbc350f5448e31c71053309e48a71df15f1 data/numismatics/recipes/crafting/green_authorized_card.json +8ec31340673a11ae32cd58f441b30432aa963a4c data/numismatics/recipes/crafting/white_authorized_card.json +8ede57d6fa0fb30cc5edf0eb842844071f8c2026 data/numismatics/advancements/recipes/misc/crafting/green_authorized_card.json +cded917dee4ac35f9499992f6e0767a8638a5113 data/numismatics/recipes/crafting/orange_authorized_card.json +fca73628e0fc837c1e8f06f0f63d4b8983651d83 data/numismatics/advancements/recipes/misc/crafting/yellow_id_card.json +0d9dc5041578195c578860f7af550cae670b1016 data/numismatics/advancements/recipes/misc/crafting/cyan_authorized_card.json +d8a8bdef01cc07e8902c89c247da5b53c6b3cda8 data/numismatics/advancements/recipes/misc/crafting/yellow_card.json +ba04c62863e2c847ad7ac240e282c3f6ecd85d62 data/numismatics/recipes/crafting/banking_guide.json +136bf9f53ce695973fba2719ce75872a05dc3bf2 data/numismatics/recipes/crafting/cyan_authorized_card.json 5d68fafc0fe40d0cbbc02c778641edb7118026de data/numismatics/advancements/recipes/misc/crafting/lime_id_card.json -12014c6c5ac12fdddc45d61bdb3841e2f930125d data/numismatics/recipes/crafting/red_card.json -dca08f89788e5995829190522f0b65518ba4662a data/numismatics/recipes/crafting/orange_card.json -001236743f26b5c2df8d050b4182562e84a69779 data/numismatics/advancements/recipes/misc/crafting/magenta_id_card.json -13b984e17c52cc24968f4fd1ba67b915243a4b27 data/numismatics/recipes/crafting/vendor.json -b33377448ad6812c10b1405051359e58172299e9 data/numismatics/advancements/recipes/misc/crafting/brown_id_card.json +af8adf907389ccfa18bfa035d40108f9c5755ddd data/numismatics/recipes/crafting/white_id_card.json +c5c615ba24d8d06bd315053984225ae34124761c data/numismatics/recipes/crafting/magenta_id_card.json 7ab921d57812521611aa6185e5fe46af466fdf0c data/numismatics/recipes/crafting/yellow_id_card.json 42b664e5f199b76e54518baf529c2dfe434a929f data/numismatics/recipes/crafting/lime_id_card.json -cf3fa950d39273b32ae4dde3ba84f77820d0cb25 data/numismatics/recipes/crafting/purple_id_card.json -011bfd082068cb75738cb9ea54e5f76147c0436f data/numismatics/advancements/recipes/misc/crafting/black_card.json -4f07744fcb39c07782b21f31584dbd041f7d172e data/numismatics/advancements/recipes/misc/crafting/light_blue_card.json -fca73628e0fc837c1e8f06f0f63d4b8983651d83 data/numismatics/advancements/recipes/misc/crafting/yellow_id_card.json -d7a7609aa109440f0f47b8ba7c598d9f7a667734 data/numismatics/advancements/recipes/misc/crafting/blue_id_card.json -a87641c131fe00d2ef54caed44ec741ef0dd6dee data/numismatics/recipes/crafting/magenta_card.json +39047da0807eb1054a179e6ecf63e85676a9f0a0 data/numismatics/advancements/recipes/misc/crafting/brass_depositor.json +f160e3f01433b3815e8734e0ae0ed7eadc19e53b data/numismatics/recipes/crafting/cyan_card.json +8fd00cd399cf9329a63b6264918372ebf90ad79b data/numismatics/recipes/crafting/light_gray_id_card.json +caff153f8b3751f805227c8fc20a145dae8406b6 data/numismatics/advancements/recipes/misc/crafting/light_gray_id_card.json +7ced89d9f2a4266155fc5e8b650ffbecac27fd6e data/numismatics/advancements/recipes/misc/crafting/lime_authorized_card.json +753e91e51246f8ac75ac67fbd3b912e663ba8ee8 data/numismatics/advancements/recipes/misc/crafting/purple_card.json +d518f47ea8446f1ebd592d7d74d96dec66755651 data/numismatics/recipes/crafting/gray_card.json 073f5238842a1e3bb7624479e6e061e25a6d551b data/numismatics/advancements/recipes/misc/crafting/gray_id_card.json -5bf1eddd9bf4c4d910728c812c392f88ce427012 data/numismatics/recipes/crafting/red_id_card.json -606c6054ab3ab165654c4de002c7e93d3f7fab3b data/numismatics/recipes/crafting/green_card.json +4f6314ea11c7524569cf9ea711e7d5dc90abee37 data/numismatics/advancements/recipes/misc/crafting/purple_authorized_card.json +cf3fa950d39273b32ae4dde3ba84f77820d0cb25 data/numismatics/recipes/crafting/purple_id_card.json a30c11ea13bb0d445ed47725ed4995dd291bc700 data/numismatics/advancements/recipes/misc/crafting/cyan_id_card.json -06323df9c938f4a44bb98ab5236c8d28af1daff8 data/numismatics/advancements/recipes/misc/crafting/green_id_card.json +360f03b664bac1cf6fde98e1ec77ca6e93933c4a data/numismatics/advancements/recipes/misc/crafting/banking_guide.json diff --git a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 index 88d72ef3..6dd8ed86 100644 --- a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 +++ b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 @@ -1 +1 @@ -// 1.20.1 2024-07-03T10:53:15.138642657 Create: Numismatics/Numismatics' Sequenced Assembly Recipes +// 1.20.1 2024-07-21T07:28:28.810455961 Create: Numismatics/Numismatics' Sequenced Assembly Recipes diff --git a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 index 168db413..c832c265 100644 --- a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 +++ b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 @@ -1,101 +1,119 @@ -// 1.20.1 2024-07-03T10:53:15.136472954 Create: Numismatics/Registrate Provider for numismatics [Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud)] +// 1.20.1 2024-07-21T07:28:28.803638784 Create: Numismatics/Registrate Provider for numismatics [Recipes, Advancements, Loot Tables, Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), Blockstates, Item models, Lang (en_us/en_ud)] +2f1dad2a2e0086d54cf4b88378feacc04341d87f data/numismatics/tags/items/internal/ingots/iron_ingots.json +dc5c60bbbaf3a5d7bc1f9bc0c9377757dbd8de49 data/numismatics/loot_tables/blocks/bank_terminal.json +5b0244502972f49d063d98fa0cb3f6fc65af82b2 data/numismatics/tags/items/internal/string.json +a96d3d02794064cd9be1bca25a9ba6217675e6c5 assets/numismatics/models/item/white_id_card.json +4d944b6e0e93a3444591a2e540530da0b2a0ff08 data/numismatics/tags/items/internal/dyes/light_blue_dyes.json +228b67a48aa045bfe809c54c756df80eb0765aad assets/numismatics/models/item/bank_terminal.json +bb2a77462e6213eddde134f3cc3e9a3f07f07f3f assets/numismatics/models/item/yellow_authorized_card.json +74a4c7ca7a48382782e5dba33018dfc8255192c5 assets/numismatics/models/block/brass_depositor_locked.json +3f0d912779200aaaf55bef102d9b96acead1a636 data/numismatics/tags/items/internal/dyes/purple_dyes.json +c15ac766d96414de2c90afc41e6e98dbce51d97c assets/numismatics/lang/en_us.json +377e460c0dcf6d7de1b7ae235959105a7c45e4c4 assets/numismatics/models/item/cyan_authorized_card.json +bde18ccd9c21484154597c6271750c0406082f61 data/forge/tags/blocks/relocation_not_supported.json +eca751589c40725750e2c2baa6607e83255fd5f4 assets/numismatics/models/item/brown_authorized_card.json +ad712dd2a2a7268dfa773f38a50d526952758d5c data/numismatics/tags/items/internal/dyes/cyan_dyes.json +84ab8c91452f94501b3acc31ec1e0bc64417f839 assets/numismatics/models/item/black_card.json +83ce6c9d27970b4c643f0f9f3dfeb58668fca3d4 assets/numismatics/models/item/banking_guide.json +8550097149cebbfd50bdeac2003327b60a4aee9a assets/numismatics/models/item/light_gray_card.json +95b492bd9230dc90fca9395c823cef39e644d8f2 assets/numismatics/models/item/sprocket.json 70c481f36a9718ac48632e6939ac6ba785be4c9e assets/numismatics/models/item/black_id_card.json -95ef415a564eba1d212053195d25b199427b94e3 assets/numismatics/blockstates/creative_vendor.json +5553762668322d02797be81ac5da7b6563c4131d assets/numismatics/lang/en_ud.json +1e78f650091a4a2c43e36fb815f23d0591e058a6 assets/numismatics/models/item/magenta_card.json +909f5d14f23199c064f6b91a421bb7b15e0f1a7d assets/numismatics/models/item/orange_authorized_card.json +d6f017479b3cc538f73d7fb0a1e65d1742bab266 assets/numismatics/models/item/light_blue_id_card.json 4458283178334ae169a7cbbd1aa09067cbb99ee7 data/numismatics/tags/items/internal/dyes/green_dyes.json -ee60b7c614946045f0671976ef12e43151c33ce1 assets/numismatics/models/item/blue_id_card.json -4f78ca868db20495aa20be7c6a14e2678fb16f9f assets/numismatics/models/block/andesite_depositor_locked.json -7ebbfe751724c7a9b8b57cd9b4aae2a71a8da840 assets/numismatics/models/item/green_id_card.json ad693bfb3bb45d661f989071bd896e3020fcbe87 assets/numismatics/models/item/pink_card.json -77de205f7ee2b6736ece646c399aaa194def42f0 assets/numismatics/models/item/brown_card.json -b6efde0135fab023b1b51f219254e5e9d7439f6a assets/numismatics/models/item/cog.json -17b5bc6d0bfd98157c3d2ed8ee6ebc81fd6d7599 data/numismatics/tags/items/internal/nuggets/iron_nuggets.json -3f0d912779200aaaf55bef102d9b96acead1a636 data/numismatics/tags/items/internal/dyes/purple_dyes.json +cca7e7be961c6ed6272f19211bb17707b7934155 assets/numismatics/models/item/creative_vendor.json +7ebbfe751724c7a9b8b57cd9b4aae2a71a8da840 assets/numismatics/models/item/green_id_card.json +5f6e841fc0eae95df179de8d4b2eae325a19e015 data/numismatics/tags/items/cards.json +b5533a44ad137e21ee8aab5c200f673d1e8a235f assets/numismatics/models/item/pink_id_card.json +facbd710d107ebc9b2c6ddfa3b59a16d5f85c992 assets/numismatics/models/item/spur.json +f6ee547a5678792e225e7d897c559d7493918844 data/numismatics/tags/items/internal/plates/gold_plates.json 6cb764824a2190dab6219b7502ec77f14c1a90e0 data/numismatics/loot_tables/blocks/creative_vendor.json -bde18ccd9c21484154597c6271750c0406082f61 data/c/tags/blocks/relocation_not_supported.json -bde18ccd9c21484154597c6271750c0406082f61 data/forge/tags/blocks/relocation_not_supported.json -a2ff135c1fea203b49dbbf4cae010664aa1cf909 assets/numismatics/models/item/magenta_id_card.json -5849c2cae2ca479893e1e4063d2efb75eada281a assets/numismatics/models/item/cyan_id_card.json +52b48750de8a5a571a08bce3f2f025474153d50b assets/numismatics/models/item/bevel.json +2a6aaab63efb82be5fee5de0f9d96824d520b25e data/numismatics/tags/items/internal/dyes/blue_dyes.json +fd289500be71ae25ed8c08b5f9fea41054cf6a61 assets/numismatics/models/item/brown_id_card.json +411b79f79547a0adcb665bf7440e8169f7dcb24e assets/numismatics/models/block/brass_depositor.json +921085f1caf23e8fd003fc38c439270950a306c3 assets/numismatics/models/item/gray_card.json 7b126eb3ff0b2e9af171e5464fc9ff9f7fcfd653 assets/numismatics/models/item/lime_card.json -9ac23febc1b0d808cb545b3cdda93fae40081b3d assets/numismatics/models/item/brass_depositor.json -5ec9eeaf96af5a8587ec71a9bcf3a5728f99c33d data/minecraft/tags/blocks/mineable/axe.json -a96d3d02794064cd9be1bca25a9ba6217675e6c5 assets/numismatics/models/item/white_id_card.json -c1863c2bd08a5910a534aee0dcbc61a352fb9577 assets/numismatics/models/item/white_card.json -0d06a3a44565e63cf98c451e7a4a6c28681d49be assets/numismatics/models/item/red_id_card.json -4d944b6e0e93a3444591a2e540530da0b2a0ff08 data/numismatics/tags/items/internal/dyes/light_blue_dyes.json +ee60b7c614946045f0671976ef12e43151c33ce1 assets/numismatics/models/item/blue_id_card.json 890e519d407cab18c04ee439e7d5f67eb4f76ab3 assets/numismatics/models/item/blaze_banker.json -8fd12493390894fa5b3988f499f758c17137af16 assets/numismatics/models/item/sun.json -27788e1854c12b323c1fe5945858fce4d1544e3c data/numismatics/tags/items/internal/dyes/white_dyes.json -41b79e319044d6179f7757f73ef67c9acdbfe87d assets/numismatics/models/item/lime_id_card.json -dcf8ea4cef1226fb52d84359d1d2ff403ddb556a assets/numismatics/models/item/orange_id_card.json -36e1dad2803241c11c646b9737be8af6d67ef8fe data/c/tags/items/string.json +090a0f41ed3b7739c4d4768e30a0b1de8986825e assets/numismatics/models/item/pink_authorized_card.json c1878dd808cf36e400e13885adfab22b60ac291e assets/numismatics/models/item/purple_id_card.json -9c20dd40c03605721d0231ffde829d55e36b1c05 assets/numismatics/models/item/yellow_card.json c05836600bd1689f598515841869634b1d709cca assets/numismatics/models/item/yellow_id_card.json -4e3215ab9d54a9e751caa9a946ad54da40586789 assets/numismatics/models/item/purple_card.json +ce821bcccb920fd51237904e253fb29100882648 data/numismatics/tags/items/internal/dyes/brown_dyes.json +a28cf7778f3cf79ca94ac5196ce4aee934961519 assets/numismatics/models/item/cyan_card.json +8fd12493390894fa5b3988f499f758c17137af16 assets/numismatics/models/item/sun.json +c71ebb661adcdddcecd0f74c062718c3e55c1af4 data/create/tags/blocks/fan_transparent.json +99e3dd233c66e14a6e572e332ac8b7af1f8ed94e assets/numismatics/models/item/orange_card.json +bde18ccd9c21484154597c6271750c0406082f61 data/c/tags/blocks/relocation_not_supported.json +0df8c2e77d6563fa3899070a6463d81b95e65cf0 data/numismatics/tags/items/authorized_cards.json +187e917e6a02d61b15493f292d7b1db2151ddfd0 assets/numismatics/models/item/crown.json +d048d04208faa63f0014d614d6026a66fe118c11 data/numismatics/loot_tables/blocks/brass_depositor.json +790ff3c5da6a67a5de1ceb7138fa3e1c0fe97f80 data/numismatics/tags/items/internal/dyes/lime_dyes.json a8cb82f19034a0e724e12df45c883e9cd469c210 assets/numismatics/models/item/green_card.json -2a6aaab63efb82be5fee5de0f9d96824d520b25e data/numismatics/tags/items/internal/dyes/blue_dyes.json +e1087e56db7b4d8812ab4617344f0ac8b0f0e6c7 assets/numismatics/models/item/light_gray_authorized_card.json +390db78c5393fca4f90018df51d1a79d11a64f72 assets/numismatics/models/item/light_blue_authorized_card.json +c09892d2d189f147997d77f4ce39b0570729f030 assets/numismatics/models/item/lime_authorized_card.json 06ecd28cd97f4e8200dc396858695cad57b871c8 assets/numismatics/blockstates/blaze_banker.json -cca7e7be961c6ed6272f19211bb17707b7934155 assets/numismatics/models/item/creative_vendor.json +95ef415a564eba1d212053195d25b199427b94e3 assets/numismatics/blockstates/creative_vendor.json 9fdcd12c871f136e66973a8c02be94a675a4b727 data/numismatics/tags/items/internal/dyes/yellow_dyes.json -dc5c60bbbaf3a5d7bc1f9bc0c9377757dbd8de49 data/numismatics/loot_tables/blocks/bank_terminal.json -aed88ddc55f53f022f96f0685b39d989667a2cb9 assets/numismatics/lang/en_us.json -edd6109002439af0f15959debe4cb9cca254add8 data/minecraft/tags/blocks/mineable/pickaxe.json -facbd710d107ebc9b2c6ddfa3b59a16d5f85c992 assets/numismatics/models/item/spur.json -d6f017479b3cc538f73d7fb0a1e65d1742bab266 assets/numismatics/models/item/light_blue_id_card.json -359ae558c1863eafeb0b0e762d472ea201473701 assets/numismatics/lang/en_ud.json e62db1a880d468865769307ad19f16d9b7dac7c1 data/numismatics/tags/items/internal/dyes/light_gray_dyes.json c5958ebbc2782c2611690c642713cadc59656814 assets/numismatics/models/item/light_blue_card.json -9e6e50d40e3688ae681107e60ac5ff5fc22585f9 data/numismatics/loot_tables/blocks/andesite_depositor.json -265ef24d62bc7580e763e1fb6802bf4e58dc0194 assets/numismatics/models/block/andesite_depositor.json -2f1dad2a2e0086d54cf4b88378feacc04341d87f data/numismatics/tags/items/internal/ingots/iron_ingots.json -d2b105f0657bad99b8efed45dc0a8df8ff775c10 assets/numismatics/blockstates/vendor.json -6965cf99471bb8c63f5f8a94577e2cddc3b2bc33 assets/numismatics/models/item/vendor.json -ac8c537dfc0e6704a0abe4f47130c41b19cde231 data/numismatics/tags/items/internal/dyes/magenta_dyes.json -62ab2750314492e8da73768bd891faee34cfdcd6 data/numismatics/tags/items/internal/dyes/red_dyes.json -790ff3c5da6a67a5de1ceb7138fa3e1c0fe97f80 data/numismatics/tags/items/internal/dyes/lime_dyes.json -d048d04208faa63f0014d614d6026a66fe118c11 data/numismatics/loot_tables/blocks/brass_depositor.json +224bcb5095af5ab25eb16ab0d9c1993323734cf9 data/numismatics/tags/items/internal/nuggets/zinc_nuggets.json +2449b7346e1657ef1c6ab4c134aab55b216ec783 assets/numismatics/models/item/andesite_depositor.json +a6a8db1faafaf7833406120a76fe5c21eb21d2e6 data/numismatics/tags/items/id_cards.json d4b100dee3fb5ad235f06a247a4c2c0ed04d1e0d data/numismatics/tags/blocks/internal/relocation_not_supported.json -f4aefe87cb9cc08511dc226984628771538a42d9 data/numismatics/tags/blocks/numismatics_blocks.json -5f6e841fc0eae95df179de8d4b2eae325a19e015 data/numismatics/tags/items/cards.json -a2dec3b886deae84d88babd6fb1ce2997d193533 data/numismatics/tags/items/coins.json -b5533a44ad137e21ee8aab5c200f673d1e8a235f assets/numismatics/models/item/pink_id_card.json -3c36bec4bc30ac2bd5f0e0c881d6505b5cce35fe data/numismatics/loot_tables/blocks/vendor.json -99bfe9fe8c163701a2a9784d29f26fa2b67d54d3 assets/numismatics/models/item/gray_id_card.json -c71ebb661adcdddcecd0f74c062718c3e55c1af4 data/create/tags/blocks/fan_transparent.json -1e78f650091a4a2c43e36fb815f23d0591e058a6 assets/numismatics/models/item/magenta_card.json +dada04ceb5107ca4b311d8085ca699deda3c60de assets/numismatics/models/item/black_authorized_card.json 3961fdf3030140fc32e0e8c1d440ac395e62f5b6 assets/numismatics/blockstates/bank_terminal.json -52b48750de8a5a571a08bce3f2f025474153d50b assets/numismatics/models/item/bevel.json +6dfeabbb1336aa18bd42d7ab4de00a6ead2f7270 assets/numismatics/models/item/gray_authorized_card.json +182450e6ad4229f2959e6c50e38ef6e2ff5259d0 data/numismatics/tags/items/internal/dyes/orange_dyes.json +9e6e50d40e3688ae681107e60ac5ff5fc22585f9 data/numismatics/loot_tables/blocks/andesite_depositor.json +3c36bec4bc30ac2bd5f0e0c881d6505b5cce35fe data/numismatics/loot_tables/blocks/vendor.json +0e4add47ede4986c6535d74c058d424a4960b36e assets/numismatics/models/item/white_authorized_card.json 82bc77ac080aa62bc6cdf0a932f4e80de50412dc data/numismatics/tags/items/internal/dyes/pink_dyes.json -a7e754dd80af7eff6447f4376b98ebe4eb54e7d6 data/numismatics/tags/items/internal/dyes/black_dyes.json -160d556c6bfdb651082b39784258f6d06c21ca8f assets/numismatics/blockstates/brass_depositor.json -187e917e6a02d61b15493f292d7b1db2151ddfd0 assets/numismatics/models/item/crown.json -2449b7346e1657ef1c6ab4c134aab55b216ec783 assets/numismatics/models/item/andesite_depositor.json -224bcb5095af5ab25eb16ab0d9c1993323734cf9 data/numismatics/tags/items/internal/nuggets/zinc_nuggets.json -8550097149cebbfd50bdeac2003327b60a4aee9a assets/numismatics/models/item/light_gray_card.json -fd289500be71ae25ed8c08b5f9fea41054cf6a61 assets/numismatics/models/item/brown_id_card.json -5b0244502972f49d063d98fa0cb3f6fc65af82b2 data/numismatics/tags/items/internal/string.json -b1f339ffecbae2c812e18a1286162d31429ce356 data/numismatics/tags/items/internal/dyes/gray_dyes.json +77de205f7ee2b6736ece646c399aaa194def42f0 assets/numismatics/models/item/brown_card.json +a2ff135c1fea203b49dbbf4cae010664aa1cf909 assets/numismatics/models/item/magenta_id_card.json +9ac23febc1b0d808cb545b3cdda93fae40081b3d assets/numismatics/models/item/brass_depositor.json +56973a6ce09377c8f235f46aa4d71a2a9fabf587 assets/numismatics/models/item/red_card.json 4a6ca666740b098929798ad132260f288cc228c0 data/numismatics/tags/items/internal/ingots/copper_ingots.json -a6a8db1faafaf7833406120a76fe5c21eb21d2e6 data/numismatics/tags/items/id_cards.json -228b67a48aa045bfe809c54c756df80eb0765aad assets/numismatics/models/item/bank_terminal.json -a28cf7778f3cf79ca94ac5196ce4aee934961519 assets/numismatics/models/item/cyan_card.json -921085f1caf23e8fd003fc38c439270950a306c3 assets/numismatics/models/item/gray_card.json 36e1dad2803241c11c646b9737be8af6d67ef8fe data/forge/tags/items/string.json -d38d7d40599c66ac84ef7dd2c1635d3ba7794871 data/numismatics/tags/items/internal/nuggets/brass_nuggets.json -ad712dd2a2a7268dfa773f38a50d526952758d5c data/numismatics/tags/items/internal/dyes/cyan_dyes.json -182450e6ad4229f2959e6c50e38ef6e2ff5259d0 data/numismatics/tags/items/internal/dyes/orange_dyes.json -56973a6ce09377c8f235f46aa4d71a2a9fabf587 assets/numismatics/models/item/red_card.json -bdf101b181fa593ac3f92224b80c8ec45b5f046a data/numismatics/tags/items/numismatics_items.json +b1f339ffecbae2c812e18a1286162d31429ce356 data/numismatics/tags/items/internal/dyes/gray_dyes.json +88219edf7b658e79cfaeead5e314dab8db133f79 assets/numismatics/models/item/blue_authorized_card.json +b6efde0135fab023b1b51f219254e5e9d7439f6a assets/numismatics/models/item/cog.json +edd6109002439af0f15959debe4cb9cca254add8 data/minecraft/tags/blocks/mineable/pickaxe.json +36e1dad2803241c11c646b9737be8af6d67ef8fe data/c/tags/items/string.json +27788e1854c12b323c1fe5945858fce4d1544e3c data/numismatics/tags/items/internal/dyes/white_dyes.json +65b989259bb3583d85f4093cf171b224bbd16a3a data/numismatics/tags/items/numismatics_items.json +5ec9eeaf96af5a8587ec71a9bcf3a5728f99c33d data/minecraft/tags/blocks/mineable/axe.json +6965cf99471bb8c63f5f8a94577e2cddc3b2bc33 assets/numismatics/models/item/vendor.json +5849c2cae2ca479893e1e4063d2efb75eada281a assets/numismatics/models/item/cyan_id_card.json +b60a4818cad76e2fecad9750f7d576cf5528b5a8 assets/numismatics/models/item/red_authorized_card.json +6f77b42eb7ac7888619ea7c96f7d560ec1ec3db6 assets/numismatics/models/item/green_authorized_card.json +160d556c6bfdb651082b39784258f6d06c21ca8f assets/numismatics/blockstates/brass_depositor.json +dcf8ea4cef1226fb52d84359d1d2ff403ddb556a assets/numismatics/models/item/orange_id_card.json +4f78ca868db20495aa20be7c6a14e2678fb16f9f assets/numismatics/models/block/andesite_depositor_locked.json f7f43dd6d567ec8303c73b79409bc92d8b56574a assets/numismatics/blockstates/andesite_depositor.json -266d9b0eb6fdecc4bcf6da465078d059009a3b54 data/numismatics/loot_tables/blocks/blaze_banker.json -411b79f79547a0adcb665bf7440e8169f7dcb24e assets/numismatics/models/block/brass_depositor.json -99e3dd233c66e14a6e572e332ac8b7af1f8ed94e assets/numismatics/models/item/orange_card.json -83ce6c9d27970b4c643f0f9f3dfeb58668fca3d4 assets/numismatics/models/item/banking_guide.json -ce821bcccb920fd51237904e253fb29100882648 data/numismatics/tags/items/internal/dyes/brown_dyes.json -74a4c7ca7a48382782e5dba33018dfc8255192c5 assets/numismatics/models/block/brass_depositor_locked.json -95b492bd9230dc90fca9395c823cef39e644d8f2 assets/numismatics/models/item/sprocket.json -b3293e39ea5d4a1fdf65d014ec370b328ae36949 assets/numismatics/models/item/light_gray_id_card.json +0d06a3a44565e63cf98c451e7a4a6c28681d49be assets/numismatics/models/item/red_id_card.json fa326874015c5f24f6a65390c31f96324eecc96d assets/numismatics/models/item/blue_card.json +266d9b0eb6fdecc4bcf6da465078d059009a3b54 data/numismatics/loot_tables/blocks/blaze_banker.json +4e3215ab9d54a9e751caa9a946ad54da40586789 assets/numismatics/models/item/purple_card.json +d2b105f0657bad99b8efed45dc0a8df8ff775c10 assets/numismatics/blockstates/vendor.json +e720c18026dc758acf223c2e6247ca3bf4852b59 assets/numismatics/models/item/magenta_authorized_card.json d36f0cc1a6b0873730d353bd84dda701d169265b data/numismatics/tags/items/internal/plates/iron_plates.json -84ab8c91452f94501b3acc31ec1e0bc64417f839 assets/numismatics/models/item/black_card.json +a2dec3b886deae84d88babd6fb1ce2997d193533 data/numismatics/tags/items/coins.json +3e282ab122ced259d5d9bfa58010e71f7e8372f0 assets/numismatics/models/item/purple_authorized_card.json +b3293e39ea5d4a1fdf65d014ec370b328ae36949 assets/numismatics/models/item/light_gray_id_card.json +62ab2750314492e8da73768bd891faee34cfdcd6 data/numismatics/tags/items/internal/dyes/red_dyes.json +c1863c2bd08a5910a534aee0dcbc61a352fb9577 assets/numismatics/models/item/white_card.json +d38d7d40599c66ac84ef7dd2c1635d3ba7794871 data/numismatics/tags/items/internal/nuggets/brass_nuggets.json +ac8c537dfc0e6704a0abe4f47130c41b19cde231 data/numismatics/tags/items/internal/dyes/magenta_dyes.json +265ef24d62bc7580e763e1fb6802bf4e58dc0194 assets/numismatics/models/block/andesite_depositor.json +a7e754dd80af7eff6447f4376b98ebe4eb54e7d6 data/numismatics/tags/items/internal/dyes/black_dyes.json +f4aefe87cb9cc08511dc226984628771538a42d9 data/numismatics/tags/blocks/numismatics_blocks.json +9c20dd40c03605721d0231ffde829d55e36b1c05 assets/numismatics/models/item/yellow_card.json +41b79e319044d6179f7757f73ef67c9acdbfe87d assets/numismatics/models/item/lime_id_card.json +99bfe9fe8c163701a2a9784d29f26fa2b67d54d3 assets/numismatics/models/item/gray_id_card.json c71ebb661adcdddcecd0f74c062718c3e55c1af4 data/create/tags/blocks/passive_boiler_heaters.json +17b5bc6d0bfd98157c3d2ed8ee6ebc81fd6d7599 data/numismatics/tags/items/internal/nuggets/iron_nuggets.json diff --git a/common/src/generated/resources/assets/numismatics/lang/en_ud.json b/common/src/generated/resources/assets/numismatics/lang/en_ud.json index 5b383c00..b7768cb3 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_ud.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_ud.json @@ -33,7 +33,30 @@ "block.numismatics.vendor.tooltip.summary": "˙ʇı ǝɹnbıɟuoɔ oʇ ‾ʞɔıןɔ ʇɟıɥs‾ ɹo 'ǝpɐɹʇ oʇ ‾ʞɔıןɔ ʇɥbıᴚ‾ ˙sdoɥs ǝpɐɯ ɹǝʎɐןd ɥbnoɹɥʇ sɯǝʇı ɟo buıpɐɹʇ ǝɥʇ ɹoɟ sʍoןןⱯ", "block.numismatics.vendor.tooltip.trade_item": "ǝpɐɹ⟘ oʇ ɯǝʇI", "command.numismatics.arguments.enum.invalid": "%s :ǝɹɐ sǝnןɐʌ pıןɐΛ ˙,%s, ǝnןɐʌ ɯnuǝ pıןɐʌuI :ɹoɹɹƎ", + "error.numismatics.authorized_card.account_not_found": "punoɟ ʇou ʇunoɔɔⱯ qnS", + "error.numismatics.authorized_card.limit_reached": "pǝɥɔɐǝɹ ʇıɯıן buıpuǝdS", + "error.numismatics.card.account_not_found": "punoɟ ʇou ʇunoɔɔⱯ", + "error.numismatics.card.not_authorized": "pǝzıɹoɥʇnɐ ʇoN", + "error.numismatics.card.not_bound": "punoq ʇou pɹɐƆ", "gui.numismatics.bank_terminal.balance": "¤%s '%s %s :ǝɔuɐןɐᗺ", + "gui.numismatics.bank_terminal.sub_accounts": "sʇunoɔɔⱯ qnS", + "gui.numismatics.bank_terminal.sub_accounts.authorization_type": "ǝdʎ⟘ uoıʇɐzıɹoɥʇnⱯ", + "gui.numismatics.bank_terminal.sub_accounts.edit": "ʇunoɔɔⱯ qnS ʇıpƎ", + "gui.numismatics.bank_terminal.sub_accounts.help": "sʇunoɔɔⱯ qnS oN", + "gui.numismatics.bank_terminal.sub_accounts.help.line.1": "ppɐ ǝɥʇ ʞɔıןɔ uǝɥʇ puɐ ǝɯɐu ɐ ɹǝʇuƎ", + "gui.numismatics.bank_terminal.sub_accounts.help.line.2": "˙ʇunoɔɔⱯ qnS ʍǝu ɐ ǝʇɐǝɹɔ oʇ uoʇʇnq", + "gui.numismatics.bank_terminal.sub_accounts.help.line.3": "ǝpıʌoɹd oʇ pǝsn ǝq uɐɔ sʇunoɔɔⱯ qnS", + "gui.numismatics.bank_terminal.sub_accounts.help.line.4": "ɹo sɹǝʎɐןd pǝʇɔǝןǝs oʇ ssǝɔɔɐ pǝʇıɯıן", + "gui.numismatics.bank_terminal.sub_accounts.help.line.5": "˙suoıʇɔɐsuɐɹʇ pǝʇɐɯoʇnɐ ɹǝɟɐs ǝןqɐuǝ", + "gui.numismatics.bank_terminal.sub_accounts.help.line.6": "", + "gui.numismatics.bank_terminal.sub_accounts.name_box": "ǝɯɐN", + "gui.numismatics.bank_terminal.sub_accounts.named": "sʇunoɔɔⱯ qnS :%s", + "gui.numismatics.bank_terminal.sub_accounts.remove": "ʇunoɔɔⱯ qnS ǝʌoɯǝᴚ", + "gui.numismatics.bank_terminal.sub_accounts.remove.confirm": "ǝʌoɯǝɹ ʎןןɐnʇɔɐ oʇ uıɐbɐ ʞɔıןƆ ¿ǝɹns noʎ ǝɹⱯ", + "gui.numismatics.bank_terminal.sub_accounts.reset_spending": "buıpuǝdS ʇǝsǝᴚ", + "gui.numismatics.limit": "%s ɟo %s ʇuǝdS", + "gui.numismatics.limit.monetary": "¤%s '%s %s ɟo ¤%s '%s %s ʇuǝdS", + "gui.numismatics.limit.none": "ʇıɯıן oN", "gui.numismatics.trust_list": "ʇsıꞀ ʇsnɹ⟘", "gui.numismatics.vendor.count": ")x%s( ", "gui.numismatics.vendor.full": "ןןnɟ sı ɹopuǝΛ", @@ -41,26 +64,35 @@ "gui.numismatics.vendor.generic_named": "%s ʇɔɐʇuoƆ", "gui.numismatics.vendor.incorrect_item": "ɯǝʇı ʇɔǝɹɹoɔuI", "gui.numismatics.vendor.insufficient_funds": "spunɟ ʇuǝıɔıɟɟnsuI", - "gui.numismatics.vendor.insufficient_funds.named": "ןןıɟǝɹ ɐ ɹoɟ %s ʇɔɐʇuoɔ 'spunɟ ʇuǝıɔıɟɟnsuI", "gui.numismatics.vendor.mode.buy": "ʎnᗺ", "gui.numismatics.vendor.mode.buy.action": "ʎnᗺ oʇ ǝs∩", "gui.numismatics.vendor.mode.sell": "ןןǝS", "gui.numismatics.vendor.mode.sell.action": "ןןǝS oʇ ǝs∩", "gui.numismatics.vendor.no_item_in_hand": "ןןǝs oʇ ʇuɐʍ noʎ sɯǝʇı ɟo ʞɔɐʇs ǝɥʇ pןoH", "gui.numismatics.vendor.out_of_stock": "ʞɔoʇs ɟo ʇnO", + "gui.numismatics.vendor.out_of_stock.funds": "spunɟ ʇuǝıɔıɟɟnsuı sɐɥ ɹopuǝΛ", + "gui.numismatics.vendor.out_of_stock.funds.named": "ןןıɟǝɹ ɐ ɹoɟ %s ʇɔɐʇuoɔ 'spunɟ ʇuǝıɔıɟɟnsuı sɐɥ ɹopuǝΛ", "gui.numismatics.vendor.out_of_stock.named": "ןןıɟǝɹ ɐ ɹoɟ %s ʇɔɐʇuoɔ 'ʞɔoʇs ɟo ʇnO", "gui.numismatics.vendor.too_few_items": "sɯǝʇı ʍǝɟ oo⟘", + "item.numismatics.authorized_bank_card.tooltip": "ᗡᴚⱯƆ ʞNⱯᗺ ᗡƎZIᴚOH⟘∩Ɐ", + "item.numismatics.authorized_bank_card.tooltip.summary": "˙ʇunoɔɔɐ punoq ǝɥʇ oʇ ɯǝɥʇ ppɐ puɐ suıoɔ ǝɥʇ ʇɔǝןןoɔ ʎןןɐɔıʇɐɯoʇnɐ oʇ ‾ɹoʇısodǝᗡ/ɹopuǝΛ‾ ɐ uı pǝɔɐןd ǝq uɐƆ ˙uoıʇɐɯoʇnɐ ɹo sɹǝʎɐןd pǝʇsnɹʇ oʇ ssǝɔɔɐ ʇunoɔɔⱯ ʞuɐᗺ pǝʇıɯıן buıpıʌoɹd sʍoןןⱯ ˙ɹɐǝןɔ oʇ ‾ʞɔıןɔ ʇɟıɥs‾ 'puıq oʇ ‾nuǝɯ ʇunoɔɔⱯ qnS‾ ןɐuıɯɹǝ⟘ ʞuɐᗺ uı ʇnԀ", + "item.numismatics.authorized_card.tooltip.bound.no_label": "uʍouʞu∩ :ʇunoɔɔⱯ qnS", + "item.numismatics.authorized_card.tooltip.bound.with_label": "%s :ʇunoɔɔⱯ qnS", + "item.numismatics.authorized_card.tooltip.hold_shift": "ןɐuıɯɹǝ⟘ ʞuɐᗺ ɐ uı puıᗺ ˙ɹɐǝןɔ oʇ ʞɐǝus pןoH", "item.numismatics.bank_card.tooltip": "ᗡᴚⱯƆ ʞNⱯᗺ", - "item.numismatics.bank_card.tooltip.summary": "˙ʇunoɔɔɐ punoq ǝɥʇ oʇ ɯǝɥʇ ppɐ puɐ suıoɔ ǝɥʇ ʇɔǝןןoɔ ʎןןɐɔıʇɐɯoʇnɐ oʇ ‾ɹoʇısodǝᗡ/ɹopuǝΛ‾ ɐ uı pǝɔɐןd ǝq uɐɔ ɹo '‾ןɐuıɯɹǝ⟘ ʞuɐᗺ‾ ɐ uı pǝsn uǝɥʍ ʇunoɔɔⱯ ʞuɐᗺ punoq ǝɥʇ oʇ ssǝɔɔⱯ sʍoןןⱯ ˙ɹɐǝןɔ oʇ ‾ʞɔıןɔ ʇɟıɥs‾ 'puıq oʇ ‾ʞɔıןƆ ʇɥbıᴚ‾", + "item.numismatics.bank_card.tooltip.summary": "˙ʇunoɔɔɐ punoq ǝɥʇ oʇ ɯǝɥʇ ppɐ puɐ suıoɔ ǝɥʇ ʇɔǝןןoɔ ʎןןɐɔıʇɐɯoʇnɐ oʇ ‾ɹoʇısodǝᗡ/ɹopuǝΛ‾ ɐ uı pǝɔɐןd ǝq uɐɔ ɹo '‾ןɐuıɯɹǝ⟘ ʞuɐᗺ‾ ɐ uı pǝsn uǝɥʍ ʇunoɔɔⱯ ʞuɐᗺ punoq ǝɥʇ oʇ ssǝɔɔɐ sʍoןןⱯ ˙ɹɐǝןɔ oʇ ‾ʞɔıןɔ ʇɟıɥs‾ 'puıq oʇ ‾ʞɔıןƆ ʇɥbıᴚ‾", "item.numismatics.banking_guide": "ǝpın⅁ buıʞuɐᗺ", "item.numismatics.banking_guide.tooltip": "ƎᗡI∩⅁ ⅁NIʞNⱯᗺ", "item.numismatics.banking_guide.tooltip.summary": "˙‾ɹǝʞuɐᗺ ǝzɐןᗺ‾ ɐ oʇuı ʇı ʇɹǝʌuoɔ oʇ ‾ɹǝuɹnᗺ ǝzɐןᗺ‾ ɐ uo ǝs∩", "item.numismatics.bevel": "ןǝʌǝᗺ", "item.numismatics.bevel.plural": "sןǝʌǝᗺ", + "item.numismatics.black_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ʞɔɐןᗺ", "item.numismatics.black_card": "pɹɐƆ ʞuɐᗺ ʞɔɐןᗺ", "item.numismatics.black_id_card": "pɹɐƆ ᗡI ʞɔɐןᗺ", + "item.numismatics.blue_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ǝnןᗺ", "item.numismatics.blue_card": "pɹɐƆ ʞuɐᗺ ǝnןᗺ", "item.numismatics.blue_id_card": "pɹɐƆ ᗡI ǝnןᗺ", + "item.numismatics.brown_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ uʍoɹᗺ", "item.numismatics.brown_card": "pɹɐƆ ʞuɐᗺ uʍoɹᗺ", "item.numismatics.brown_id_card": "pɹɐƆ ᗡI uʍoɹᗺ", "item.numismatics.card.tooltip.blank": "ʞuɐןᗺ", @@ -73,10 +105,13 @@ "item.numismatics.coin.tooltip.value.basic": "¤%s :ǝnןɐΛ", "item.numismatics.crown": "uʍoɹƆ", "item.numismatics.crown.plural": "suʍoɹƆ", + "item.numismatics.cyan_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ uɐʎƆ", "item.numismatics.cyan_card": "pɹɐƆ ʞuɐᗺ uɐʎƆ", "item.numismatics.cyan_id_card": "pɹɐƆ ᗡI uɐʎƆ", + "item.numismatics.gray_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ʎɐɹ⅁", "item.numismatics.gray_card": "pɹɐƆ ʞuɐᗺ ʎɐɹ⅁", "item.numismatics.gray_id_card": "pɹɐƆ ᗡI ʎɐɹ⅁", + "item.numismatics.green_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ uǝǝɹ⅁", "item.numismatics.green_card": "pɹɐƆ ʞuɐᗺ uǝǝɹ⅁", "item.numismatics.green_id_card": "pɹɐƆ ᗡI uǝǝɹ⅁", "item.numismatics.id_card.tooltip": "ᗡᴚⱯƆ ᗡI", @@ -84,20 +119,28 @@ "item.numismatics.id_card.tooltip.bound": "ɟןǝs oʇ punoᗺ", "item.numismatics.id_card.tooltip.cleared": "pǝɹɐǝןƆ", "item.numismatics.id_card.tooltip.summary": "˙ʞɔoןq ʇɐɥʇ oʇ ssǝɔɔɐ ɹǝʎɐןd punoq ǝɥʇ ǝʌıb oʇ sʞɔoןq sɔıʇɐɯsıɯnN ʎuɐɯ ɟo ‾nuǝW pǝʇsnɹ⟘‾ ǝɥʇ uı pǝɔɐןd ǝq uɐƆ ˙ɹɐǝןɔ oʇ ‾ʞɔıןɔ ʇɟıɥs‾ 'puıq oʇ ‾ʞɔıןƆ ʇɥbıᴚ‾", + "item.numismatics.light_blue_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ǝnןᗺ ʇɥbıꞀ", "item.numismatics.light_blue_card": "pɹɐƆ ʞuɐᗺ ǝnןᗺ ʇɥbıꞀ", "item.numismatics.light_blue_id_card": "pɹɐƆ ᗡI ǝnןᗺ ʇɥbıꞀ", + "item.numismatics.light_gray_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ʎɐɹ⅁ ʇɥbıꞀ", "item.numismatics.light_gray_card": "pɹɐƆ ʞuɐᗺ ʎɐɹ⅁ ʇɥbıꞀ", "item.numismatics.light_gray_id_card": "pɹɐƆ ᗡI ʎɐɹ⅁ ʇɥbıꞀ", + "item.numismatics.lime_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ǝɯıꞀ", "item.numismatics.lime_card": "pɹɐƆ ʞuɐᗺ ǝɯıꞀ", "item.numismatics.lime_id_card": "pɹɐƆ ᗡI ǝɯıꞀ", + "item.numismatics.magenta_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ɐʇuǝbɐW", "item.numismatics.magenta_card": "pɹɐƆ ʞuɐᗺ ɐʇuǝbɐW", "item.numismatics.magenta_id_card": "pɹɐƆ ᗡI ɐʇuǝbɐW", + "item.numismatics.orange_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ǝbuɐɹO", "item.numismatics.orange_card": "pɹɐƆ ʞuɐᗺ ǝbuɐɹO", "item.numismatics.orange_id_card": "pɹɐƆ ᗡI ǝbuɐɹO", + "item.numismatics.pink_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ʞuıԀ", "item.numismatics.pink_card": "pɹɐƆ ʞuɐᗺ ʞuıԀ", "item.numismatics.pink_id_card": "pɹɐƆ ᗡI ʞuıԀ", + "item.numismatics.purple_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ǝןdɹnԀ", "item.numismatics.purple_card": "pɹɐƆ ʞuɐᗺ ǝןdɹnԀ", "item.numismatics.purple_id_card": "pɹɐƆ ᗡI ǝןdɹnԀ", + "item.numismatics.red_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ pǝᴚ", "item.numismatics.red_card": "pɹɐƆ ʞuɐᗺ pǝᴚ", "item.numismatics.red_id_card": "pɹɐƆ ᗡI pǝᴚ", "item.numismatics.sprocket": "ʇǝʞɔoɹdS", @@ -106,11 +149,20 @@ "item.numismatics.spur.plural": "sɹndS", "item.numismatics.sun": "unS", "item.numismatics.sun.plural": "sunS", + "item.numismatics.white_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ǝʇıɥM", "item.numismatics.white_card": "pɹɐƆ ʞuɐᗺ ǝʇıɥM", "item.numismatics.white_id_card": "pɹɐƆ ᗡI ǝʇıɥM", + "item.numismatics.yellow_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ʍoןןǝʎ", "item.numismatics.yellow_card": "pɹɐƆ ʞuɐᗺ ʍoןןǝʎ", "item.numismatics.yellow_id_card": "pɹɐƆ ᗡI ʍoןןǝʎ", "itemGroup.numismatics": "sɔıʇɐɯsıɯnN :ǝʇɐǝɹƆ", "numismatics.andesite_depositor.price": "ǝɔıɹԀ", + "numismatics.authorization_type.anybody": "ʎpoqʎuⱯ", + "numismatics.authorization_type.anybody.description": "sɹǝʇndɯoɔ ʇɟɐɹƆɹǝʇndɯoƆ sɐ ɥɔns uoıʇɐɯoʇnɐ buıpnןɔuı 'ᗡI ǝɥʇ ɥʇıʍ ʎpoqʎuⱯ", + "numismatics.authorization_type.trusted_automation": "uoıʇɐɯoʇnⱯ + sɹǝʎɐןԀ pǝʇsnɹ⟘", + "numismatics.authorization_type.trusted_automation.description": ")sɹǝʎoןdǝᗡ ˙b˙ǝ( ɯǝɥʇ ʎq pǝɔɐןd uoıʇɐɯoʇnɐ puɐ ʇsıן ʇsnɹʇ ǝɥʇ uo sɹǝʎɐןԀ", + "numismatics.authorization_type.trusted_players": "ʎןuO sɹǝʎɐןԀ pǝʇsnɹ⟘", + "numismatics.authorization_type.trusted_players.description": "ʇsıן ʇsnɹʇ ǝɥʇ uo sɹǝʎɐןd ʎןuO", + "numismatics.special.ltr": "ǝnɹʇ", "numismatics.trust_list.configure": "ʇsıꞀ ʇsnɹ⟘ ǝɹnbıɟuoƆ" } \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/lang/en_us.json b/common/src/generated/resources/assets/numismatics/lang/en_us.json index d03a2de9..9ec7ed19 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_us.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_us.json @@ -33,7 +33,30 @@ "block.numismatics.vendor.tooltip.summary": "Allows for the trading of items through player made shops. _Right click_ to trade, or _shift click_ to configure it.", "block.numismatics.vendor.tooltip.trade_item": "Item to Trade", "command.numismatics.arguments.enum.invalid": "Error: Invalid enum value '%s'. Valid values are: %s", + "error.numismatics.authorized_card.account_not_found": "Sub Account not found", + "error.numismatics.authorized_card.limit_reached": "Spending limit reached", + "error.numismatics.card.account_not_found": "Account not found", + "error.numismatics.card.not_authorized": "Not authorized", + "error.numismatics.card.not_bound": "Card not bound", "gui.numismatics.bank_terminal.balance": "Balance: %s %s, %s¤", + "gui.numismatics.bank_terminal.sub_accounts": "Sub Accounts", + "gui.numismatics.bank_terminal.sub_accounts.authorization_type": "Authorization Type", + "gui.numismatics.bank_terminal.sub_accounts.edit": "Edit Sub Account", + "gui.numismatics.bank_terminal.sub_accounts.help": "No Sub Accounts", + "gui.numismatics.bank_terminal.sub_accounts.help.line.1": "Enter a name and then click the add", + "gui.numismatics.bank_terminal.sub_accounts.help.line.2": "button to create a new Sub Account.", + "gui.numismatics.bank_terminal.sub_accounts.help.line.3": "Sub Accounts can be used to provide", + "gui.numismatics.bank_terminal.sub_accounts.help.line.4": "limited access to selected players or", + "gui.numismatics.bank_terminal.sub_accounts.help.line.5": "enable safer automated transactions.", + "gui.numismatics.bank_terminal.sub_accounts.help.line.6": "", + "gui.numismatics.bank_terminal.sub_accounts.name_box": "Name", + "gui.numismatics.bank_terminal.sub_accounts.named": "%s: Sub Accounts", + "gui.numismatics.bank_terminal.sub_accounts.remove": "Remove Sub Account", + "gui.numismatics.bank_terminal.sub_accounts.remove.confirm": "Are you sure? Click again to actually remove", + "gui.numismatics.bank_terminal.sub_accounts.reset_spending": "Reset Spending", + "gui.numismatics.limit": "Spent %s of %s", + "gui.numismatics.limit.monetary": "Spent %s %s, %s¤ of %s %s, %s¤", + "gui.numismatics.limit.none": "No limit", "gui.numismatics.trust_list": "Trust List", "gui.numismatics.vendor.count": " (%sx)", "gui.numismatics.vendor.full": "Vendor is full", @@ -41,26 +64,35 @@ "gui.numismatics.vendor.generic_named": "Contact %s", "gui.numismatics.vendor.incorrect_item": "Incorrect item", "gui.numismatics.vendor.insufficient_funds": "Insufficient funds", - "gui.numismatics.vendor.insufficient_funds.named": "Insufficient funds, contact %s for a refill", "gui.numismatics.vendor.mode.buy": "Buy", "gui.numismatics.vendor.mode.buy.action": "Use to Buy", "gui.numismatics.vendor.mode.sell": "Sell", "gui.numismatics.vendor.mode.sell.action": "Use to Sell", "gui.numismatics.vendor.no_item_in_hand": "Hold the stack of items you want to sell", "gui.numismatics.vendor.out_of_stock": "Out of stock", + "gui.numismatics.vendor.out_of_stock.funds": "Vendor has insufficient funds", + "gui.numismatics.vendor.out_of_stock.funds.named": "Vendor has insufficient funds, contact %s for a refill", "gui.numismatics.vendor.out_of_stock.named": "Out of stock, contact %s for a refill", "gui.numismatics.vendor.too_few_items": "Too few items", + "item.numismatics.authorized_bank_card.tooltip": "AUTHORIZED BANK CARD", + "item.numismatics.authorized_bank_card.tooltip.summary": "Put in Bank Terminal _Sub Account menu_ to bind, _shift click_ to clear. Allows providing limited Bank Account access to trusted players or automation. Can be placed in a _Vendor/Depositor_ to automatically collect the coins and add them to the bound account.", + "item.numismatics.authorized_card.tooltip.bound.no_label": "Sub Account: Unknown", + "item.numismatics.authorized_card.tooltip.bound.with_label": "Sub Account: %s", + "item.numismatics.authorized_card.tooltip.hold_shift": "Hold sneak to clear. Bind in a Bank Terminal", "item.numismatics.bank_card.tooltip": "BANK CARD", - "item.numismatics.bank_card.tooltip.summary": "_Right Click_ to bind, _shift click_ to clear. Allows Access to the bound Bank Account when used in a _Bank Terminal_, or can be placed in a _Vendor/Depositor_ to automatically collect the coins and add them to the bound account.", + "item.numismatics.bank_card.tooltip.summary": "_Right Click_ to bind, _shift click_ to clear. Allows access to the bound Bank Account when used in a _Bank Terminal_, or can be placed in a _Vendor/Depositor_ to automatically collect the coins and add them to the bound account.", "item.numismatics.banking_guide": "Banking Guide", "item.numismatics.banking_guide.tooltip": "BANKING GUIDE", "item.numismatics.banking_guide.tooltip.summary": "Use on a _Blaze Burner_ to convert it into a _Blaze Banker_.", "item.numismatics.bevel": "Bevel", "item.numismatics.bevel.plural": "Bevels", + "item.numismatics.black_authorized_card": "Black Authorized Card", "item.numismatics.black_card": "Black Bank Card", "item.numismatics.black_id_card": "Black ID Card", + "item.numismatics.blue_authorized_card": "Blue Authorized Card", "item.numismatics.blue_card": "Blue Bank Card", "item.numismatics.blue_id_card": "Blue ID Card", + "item.numismatics.brown_authorized_card": "Brown Authorized Card", "item.numismatics.brown_card": "Brown Bank Card", "item.numismatics.brown_id_card": "Brown ID Card", "item.numismatics.card.tooltip.blank": "Blank", @@ -73,10 +105,13 @@ "item.numismatics.coin.tooltip.value.basic": "Value: %s¤", "item.numismatics.crown": "Crown", "item.numismatics.crown.plural": "Crowns", + "item.numismatics.cyan_authorized_card": "Cyan Authorized Card", "item.numismatics.cyan_card": "Cyan Bank Card", "item.numismatics.cyan_id_card": "Cyan ID Card", + "item.numismatics.gray_authorized_card": "Gray Authorized Card", "item.numismatics.gray_card": "Gray Bank Card", "item.numismatics.gray_id_card": "Gray ID Card", + "item.numismatics.green_authorized_card": "Green Authorized Card", "item.numismatics.green_card": "Green Bank Card", "item.numismatics.green_id_card": "Green ID Card", "item.numismatics.id_card.tooltip": "ID CARD", @@ -84,20 +119,28 @@ "item.numismatics.id_card.tooltip.bound": "Bound to self", "item.numismatics.id_card.tooltip.cleared": "Cleared", "item.numismatics.id_card.tooltip.summary": "_Right Click_ to bind, _shift click_ to clear. Can be placed in the _Trusted Menu_ of many Numismatics blocks to give the bound player access to that block.", + "item.numismatics.light_blue_authorized_card": "Light Blue Authorized Card", "item.numismatics.light_blue_card": "Light Blue Bank Card", "item.numismatics.light_blue_id_card": "Light Blue ID Card", + "item.numismatics.light_gray_authorized_card": "Light Gray Authorized Card", "item.numismatics.light_gray_card": "Light Gray Bank Card", "item.numismatics.light_gray_id_card": "Light Gray ID Card", + "item.numismatics.lime_authorized_card": "Lime Authorized Card", "item.numismatics.lime_card": "Lime Bank Card", "item.numismatics.lime_id_card": "Lime ID Card", + "item.numismatics.magenta_authorized_card": "Magenta Authorized Card", "item.numismatics.magenta_card": "Magenta Bank Card", "item.numismatics.magenta_id_card": "Magenta ID Card", + "item.numismatics.orange_authorized_card": "Orange Authorized Card", "item.numismatics.orange_card": "Orange Bank Card", "item.numismatics.orange_id_card": "Orange ID Card", + "item.numismatics.pink_authorized_card": "Pink Authorized Card", "item.numismatics.pink_card": "Pink Bank Card", "item.numismatics.pink_id_card": "Pink ID Card", + "item.numismatics.purple_authorized_card": "Purple Authorized Card", "item.numismatics.purple_card": "Purple Bank Card", "item.numismatics.purple_id_card": "Purple ID Card", + "item.numismatics.red_authorized_card": "Red Authorized Card", "item.numismatics.red_card": "Red Bank Card", "item.numismatics.red_id_card": "Red ID Card", "item.numismatics.sprocket": "Sprocket", @@ -106,11 +149,20 @@ "item.numismatics.spur.plural": "Spurs", "item.numismatics.sun": "Sun", "item.numismatics.sun.plural": "Suns", + "item.numismatics.white_authorized_card": "White Authorized Card", "item.numismatics.white_card": "White Bank Card", "item.numismatics.white_id_card": "White ID Card", + "item.numismatics.yellow_authorized_card": "Yellow Authorized Card", "item.numismatics.yellow_card": "Yellow Bank Card", "item.numismatics.yellow_id_card": "Yellow ID Card", "itemGroup.numismatics": "Create: Numismatics", "numismatics.andesite_depositor.price": "Price", + "numismatics.authorization_type.anybody": "Anybody", + "numismatics.authorization_type.anybody.description": "Anybody with the ID, including automation such as ComputerCraft computers", + "numismatics.authorization_type.trusted_automation": "Trusted Players + Automation", + "numismatics.authorization_type.trusted_automation.description": "Players on the trust list and automation placed by them (e.g. Deployers)", + "numismatics.authorization_type.trusted_players": "Trusted Players Only", + "numismatics.authorization_type.trusted_players.description": "Only players on the trust list", + "numismatics.special.ltr": "true", "numismatics.trust_list.configure": "Configure Trust List" } \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/black_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/black_authorized_card.json new file mode 100644 index 00000000..259159b9 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/black_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/black_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/blue_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/blue_authorized_card.json new file mode 100644 index 00000000..52914174 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/blue_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/blue_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/brown_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/brown_authorized_card.json new file mode 100644 index 00000000..91362576 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/brown_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/brown_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/cyan_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/cyan_authorized_card.json new file mode 100644 index 00000000..d2c9280d --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/cyan_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/cyan_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/gray_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/gray_authorized_card.json new file mode 100644 index 00000000..a366c0cb --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/gray_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/gray_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/green_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/green_authorized_card.json new file mode 100644 index 00000000..0a83755d --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/green_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/green_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/light_blue_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/light_blue_authorized_card.json new file mode 100644 index 00000000..a0afc47a --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/light_blue_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/light_blue_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/light_gray_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/light_gray_authorized_card.json new file mode 100644 index 00000000..c83760f8 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/light_gray_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/light_gray_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/lime_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/lime_authorized_card.json new file mode 100644 index 00000000..eb420bd0 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/lime_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/lime_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/magenta_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/magenta_authorized_card.json new file mode 100644 index 00000000..d65a5f97 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/magenta_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/magenta_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/orange_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/orange_authorized_card.json new file mode 100644 index 00000000..cb58c93a --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/orange_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/orange_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/pink_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/pink_authorized_card.json new file mode 100644 index 00000000..ec5f1d57 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/pink_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/pink_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/purple_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/purple_authorized_card.json new file mode 100644 index 00000000..362bbe03 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/purple_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/purple_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/red_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/red_authorized_card.json new file mode 100644 index 00000000..db971d22 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/red_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/red_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/white_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/white_authorized_card.json new file mode 100644 index 00000000..ea3feba1 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/white_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/white_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/assets/numismatics/models/item/yellow_authorized_card.json b/common/src/generated/resources/assets/numismatics/models/item/yellow_authorized_card.json new file mode 100644 index 00000000..59066c69 --- /dev/null +++ b/common/src/generated/resources/assets/numismatics/models/item/yellow_authorized_card.json @@ -0,0 +1,6 @@ +{ + "parent": "minecraft:item/generated", + "textures": { + "layer0": "numismatics:item/authorized_card/yellow_authorized_card" + } +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/black_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/black_authorized_card.json new file mode 100644 index 00000000..0b871074 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/black_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///black_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///black_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/blue_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/blue_authorized_card.json new file mode 100644 index 00000000..1e4f2276 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/blue_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///blue_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///blue_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/brown_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/brown_authorized_card.json new file mode 100644 index 00000000..ed1bc3ac --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/brown_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///brown_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///brown_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/cyan_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/cyan_authorized_card.json new file mode 100644 index 00000000..99b4ecd9 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/cyan_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///cyan_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///cyan_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/gray_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/gray_authorized_card.json new file mode 100644 index 00000000..5754cfde --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/gray_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///gray_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///gray_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/green_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/green_authorized_card.json new file mode 100644 index 00000000..0a4d3210 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/green_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///green_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///green_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/light_blue_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/light_blue_authorized_card.json new file mode 100644 index 00000000..85b96be4 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/light_blue_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///light_blue_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///light_blue_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/light_gray_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/light_gray_authorized_card.json new file mode 100644 index 00000000..4e188fe2 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/light_gray_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///light_gray_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///light_gray_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/lime_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/lime_authorized_card.json new file mode 100644 index 00000000..929beeaa --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/lime_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///lime_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///lime_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/magenta_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/magenta_authorized_card.json new file mode 100644 index 00000000..8809b958 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/magenta_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///magenta_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///magenta_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/orange_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/orange_authorized_card.json new file mode 100644 index 00000000..7ef8ffa4 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/orange_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///orange_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///orange_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/pink_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/pink_authorized_card.json new file mode 100644 index 00000000..f9c5f443 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/pink_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///pink_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///pink_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/purple_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/purple_authorized_card.json new file mode 100644 index 00000000..6e4b8fa9 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/purple_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///purple_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///purple_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/red_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/red_authorized_card.json new file mode 100644 index 00000000..2d3f6c0d --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/red_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///red_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///red_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/white_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/white_authorized_card.json new file mode 100644 index 00000000..bcd2f148 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/white_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///white_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///white_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/yellow_authorized_card.json b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/yellow_authorized_card.json new file mode 100644 index 00000000..fb40cf2f --- /dev/null +++ b/common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/yellow_authorized_card.json @@ -0,0 +1,35 @@ +{ + "parent": "minecraft:recipes/root", + "criteria": { + "has_item": { + "conditions": { + "items": [ + { + "items": [ + "create:precision_mechanism" + ] + } + ] + }, + "trigger": "minecraft:inventory_changed" + }, + "has_the_recipe": { + "conditions": { + "recipe": "numismatics:crafting///yellow_authorized_card" + }, + "trigger": "minecraft:recipe_unlocked" + } + }, + "requirements": [ + [ + "has_item", + "has_the_recipe" + ] + ], + "rewards": { + "recipes": [ + "numismatics:crafting///yellow_authorized_card" + ] + }, + "sends_telemetry_event": false +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/black_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/black_authorized_card.json new file mode 100644 index 00000000..4c5a7429 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/black_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/black_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:black_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/blue_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/blue_authorized_card.json new file mode 100644 index 00000000..580cd6be --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/blue_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/blue_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:blue_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/brown_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/brown_authorized_card.json new file mode 100644 index 00000000..39b4d132 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/brown_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/brown_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:brown_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/cyan_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/cyan_authorized_card.json new file mode 100644 index 00000000..562f9193 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/cyan_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/cyan_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:cyan_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/gray_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/gray_authorized_card.json new file mode 100644 index 00000000..5a72b9b1 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/gray_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/gray_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:gray_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/green_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/green_authorized_card.json new file mode 100644 index 00000000..eea8bf59 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/green_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/green_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:green_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/light_blue_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/light_blue_authorized_card.json new file mode 100644 index 00000000..42cb32d4 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/light_blue_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/light_blue_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:light_blue_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/light_gray_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/light_gray_authorized_card.json new file mode 100644 index 00000000..33e4887d --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/light_gray_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/light_gray_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:light_gray_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/lime_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/lime_authorized_card.json new file mode 100644 index 00000000..c8ec72cb --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/lime_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/lime_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:lime_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/magenta_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/magenta_authorized_card.json new file mode 100644 index 00000000..390da298 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/magenta_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/magenta_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:magenta_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/orange_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/orange_authorized_card.json new file mode 100644 index 00000000..5e1ddc32 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/orange_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/orange_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:orange_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/pink_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/pink_authorized_card.json new file mode 100644 index 00000000..65a8adbe --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/pink_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/pink_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:pink_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/purple_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/purple_authorized_card.json new file mode 100644 index 00000000..714f0cb2 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/purple_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/purple_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:purple_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/red_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/red_authorized_card.json new file mode 100644 index 00000000..db6ee1f2 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/red_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/red_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:red_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/white_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/white_authorized_card.json new file mode 100644 index 00000000..0bbf6468 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/white_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/white_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:white_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/recipes/crafting/yellow_authorized_card.json b/common/src/generated/resources/data/numismatics/recipes/crafting/yellow_authorized_card.json new file mode 100644 index 00000000..200ef348 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/recipes/crafting/yellow_authorized_card.json @@ -0,0 +1,22 @@ +{ + "type": "minecraft:crafting_shaped", + "category": "misc", + "key": { + "/": { + "tag": "numismatics:internal/dyes/yellow_dyes" + }, + "@": { + "item": "create:precision_mechanism" + }, + "_": { + "tag": "numismatics:internal/plates/gold_plates" + } + }, + "pattern": [ + "@_/" + ], + "result": { + "item": "numismatics:yellow_authorized_card" + }, + "show_notification": true +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/tags/items/authorized_cards.json b/common/src/generated/resources/data/numismatics/tags/items/authorized_cards.json new file mode 100644 index 00000000..1f2c0238 --- /dev/null +++ b/common/src/generated/resources/data/numismatics/tags/items/authorized_cards.json @@ -0,0 +1,21 @@ +{ + "replace": false, + "values": [ + "numismatics:white_authorized_card", + "numismatics:orange_authorized_card", + "numismatics:magenta_authorized_card", + "numismatics:light_blue_authorized_card", + "numismatics:yellow_authorized_card", + "numismatics:lime_authorized_card", + "numismatics:pink_authorized_card", + "numismatics:gray_authorized_card", + "numismatics:light_gray_authorized_card", + "numismatics:cyan_authorized_card", + "numismatics:purple_authorized_card", + "numismatics:blue_authorized_card", + "numismatics:brown_authorized_card", + "numismatics:green_authorized_card", + "numismatics:red_authorized_card", + "numismatics:black_authorized_card" + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/tags/items/internal/plates/gold_plates.json b/common/src/generated/resources/data/numismatics/tags/items/internal/plates/gold_plates.json new file mode 100644 index 00000000..701f08da --- /dev/null +++ b/common/src/generated/resources/data/numismatics/tags/items/internal/plates/gold_plates.json @@ -0,0 +1,13 @@ +{ + "replace": false, + "values": [ + { + "id": "#c:gold_plates", + "required": false + }, + { + "id": "#forge:plates/gold", + "required": false + } + ] +} \ No newline at end of file diff --git a/common/src/generated/resources/data/numismatics/tags/items/numismatics_items.json b/common/src/generated/resources/data/numismatics/tags/items/numismatics_items.json index 0dd4b13d..63d2c47b 100644 --- a/common/src/generated/resources/data/numismatics/tags/items/numismatics_items.json +++ b/common/src/generated/resources/data/numismatics/tags/items/numismatics_items.json @@ -5,45 +5,61 @@ "numismatics:bank_terminal", "numismatics:banking_guide", "numismatics:bevel", + "numismatics:black_authorized_card", "numismatics:black_card", "numismatics:black_id_card", "numismatics:blaze_banker", + "numismatics:blue_authorized_card", "numismatics:blue_card", "numismatics:blue_id_card", "numismatics:brass_depositor", + "numismatics:brown_authorized_card", "numismatics:brown_card", "numismatics:brown_id_card", "numismatics:cog", "numismatics:creative_vendor", "numismatics:crown", + "numismatics:cyan_authorized_card", "numismatics:cyan_card", "numismatics:cyan_id_card", + "numismatics:gray_authorized_card", "numismatics:gray_card", "numismatics:gray_id_card", + "numismatics:green_authorized_card", "numismatics:green_card", "numismatics:green_id_card", + "numismatics:light_blue_authorized_card", "numismatics:light_blue_card", "numismatics:light_blue_id_card", + "numismatics:light_gray_authorized_card", "numismatics:light_gray_card", "numismatics:light_gray_id_card", + "numismatics:lime_authorized_card", "numismatics:lime_card", "numismatics:lime_id_card", + "numismatics:magenta_authorized_card", "numismatics:magenta_card", "numismatics:magenta_id_card", + "numismatics:orange_authorized_card", "numismatics:orange_card", "numismatics:orange_id_card", + "numismatics:pink_authorized_card", "numismatics:pink_card", "numismatics:pink_id_card", + "numismatics:purple_authorized_card", "numismatics:purple_card", "numismatics:purple_id_card", + "numismatics:red_authorized_card", "numismatics:red_card", "numismatics:red_id_card", "numismatics:sprocket", "numismatics:spur", "numismatics:sun", "numismatics:vendor", + "numismatics:white_authorized_card", "numismatics:white_card", "numismatics:white_id_card", + "numismatics:yellow_authorized_card", "numismatics:yellow_card", "numismatics:yellow_id_card" ] diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/NumismaticsClient.java b/common/src/main/java/dev/ithundxr/createnumismatics/NumismaticsClient.java index 6c12e972..436e7bb6 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/NumismaticsClient.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/NumismaticsClient.java @@ -28,7 +28,8 @@ public class NumismaticsClient { - public final static Map bankAccountLabels = new HashMap<>(); + public static final Map bankAccountLabels = new HashMap<>(); + public static final Map subAccountLabels = new HashMap<>(); public static void init() { NumismaticsPackets.PACKETS.registerS2CListener(); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/base/client/rendering/UIRenderHelper.java b/common/src/main/java/dev/ithundxr/createnumismatics/base/client/rendering/UIRenderHelper.java new file mode 100644 index 00000000..adb89381 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/client/rendering/UIRenderHelper.java @@ -0,0 +1,61 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.base.client.rendering; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferBuilder; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.Tesselator; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.simibubi.create.foundation.utility.Color; +import dev.ithundxr.createnumismatics.registry.NumismaticsGuiTextures; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.GameRenderer; +import org.joml.Matrix4f; + +public class UIRenderHelper extends com.simibubi.create.foundation.gui.UIRenderHelper { + public static void drawStretched(GuiGraphics graphics, int left, int top, int w, int h, int z, NumismaticsGuiTextures tex) { + tex.bind(); + drawTexturedQuad(graphics.pose().last() + .pose(), Color.WHITE, left, left + w, top, top + h, z, tex.startX / 256f, (tex.startX + tex.width) / 256f, + tex.startY / 256f, (tex.startY + tex.height) / 256f); + } + + public static void drawCropped(GuiGraphics graphics, int left, int top, int w, int h, int z, NumismaticsGuiTextures tex) { + tex.bind(); + drawTexturedQuad(graphics.pose().last() + .pose(), Color.WHITE, left, left + w, top, top + h, z, tex.startX / 256f, (tex.startX + w) / 256f, + tex.startY / 256f, (tex.startY + h) / 256f); + } + + private static void drawTexturedQuad(Matrix4f m, Color c, int left, int right, int top, int bot, int z, float u1, float u2, float v1, float v2) { + Tesselator tesselator = Tesselator.getInstance(); + BufferBuilder bufferbuilder = tesselator.getBuilder(); + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + RenderSystem.setShader(GameRenderer::getPositionColorTexShader); + bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR_TEX); + bufferbuilder.vertex(m, (float) left , (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u1, v2).endVertex(); + bufferbuilder.vertex(m, (float) right, (float) bot, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u2, v2).endVertex(); + bufferbuilder.vertex(m, (float) right, (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u2, v1).endVertex(); + bufferbuilder.vertex(m, (float) left , (float) top, (float) z).color(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()).uv(u1, v1).endVertex(); + tesselator.end(); + RenderSystem.disableBlend(); + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/base/data/NumismaticsTagGen.java b/common/src/main/java/dev/ithundxr/createnumismatics/base/data/NumismaticsTagGen.java index 2b127e0a..645f43ce 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/base/data/NumismaticsTagGen.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/data/NumismaticsTagGen.java @@ -21,17 +21,14 @@ import com.simibubi.create.foundation.data.TagGen; import com.tterrag.registrate.providers.RegistrateItemTagsProvider; import com.tterrag.registrate.providers.RegistrateTagsProvider; -import com.tterrag.registrate.util.entry.RegistryEntry; import dev.architectury.injectables.annotations.ExpectPlatform; import dev.ithundxr.createnumismatics.Numismatics; import dev.ithundxr.createnumismatics.multiloader.CommonTags; -import dev.ithundxr.createnumismatics.registry.NumismaticsBlocks; import dev.ithundxr.createnumismatics.registry.NumismaticsTags; import dev.ithundxr.createnumismatics.registry.NumismaticsTags.AllBlockTags; import dev.ithundxr.createnumismatics.registry.NumismaticsTags.AllItemTags; import net.minecraft.core.DefaultedRegistry; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.core.registries.Registries; import net.minecraft.data.tags.TagsProvider; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; @@ -79,6 +76,7 @@ public static void generateItemTags(RegistrateItemTagsProvider tags) { CommonTags.STRING.generateCommon(tags) .generateBoth(tags, tag -> tag.add(Items.STRING.builtInRegistryHolder().key())); CommonTags.IRON_PLATES.generateCommon(tags); + CommonTags.GOLD_PLATES.generateCommon(tags); // .generateBoth(tags, tag -> tag.add(AllItems.IRON_SHEET.get())); for (AllItemTags tag : AllItemTags.values()) { diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/base/data/lang/NumismaticsLangGen.java b/common/src/main/java/dev/ithundxr/createnumismatics/base/data/lang/NumismaticsLangGen.java index 7e282ed2..2979308e 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/base/data/lang/NumismaticsLangGen.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/data/lang/NumismaticsLangGen.java @@ -22,6 +22,8 @@ import com.google.gson.JsonObject; import com.simibubi.create.foundation.utility.FilesHelper; import com.tterrag.registrate.providers.RegistrateLangProvider; +import dev.ithundxr.createnumismatics.content.backend.Coin; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.AuthorizationType; import dev.ithundxr.createnumismatics.registry.NumismaticsAdvancements; import java.util.Map; @@ -34,6 +36,15 @@ public static void generate(RegistrateLangProvider provider) { provideDefaultLang("interface", langConsumer); provideDefaultLang("tooltips", langConsumer); NumismaticsAdvancements.provideLang(langConsumer); + AuthorizationType.provideLang(langConsumer); + Coin.provideLang(langConsumer); + + /* ================= */ + /* Special data keys */ + /* ================= */ + + // Is the language read left-to-right? + provider.add("numismatics.special.ltr", "true"); } private static void provideDefaultLang(String fileName, BiConsumer consumer) { diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/base/data/recipe/NumismaticsRecipeProvider.java b/common/src/main/java/dev/ithundxr/createnumismatics/base/data/recipe/NumismaticsRecipeProvider.java index dd177476..615b1311 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/base/data/recipe/NumismaticsRecipeProvider.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/data/recipe/NumismaticsRecipeProvider.java @@ -100,6 +100,10 @@ public static TagKey ironSheet() { return CommonTags.IRON_PLATES.tag; } + public static TagKey goldSheet() { + return CommonTags.GOLD_PLATES.tag; + } + public static TagKey dye(@NotNull DyeColor color) { return CommonTags.DYES.get(color).tag; } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/base/data/recipe/NumismaticsStandardRecipeGen.java b/common/src/main/java/dev/ithundxr/createnumismatics/base/data/recipe/NumismaticsStandardRecipeGen.java index 56cd373f..fb830502 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/base/data/recipe/NumismaticsStandardRecipeGen.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/data/recipe/NumismaticsStandardRecipeGen.java @@ -116,6 +116,15 @@ public class NumismaticsStandardRecipeGen extends NumismaticsRecipeProvider { .define('/', Ingredients.dye(color))) ); + DyedRecipeList AUTHORIZED_CARDS = new DyedRecipeList(color -> create(NumismaticsItems.AUTHORIZED_CARDS.get(color)) + .unlockedBy(Ingredients::precisionMechanism) + .viaShaped(b -> b + .pattern("@_/") + .define('@', Ingredients.precisionMechanism()) + .define('_', Ingredients.goldSheet()) + .define('/', Ingredients.dye(color))) + ); + GeneratedRecipeBuilder create(Supplier result) { return new GeneratedRecipeBuilder("/", result); } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/base/item/DelegatingContainer.java b/common/src/main/java/dev/ithundxr/createnumismatics/base/item/DelegatingContainer.java new file mode 100644 index 00000000..3917f2a6 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/item/DelegatingContainer.java @@ -0,0 +1,89 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.base.item; + +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +public abstract class DelegatingContainer implements Container { + + protected abstract Container getContainer(); + + @Override + public int getContainerSize() { + Container container = getContainer(); + return container == null ? 0 : container.getContainerSize(); + } + + @Override + public boolean isEmpty() { + Container container = getContainer(); + return container == null || container.isEmpty(); + } + + @Override + public @NotNull ItemStack getItem(int slot) { + Container container = getContainer(); + return container == null ? ItemStack.EMPTY : container.getItem(slot); + } + + @Override + public @NotNull ItemStack removeItem(int slot, int amount) { + Container container = getContainer(); + return container == null ? ItemStack.EMPTY : container.removeItem(slot, amount); + } + + @Override + public @NotNull ItemStack removeItemNoUpdate(int slot) { + Container container = getContainer(); + return container == null ? ItemStack.EMPTY : container.removeItemNoUpdate(slot); + } + + @Override + public void setItem(int slot, @NotNull ItemStack stack) { + Container container = getContainer(); + if (container != null) { + container.setItem(slot, stack); + } + } + + @Override + public void setChanged() { + Container container = getContainer(); + if (container != null) { + container.setChanged(); + } + } + + @Override + public boolean stillValid(@NotNull Player player) { + Container container = getContainer(); + return container != null && container.stillValid(player); + } + + @Override + public void clearContent() { + Container container = getContainer(); + if (container != null) { + container.clearContent(); + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/base/item/DynamicContainer.java b/common/src/main/java/dev/ithundxr/createnumismatics/base/item/DynamicContainer.java new file mode 100644 index 00000000..7b697f72 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/item/DynamicContainer.java @@ -0,0 +1,36 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.base.item; + +import net.minecraft.world.Container; + +import java.util.function.Supplier; + +public class DynamicContainer extends DelegatingContainer { + private final Supplier containerSupplier; + + public DynamicContainer(Supplier containerSupplier) { + this.containerSupplier = containerSupplier; + } + + @Override + protected Container getContainer() { + return containerSupplier.get(); + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/base/item/SingleCallbackContainer.java b/common/src/main/java/dev/ithundxr/createnumismatics/base/item/SingleCallbackContainer.java new file mode 100644 index 00000000..0d40e7ea --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/item/SingleCallbackContainer.java @@ -0,0 +1,44 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.base.item; + +import net.minecraft.world.Container; +import net.minecraft.world.ContainerListener; + +public class SingleCallbackContainer extends DelegatingContainer { + + private final Container container; + private final ContainerListener onChanged; + + public SingleCallbackContainer(Container container, ContainerListener onChanged) { + this.container = container; + this.onChanged = onChanged; + } + + @Override + protected Container getContainer() { + return container; + } + + @Override + public void setChanged() { + super.setChanged(); + onChanged.containerChanged(this); + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/implementation/peripherals/BankTerminalPeripheral.java b/common/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/implementation/peripherals/BankTerminalPeripheral.java new file mode 100644 index 00000000..8cb0bece --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/implementation/peripherals/BankTerminalPeripheral.java @@ -0,0 +1,150 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.compat.computercraft.implementation.peripherals; + +import com.simibubi.create.foundation.utility.Components; +import dan200.computercraft.api.lua.LuaException; +import dan200.computercraft.api.lua.LuaFunction; +import dan200.computercraft.api.peripheral.IComputerAccess; +import dan200.computercraft.api.peripheral.IPeripheral; +import dev.ithundxr.createnumismatics.Numismatics; +import dev.ithundxr.createnumismatics.content.backend.BankAccount; +import dev.ithundxr.createnumismatics.content.backend.IDeductable; +import dev.ithundxr.createnumismatics.content.backend.ReasonHolder; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.Authorization; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.SubAccount; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public enum BankTerminalPeripheral implements IPeripheral { + INSTANCE + ; + + @LuaFunction + public final int getBalance(String accountID) throws LuaException { + UUID account$; + try { + account$ = UUID.fromString(accountID); + } catch (IllegalArgumentException e) { + throw new LuaException("Invalid UUID"); + } + + BankAccount bankAccount = Numismatics.BANK.getAccount(account$); + if (bankAccount == null) { + throw new LuaException("Account not found"); + } + + return bankAccount.getBalance(); + } + + @LuaFunction + public final int getMaxAvailableWithdrawal(String accountID, String authorizationID) throws LuaException { + UUID account$, authorization$; + try { + account$ = UUID.fromString(accountID); + authorization$ = UUID.fromString(authorizationID); + } catch (IllegalArgumentException e) { + throw new LuaException("Invalid UUID"); + } + + Authorization authorization = new Authorization.Anonymous(authorization$); + + BankAccount bankAccount = Numismatics.BANK.getAccount(account$); + if (bankAccount == null) { + throw new LuaException("Account not found"); + } + + ReasonHolder reasonHolder = new ReasonHolder(); + SubAccount subAccount = bankAccount.getSubAccount(authorization, reasonHolder); + + if (subAccount == null) { + Component errorMessage = reasonHolder.getMessageOrDefault(Components.translatable("error.numismatics.authorized_card.account_not_found")); + throw new LuaException(errorMessage.getString()); + } + + IDeductable deductable = subAccount.getDeductor(authorization); + + if (deductable == null) { + throw new LuaException("Deductor not found"); + } + + return deductable.getMaxWithdrawal(); + } + + @LuaFunction(mainThread = true) + public final void transfer(String fromAccountID, String fromAuthorizationID, String toAccountID, int amount) throws LuaException { + UUID from$, fromAuthorization$, to$; + try { + from$ = UUID.fromString(fromAccountID); + fromAuthorization$ = UUID.fromString(fromAuthorizationID); + to$ = UUID.fromString(toAccountID); + } catch (IllegalArgumentException e) { + throw new LuaException("Invalid UUID"); + } + + Authorization authorization = new Authorization.Anonymous(fromAuthorization$); + + BankAccount account = Numismatics.BANK.getAccount(from$); + BankAccount toAccount = Numismatics.BANK.getAccount(to$); + if (account == null || toAccount == null) { + throw new LuaException("Account not found"); + } + + ReasonHolder reasonHolder = new ReasonHolder(); + SubAccount subAccount = account.getSubAccount(authorization, reasonHolder); + + if (subAccount == null) { + Component errorMessage = reasonHolder.getMessageOrDefault(Components.translatable("error.numismatics.authorized_card.account_not_found")); + throw new LuaException(errorMessage.getString()); + } + + IDeductable deductable = subAccount.getDeductor(authorization); + + if (deductable == null) { + throw new LuaException("Deductor not found"); + } + + if (deductable.getMaxWithdrawal() < amount) { + throw new LuaException("Insufficient funds"); + } + + if (deductable.deduct(amount, reasonHolder)) { + toAccount.deposit(amount); + } else { + throw new LuaException(reasonHolder.getMessageOrDefault().getString()); + } + } + + @Override + public String getType() { + return "Numismatics_BankTerminal"; + } + + @Override + public void attach(IComputerAccess computer) { + IPeripheral.super.attach(computer); + } + + @Override + public boolean equals(@Nullable IPeripheral other) { + return other == INSTANCE; + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/BankAccount.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/BankAccount.java index dc4897b0..fac676b9 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/BankAccount.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/BankAccount.java @@ -21,18 +21,26 @@ import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.NBTHelper; import dev.ithundxr.createnumismatics.Numismatics; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.Authorization; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.SubAccount; import dev.ithundxr.createnumismatics.content.bank.BankMenu; +import dev.ithundxr.createnumismatics.content.bank.SubAccountListMenu; import dev.ithundxr.createnumismatics.content.coins.LinkedMergingCoinBag; import dev.ithundxr.createnumismatics.content.coins.MergingCoinBag; import dev.ithundxr.createnumismatics.multiloader.PlayerSelection; import dev.ithundxr.createnumismatics.registry.NumismaticsMenuTypes; import dev.ithundxr.createnumismatics.registry.NumismaticsPackets; import dev.ithundxr.createnumismatics.registry.packets.BankAccountLabelPacket; +import dev.ithundxr.createnumismatics.registry.packets.sub_account.OpenSubAccountsMenuPacket; import dev.ithundxr.createnumismatics.util.UsernameUtils; +import dev.ithundxr.createnumismatics.util.Utils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.chat.Component; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; @@ -47,7 +55,7 @@ import static dev.ithundxr.createnumismatics.Numismatics.crashDev; -public class BankAccount implements MenuProvider { +public class BankAccount implements MenuProvider, IDeductable { public enum Type { PLAYER(false, false), BLAZE_BANKER(true, true); @@ -88,6 +96,9 @@ public void write(CompoundTag nbt) { @Nullable private List trustList; // only present on server + @Nullable + private Map subAccounts; // only present on server + @Nullable private String label; @@ -113,6 +124,8 @@ public int getCount() { } }; + private final MenuProvider subAccountsMenuProvider = new SubAccountsMenuProvider(); + public BankAccount(UUID id, Type type) { this(id, 0, type); } @@ -128,12 +141,52 @@ protected BankAccount(UUID id, Type type, int balance, boolean clientSide) { this.clientSide = clientSide; if (type.useTrustList && !clientSide) trustList = new ArrayList<>(); + if (!clientSide) + subAccounts = new HashMap<>(); } public static BankAccount clientSide(FriendlyByteBuf buf) { return new BankAccount(buf.readUUID(), Type.read(buf), buf.readVarInt(), true); } + public static BankAccount clientSideSubAccountList(FriendlyByteBuf buf) { + BankAccount account = clientSide(buf); + int subAccountCount = buf.readVarInt(); + account.subAccounts = new HashMap<>(); + for (int i = 0; i < subAccountCount; i++) { + SubAccount subAccount = SubAccount.clientSide(account, buf); + account.subAccounts.put(subAccount.getAuthorizationID(), subAccount); + } + return account; + } + + public void updateSubAccountsFrom(FriendlyByteBuf buf) { + if (!clientSide) { + crashDev("updateSubAccountsFrom called on server side! (Account: "+this+")"); + return; + } + + Map oldSubAccounts = subAccounts; + + if (oldSubAccounts == null) + oldSubAccounts = new HashMap<>(); + + subAccounts = new HashMap<>(); + int subAccountCount = buf.readVarInt(); + for (int i = 0; i < subAccountCount; i++) { + SubAccount newSubAccount = SubAccount.clientSide(this, buf); + SubAccount existingSubAccount = oldSubAccounts.remove(newSubAccount.getAuthorizationID()); + if (existingSubAccount == null) { + existingSubAccount = newSubAccount; + } else { + existingSubAccount.updateFrom(newSubAccount); + } + subAccounts.put(existingSubAccount.getAuthorizationID(), existingSubAccount); + } + + oldSubAccounts.values().forEach(SubAccount::setRemoved); + } + public int getBalance() { return balance; } @@ -160,14 +213,21 @@ public void deposit(int amount) { setBalance(getBalance() + amount); } - public boolean deduct(Coin coin, int amount) { + @Override + public boolean deduct(Coin coin, int amount, ReasonHolder reasonHolder) { return deduct(coin, amount, false); } - public boolean deduct(int amount) { + @Override + public boolean deduct(int amount, ReasonHolder reasonHolder) { return deduct(amount, false); } + @Override + public int getMaxWithdrawal() { + return getBalance(); + } + public boolean deduct(Coin coin, int amount, boolean force) { return deduct(coin.toSpurs(amount), force); } @@ -214,6 +274,16 @@ public static BankAccount load(CompoundTag nbt) { } if (account.type.hasLabel && nbt.contains("Label", Tag.TAG_STRING)) account.label = nbt.getString("Label"); + + if (account.subAccounts != null && nbt.contains("SubAccounts")) { + account.subAccounts.clear(); + + NBTHelper.readCompoundList( + nbt.getList("SubAccounts", Tag.TAG_COMPOUND), + (tag) -> SubAccount.read(account, tag) + ).forEach(subAccount -> account.subAccounts.put(subAccount.getAuthorizationID(), subAccount)); + } + return account; } @@ -233,6 +303,11 @@ public CompoundTag save(CompoundTag nbt) { if (type.hasLabel && label != null) nbt.putString("Label", label); + + if (subAccounts != null) { + nbt.put("SubAccounts", NBTHelper.writeCompoundList(subAccounts.values(), SubAccount::write)); + } + return nbt; } @@ -279,6 +354,44 @@ public void sendToMenu(FriendlyByteBuf buf) { buf.writeVarInt(this.balance); } + public void sendToSubAccountsMenu(FriendlyByteBuf buf) { + sendToMenu(buf); + sendSubAccountsOnlyToMenu(buf); + } + + public void sendSubAccountsOnlyToMenu(FriendlyByteBuf buf) { + if (subAccounts == null) { + buf.writeVarInt(0); + } else { + buf.writeVarInt(subAccounts.size()); + for (SubAccount subAccount : subAccounts.values()) { + subAccount.sendToMenu(buf); + } + } + } + + public @Nullable UUID addSubAccount(@NotNull String label) { + if (subAccounts == null) + return null; + + SubAccount subAccount = new SubAccount(this, label, UUID.randomUUID()); + subAccounts.put(subAccount.getAuthorizationID(), subAccount); + NumismaticsPackets.PACKETS.sendTo(PlayerSelection.all(), new BankAccountLabelPacket(subAccount)); + markDirty(); + return subAccount.getAuthorizationID(); + } + + public @Nullable SubAccount removeSubAccount(UUID subAccountID) { + if (subAccounts == null) + return null; + + SubAccount subAccount = subAccounts.remove(subAccountID); + subAccount.setRemoved(); + NumismaticsPackets.PACKETS.sendTo(PlayerSelection.all(), BankAccountLabelPacket.remove(subAccount)); + markDirty(); + return subAccount; + } + public boolean isClientSide() { return clientSide; } @@ -299,6 +412,9 @@ public boolean isAuthorized(Player player) { return isAuthorized(player.getUUID()); } + /** + * If possible, use {@link #isAuthorized(Player)} instead. + */ public boolean isAuthorized(@Nullable UUID uuid) { if (uuid == null) return false; return uuid.equals(this.id) || (this.type.useTrustList && this.trustList != null && this.trustList.contains(uuid)); @@ -310,4 +426,86 @@ public void updateTrustList(Consumer> updater) { markDirty(); } } + + public boolean hasSubAccounts() { + return subAccounts != null && !subAccounts.isEmpty(); + } + + public @Nullable Collection getSubAccounts() { + return subAccounts == null ? null : subAccounts.values(); + } + + public @NotNull Collection getAlphabetizedSubAccounts() { + if (subAccounts == null) + return Collections.emptyList(); + + return subAccounts.values().stream() + .sorted(Comparator.comparing(SubAccount::getLabel)) + .collect(Collectors.toList()); + } + + public @Nullable SubAccount getSubAccountNoAuth(UUID subAccountID) { + return subAccounts == null ? null : subAccounts.get(subAccountID); + } + + public @Nullable SubAccount getSubAccount(Authorization authorization, ReasonHolder reasonHolder) { + if (subAccounts == null) { + reasonHolder.setMessage(Components.translatable("error.numismatics.authorized_card.account_not_found")); + return null; + } + + SubAccount subAccount = subAccounts.get(authorization.getAuthorizationID()); + if (subAccount == null) { + reasonHolder.setMessage(Components.translatable("error.numismatics.authorized_card.account_not_found")); + return null; + } + + if (!subAccount.isAuthorized(authorization)) { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.not_authorized")); + return null; + } + + return subAccount; + } + + public void openSubAccountsMenu(ServerPlayer player) { + Utils.openScreen( + player, + subAccountsMenuProvider, + this::sendToSubAccountsMenu + ); + } + + @Environment(EnvType.CLIENT) + public void openSubAccountsMenu() { + NumismaticsPackets.PACKETS.send(new OpenSubAccountsMenuPacket(this)); + } + + @Environment(EnvType.CLIENT) + public void openNormalMenu() { + NumismaticsPackets.PACKETS.send(new OpenSubAccountsMenuPacket(this, false)); + } + + private class SubAccountsMenuProvider implements MenuProvider { + @Override + public @NotNull Component getDisplayName() { + String for_ = getLabel(); + + if (for_ == null) + for_ = UsernameUtils.INSTANCE.getName(id, null); + + if (for_ != null) { + return Components.translatable("gui.numismatics.bank_terminal.sub_accounts.named", for_); + } else { + return Components.translatable("gui.numismatics.bank_terminal.sub_accounts"); + } + } + + @Override + @Nullable + public AbstractContainerMenu createMenu(int i, @NotNull Inventory inventory, @NotNull Player player) { + + return new SubAccountListMenu(NumismaticsMenuTypes.SUB_ACCOUNT_LIST.get(), i, inventory, BankAccount.this); + } + } } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/Coin.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/Coin.java index 336e0491..24856836 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/Coin.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/Coin.java @@ -31,6 +31,7 @@ import net.minecraft.world.item.Rarity; import java.util.*; +import java.util.function.BiConsumer; import static dev.ithundxr.createnumismatics.registry.NumismaticsIcons.*; @@ -93,6 +94,23 @@ public Couple convert(int amount) { return Couple.create(converted, remainder); } + /** + * Convert spurs to this coin + * @param amount Number of spurs + * @param max Maximum number of this coin + * @return Couple of (amount of this coin, remainder of spurs) + */ + public Couple convert(int amount, int max) { + if (this == SPUR) return Couple.create(amount, 0); + int remainder = amount % value; + int converted = (amount - remainder) / value; + if (converted > max) { + remainder += (converted - max) * value; + converted = max; + } + return Couple.create(converted, remainder); + } + public String getName() { return name().toLowerCase(Locale.ROOT); } @@ -109,7 +127,7 @@ public String getName(int amount) { return (amount != 1 ? getTranslatedNamePlural() : getTranslatedName()); } - public String getDisplayName() { + public String getDefaultLangName() { return TextUtils.titleCaseConversion(getName()); } @@ -169,6 +187,12 @@ public static Coin getCoinFromName(String name){ return selectedCoin; } + public static void provideLang(BiConsumer consumer) { + for (Coin coin : values()) { + consumer.accept(coin.getTranslationKey() + ".plural", coin.getDefaultLangName()+"s"); + } + } + public static Iterable valuesHighToLow() { return Arrays.stream(values()).sorted(Comparator.comparingInt(c -> -c.value))::iterator; } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/IDeductable.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/IDeductable.java new file mode 100644 index 00000000..ec46cdff --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/IDeductable.java @@ -0,0 +1,123 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.backend; + +import com.mojang.datafixers.util.Either; +import com.simibubi.create.content.kinetics.deployer.DeployerFakePlayer; +import com.simibubi.create.foundation.utility.Components; +import dev.ithundxr.createnumismatics.Numismatics; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.Authorization; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.SubAccount; +import dev.ithundxr.createnumismatics.content.bank.AuthorizedCardItem; +import dev.ithundxr.createnumismatics.content.bank.AuthorizedCardItem.AuthorizationPair; +import dev.ithundxr.createnumismatics.content.bank.CardItem; +import dev.ithundxr.createnumismatics.registry.NumismaticsTags; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; +import java.util.UUID; + +public interface IDeductable { + boolean deduct(Coin coin, int amount, ReasonHolder reasonHolder); + boolean deduct(int spurs, ReasonHolder reasonHolder); + int getMaxWithdrawal(); + + @Nullable + static IDeductable get(ItemStack stack, @Nullable Player player, ReasonHolder reasonHolder) { + return IDeductable.getInternal(stack, player == null ? null : Either.left(player), reasonHolder); + } + + @Nullable + static IDeductable getAutomated(ItemStack stack, @Nullable UUID owningPlayer, ReasonHolder reasonHolder) { + return IDeductable.getInternal(stack, owningPlayer == null ? null : Either.right(owningPlayer), reasonHolder); + } + + @Nullable + private static IDeductable getInternal(ItemStack stack, @Nullable Either player, ReasonHolder reasonHolder) { + if (NumismaticsTags.AllItemTags.CARDS.matches(stack)) { + if (player == null) + return null; + + Optional left = player.left(); + if (left.isEmpty()) + return null; + + Player player$ = left.get(); + if (player$ instanceof DeployerFakePlayer) + return null; + + if (CardItem.isBound(stack)) { + UUID id = CardItem.get(stack); + BankAccount account = Numismatics.BANK.getAccount(id); + + if (account != null && account.isAuthorized(player$)) { + return account; + } else if (account == null) { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.account_not_found")); + } else { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.not_authorized")); + } + } else { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.not_bound")); + } + } else if (NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(stack)) { + AuthorizationPair authorizedPair = AuthorizedCardItem.get(stack); + + if (authorizedPair == null) { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.not_bound")); + return null; + } + + Authorization authorization; + if (player == null) { + authorization = new Authorization.Anonymous(authorizedPair.authorizationID()); + } else { + authorization = player.map( + p -> p instanceof DeployerFakePlayer + ? new Authorization.Automation(p.getUUID(), authorizedPair.authorizationID()) + : new Authorization.Player(p, authorizedPair.authorizationID()), + uuid -> new Authorization.Automation(uuid, authorizedPair.authorizationID()) + ); + } + + BankAccount account = Numismatics.BANK.getAccount(authorizedPair.accountID()); + + if (account == null) { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.account_not_found")); + return null; + } + + SubAccount subAccount = account.getSubAccount(authorization, reasonHolder); + + if (subAccount != null) { + IDeductable deductor = subAccount.getDeductor(authorization); + if (deductor == null) { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.not_authorized")); + } + return deductor; + } else if (!reasonHolder.hasMessage()) { + reasonHolder.setMessage(Components.translatable("error.numismatics.authorized_card.account_not_found")); + } + } + + return null; + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/ItemWritingContainer.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/ItemWritingContainer.java new file mode 100644 index 00000000..7bba0d91 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/ItemWritingContainer.java @@ -0,0 +1,98 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.backend; + +import net.minecraft.world.Container; +import net.minecraft.world.ContainerHelper; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Consumer; + +public abstract class ItemWritingContainer> implements Container { + private final Consumer slotsChangedCallback; + + @NotNull + protected final List stacks = new ArrayList<>(); + + public ItemWritingContainer(Consumer slotsChangedCallback) { + this.slotsChangedCallback = slotsChangedCallback; + stacks.add(ItemStack.EMPTY); + } + + @Override + public int getContainerSize() { + return 1; + } + + protected ItemStack getStack() { + return stacks.get(0); + } + + @Override + public boolean isEmpty() { + return getStack().isEmpty(); + } + + @Override + public @NotNull ItemStack getItem(int slot) { + return getStack(); + } + + @Override + public @NotNull ItemStack removeItem(int slot, int amount) { + ItemStack stack = ContainerHelper.removeItem(this.stacks, 0, amount); + if (!stack.isEmpty()) { + this.slotsChangedCallback.accept((SELF) this); + } + return stack; + } + + @Override + public @NotNull ItemStack removeItemNoUpdate(int slot) { + return ContainerHelper.takeItem(this.stacks, 0); + } + + protected abstract void doWriteItem(ItemStack stack); + + @Override + public void setItem(int slot, @NotNull ItemStack stack) { + this.stacks.set(0, stack); + doWriteItem(stack); + this.slotsChangedCallback.accept((SELF) this); + } + + @Override + public void setChanged() { + + } + + @Override + public boolean stillValid(@NotNull Player player) { + return true; + } + + @Override + public void clearContent() { + this.stacks.set(0, ItemStack.EMPTY); + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/ReasonHolder.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/ReasonHolder.java new file mode 100644 index 00000000..526f407f --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/ReasonHolder.java @@ -0,0 +1,63 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.backend; + +import com.simibubi.create.foundation.utility.Components; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * A helper class to hold a message indicating the reason a transaction failed. + * If a method takes this as a parameter and you don't care about the message, you can pass {@link ReasonHolder#IGNORED}. + */ +public class ReasonHolder { + + public static final ReasonHolder IGNORED = new ReasonHolder() { + @Override + public void setMessage(@NotNull Component message) {} + }; + + private @Nullable Component message; + + public ReasonHolder() { + this.message = null; + } + + public void setMessage(@NotNull Component message) { + this.message = message; + } + + public boolean hasMessage() { + return message != null; + } + + public @Nullable Component getMessage() { + return message; + } + + public @NotNull MutableComponent getMessageOrDefault() { + return getMessageOrDefault(Components.translatable("gui.numismatics.vendor.insufficient_funds")); + } + + public @NotNull MutableComponent getMessageOrDefault(@NotNull Component defaultMessage) { + return (message != null ? message : defaultMessage).copy(); + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/behaviours/SliderStylePriceBehaviour.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/behaviours/SliderStylePriceBehaviour.java index 7851635a..20e9c121 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/behaviours/SliderStylePriceBehaviour.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/behaviours/SliderStylePriceBehaviour.java @@ -22,12 +22,10 @@ import com.simibubi.create.foundation.blockEntity.behaviour.BehaviourType; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; import com.simibubi.create.foundation.utility.Components; -import dev.ithundxr.createnumismatics.Numismatics; -import dev.ithundxr.createnumismatics.content.backend.BankAccount; import dev.ithundxr.createnumismatics.content.backend.Coin; -import dev.ithundxr.createnumismatics.content.bank.CardItem; +import dev.ithundxr.createnumismatics.content.backend.IDeductable; +import dev.ithundxr.createnumismatics.content.backend.ReasonHolder; import dev.ithundxr.createnumismatics.content.coins.CoinItem; -import dev.ithundxr.createnumismatics.registry.NumismaticsTags; import dev.ithundxr.createnumismatics.util.ItemUtil; import dev.ithundxr.createnumismatics.util.TextUtils; import net.minecraft.nbt.CompoundTag; @@ -38,7 +36,10 @@ import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.ArrayList; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Function; @@ -112,25 +113,20 @@ public void read(CompoundTag tag, boolean clientPacket) { calculateTotalPrice(); } - public boolean deduct(@NotNull Player player, @NotNull InteractionHand hand, boolean addToSource) { + public boolean deduct(@NotNull Player player, @NotNull InteractionHand hand, boolean addToSource, ReasonHolder reasonHolder) { int totalPrice = getTotalPrice(); ItemStack handStack = player.getItemInHand(hand); - if (NumismaticsTags.AllItemTags.CARDS.matches(handStack)) { - if (CardItem.isBound(handStack)) { - UUID id = CardItem.get(handStack); - BankAccount account = Numismatics.BANK.getAccount(id); - if (account != null && account.isAuthorized(player)) { - if (account.deduct(totalPrice)) { - //activate(state, level, pos); - if (addToSource) { - for (Map.Entry entry : prices.entrySet()) { - addCoin.accept(entry.getKey(), entry.getValue()); - } - } - return true; + IDeductable deductable = IDeductable.get(handStack, player, reasonHolder); + if (deductable != null) { + if (deductable.deduct(totalPrice, reasonHolder)) { + //activate(state, level, pos); + if (addToSource) { + for (Map.Entry entry : prices.entrySet()) { + addCoin.accept(entry.getKey(), entry.getValue()); } } + return true; } } else if (CoinItem.extract(player, hand, prices, false)) { //activate(state, level, pos); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/Authorization.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/Authorization.java new file mode 100644 index 00000000..63380b5f --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/Authorization.java @@ -0,0 +1,117 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.backend.sub_authorization; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public interface Authorization { + boolean isHuman(); + + @Nullable + UUID getPersonalID(); + + @NotNull + UUID getAuthorizationID(); + + final class Player implements Authorization { + + @Nullable + private final UUID uuid; + + @NotNull + private final UUID authorizationID; + + public Player(@NotNull net.minecraft.world.entity.player.Player player, @NotNull UUID authorizationID) { + this.uuid = player.getUUID(); + this.authorizationID = authorizationID; + } + + @Override + public boolean isHuman() { + return true; + } + + @Override + public @Nullable UUID getPersonalID() { + return uuid; + } + + @Override + public @NotNull UUID getAuthorizationID() { + return authorizationID; + } + } + + final class Automation implements Authorization { + + @Nullable + private final UUID uuid; + + @NotNull + private final UUID authorizationID; + + public Automation(@Nullable UUID uuid, @NotNull UUID authorizationID) { + this.uuid = uuid; + this.authorizationID = authorizationID; + } + + @Override + public boolean isHuman() { + return false; + } + + @Override + public @Nullable UUID getPersonalID() { + return uuid; + } + + @Override + public @NotNull UUID getAuthorizationID() { + return authorizationID; + } + } + + final class Anonymous implements Authorization { + + @NotNull + private final UUID authorizationID; + + public Anonymous(@NotNull UUID authorizationID) { + this.authorizationID = authorizationID; + } + + @Override + public boolean isHuman() { + return false; + } + + @Override + public @Nullable UUID getPersonalID() { + return null; + } + + @Override + public @NotNull UUID getAuthorizationID() { + return authorizationID; + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/AuthorizationType.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/AuthorizationType.java new file mode 100644 index 00000000..111ddcc4 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/AuthorizationType.java @@ -0,0 +1,108 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.backend.sub_authorization; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.foundation.utility.Components; +import dev.ithundxr.createnumismatics.registry.NumismaticsGuiTextures; +import net.minecraft.network.chat.Component; +import net.minecraft.util.StringRepresentable; +import org.jetbrains.annotations.NotNull; + +import java.util.List; +import java.util.Locale; +import java.util.function.BiConsumer; + +public enum AuthorizationType implements StringRepresentable { + TRUSTED_PLAYERS( + "Trusted Players Only", + "Only players on the trust list", + NumismaticsGuiTextures.SUB_ACCOUNT_MODE_TRUSTED_PLAYERS + ), + TRUSTED_AUTOMATION( + "Trusted Players + Automation", + "Players on the trust list and automation placed by them (e.g. Deployers)", + NumismaticsGuiTextures.SUB_ACCOUNT_MODE_TRUSTED_AUTOMATION + ), + ANYBODY( + "Anybody", + "Anybody with the ID, including automation such as ComputerCraft computers", + NumismaticsGuiTextures.SUB_ACCOUNT_MODE_ANY + ); + + private final String englishTitle; + private final String englishDescription; + public final NumismaticsGuiTextures icon; + + AuthorizationType(String englishTitle, String englishDescription, NumismaticsGuiTextures icon) { + this.englishTitle = englishTitle; + this.englishDescription = englishDescription; + this.icon = icon; + } + + private String titleKey() { + return "numismatics.authorization_type." + name().toLowerCase(Locale.ROOT); + } + + private String descriptionKey() { + return titleKey() + ".description"; + } + + public Component title() { + return Components.translatable(titleKey()); + } + + public Component description() { + return Components.translatable(descriptionKey()); + } + + public static void provideLang(BiConsumer consumer) { + for (AuthorizationType type : values()) { + consumer.accept(type.titleKey(), type.englishTitle); + consumer.accept(type.descriptionKey(), type.englishDescription); + } + } + + @Override + public @NotNull String getSerializedName() { + return name().toLowerCase(Locale.ROOT); + } + + public static AuthorizationType deserialize(String string) { + if (string == null) { + return TRUSTED_PLAYERS; + } + + string = string.toLowerCase(Locale.ROOT); + for (AuthorizationType type : values()) { + if (type.getSerializedName().equals(string)) { + return type; + } + } + return TRUSTED_PLAYERS; + } + + public static List labeledComponents() { + Component[] tmp = new Component[values().length]; + for (AuthorizationType at : values()) { + tmp[at.ordinal()] = at.title(); + } + return ImmutableList.copyOf(tmp); + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/Limit.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/Limit.java new file mode 100644 index 00000000..1b42fba9 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/Limit.java @@ -0,0 +1,155 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.backend.sub_authorization; + +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Couple; +import dev.ithundxr.createnumismatics.content.backend.Coin; +import dev.ithundxr.createnumismatics.util.TextUtils; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.MutableComponent; +import org.jetbrains.annotations.Nullable; + +public class Limit { + @Nullable + private Integer limit; + private int spent; + + public Limit(@Nullable Integer limit) { + this(limit, 0); + } + + public Limit(@Nullable Integer limit, int spent) { + this.limit = limit; + this.spent = spent; + + if (limit == null) { + resetSpent(); + } + } + + @Nullable + public Integer getLimit() { + return limit; + } + + public int getSpent() { + return spent; + } + + public boolean hasLimit() { + return limit != null; + } + + public boolean spend(int amount) { + return spend(amount, false); + } + + public boolean spend(int amount, boolean simulate) { + if (amount < 0) { + return false; + } + + Integer limit = getLimit(); + if (limit != null && amount + spent > limit) { + return false; + } + + if (!simulate && limit != null) + spent += amount; + + return true; + } + + public void setLimit(@Nullable Integer limit, boolean resetSpent) { + this.limit = limit; + + if (resetSpent || limit == null) { + resetSpent(); + } + } + + public void resetSpent() { + spent = 0; + } + + public void write(FriendlyByteBuf buf) { + buf.writeBoolean(limit != null); + if (limit != null) + buf.writeInt(limit); + buf.writeInt(spent); + } + + public CompoundTag write() { + CompoundTag tag = new CompoundTag(); + if (limit != null) + tag.putInt("limit", limit); + tag.putInt("spent", spent); + return tag; + } + + public static Limit read(CompoundTag tag) { + Integer limit; + if (tag.contains("limit")) + limit = tag.getInt("limit"); + else + limit = null; + + return new Limit(limit, tag.getInt("spent")); + } + + public static Limit read(FriendlyByteBuf buf) { + Integer limit; + if (buf.readBoolean()) + limit = buf.readInt(); + else + limit = null; + + return new Limit(limit, buf.readInt()); + } + + public MutableComponent describe() { + return describe(true); + } + + public MutableComponent describe(boolean monetary) { + if (limit == null) { + return Components.translatable("gui.numismatics.limit.none"); + } else { + if (monetary) { + Couple cogsAndSpursSpent = Coin.COG.convert(spent); + int cogsSpent = cogsAndSpursSpent.getFirst(); + int spursSpent = cogsAndSpursSpent.getSecond(); + + Couple cogsAndSpursLimit = Coin.COG.convert(limit); + int cogsLimit = cogsAndSpursLimit.getFirst(); + int spursLimit = cogsAndSpursLimit.getSecond(); + + return Components.translatable( + "gui.numismatics.limit.monetary", + TextUtils.formatInt(cogsSpent), Coin.COG.getName(cogsSpent), spursSpent, + TextUtils.formatInt(cogsLimit), Coin.COG.getName(cogsLimit), spursLimit + ); + } else { + return Components.translatable("gui.numismatics.limit", spent, limit); + } + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/SubAccount.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/SubAccount.java new file mode 100644 index 00000000..e2750938 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/SubAccount.java @@ -0,0 +1,294 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.backend.sub_authorization; + +import com.simibubi.create.foundation.utility.Components; +import dev.ithundxr.createnumismatics.Numismatics; +import dev.ithundxr.createnumismatics.content.backend.BankAccount; +import dev.ithundxr.createnumismatics.content.backend.Coin; +import dev.ithundxr.createnumismatics.content.backend.IDeductable; +import dev.ithundxr.createnumismatics.content.backend.ReasonHolder; +import dev.ithundxr.createnumismatics.content.backend.trust_list.TrustListContainer; +import dev.ithundxr.createnumismatics.multiloader.PlayerSelection; +import dev.ithundxr.createnumismatics.registry.NumismaticsPackets; +import dev.ithundxr.createnumismatics.registry.packets.BankAccountLabelPacket; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.network.FriendlyByteBuf; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public final class SubAccount { + private final BankAccount parentAccount; + + @NotNull + private String label; + + @NotNull + // In spurs, no limit if null + private Limit totalLimit; + + // This trust list is special, because the parent account owner is NOT automatically a member. + private final List trustList = new ArrayList<>(); + private final TrustListContainer trustListContainer = new TrustListContainer(trustList, this::markDirty); + + @NotNull + private final UUID authorizationID; + + @NotNull + private AuthorizationType authorizationType = AuthorizationType.TRUSTED_PLAYERS; + + private boolean removed = false; + + public SubAccount(BankAccount parentAccount, @NotNull String label, @NotNull UUID authorizationID) { + this.parentAccount = parentAccount; + this.label = label; + this.authorizationID = authorizationID; + this.totalLimit = new Limit(null); + } + + public void setLabel(@NotNull String label) { + if (this.label.equals(label)) + return; + + this.label = label; + markDirty(); + + NumismaticsPackets.PACKETS.sendTo(PlayerSelection.all(), new BankAccountLabelPacket(this)); + } + + public @NotNull String getLabel() { + return label; + } + + @NotNull + public Limit getTotalLimit() { + return totalLimit; + } + + @NotNull + public List getTrustList() { + return trustList; + } + + public @NotNull UUID getAuthorizationID() { + return authorizationID; + } + + public @NotNull AuthorizationType getAuthorizationType() { + return authorizationType; + } + + public void setAuthorizationType(@NotNull AuthorizationType authorizationType) { + this.authorizationType = authorizationType; + markDirty(); + } + + public boolean spend(Authorization authorization, Coin coin, int count, ReasonHolder reasonHolder) { + return spend(authorization, coin, count, false, reasonHolder); + } + + public boolean spend(Authorization authorization, Coin coin, int count, boolean simulate, ReasonHolder reasonHolder) { + return spend(authorization, coin.toSpurs(count), simulate, reasonHolder); + } + + public boolean spend(Authorization authorization, int spurs, ReasonHolder reasonHolder) { + return spend(authorization, spurs, false, reasonHolder); + } + + public boolean spend(Authorization authorization, int spurs, boolean simulate, ReasonHolder reasonHolder) { + if (!isAuthorized(authorization)) { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.not_authorized")); + return false; + } + + if (parentAccount.getBalance() < spurs) { + return false; + } + + if (!totalLimit.spend(spurs, simulate)) { + reasonHolder.setMessage(Components.translatable("error.numismatics.authorized_card.limit_reached")); + return false; + } + + if (!simulate) { + markDirty(); + parentAccount.deduct(spurs, reasonHolder); + } + + return true; + } + + public boolean isAuthorized(Authorization request) { + if (!request.getAuthorizationID().equals(authorizationID)) { + return false; + } + + if (removed) + return false; + + return switch (authorizationType) { + case TRUSTED_PLAYERS -> { + if (!request.isHuman()) + yield false; + + if (request.getPersonalID() == null) + yield false; + + yield trustList.contains(request.getPersonalID()); + } + case TRUSTED_AUTOMATION -> { + if (request.getPersonalID() == null) + yield false; + + yield trustList.contains(request.getPersonalID()); + } + case ANYBODY -> true; + }; + } + + public void markDirty() { + parentAccount.markDirty(); + } + + public TrustListContainer getTrustListContainer() { + return trustListContainer; + } + + public CompoundTag write() { + CompoundTag tag = new CompoundTag(); + + tag.putString("label", label); + tag.putUUID("authorizationID", authorizationID); + + tag.putString("authorizationType", authorizationType.getSerializedName()); + + tag.put("TotalLimit", totalLimit.write()); + + if (!trustListContainer.isEmpty()) { + tag.put("TrustListInv", trustListContainer.save(new CompoundTag())); + } + + return tag; + } + + public static SubAccount read(BankAccount parentAccount, CompoundTag tag) { + SubAccount subAccount = new SubAccount( + parentAccount, + tag.getString("label"), + tag.getUUID("authorizationID") + ); + + subAccount.authorizationType = AuthorizationType.deserialize(tag.getString("authorizationType")); + + if (tag.contains("TotalLimit", Tag.TAG_COMPOUND)) { + subAccount.totalLimit = Limit.read(tag.getCompound("TotalLimit")); + } + + subAccount.trustListContainer.clearContent(); + subAccount.trustList.clear(); + if (tag.contains("TrustListInv", Tag.TAG_COMPOUND)) { + subAccount.trustListContainer.load(tag.getCompound("TrustListInv")); + } + + return subAccount; + } + + public @Nullable IDeductable getDeductor(Authorization authorization) { + if (!isAuthorized(authorization)) + return null; + + return new PreAuthorizedDeductor(authorization); + } + + public void sendToMenu(FriendlyByteBuf buf) { + buf.writeUtf(label); + buf.writeUUID(authorizationID); + buf.writeEnum(authorizationType); + totalLimit.write(buf); + } + + public void updateFrom(SubAccount other) { + if (this.authorizationID != other.authorizationID) { + Numismatics.LOGGER.warn("Tried to update a sub account with a different authorization ID"); + return; + } + this.label = other.label; + this.authorizationType = other.authorizationType; + this.totalLimit = other.totalLimit; + this.trustListContainer.load(other.trustListContainer.save(new CompoundTag())); + other.setRemoved(); + } + + public static SubAccount clientSide(BankAccount parentAccount, FriendlyByteBuf buf) { + SubAccount subAccount = new SubAccount( + parentAccount, + buf.readUtf(), + buf.readUUID() + ); + + subAccount.authorizationType = buf.readEnum(AuthorizationType.class); + + subAccount.totalLimit = Limit.read(buf); + + return subAccount; + } + + public void setRemoved() { + this.removed = true; + markDirty(); + } + + private class PreAuthorizedDeductor implements IDeductable { + private final Authorization authorization; + + private PreAuthorizedDeductor(Authorization authorization) { + this.authorization = authorization; + } + + @Override + public boolean deduct(Coin coin, int amount, ReasonHolder reasonHolder) { + return spend(authorization, coin, amount, reasonHolder); + } + + @Override + public boolean deduct(int spurs, ReasonHolder reasonHolder) { + return spend(authorization, spurs, reasonHolder); + } + + @Override + public int getMaxWithdrawal() { + if (!isAuthorized(authorization)) + return 0; + + int max = parentAccount.getMaxWithdrawal(); + + Integer limit = totalLimit.getLimit(); + if (limit != null) { + max = Math.min(max, limit - totalLimit.getSpent()); + } + + return max; + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/trust_list/TrustListMenu.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/trust_list/TrustListMenu.java index 7df60bdb..e5e71f9d 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/trust_list/TrustListMenu.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/trust_list/TrustListMenu.java @@ -163,7 +163,7 @@ protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, if (reverseDirection) { i = endIndex - 1; } - if (stack.isStackable() && startIndex >= CARD_SLOTS) { + if (stack.isStackable() && startIndex >= CARD_SLOTS) { // CHANGED LINE while (!stack.isEmpty() && (reverseDirection ? i >= startIndex : i < endIndex)) { slot = this.slots.get(i); itemStack = slot.getItem(); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AnyCardSlot.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AnyCardSlot.java new file mode 100644 index 00000000..1f5aa417 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AnyCardSlot.java @@ -0,0 +1,69 @@ +/* + * Numismatics + * Copyright (c) 2023-2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.bank; + +import com.mojang.datafixers.util.Pair; +import dev.ithundxr.createnumismatics.Numismatics; +import dev.ithundxr.createnumismatics.registry.NumismaticsTags; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.InventoryMenu; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class AnyCardSlot extends Slot { + public AnyCardSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + + @Override + public boolean mayPlace(@NotNull ItemStack stack) { + return NumismaticsTags.AllItemTags.CARDS.matches(stack) || NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(stack); + } + + @Nullable + @Override + public Pair getNoItemIcon() { + return Pair.of(InventoryMenu.BLOCK_ATLAS, Numismatics.asResource("item/any_card_outline")); + } + + public static class UnboundAnyCardSlot extends AnyCardSlot { + public UnboundAnyCardSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + + @Override + public boolean mayPlace(@NotNull ItemStack stack) { + return super.mayPlace(stack) && !CardItem.isBound(stack); + } + } + + public static class BoundAnyCardSlot extends AnyCardSlot { + public BoundAnyCardSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + + @Override + public boolean mayPlace(@NotNull ItemStack stack) { + return super.mayPlace(stack) && CardItem.isBound(stack); + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AuthorizedCardItem.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AuthorizedCardItem.java new file mode 100644 index 00000000..860b0183 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AuthorizedCardItem.java @@ -0,0 +1,161 @@ +/* + * Numismatics + * Copyright (c) 2023-2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.bank; + +import com.simibubi.create.foundation.utility.Components; +import dev.ithundxr.createnumismatics.NumismaticsClient; +import dev.ithundxr.createnumismatics.util.UsernameUtils; +import net.minecraft.ChatFormatting; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.DyeColor; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; +import java.util.UUID; + +public class AuthorizedCardItem extends Item { + public final DyeColor color; + public AuthorizedCardItem(Properties properties, DyeColor color) { + super(properties); + this.color = color; + } + + @SuppressWarnings("DataFlowIssue") + public static ItemStack clear(ItemStack itemStack) { + if (!itemStack.hasTag()) + return itemStack; + + CompoundTag tag = itemStack.getTag(); + tag.remove("AccountID"); + tag.remove("AuthorizationID"); + itemStack.setTag(tag); + return itemStack; + } + + public static ItemStack set(ItemStack itemStack, AuthorizationPair pair) { + CompoundTag tag = itemStack.getOrCreateTag(); + tag.putUUID("AccountID", pair.accountID()); + tag.putUUID("AuthorizationID", pair.authorizationID()); + itemStack.setTag(tag); + return itemStack; + } + + @SuppressWarnings("DataFlowIssue") + @Nullable + public static AuthorizationPair get(ItemStack itemStack) { + if (!itemStack.hasTag()) + return null; + + CompoundTag tag = itemStack.getTag(); + return AuthorizationPair.get(tag); + } + + @SuppressWarnings("DataFlowIssue") + public static boolean isBound(ItemStack itemStack) { + return get(itemStack) != null; + } + + @Nullable + public static String getPlayerName(ItemStack itemStack) { + AuthorizationPair pair = get(itemStack); + + if (pair == null) + return null; + + return UsernameUtils.INSTANCE.getName(pair.accountID(), null); + } + + @Nullable + public static String getAccountLabel(ItemStack itemStack) { + AuthorizationPair pair = get(itemStack); + + if (pair == null) + return null; + + return NumismaticsClient.subAccountLabels.getOrDefault(pair.authorizationID(), null); + } + + @Override + public void appendHoverText(@NotNull ItemStack stack, @Nullable Level level, @NotNull List tooltipComponents, @NotNull TooltipFlag isAdvanced) { + super.appendHoverText(stack, level, tooltipComponents, isAdvanced); + if (isBound(stack)) { + String name = getPlayerName(stack); + String label = getAccountLabel(stack); + + if (name == null) { + tooltipComponents.add(Components.translatable("item.numismatics.card.tooltip.bound") + .withStyle(ChatFormatting.GREEN)); + } else { + tooltipComponents.add(Components.translatable("item.numismatics.card.tooltip.bound.to", name) + .withStyle(ChatFormatting.GREEN)); + } + + if (label == null) { + tooltipComponents.add(Components.translatable("item.numismatics.authorized_card.tooltip.bound.no_label") + .withStyle(ChatFormatting.GREEN)); + } else { + tooltipComponents.add(Components.translatable("item.numismatics.authorized_card.tooltip.bound.with_label", label) + .withStyle(ChatFormatting.GREEN)); + } + } else { + tooltipComponents.add(Components.translatable("item.numismatics.card.tooltip.blank")); + } + } + + @Override + public @NotNull InteractionResultHolder use(Level level, Player player, @NotNull InteractionHand usedHand) { + ItemStack handStack = player.getItemInHand(usedHand); + if (level.isClientSide) + return InteractionResultHolder.success(handStack); + + if (isBound(handStack)) { + if(player.isShiftKeyDown()) { + clear(handStack); + player.displayClientMessage(Components.translatable("item.numismatics.id_card.tooltip.cleared"), true); + return InteractionResultHolder.success(handStack); + } + } else { + player.displayClientMessage(Components.translatable("item.numismatics.authorized_card.tooltip.hold_shift"), true); + return InteractionResultHolder.success(handStack); + } + + return InteractionResultHolder.pass(handStack); + } + + public record AuthorizationPair(UUID accountID, UUID authorizationID) { + private static @Nullable AuthorizationPair get(CompoundTag tag) { + if (!(tag.hasUUID("AccountID") && tag.hasUUID("AuthorizationID"))) + return null; + + UUID accountID = tag.getUUID("AccountID"); + UUID authorizationID = tag.getUUID("AuthorizationID"); + + return new AuthorizationPair(accountID, authorizationID); + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AuthorizedCardSlot.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AuthorizedCardSlot.java new file mode 100644 index 00000000..ceed7061 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AuthorizedCardSlot.java @@ -0,0 +1,69 @@ +/* + * Numismatics + * Copyright (c) 2023-2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.bank; + +import com.mojang.datafixers.util.Pair; +import dev.ithundxr.createnumismatics.Numismatics; +import dev.ithundxr.createnumismatics.registry.NumismaticsTags; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.Container; +import net.minecraft.world.inventory.InventoryMenu; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class AuthorizedCardSlot extends Slot { + public AuthorizedCardSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + + @Override + public boolean mayPlace(@NotNull ItemStack stack) { + return NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(stack); + } + + @Nullable + @Override + public Pair getNoItemIcon() { + return Pair.of(InventoryMenu.BLOCK_ATLAS, Numismatics.asResource("item/authorized_card/outline")); + } + + public static class UnboundAuthorizedCardSlot extends AuthorizedCardSlot { + public UnboundAuthorizedCardSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + + @Override + public boolean mayPlace(@NotNull ItemStack stack) { + return super.mayPlace(stack) && !AuthorizedCardItem.isBound(stack); + } + } + + public static class BoundAuthorizedCardSlot extends AuthorizedCardSlot { + public BoundAuthorizedCardSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + + @Override + public boolean mayPlace(@NotNull ItemStack stack) { + return super.mayPlace(stack) && AuthorizedCardItem.isBound(stack); + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/BankScreen.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/BankScreen.java index b165ad90..156f4588 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/BankScreen.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/BankScreen.java @@ -19,7 +19,6 @@ package dev.ithundxr.createnumismatics.content.bank; import com.google.common.collect.ImmutableList; -import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.gui.AllGuiTextures; import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.gui.element.GuiGameElement; @@ -30,6 +29,7 @@ import dev.ithundxr.createnumismatics.content.backend.Coin; import dev.ithundxr.createnumismatics.registry.NumismaticsBlocks; import dev.ithundxr.createnumismatics.registry.NumismaticsGuiTextures; +import dev.ithundxr.createnumismatics.registry.NumismaticsIcons; import dev.ithundxr.createnumismatics.util.TextUtils; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.renderer.Rect2i; @@ -65,6 +65,10 @@ protected void init() { confirmButton.withCallback(this::onClose); addRenderableWidget(confirmButton); + IconButton openSubAccountsButton = new IconButton(x + background.width - 61, y + background.height - 24, NumismaticsIcons.I_OPEN_SUB_LIST); + openSubAccountsButton.withCallback(menu.contentHolder::openSubAccountsMenu); + addRenderableWidget(openSubAccountsButton); + extraAreas = ImmutableList.of(new Rect2i(x + background.width, y + background.height - 64, 84, 74)); } @@ -75,7 +79,6 @@ public List getExtraAreas() { @Override protected void renderBg(@NotNull GuiGraphics graphics, float partialTick, int mouseX, int mouseY) { - PoseStack ms = graphics.pose(); int invX = getLeftOfCentered(AllGuiTextures.PLAYER_INVENTORY.width); int invY = topPos + background.height + 2; renderPlayerInventory(graphics, invX, invY); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/ScrollingLabel.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/ScrollingLabel.java new file mode 100644 index 00000000..057b7a17 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/ScrollingLabel.java @@ -0,0 +1,75 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.bank; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.simibubi.create.foundation.gui.widget.Label; +import dev.ithundxr.createnumismatics.util.TextUtils; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; + +import javax.annotation.Nonnull; + +public class ScrollingLabel extends Label { + + protected int ticks = 0; + + protected final boolean languageLTR; + + public ScrollingLabel(int x, int y, Component text, int width) { + super(x, y, text); + + this.width = width; + this.languageLTR = TextUtils.isLeftToRight(); + } + + @Override + public void tick() { + super.tick(); + + ticks += 1; + } + + @Override + protected void doRender(@Nonnull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + if (text == null || text.getString().isEmpty()) + return; + + RenderSystem.setShaderColor(1, 1, 1, 1); + MutableComponent copy = text.plainCopy(); + if (suffix != null && !suffix.isEmpty()) + copy.append(suffix); + + int textWidth = font.width(copy); + if (textWidth <= getWidth()) { + graphics.drawString(font, copy, getX(), getY(), color, hasShadow); + } else { + String raw = copy.getString() + " ".repeat(10); + int offset = ((languageLTR ? ticks : -ticks) / 2) % (raw.length()); + + String substring = (raw + raw).substring(offset, offset + raw.length()); + // shrink until it fits in the right width + while (font.width(substring) > getWidth()) { + substring = substring.substring(0, substring.length() - 1); + } + graphics.drawString(font, substring, getX(), getY(), color, hasShadow); + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListMenu.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListMenu.java new file mode 100644 index 00000000..434199e2 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListMenu.java @@ -0,0 +1,410 @@ +/* + * Numismatics + * Copyright (c) 2023-2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.bank; + +import com.simibubi.create.foundation.gui.menu.MenuBase; +import dev.ithundxr.createnumismatics.base.item.DynamicContainer; +import dev.ithundxr.createnumismatics.base.item.SingleCallbackContainer; +import dev.ithundxr.createnumismatics.content.backend.BankAccount; +import dev.ithundxr.createnumismatics.content.backend.ItemWritingContainer; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.AuthorizationType; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.SubAccount; +import dev.ithundxr.createnumismatics.multiloader.PlayerSelection; +import dev.ithundxr.createnumismatics.registry.NumismaticsPackets; +import dev.ithundxr.createnumismatics.registry.NumismaticsTags; +import dev.ithundxr.createnumismatics.registry.packets.sub_account.*; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.Container; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.MenuType; +import net.minecraft.world.inventory.Slot; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; +import java.util.UUID; + +public class SubAccountListMenu extends MenuBase { + public static final int TRUST_SLOTS = 27; + public static final int TRUST_START_INDEX = 0; + public static final int TRUST_END_INDEX = TRUST_START_INDEX + TRUST_SLOTS; // exclusive + public static final int CARD_WRITING_INDEX = TRUST_END_INDEX; + public static final int PLAYER_INV_START_INDEX = CARD_WRITING_INDEX + 1; + public static final int PLAYER_HOTBAR_END_INDEX = PLAYER_INV_START_INDEX + 9; + public static final int PLAYER_INV_END_INDEX = PLAYER_INV_START_INDEX + 36; + + private AuthorizedCardWritingContainer authorizedCardContainer; + + @Nullable + private OpenSubAccountInformation openSubAccount; + + private DynamicContainer trustListContainer; + + public SubAccountListMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public SubAccountListMenu(MenuType type, int id, Inventory inv, BankAccount contentHolder) { + super(type, id, inv, contentHolder); + } + + public boolean slotsActive() { + return openSubAccount != null; + } + + @Nullable OpenSubAccountInformation getOpenSubAccount() { + return openSubAccount; + } + + @Override + protected BankAccount createOnClient(FriendlyByteBuf extraData) { + return BankAccount.clientSideSubAccountList(extraData); + } + + @Override + protected void initAndReadInventory(BankAccount contentHolder) {} + + @Override + protected void addSlots() { + if (authorizedCardContainer == null) + authorizedCardContainer = new AuthorizedCardWritingContainer(); + if (trustListContainer == null) + trustListContainer = new DynamicContainer(() -> openSubAccount == null ? null : openSubAccount.container); + + int x = 33; + int y = 20; + + for (int i = 0; i < TRUST_SLOTS; i++) { + if (i % 9 == 0 && i > 0) { + x = 33; + y += 18; + } + addSlot(new InactiveBoundIDCardSlot(trustListContainer, i, x, y)); + x += 18; + } + + addSlot(new InactiveUnboundAuthorizedCardSlot(authorizedCardContainer, CARD_WRITING_INDEX, 176, 85)); + + addPlayerSlots(40-4, 140); + } + + @Override + protected void addPlayerSlots(int x, int y) { + for (int hotbarSlot = 0; hotbarSlot < 9; ++hotbarSlot) + this.addSlot(new InactiveSlot(playerInventory, hotbarSlot, x + hotbarSlot * 18, y + 58)); + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 9; ++col) + this.addSlot(new InactiveSlot(playerInventory, col + row * 9 + 9, x + col * 18, y + row * 18)); + } + + @Override + protected void saveData(BankAccount contentHolder) {} + + @Override + public void removed(Player playerIn) { + super.removed(playerIn); + if (playerIn instanceof ServerPlayer) { + clearContainer(player, authorizedCardContainer); + } + } + + @Override + protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, boolean reverseDirection) { + ItemStack itemStack; + Slot slot; + boolean bl = false; + int i = startIndex; + if (reverseDirection) { + i = endIndex - 1; + } + if (stack.isStackable() && startIndex >= TRUST_SLOTS) { // CHANGED LINE + while (!stack.isEmpty() && (reverseDirection ? i >= startIndex : i < endIndex)) { + slot = this.slots.get(i); + itemStack = slot.getItem(); + if (!itemStack.isEmpty() && ItemStack.isSameItemSameTags(stack, itemStack)) { + int j = itemStack.getCount() + stack.getCount(); + if (j <= stack.getMaxStackSize()) { + stack.setCount(0); + itemStack.setCount(j); + slot.setChanged(); + bl = true; + } else if (itemStack.getCount() < stack.getMaxStackSize()) { + stack.shrink(stack.getMaxStackSize() - itemStack.getCount()); + itemStack.setCount(stack.getMaxStackSize()); + slot.setChanged(); + bl = true; + } + } + if (reverseDirection) { + --i; + continue; + } + ++i; + } + } + if (!stack.isEmpty()) { + i = reverseDirection ? endIndex - 1 : startIndex; + while (reverseDirection ? i >= startIndex : i < endIndex) { + slot = this.slots.get(i); + itemStack = slot.getItem(); + if (itemStack.isEmpty() && slot.mayPlace(stack)) { + if (stack.getCount() > slot.getMaxStackSize()) { + slot.setByPlayer(stack.split(slot.getMaxStackSize())); + } else { + slot.setByPlayer(stack.split(stack.getCount())); + } + slot.setChanged(); + bl = true; + break; + } + if (reverseDirection) { + --i; + continue; + } + ++i; + } + } + return bl; + } + + @Override + public @NotNull ItemStack quickMoveStack(@NotNull Player player, int index) { // index is slot that was clicked + Slot clickedSlot = this.slots.get(index); + + if (!clickedSlot.hasItem()) + return ItemStack.EMPTY; + + ItemStack slotStack = clickedSlot.getItem(); + + if (!slotsActive()) + return slotStack; + + ItemStack returnStack = slotStack.copy(); + + if (index <= CARD_WRITING_INDEX && !moveItemStackTo(slotStack, PLAYER_INV_START_INDEX, PLAYER_INV_END_INDEX, false)) { + return ItemStack.EMPTY; // failed to move to player inventory + } else if (slotStack.getItem() instanceof IDCardItem && IDCardItem.isBound(slotStack) && !moveItemStackTo(slotStack, TRUST_START_INDEX, TRUST_END_INDEX, false)) { + return ItemStack.EMPTY; // failed to move to id card slots + } else if (slotStack.getItem() instanceof AuthorizedCardItem && !AuthorizedCardItem.isBound(slotStack) && !moveItemStackTo(slotStack, CARD_WRITING_INDEX, CARD_WRITING_INDEX + 1, false)) { + return ItemStack.EMPTY; // failed to move to authorized card slot + } else if (index >= PLAYER_INV_START_INDEX && index < PLAYER_HOTBAR_END_INDEX && !moveItemStackTo(slotStack, PLAYER_HOTBAR_END_INDEX, PLAYER_INV_END_INDEX, false)) { + return ItemStack.EMPTY; + } else if (index >= PLAYER_HOTBAR_END_INDEX && index < PLAYER_INV_END_INDEX && !moveItemStackTo(slotStack, PLAYER_INV_START_INDEX, PLAYER_HOTBAR_END_INDEX, false)) { + return ItemStack.EMPTY; + } + + if (slotStack.isEmpty()) { + clickedSlot.set(ItemStack.EMPTY); + } else { + clickedSlot.setChanged(); + } + + return returnStack; + } + + public void openSubAccountEditScreen(@Nullable UUID subAccountID) { + SubAccount subAccount = contentHolder.getSubAccountNoAuth(subAccountID); + if (subAccount != null) { + openSubAccount = new OpenSubAccountInformation(subAccount); + } else { + openSubAccount = null; + } + + if (player instanceof ServerPlayer) { + slotsChanged(trustListContainer); + } + } + + private void sendUpdateToOthers() { + sendUpdate(false); + } + + private void sendUpdate(boolean includeSelf) { + if (player instanceof ServerPlayer serverPlayer) { + NumismaticsPackets.PACKETS.sendTo(PlayerSelection.allWith((p) -> { + if (!includeSelf && p == serverPlayer) + return false; + + if (p.containerMenu instanceof SubAccountListMenu subAccountListMenu) + return subAccountListMenu.contentHolder.id.equals(contentHolder.id); + + return false; + }), new UpdateSubAccountsPacket(contentHolder)); + } + } + + public void addSubAccount(@NotNull String label) { + if (player instanceof ServerPlayer) { + contentHolder.addSubAccount(label); + sendUpdate(true); + } else { + NumismaticsPackets.PACKETS.send(new AddSubAccountPacket(label)); + } + } + + /** Must not be called with open SubAccount */ + public void removeSubAccount(@NotNull UUID subAccountID) { + if (contentHolder == null) + return; + SubAccount subAccount = contentHolder.removeSubAccount(subAccountID); + + if (player instanceof ServerPlayer) { + if (subAccount != null) + clearContainer(player, subAccount.getTrustListContainer()); + sendUpdateToOthers(); + } else { + NumismaticsPackets.PACKETS.send(new RemoveSubAccountPacket(subAccountID)); + } + } + + public void resetSubAccountSpending(@NotNull UUID subAccountID) { + SubAccount subAccount = contentHolder.getSubAccountNoAuth(subAccountID); + + if (subAccount != null) { + subAccount.getTotalLimit().resetSpent(); + subAccount.markDirty(); + } + + if (player instanceof ServerPlayer) { + sendUpdateToOthers(); + } else { + NumismaticsPackets.PACKETS.send(new ResetSubAccountSpendingPacket(subAccountID)); + } + } + + public void setLimit(@NotNull UUID subAccountID, @Nullable Integer limit) { + SubAccount subAccount = contentHolder.getSubAccountNoAuth(subAccountID); + + if (subAccount == null || !Objects.equals(subAccount.getTotalLimit().getLimit(), limit)) { + if (subAccount != null) + subAccount.getTotalLimit().setLimit(limit, false); + + if (player instanceof ServerPlayer) { + sendUpdateToOthers(); + } else { + NumismaticsPackets.PACKETS.send(new ConfigureSubAccountPacket(subAccountID, limit)); + } + } + } + + public void setAuthorizationType(@NotNull UUID subAccountID, @NotNull AuthorizationType authorizationType) { + SubAccount subAccount = contentHolder.getSubAccountNoAuth(subAccountID); + + if (subAccount == null || subAccount.getAuthorizationType() != authorizationType) { + if (subAccount != null) + subAccount.setAuthorizationType(authorizationType); + + if (player instanceof ServerPlayer) { + sendUpdateToOthers(); + } else { + NumismaticsPackets.PACKETS.send(new ConfigureSubAccountPacket(subAccountID, authorizationType)); + } + } + } + + public void setLabel(@NotNull UUID subAccountID, @NotNull String label) { + if (label.isBlank()) { + label = "Sub Account"; + } + + SubAccount subAccount = contentHolder.getSubAccountNoAuth(subAccountID); + + if (subAccount == null || !subAccount.getLabel().equals(label)) { + if (subAccount != null) + subAccount.setLabel(label); + + if (player instanceof ServerPlayer) { + sendUpdateToOthers(); + } else { + NumismaticsPackets.PACKETS.send(new ConfigureSubAccountPacket(subAccountID, label)); + } + } + } + + private class InactiveUnboundAuthorizedCardSlot extends AuthorizedCardSlot.UnboundAuthorizedCardSlot { + + public InactiveUnboundAuthorizedCardSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + + @Override + public boolean isActive() { + return super.isActive() && slotsActive(); + } + } + + private class InactiveBoundIDCardSlot extends IDCardSlot.BoundIDCardSlot { + + public InactiveBoundIDCardSlot(Container container, int slot, int x, int y) { + super(container, slot, x, y); + } + + @Override + public boolean isActive() { + return super.isActive() && slotsActive(); + } + } + + private class InactiveSlot extends Slot { + + public InactiveSlot(Container pContainer, int pIndex, int pX, int pY) { + super(pContainer, pIndex, pX, pY); + } + + @Override + public boolean isActive() { + return slotsActive(); + } + + } + + class OpenSubAccountInformation { + public final UUID authorizationID; + public final Container container; + + public OpenSubAccountInformation(SubAccount subAccount) { + this.authorizationID = subAccount.getAuthorizationID(); + this.container = new SingleCallbackContainer(subAccount.getTrustListContainer(), this::trustListChanged); + } + + private void trustListChanged(Container container) { + SubAccountListMenu.this.slotsChanged(container); + SubAccount subAccount = contentHolder.getSubAccountNoAuth(authorizationID); + if (subAccount != null) + subAccount.markDirty(); + } + } + + private class AuthorizedCardWritingContainer extends ItemWritingContainer { + + public AuthorizedCardWritingContainer() { + super(SubAccountListMenu.this::slotsChanged); + } + + @Override + protected void doWriteItem(ItemStack stack) { + if (NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(stack) && !AuthorizedCardItem.isBound(stack) && openSubAccount != null) { + AuthorizedCardItem.set(stack, new AuthorizedCardItem.AuthorizationPair(contentHolder.id, openSubAccount.authorizationID)); + } + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListScreen.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListScreen.java new file mode 100644 index 00000000..d6b53e88 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListScreen.java @@ -0,0 +1,685 @@ +/* + * Numismatics + * Copyright (c) 2023-2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.bank; + +import com.google.common.collect.ImmutableList; +import com.mojang.blaze3d.platform.InputConstants; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.content.trains.station.NoShadowFontWrapper; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.UIRenderHelper; +import com.simibubi.create.foundation.gui.element.GuiGameElement; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.gui.widget.Label; +import com.simibubi.create.foundation.gui.widget.SelectionScrollInput; +import com.simibubi.create.foundation.utility.Color; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.animation.LerpedFloat; +import dev.ithundxr.createnumismatics.content.backend.Coin; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.AuthorizationType; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.Limit; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.SubAccount; +import dev.ithundxr.createnumismatics.registry.NumismaticsBlocks; +import dev.ithundxr.createnumismatics.registry.NumismaticsGuiTextures; +import dev.ithundxr.createnumismatics.registry.NumismaticsPackets; +import dev.ithundxr.createnumismatics.registry.packets.sub_account.OpenSubAccountEditScreenPacket; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.EditBox; +import net.minecraft.client.gui.components.Renderable; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.Component; +import net.minecraft.util.FormattedCharSequence; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL30; + +import java.util.*; +import java.util.function.Consumer; + +public class SubAccountListScreen extends AbstractSimiContainerScreen { + private static final int CARD_HEADER = 22; + private static final int CARD_BODY = 66; + private static final int CARD_WIDTH = 208; + private static final int CARD_SPACING = 2; + private static final int UNLIMITED_VALUE = Coin.SUN.toSpurs(64) + Coin.COG.toSpurs(64) + 64; + + private static final Color REMOVE_OFF_COLOR = new Color(0x606060, false).setImmutable(); + private static final Color REMOVE_ON_COLOR = new Color(0xff0029, false).setImmutable(); + + private final NumismaticsGuiTextures background = NumismaticsGuiTextures.SUB_ACCOUNT_LIST; + private final ItemStack renderedItem = NumismaticsBlocks.BANK_TERMINAL.asStack(); + + private List extraAreas = Collections.emptyList(); + + private final LerpedFloat scroll = LerpedFloat.linear() + .startWithValue(0); + + private final LerpedFloat removeProgress = LerpedFloat.linear() + .startWithValue(0); + private UUID removeTarget = null; + + private IconButton confirmButton; + private IconButton addButton; + private EditBox nameBox; + + private boolean hasPopup = false; + + private IconButton editorConfirm; + private EditBox editorLabelBox; + + private final Map sliders = new HashMap<>(); + + + public SubAccountListScreen(SubAccountListMenu container, Inventory inv, Component title) { + super(container, inv, title); + } + + @Override + protected void init() { + setWindowSize(background.width, background.height); + super.init(); + clearWidgets(); + + int x = leftPos; + int y = topPos; + + confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); + confirmButton.withCallback(menu.contentHolder::openNormalMenu); + addRenderableWidget(confirmButton); + + addButton = new IconButton(x + 173, y + background.height - 24, AllIcons.I_ADD); + addButton.withCallback(() -> { + String label = nameBox.getValue(); + if (label.isBlank()) + label = "Sub Account"; + menu.addSubAccount(label); + nameBox.setValue(""); + }); + addRenderableWidget(addButton); + + nameBox = new EditBox(this.font, x + 12+1, y + 197+4, 152, 16, Components.translatable("gui.numismatics.bank_terminal.sub_accounts.name_box")); + nameBox.setBordered(false); + nameBox.setMaxLength(25); + nameBox.setValue(""); + addRenderableWidget(nameBox); + + extraAreas = ImmutableList.of(new Rect2i(x + background.width, y + background.height - 64, 84, 74)); + stopPopup(); + } + + protected void editSubAccount(UUID subAccountID) { + menu.openSubAccountEditScreen(subAccountID); + NumismaticsPackets.PACKETS.send(new OpenSubAccountEditScreenPacket(subAccountID)); + } + + protected void startPopup() { + confirmButton.visible = false; + addButton.visible = false; + nameBox.visible = false; + nameBox.setFocused(false); + + if (hasPopup) + return; + + hasPopup = true; + + editorConfirm = new IconButton(leftPos + 56 + 168 - 13, topPos + 65 + 22, AllIcons.I_CONFIRM); + addRenderableWidget(editorConfirm); + + int x = leftPos - 12; + int y = topPos - 5; + Label authorizationTypeLabel = new ScrollingLabel(x + 67 + 3, y + 89 + 5, Components.immutableEmpty(), 108 - 6).withShadow(); + + SelectionScrollInput authorizationTypeScroll = new SelectionScrollInput(x + 67, y + 89, 108, 18); + authorizationTypeScroll.forOptions(AuthorizationType.labeledComponents()); + authorizationTypeScroll.writingTo(authorizationTypeLabel); + authorizationTypeScroll.titled(Components.translatable("gui.numismatics.bank_terminal.sub_accounts.authorization_type")); + authorizationTypeScroll.calling(idx -> { + SubAccountListMenu.OpenSubAccountInformation osa = menu.getOpenSubAccount(); + if (osa == null) + return; + + menu.setAuthorizationType(osa.authorizationID, AuthorizationType.values()[idx]); + }); + + SubAccountListMenu.OpenSubAccountInformation osa = menu.getOpenSubAccount(); + SubAccount subAccount = null; + if (osa != null) { + subAccount = menu.contentHolder.getSubAccountNoAuth(osa.authorizationID); + if (subAccount != null) { + authorizationTypeScroll.setState(subAccount.getAuthorizationType().ordinal()); + authorizationTypeScroll.onChanged(); + } + } + + addRenderableWidget(authorizationTypeScroll); + addRenderableWidget(authorizationTypeLabel); + + String existingLabel = subAccount == null ? null : subAccount.getLabel(); + if (existingLabel == null || existingLabel.isBlank()) { + existingLabel = "Sub Account"; + } + + Consumer onTextChanged = s -> editorLabelBox.setX(nameBoxX(s, editorLabelBox)); + editorLabelBox = new EditBox(new NoShadowFontWrapper(font), x + 23, y + 4, background.width - 20, 10, + Components.literal(existingLabel)); + editorLabelBox.setBordered(false); + editorLabelBox.setMaxLength(25); + editorLabelBox.setTextColor(0x592424); + editorLabelBox.setValue(existingLabel); + editorLabelBox.setFocused(false); + editorLabelBox.mouseClicked(0, 0, 0); + editorLabelBox.setResponder(onTextChanged); + editorLabelBox.setX(nameBoxX(editorLabelBox.getValue(), editorLabelBox)); + addRenderableWidget(editorLabelBox); + + //popupWidgets = ImmutableList.of(authorizationTypeLabel, authorizationTypeScroll); + } + + protected void stopPopup() { + confirmButton.visible = true; + addButton.visible = true; + nameBox.visible = true; + + if (!hasPopup) + return; + + sliders.clear(); + removeWidget(editorConfirm); + editorConfirm = null; + // syncName(); - this doesn't do anything because there's no open sub account anymore by the time this gets called + + hasPopup = false; + init(); + } + + @Override + protected void containerTick() { + super.containerTick(); + scroll.tickChaser(); + removeProgress.tickChaser(); + + if (editorLabelBox != null && getFocused() != editorLabelBox) { + editorLabelBox.setCursorPosition(editorLabelBox.getValue().length()); + editorLabelBox.setHighlightPos(editorLabelBox.getCursorPosition()); + } + + nameBox.tick(); + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + + @Override + public void render(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + partialTicks = minecraft.getFrameTime(); + + if (menu.slotsActive()) { + if (!hasPopup) { + startPopup(); + } + super.render(graphics, mouseX, mouseY, partialTicks); + } else { + if (hasPopup) { + stopPopup(); + } + renderBackground(graphics); + renderBg(graphics, partialTicks, mouseX, mouseY); + for (Renderable widget : renderables) + widget.render(graphics, mouseX, mouseY, partialTicks); + renderForeground(graphics, mouseX, mouseY, partialTicks); + } + } + + protected void renderSubAccounts(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + PoseStack ms = graphics.pose(); + UIRenderHelper.swapAndBlitColor(minecraft.getMainRenderTarget(), UIRenderHelper.framebuffer); + + int yOffset = 25; + float scrollOffset = -scroll.getValue(partialTicks); + + if (menu.contentHolder.hasSubAccounts()) { + for (SubAccount subAccount : menu.contentHolder.getAlphabetizedSubAccounts()) { + startStencil(graphics, leftPos + 3, topPos + 16, 220, 173); + ms.pushPose(); + ms.translate(0, scrollOffset, 0); + + int cardHeight = renderSubAccount(graphics, subAccount, yOffset, mouseX, mouseY, partialTicks); + yOffset += cardHeight + CARD_SPACING; + + ms.popPose(); + endStencil(); + } + } else { + startStencil(graphics, leftPos + 3, topPos + 16, 220, 173); + ms.pushPose(); + ms.translate(0, scrollOffset, 0); + + renderSubAccountHelp(graphics, yOffset, mouseX, mouseY, partialTicks); + + ms.popPose(); + endStencil(); + } + + int zLevel = 200; + graphics.fillGradient(leftPos + 3, topPos + 16, leftPos + 3 + 220, topPos + 16 + 10, zLevel, 0x77000000, + 0x00000000); + graphics.fillGradient(leftPos + 3, topPos + 179, leftPos + 3 + 220, topPos + 179 + 10, zLevel, 0x00000000, + 0x77000000); + UIRenderHelper.swapAndBlitColor(UIRenderHelper.framebuffer, minecraft.getMainRenderTarget()); + } + + protected TripleCoinSliderWidget getOrCreateWidgetForSubAccount(SubAccount subAccount) { + Integer limit = subAccount.getTotalLimit().getLimit(); + return sliders.computeIfAbsent( + subAccount.getAuthorizationID(), + $ -> new TripleCoinSliderWidget(font, 2, CARD_HEADER + 18) + .setMaxIsInfinite(true) + .withValue(limit == null ? UNLIMITED_VALUE : limit) + .withEditCallback((int spurs, int cogs, int suns) -> { + int total = Coin.SUN.toSpurs(suns) + Coin.COG.toSpurs(cogs) + spurs; + if (total == UNLIMITED_VALUE) { + menu.setLimit(subAccount.getAuthorizationID(), null); + } else { + menu.setLimit(subAccount.getAuthorizationID(), total); + } + }) + ); + } + + protected int renderSubAccount(GuiGraphics graphics, SubAccount subAccount, int yOffset, int mouseX, int mouseY, + float partialTicks) { + int zLevel = -100; + + AllGuiTextures light = AllGuiTextures.SCHEDULE_CARD_LIGHT; + AllGuiTextures medium = AllGuiTextures.SCHEDULE_CARD_MEDIUM; + AllGuiTextures dark = AllGuiTextures.SCHEDULE_CARD_DARK; + + int cardWidth = CARD_WIDTH; + int cardHeader = CARD_HEADER; + int cardHeight = cardHeader + CARD_BODY; + + PoseStack ms = graphics.pose(); + ms.pushPose(); + ms.translate(leftPos + 9, topPos + yOffset, 0); + + UIRenderHelper.drawStretched(graphics, 0, 1, cardWidth, cardHeight - 2, zLevel, light); + UIRenderHelper.drawStretched(graphics, 1, 0, cardWidth - 2, cardHeight, zLevel, light); + UIRenderHelper.drawStretched(graphics, 1, 1, cardWidth - 2, cardHeight - 2, zLevel, dark); + UIRenderHelper.drawStretched(graphics, 2, 2, cardWidth - 4, cardHeight - 4, zLevel, medium); + UIRenderHelper.drawStretched(graphics, 2, 2, cardWidth - 4, cardHeader, zLevel, medium); + UIRenderHelper.drawStretched(graphics, 8, cardHeader, cardWidth - 16, 1, zLevel, light); + UIRenderHelper.drawStretched(graphics, 9, cardHeader + 1, cardWidth - 16, 1, zLevel, dark); + + boolean isTargeted = removeTarget != null && removeTarget.equals(subAccount.getAuthorizationID()); + NumismaticsGuiTextures.SUB_ACCOUNT_LIST_DELETE_COLORABLE.render(graphics, 2, 2, + REMOVE_OFF_COLOR.mixWith(REMOVE_ON_COLOR, isTargeted ? removeProgress.getValue() : 0.0f)); + NumismaticsGuiTextures.SUB_ACCOUNT_LIST_EDIT.render(graphics, cardWidth - 14, 2); + NumismaticsGuiTextures.SUB_ACCOUNT_LIST_RESET.render(graphics, cardWidth - 15, 26); + + // Render label + graphics.drawCenteredString(font, subAccount.getLabel(), cardWidth / 2, 6, 0xFFFFFF); + + // Draw spending info + Limit totalLimit = subAccount.getTotalLimit(); + { + //graphics.drawCenteredString(font, totalLimit.describe(), cardWidth / 2, CARD_HEADER + 6, 0xAAAAAA); + FormattedCharSequence formattedCharSequence = totalLimit.describe().getVisualOrderText(); + int width = font.width(formattedCharSequence); + + int x = (cardWidth / 2) - (width / 2); + + int max_x = cardWidth - 17; + if (x + width > max_x) { + x = max_x - width; + } + graphics.drawString(font, formattedCharSequence, x, CARD_HEADER + 6, 0xAAAAAA); + } + + // Draw sliders + TripleCoinSliderWidget widget = getOrCreateWidgetForSubAccount(subAccount); + widget.render(graphics, mouseX - leftPos - 3 - 6, mouseY - topPos - 16 - 9, partialTicks); + + ms.popPose(); + + return cardHeight; + } + + protected void renderSubAccountHelp(GuiGraphics graphics, int yOffset, int mouseX, int mouseY, float partialTicks) { + int zLevel = -100; + + AllGuiTextures light = AllGuiTextures.SCHEDULE_CARD_LIGHT; + AllGuiTextures medium = AllGuiTextures.SCHEDULE_CARD_MEDIUM; + AllGuiTextures dark = AllGuiTextures.SCHEDULE_CARD_DARK; + + int cardWidth = CARD_WIDTH; + int cardHeader = CARD_HEADER; + int cardHeight = cardHeader + CARD_BODY; + + PoseStack ms = graphics.pose(); + ms.pushPose(); + ms.translate(leftPos + 9, topPos + yOffset, 0); + + UIRenderHelper.drawStretched(graphics, 0, 1, cardWidth, cardHeight - 2, zLevel, light); + UIRenderHelper.drawStretched(graphics, 1, 0, cardWidth - 2, cardHeight, zLevel, light); + UIRenderHelper.drawStretched(graphics, 1, 1, cardWidth - 2, cardHeight - 2, zLevel, dark); + UIRenderHelper.drawStretched(graphics, 2, 2, cardWidth - 4, cardHeight - 4, zLevel, medium); + UIRenderHelper.drawStretched(graphics, 2, 2, cardWidth - 4, cardHeader, zLevel, medium); + UIRenderHelper.drawStretched(graphics, 8, cardHeader, cardWidth - 16, 1, zLevel, light); + UIRenderHelper.drawStretched(graphics, 9, cardHeader + 1, cardWidth - 16, 1, zLevel, dark); + + graphics.drawCenteredString( + font, Components.translatable("gui.numismatics.bank_terminal.sub_accounts.help"), + cardWidth / 2, 6, + 0xFFFFFF + ); + + for (int i = 0; i < 6; i++) { + graphics.drawString( + font, Components.translatable("gui.numismatics.bank_terminal.sub_accounts.help.line."+(i+1)), + 6, CARD_HEADER + 6 + (i * font.lineHeight), + 0xC0C0C0 + ); + } + + ms.popPose(); + } + + public boolean action(@Nullable GuiGraphics graphics, double mouseX, double mouseY, int click) { + if (menu.slotsActive()) + return false; + + int mx = (int) mouseX; + int my = (int) mouseY; + int x = mx - leftPos - 3; + int y = my - topPos - 16; + + //renderActionTooltip(graphics, ImmutableList.of(Components.literal("x: "+x), Components.literal("y: "+y)), mx, my); + + if (x < 0 || x >= 219) + return false; + if (y < 0 || y >= 172) + return false; + y += (int) scroll.getValue(0); + + int yOffset = 0; + + for (SubAccount subAccount : menu.contentHolder.getAlphabetizedSubAccounts()) { + int cardHeight = CARD_HEADER + CARD_BODY; + + int cx = x - 6; + int cy = y - 9 - yOffset; + + yOffset += cardHeight + CARD_SPACING; + + if (cx < 0 || cx >= CARD_WIDTH) + continue; + if (cy < 0 || cy >= cardHeight) + continue; + + //renderActionTooltip(graphics, ImmutableList.of(Components.literal("cx: "+cx), Components.literal("cy: "+cy)), mx, my + 30); + + if (cy >= 4 && cy <= 12) { + if (cx >= 3 && cx <= 11) { + boolean ready = removeProgress.settled() && removeProgress.getValue() > 0.9f + && removeTarget != null && removeTarget.equals(subAccount.getAuthorizationID()); + if (ready) { + renderActionTooltip(graphics, ImmutableList.of(Components.translatable("gui.numismatics.bank_terminal.sub_accounts.remove.confirm")), mx, my); + } else { + renderActionTooltip(graphics, ImmutableList.of(Components.translatable("gui.numismatics.bank_terminal.sub_accounts.remove")), mx, my); + } + if (click == 0) { + if (ready) { + menu.removeSubAccount(subAccount.getAuthorizationID()); + removeProgress.updateChaseTarget(0.0f); + removeProgress.setValue(0.0f); + removeTarget = null; + } else { + removeProgress.chase(1.0f, 0.4f, LerpedFloat.Chaser.LINEAR); + removeTarget = subAccount.getAuthorizationID(); + } + } + return true; + } else { + removeProgress.updateChaseTarget(0.0f); + removeProgress.setValue(0.0f); + removeTarget = null; + } + if (cx >= 195 && cx <= 203) { + renderActionTooltip(graphics, ImmutableList.of(Components.translatable("gui.numismatics.bank_terminal.sub_accounts.edit")), mx, my); + if (click == 0) { + editSubAccount(subAccount.getAuthorizationID()); + } + return true; + } + } else { + removeProgress.updateChaseTarget(0.0f); + removeProgress.setValue(0.0f); + removeTarget = null; + } + if (cy >= 26 && cy <= 37) { + if (cx >= 193 && cx <= 204) { + renderActionTooltip(graphics, ImmutableList.of(Components.translatable("gui.numismatics.bank_terminal.sub_accounts.reset_spending")), mx, my); + if (click == 0) { + menu.resetSubAccountSpending(subAccount.getAuthorizationID()); + } + return true; + } + } + + TripleCoinSliderWidget widget = getOrCreateWidgetForSubAccount(subAccount); + if (widget.isMouseOver(cx, cy)) + renderActionTooltip(graphics, widget.getToolTip(), mx, my); + if (widget.mouseClicked(cx, cy, click)) + return true; + } + + return false; + } + + private void renderActionTooltip(@Nullable GuiGraphics graphics, List tooltip, int mx, int my) { + if (graphics != null) + graphics.renderTooltip(font, tooltip, Optional.empty(), mx, my); + } + + protected void startStencil(GuiGraphics graphics, float x, float y, float w, float h) { + RenderSystem.clear(GL30.GL_STENCIL_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX); + + GL11.glDisable(GL11.GL_STENCIL_TEST); + RenderSystem.stencilMask(~0); + RenderSystem.clear(GL11.GL_STENCIL_BUFFER_BIT, Minecraft.ON_OSX); + GL11.glEnable(GL11.GL_STENCIL_TEST); + RenderSystem.stencilOp(GL11.GL_REPLACE, GL11.GL_KEEP, GL11.GL_KEEP); + RenderSystem.stencilMask(0xFF); + RenderSystem.stencilFunc(GL11.GL_NEVER, 1, 0xFF); + + PoseStack matrixStack = graphics.pose(); + matrixStack.pushPose(); + matrixStack.translate(x, y, 0); + matrixStack.scale(w, h, 1); + graphics.fillGradient(0, 0, 1, 1, -100, 0xff000000, 0xff000000); + matrixStack.popPose(); + + GL11.glEnable(GL11.GL_STENCIL_TEST); + RenderSystem.stencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); + RenderSystem.stencilFunc(GL11.GL_EQUAL, 1, 0xFF); + } + + protected void endStencil() { + GL11.glDisable(GL11.GL_STENCIL_TEST); + } + + @Override + public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + syncName(); + + if (editorConfirm != null && editorConfirm.isMouseOver(pMouseX, pMouseY)) { + editSubAccount(null); + return true; + } + + if (action(null, pMouseX, pMouseY, pButton)) + return true; + + int popupLeftPos = leftPos - 12; + int popupTopPos = topPos - 5; + if (hasPopup && !editorLabelBox.isFocused() && pMouseY > popupTopPos && pMouseY < popupTopPos + 14 + && pMouseX > popupLeftPos && pMouseX < popupLeftPos + NumismaticsGuiTextures.SUB_ACCOUNT_LIST_POPUP.width) { + editorLabelBox.setFocused(true); + editorLabelBox.setHighlightPos(0); + setFocused(editorLabelBox); + return true; + } + + return super.mouseClicked(pMouseX, pMouseY, pButton); + } + + private void syncName() { + if (menu.getOpenSubAccount() != null && editorLabelBox != null) { + if (editorLabelBox.getValue().isBlank()) + editorLabelBox.setValue("Sub Account"); + menu.setLabel(menu.getOpenSubAccount().authorizationID, editorLabelBox.getValue()); + } + } + + @Override + public boolean keyPressed(int pKeyCode, int pScanCode, int pModifiers) { + boolean hitEnter = getFocused() instanceof EditBox + && (pKeyCode == InputConstants.KEY_RETURN || pKeyCode == InputConstants.KEY_NUMPADENTER); + + if (hitEnter && editorLabelBox != null && editorLabelBox.isFocused()) { + if (editorLabelBox.getValue().isBlank()) + editorLabelBox.setValue("Sub Account"); + editorLabelBox.setFocused(false); + syncName(); + + return true; + } + return super.keyPressed(pKeyCode, pScanCode, pModifiers); + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + sliders.forEach((id, widget) -> widget.mouseReleased(mouseX, mouseY, button)); + + return super.mouseReleased(mouseX, mouseY, button); + } + + @Override + protected void renderForeground(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + super.renderForeground(graphics, mouseX, mouseY, partialTicks); + + GuiGameElement.of(renderedItem).at(leftPos + background.width + 6, topPos + background.height - 64, -200) + .scale(5) + .render(graphics); + action(graphics, mouseX, mouseY, -1); + + if (!hasPopup) + return; + + int x = leftPos - 12; + int y = topPos - 5; + + SubAccountListMenu.OpenSubAccountInformation osa = menu.getOpenSubAccount(); + if (osa == null) + return; + SubAccount subAccount = menu.contentHolder.getSubAccountNoAuth(osa.authorizationID); + if (subAccount == null) + return; + AuthorizationType authorizationType = subAccount.getAuthorizationType(); + authorizationType.icon.render(graphics, x + 43, y + 90); + + if (mouseX >= x + 42 && mouseY >= y + 89 && mouseX < x + 42 + 18 && mouseY < y + 89 + 18) { + renderActionTooltip(graphics, ImmutableList.of( + authorizationType.title(), + authorizationType.description() + ), mouseX, mouseY); + } + + String text = editorLabelBox.getValue(); + if (!editorLabelBox.isFocused()) + AllGuiTextures.STATION_EDIT_NAME.render(graphics, nameBoxX(text, editorLabelBox) + font.width(text) + 5, y + 1); + } + + @Override + protected void renderBg(@NotNull GuiGraphics graphics, float partialTick, int mouseX, int mouseY) { + int x = leftPos; + int y = topPos; + + background.render(graphics, x, y); + if (!hasPopup) + graphics.drawCenteredString(font, title, x + (background.width - 8) / 2, y + 3, 0xFFFFFF); + renderSubAccounts(graphics, mouseX, mouseY, partialTick); + + if (!hasPopup) + return; + + graphics.fillGradient(0, 0, this.width, this.height, -1072689136, -804253680); + + int xo = -10; + int yo = -45; + NumismaticsGuiTextures.SUB_ACCOUNT_LIST_POPUP.render(graphics, leftPos - 2+xo, topPos + 40+yo); + renderPlayerInventory(graphics, leftPos + 38+xo, topPos + 167+yo); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double delta) { + if (hasPopup) { + return super.mouseScrolled(mouseX, mouseY, delta); + } + + float chaseTarget = scroll.getChaseTarget(); + float max = 40 - 173; + + for (SubAccount ignored : menu.contentHolder.getAlphabetizedSubAccounts()) { + max += CARD_HEADER + CARD_BODY; + } + + if (max > 0) { + chaseTarget -= delta * 12; + chaseTarget = Mth.clamp(chaseTarget, 0, max); + scroll.chase((int) chaseTarget, 0.7f, LerpedFloat.Chaser.EXP); + } else { + scroll.chase(0, 0.7f, LerpedFloat.Chaser.EXP); + } + + return super.mouseScrolled(mouseX, mouseY, delta); + } + + @Override + public void removed() { + super.removed(); + syncName(); + } + + private int nameBoxX(String s, EditBox nameBox) { + return leftPos - 12 + NumismaticsGuiTextures.SUB_ACCOUNT_LIST_POPUP.width / 2 - (Math.min(font.width(s), nameBox.getWidth()) + 10) / 2; + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/TripleCoinSliderWidget.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/TripleCoinSliderWidget.java new file mode 100644 index 00000000..64c56439 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/TripleCoinSliderWidget.java @@ -0,0 +1,328 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.content.bank; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.foundation.blockEntity.behaviour.ValueSettingsScreen; +import com.simibubi.create.foundation.blockEntity.behaviour.scrollValue.ScrollValueHandler; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget; +import com.simibubi.create.foundation.utility.Components; +import com.simibubi.create.foundation.utility.Couple; +import com.simibubi.create.foundation.utility.Lang; +import dev.ithundxr.createnumismatics.base.client.rendering.UIRenderHelper; +import dev.ithundxr.createnumismatics.content.backend.Coin; +import dev.ithundxr.createnumismatics.registry.NumismaticsGuiTextures; +import dev.ithundxr.createnumismatics.util.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.Font; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; +import net.minecraft.world.phys.Vec2; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +import static net.minecraft.client.gui.screens.Screen.hasShiftDown; + +public class TripleCoinSliderWidget extends AbstractSimiWidget { + + private static final Coin[] ROWS = new Coin[] { + Coin.SPUR, + Coin.COG, + Coin.SUN + }; + private static final int milestoneSize = 4; + + protected final Font font; + protected final int maxLabelWidth; + protected final int valueBarWidth; + protected final int[] values = new int[] {0, 0, 0}; + + protected @Nullable Integer draggingRow = null; + protected int soundCooldown = 0; + protected @Nullable EditHandler onEdit; + protected boolean maxIsInfinite = false; + + protected TripleCoinSliderWidget(Font font, int x, int y) { + super(x, y, 48, 16); + this.font = font; + + int maxValue = getMaxValue(); + int milestoneCount = maxValue / getMilestoneInterval() + 1; + int scale = maxValue > 128 ? 1 : 2; + + maxLabelWidth = Arrays.stream(ROWS) + .map(Coin::getTranslatedName) + .map(TextUtils::titleCaseConversion) + .mapToInt(font::width) + .max() + .orElse(0) + 4; + + valueBarWidth = (maxValue + 1) * scale + 1 + milestoneCount * milestoneSize; + this.width = (maxLabelWidth + 14) + (valueBarWidth + 10); + this.height = (ROWS.length * 15) + 1; + } + + @Contract("_ -> this") + protected TripleCoinSliderWidget withEditCallback(EditHandler onEdit) { + this.onEdit = onEdit; + return this; + } + + @Contract("_ -> this") + protected TripleCoinSliderWidget withValue(int spur) { + Couple sunAndExtra = Coin.SUN.convert(spur, 64); + Couple cogAndExtra = Coin.COG.convert(sunAndExtra.getSecond(), 64); + return withValues( + cogAndExtra.getSecond(), // Spurs + cogAndExtra.getFirst(), // Cogs + sunAndExtra.getFirst() // Suns + ); + } + + @Contract("_, _, _ -> this") + protected TripleCoinSliderWidget withValues(int spur, int cog, int sun) { + values[0] = spur; + values[1] = cog; + values[2] = sun; + return this; + } + + @Contract("_ -> this") + protected TripleCoinSliderWidget setMaxIsInfinite(boolean maxIsInfinite) { + this.maxIsInfinite = maxIsInfinite; + return this; + } + + protected int getMaxValue() { + return 64; + } + + protected int getMilestoneInterval() { + return 16; + } + + @SuppressWarnings("IntegerDivisionInFloatingPointContext") + public Vec2 getCoordinateOfValue(int row, int column) { + int scale = getMaxValue() > 128 ? 1 : 2; + + float xOut = getX() + + ((Math.max(1, column) - 1) / getMilestoneInterval()) * milestoneSize + + column * scale + + 1.5f; + xOut += maxLabelWidth + 14 + 4 + 3; + + if (column % getMilestoneInterval() == 0) + xOut += milestoneSize / 2; + if (column > 0) + xOut += milestoneSize; + + float yOut = getY() + (row + .5f) * 15 - .5f; + return new Vec2(xOut, yOut); + } + + protected boolean canStartDragging(int mouseX, int mouseY) { + int x = getX(); + int y = getY(); + int relMouseX = mouseX - x; + int relMouseY = mouseY - y; + + return maxLabelWidth + 14 + 1 <= relMouseX && relMouseX < width + 4 + && 0 <= relMouseY && relMouseY < height; + } + + @Override + protected boolean clicked(double mouseX, double mouseY) { + if (!this.active || !this.visible) + return false; + + return mouseX >= (double)this.getX() + && mouseY >= (double)this.getY() + && mouseX < (double)(this.getX() + this.width + 4) + && mouseY < (double)(this.getY() + this.height); + } + + protected int getClosestRow(int mouseY) { + int y = getY(); + int relMouseY = mouseY - y; + + return Math.min(ROWS.length - 1, Math.max(0, relMouseY / 15)); + } + + protected int getClosestColumn(int mouseX, int row) { + int column = 0; + boolean milestonesOnly = hasShiftDown(); + + double bestDiff = Double.MAX_VALUE; + for (; column <= getMaxValue(); column++) { + Vec2 coord = getCoordinateOfValue(row, milestonesOnly ? column * getMilestoneInterval() : column); + double diff = Math.abs(coord.x - mouseX); + if (bestDiff < diff) + break; + bestDiff = diff; + } + column -= 1; + + return milestonesOnly ? Math.min(column * getMilestoneInterval(), getMaxValue()) : column; + } + + @Override + protected void doRender(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + int x = getX(); + int y = getY(); + int milestoneCount = getMaxValue() / getMilestoneInterval() + 1; + int scale = getMaxValue() > 128 ? 1 : 2; + + /*============*/ + /* Background */ + /*============*/ + int a = 0xc0 << 24; + graphics.fillGradient(x + maxLabelWidth + 14 + 3, y + 1, x + this.width - 1, y + this.height - 1, 0x101010 | a, 0x101010 | a); + + /*================*/ + /* Main Rendering */ + /*================*/ + int zLevel = 0; + + renderBrassFrame(graphics, x + maxLabelWidth + 14 + 3, y - 3 + 3, valueBarWidth + 8, ROWS.length * 15 + 1); + + int trackY = y + 3; + int labelY = trackY; + for (Coin coin : ROWS) { + String displayName = TextUtils.titleCaseConversion(coin.getTranslatedName()); + int valueBarX = x + maxLabelWidth + 14 + 4 + 3; + + UIRenderHelper.drawCropped(graphics, x - 4 + 7, labelY - 1, maxLabelWidth + 8, 15, + zLevel, NumismaticsGuiTextures.VALUE_SETTINGS_LABEL_BG_TALL); + + PoseStack ms = graphics.pose(); + ms.pushPose(); + ms.translate(x + maxLabelWidth + 2, labelY + 2, zLevel); + ms.scale(8.0f, 8.0f, 8.0f); + coin.getIcon().render(ms, graphics.bufferSource(), 0xffffff); + ms.popPose(); + + for (int w = 0; w < valueBarWidth; w += AllGuiTextures.VALUE_SETTINGS_BAR.width - 1) + UIRenderHelper.drawCropped(graphics, valueBarX + w, trackY + 1, + Math.min(AllGuiTextures.VALUE_SETTINGS_BAR.width - 1, valueBarWidth - w), 8, + zLevel, AllGuiTextures.VALUE_SETTINGS_BAR); + graphics.drawString(font, displayName, x + 7, labelY + 2, 0x442000, false); + + int milestoneX = valueBarX; + for (int milestone = 0; milestone < milestoneCount; milestone++) { + AllGuiTextures.VALUE_SETTINGS_MILESTONE.render(graphics, milestoneX, trackY + 1); + milestoneX += milestoneSize + getMilestoneInterval() * scale; + } + + trackY += 15; + labelY += 14; + } + renderBrassFrame(graphics, x, y, maxLabelWidth + 14, ROWS.length * 15 + 1); + + if (draggingRow != null) { + int closestColumn = getClosestColumn(mouseX, draggingRow); + + int lastValue = values[draggingRow]; + if (closestColumn != lastValue) { + values[draggingRow] = closestColumn; + if (onEdit != null) + onEdit.apply(values[0], values[1], values[2]); + if (soundCooldown == 0) { + float pitch = closestColumn / (float) getMaxValue(); + pitch = Mth.lerp(pitch, 1.15f, 1.5f); + Minecraft.getInstance().getSoundManager() + .play(SimpleSoundInstance.forUI(AllSoundEvents.SCROLL_VALUE.getMainEvent(), pitch, 0.25f)); + ScrollValueHandler.wrenchCog.bump(3, -(closestColumn - lastValue) * 10); + } + } + } + + boolean infinite = maxIsInfinite && values[0] == 64 && values[1] == 64 && values[2] == 64; + for (int row = 0; row < values.length; row++) { + int value = values[row]; + Vec2 coordinate = getCoordinateOfValue(row, value); + // 221E = infinity symbol + Component cursorText = infinite ? Components.literal("\u221E") : Lang.number(value).component(); + + int cursorWidth = (font.width(cursorText) / 2) * 2 + 3; + int cursorX = ((int) (coordinate.x)) - cursorWidth / 2; + int cursorY = ((int) (coordinate.y)) - 6; + + AllGuiTextures.VALUE_SETTINGS_CURSOR_LEFT.render(graphics, cursorX - 3, cursorY); + UIRenderHelper.drawCropped(graphics, cursorX, cursorY, cursorWidth, 14, + zLevel, AllGuiTextures.VALUE_SETTINGS_CURSOR); + AllGuiTextures.VALUE_SETTINGS_CURSOR_RIGHT.render(graphics, cursorX + cursorWidth, cursorY); + + graphics.drawString(font, cursorText, cursorX + 2, cursorY + 3, (draggingRow != null && row == draggingRow) ? 0x703a0a : 0x442000, false); + } + } + + /** Copied from {@link ValueSettingsScreen} */ + protected void renderBrassFrame(GuiGraphics graphics, int x, int y, int w, int h) { + AllGuiTextures.BRASS_FRAME_TL.render(graphics, x, y); + AllGuiTextures.BRASS_FRAME_TR.render(graphics, x + w - 4, y); + AllGuiTextures.BRASS_FRAME_BL.render(graphics, x, y + h - 4); + AllGuiTextures.BRASS_FRAME_BR.render(graphics, x + w - 4, y + h - 4); + int zLevel = 0; + + if (h > 8) { + UIRenderHelper.drawStretched(graphics, x, y + 4, 3, h - 8, zLevel, AllGuiTextures.BRASS_FRAME_LEFT); + UIRenderHelper.drawStretched(graphics, x + w - 3, y + 4, 3, h - 8, zLevel, AllGuiTextures.BRASS_FRAME_RIGHT); + } + + if (w > 8) { + UIRenderHelper.drawCropped(graphics, x + 4, y, w - 8, 3, zLevel, AllGuiTextures.BRASS_FRAME_TOP); + UIRenderHelper.drawCropped(graphics, x + 4, y + h - 3, w - 8, 3, zLevel, AllGuiTextures.BRASS_FRAME_BOTTOM); + } + } + + @Override + public void tick() { + if (soundCooldown > 0) + soundCooldown--; + + super.tick(); + } + + @Override + public void onClick(double mouseX, double mouseY) { + super.onClick(mouseX, mouseY); + if (!canStartDragging((int) mouseX, (int) mouseY)) + return; + + draggingRow = getClosestRow((int) mouseY); + } + + @Override + public void onRelease(double mouseX, double mouseY) { + super.onRelease(mouseX, mouseY); + draggingRow = null; + } + + @FunctionalInterface + public interface EditHandler { + void apply(int spurs, int cogs, int suns); + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/blaze_banker/BlazeBankerMenu.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/blaze_banker/BlazeBankerMenu.java index 153eb225..47ffa8a9 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/blaze_banker/BlazeBankerMenu.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/blaze_banker/BlazeBankerMenu.java @@ -19,6 +19,7 @@ package dev.ithundxr.createnumismatics.content.bank.blaze_banker; import com.simibubi.create.foundation.gui.menu.MenuBase; +import dev.ithundxr.createnumismatics.content.backend.ItemWritingContainer; import dev.ithundxr.createnumismatics.content.bank.CardItem; import dev.ithundxr.createnumismatics.content.bank.CardSlot; import dev.ithundxr.createnumismatics.content.bank.IDCardItem; @@ -29,8 +30,6 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.Container; -import net.minecraft.world.ContainerHelper; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; import net.minecraft.world.inventory.MenuType; @@ -39,8 +38,6 @@ import net.minecraft.world.level.block.entity.BlockEntity; import org.jetbrains.annotations.NotNull; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; import java.util.function.Consumer; @@ -201,73 +198,19 @@ protected boolean moveItemStackTo(ItemStack stack, int startIndex, int endIndex, return bl; } - private static class CardWritingContainer implements Container { - private final Consumer slotsChangedCallback; + private static class CardWritingContainer extends ItemWritingContainer { private final UUID uuid; - @NotNull - protected final List stacks = new ArrayList<>(); - public CardWritingContainer(Consumer slotsChangedCallback, UUID uuid) { - this.slotsChangedCallback = slotsChangedCallback; + super(slotsChangedCallback); this.uuid = uuid; - stacks.add(ItemStack.EMPTY); - } - - @Override - public int getContainerSize() { - return 1; - } - - protected ItemStack getStack() { - return stacks.get(0); - } - - @Override - public boolean isEmpty() { - return getStack().isEmpty(); - } - - @Override - public @NotNull ItemStack getItem(int slot) { - return getStack(); - } - - @Override - public @NotNull ItemStack removeItem(int slot, int amount) { - ItemStack stack = ContainerHelper.removeItem(this.stacks, 0, amount); - if (!stack.isEmpty()) { - this.slotsChangedCallback.accept(this); - } - return stack; - } - - @Override - public @NotNull ItemStack removeItemNoUpdate(int slot) { - return ContainerHelper.takeItem(this.stacks, 0); } @Override - public void setItem(int slot, @NotNull ItemStack stack) { - this.stacks.set(0, stack); - if (!CardItem.isBound(stack) && NumismaticsTags.AllItemTags.CARDS.matches(stack)) + protected void doWriteItem(ItemStack stack) { + if (NumismaticsTags.AllItemTags.CARDS.matches(stack) && !CardItem.isBound(stack)) CardItem.set(stack, uuid); - this.slotsChangedCallback.accept(this); - } - - @Override - public void setChanged() { - - } - - @Override - public boolean stillValid(@NotNull Player player) { - return true; - } - - @Override - public void clearContent() { - this.stacks.set(0, ItemStack.EMPTY); } } + } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/blaze_banker/BlazeBankerScreen.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/blaze_banker/BlazeBankerScreen.java index b43d7b6a..b7393964 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/blaze_banker/BlazeBankerScreen.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/blaze_banker/BlazeBankerScreen.java @@ -26,15 +26,15 @@ import com.simibubi.create.foundation.gui.element.GuiGameElement; import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; import com.simibubi.create.foundation.gui.widget.IconButton; -import com.simibubi.create.foundation.gui.widget.Indicator; import com.simibubi.create.foundation.utility.Components; import dev.ithundxr.createnumismatics.base.client.rendering.GuiBlockEntityRenderBuilder; -import dev.ithundxr.createnumismatics.registry.*; +import dev.ithundxr.createnumismatics.registry.NumismaticsBlocks; +import dev.ithundxr.createnumismatics.registry.NumismaticsGuiTextures; +import dev.ithundxr.createnumismatics.registry.NumismaticsPackets; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.components.EditBox; import net.minecraft.client.renderer.Rect2i; -import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.item.ItemStack; diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AbstractDepositorBlockEntity.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AbstractDepositorBlockEntity.java index f60d50da..696ac753 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AbstractDepositorBlockEntity.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AbstractDepositorBlockEntity.java @@ -27,6 +27,8 @@ import dev.ithundxr.createnumismatics.content.backend.Trusted; import dev.ithundxr.createnumismatics.content.backend.trust_list.TrustListContainer; import dev.ithundxr.createnumismatics.content.backend.trust_list.TrustListHolder; +import dev.ithundxr.createnumismatics.content.bank.AuthorizedCardItem; +import dev.ithundxr.createnumismatics.content.bank.AuthorizedCardItem.AuthorizationPair; import dev.ithundxr.createnumismatics.content.bank.CardItem; import dev.ithundxr.createnumismatics.content.coins.DiscreteCoinBag; import dev.ithundxr.createnumismatics.registry.NumismaticsPackets; @@ -77,11 +79,17 @@ public AbstractDepositorBlockEntity(BlockEntityType type, BlockPos pos, Block super(type, pos, state); } - public @Nullable UUID getCardId() { + public @Nullable UUID getDepositAccount() { ItemStack card = cardContainer.getItem(0); - if (!(card.getItem() instanceof CardItem)) + + if (NumismaticsTags.AllItemTags.CARDS.matches(card)) { + return CardItem.get(card); + } else if (NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(card)) { + AuthorizationPair authorizationPair = AuthorizedCardItem.get(card); + return authorizationPair == null ? null : authorizationPair.accountID(); + } else { return null; - return CardItem.get(card); + } } public void activate() { @@ -144,17 +152,6 @@ public boolean isTrustedInternal(Player player) { } } - @Nullable - public UUID getDepositAccount() { - ItemStack cardStack = cardContainer.getItem(0); - if (cardStack.isEmpty()) - return null; - if (!NumismaticsTags.AllItemTags.CARDS.matches(cardStack)) - return null; - - return CardItem.get(cardStack); - } - public void addCoin(Coin coin, int count) { UUID depositAccount = getDepositAccount(); if (depositAccount != null) { diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AndesiteDepositorBlock.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AndesiteDepositorBlock.java index 8cd0e6d3..deedca23 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AndesiteDepositorBlock.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AndesiteDepositorBlock.java @@ -19,19 +19,15 @@ package dev.ithundxr.createnumismatics.content.depositor; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.foundation.utility.Components; -import dev.ithundxr.createnumismatics.Numismatics; -import dev.ithundxr.createnumismatics.content.backend.BankAccount; import dev.ithundxr.createnumismatics.content.backend.Coin; -import dev.ithundxr.createnumismatics.content.bank.CardItem; +import dev.ithundxr.createnumismatics.content.backend.IDeductable; +import dev.ithundxr.createnumismatics.content.backend.ReasonHolder; import dev.ithundxr.createnumismatics.content.coins.CoinItem; import dev.ithundxr.createnumismatics.registry.NumismaticsBlockEntities; -import dev.ithundxr.createnumismatics.registry.NumismaticsTags; import dev.ithundxr.createnumismatics.util.Utils; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -43,8 +39,6 @@ import net.minecraft.world.phys.BlockHitResult; import org.jetbrains.annotations.NotNull; -import java.util.UUID; - public class AndesiteDepositorBlock extends AbstractDepositorBlock { public AndesiteDepositorBlock(Properties properties) { super(properties); @@ -88,22 +82,16 @@ public BlockEntityType getBlockEntityType() { Coin coin = andesiteDepositor.getCoin(); ItemStack handStack = player.getItemInHand(hand); - if (NumismaticsTags.AllItemTags.CARDS.matches(handStack)) { - if (CardItem.isBound(handStack)) { - UUID id = CardItem.get(handStack); - BankAccount account = Numismatics.BANK.getAccount(id); - if (account != null && account.isAuthorized(player)) { - if (account.deduct(coin, 1)) { - activate(state, level, pos); - andesiteDepositor.addCoin(coin, 1); - } - } - } + ReasonHolder reasonHolder = new ReasonHolder(); + IDeductable deductable = IDeductable.get(handStack, player, reasonHolder); + if (deductable != null && deductable.deduct(coin, 1, reasonHolder)) { + activate(state, level, pos); + andesiteDepositor.addCoin(coin, 1); } else if (CoinItem.extract(player, hand, coin, true)) { activate(state, level, pos); andesiteDepositor.addCoin(coin, 1); } else { - player.displayClientMessage(Components.translatable("gui.numismatics.vendor.insufficient_funds") + player.displayClientMessage(reasonHolder.getMessageOrDefault() .withStyle(ChatFormatting.DARK_RED), true); level.playSound(null, pos, AllSoundEvents.DENY.getMainEvent(), SoundSource.BLOCKS, 0.5f, 1.0f);} } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AndesiteDepositorMenu.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AndesiteDepositorMenu.java index 0fe8654d..864b04a4 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AndesiteDepositorMenu.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AndesiteDepositorMenu.java @@ -20,7 +20,7 @@ import com.simibubi.create.foundation.gui.menu.MenuBase; import dev.ithundxr.createnumismatics.content.backend.Coin; -import dev.ithundxr.createnumismatics.content.bank.CardSlot; +import dev.ithundxr.createnumismatics.content.bank.AnyCardSlot; import dev.ithundxr.createnumismatics.content.coins.CoinItem; import dev.ithundxr.createnumismatics.content.coins.SlotDiscreteCoinBag; import dev.ithundxr.createnumismatics.registry.NumismaticsTags; @@ -73,7 +73,7 @@ protected void addSlots() { x += 18; addSlot(new SlotDiscreteCoinBag(contentHolder.inventory, coin, x, y, true, true)); } - addSlot(new CardSlot.BoundCardSlot(contentHolder.cardContainer, 0, 11, y)); // make here to preserve slot order + addSlot(new AnyCardSlot.BoundAnyCardSlot(contentHolder.cardContainer, 0, 11, y)); // make here to preserve slot order addPlayerSlots(31, 64 + 35); } @@ -121,7 +121,7 @@ public void clicked(int slotId, int button, @NotNull ClickType clickType, @NotNu } else { // player inventory if (stack.getItem() instanceof CoinItem && !moveItemStackTo(stack, 0, COIN_SLOTS, false)) { return ItemStack.EMPTY; - } else if (NumismaticsTags.AllItemTags.CARDS.matches(stack) && !moveItemStackTo(stack, CARD_SLOT_INDEX, CARD_SLOT_INDEX+1, false)) { + } else if ((NumismaticsTags.AllItemTags.CARDS.matches(stack) || NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(stack)) && !moveItemStackTo(stack, CARD_SLOT_INDEX, CARD_SLOT_INDEX+1, false)) { return ItemStack.EMPTY; } else if (index >= PLAYER_INV_START_INDEX && index < PLAYER_HOTBAR_END_INDEX && !moveItemStackTo(stack, PLAYER_HOTBAR_END_INDEX, PLAYER_INV_END_INDEX, false)) { return ItemStack.EMPTY; diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/BrassDepositorBlock.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/BrassDepositorBlock.java index 3871fe1d..a532fbb0 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/BrassDepositorBlock.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/BrassDepositorBlock.java @@ -20,15 +20,9 @@ import com.simibubi.create.AllSoundEvents; import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; -import com.simibubi.create.foundation.utility.Components; -import dev.ithundxr.createnumismatics.Numismatics; -import dev.ithundxr.createnumismatics.content.backend.BankAccount; -import dev.ithundxr.createnumismatics.content.backend.Coin; +import dev.ithundxr.createnumismatics.content.backend.ReasonHolder; import dev.ithundxr.createnumismatics.content.backend.behaviours.SliderStylePriceBehaviour; -import dev.ithundxr.createnumismatics.content.bank.CardItem; -import dev.ithundxr.createnumismatics.content.coins.CoinItem; import dev.ithundxr.createnumismatics.registry.NumismaticsBlockEntities; -import dev.ithundxr.createnumismatics.registry.NumismaticsTags; import dev.ithundxr.createnumismatics.util.Utils; import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; @@ -37,17 +31,12 @@ import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import org.jetbrains.annotations.NotNull; -import java.util.HashMap; -import java.util.Map; -import java.util.UUID; - public class BrassDepositorBlock extends AbstractDepositorBlock { public BrassDepositorBlock(Properties properties) { super(properties); @@ -87,11 +76,12 @@ public BlockEntityType getBlockEntityType() { if (level.isClientSide) return InteractionResult.SUCCESS; + ReasonHolder reasonHolder = new ReasonHolder(); SliderStylePriceBehaviour priceBehaviour = BlockEntityBehaviour.get(level, pos, SliderStylePriceBehaviour.TYPE); - if (priceBehaviour != null && priceBehaviour.deduct(player, hand, true)) { + if (priceBehaviour != null && priceBehaviour.deduct(player, hand, true, reasonHolder)) { activate(state, level, pos); } else { - player.displayClientMessage(Components.translatable("gui.numismatics.vendor.insufficient_funds") + player.displayClientMessage(reasonHolder.getMessageOrDefault() .withStyle(ChatFormatting.DARK_RED), true); level.playSound(null, pos, AllSoundEvents.DENY.getMainEvent(), SoundSource.BLOCKS, 0.5f, 1.0f);} return InteractionResult.CONSUME; diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/BrassDepositorMenu.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/BrassDepositorMenu.java index 5f42c643..3f96688c 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/BrassDepositorMenu.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/BrassDepositorMenu.java @@ -21,7 +21,7 @@ import com.simibubi.create.foundation.gui.menu.MenuBase; import dev.ithundxr.createnumismatics.content.backend.BigStackSizeContainerSynchronizer; import dev.ithundxr.createnumismatics.content.backend.Coin; -import dev.ithundxr.createnumismatics.content.bank.CardSlot; +import dev.ithundxr.createnumismatics.content.bank.AnyCardSlot; import dev.ithundxr.createnumismatics.content.coins.CoinDisplaySlot; import dev.ithundxr.createnumismatics.content.coins.CoinItem; import dev.ithundxr.createnumismatics.content.coins.SlotDiscreteCoinBag; @@ -77,7 +77,7 @@ protected void addSlots() { x += 18; addSlot(new SlotDiscreteCoinBag(contentHolder.inventory, coin, x, y, true, true)); } - addSlot(new CardSlot.BoundCardSlot(contentHolder.cardContainer, 0, 11+26, y)); // make here to preserve slot order + addSlot(new AnyCardSlot.BoundAnyCardSlot(contentHolder.cardContainer, 0, 11+26, y)); // make here to preserve slot order addPlayerSlots(31+13, 165); @@ -140,7 +140,7 @@ public void clicked(int slotId, int button, @NotNull ClickType clickType, @NotNu } else { // player inventory if (stack.getItem() instanceof CoinItem && !moveItemStackTo(stack, 0, COIN_SLOTS, false)) { return ItemStack.EMPTY; - } else if (NumismaticsTags.AllItemTags.CARDS.matches(stack) && !moveItemStackTo(stack, CARD_SLOT_INDEX, CARD_SLOT_INDEX+1, false)) { + } else if ((NumismaticsTags.AllItemTags.CARDS.matches(stack) || NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(stack)) && !moveItemStackTo(stack, CARD_SLOT_INDEX, CARD_SLOT_INDEX+1, false)) { return ItemStack.EMPTY; } else if (index >= PLAYER_INV_START_INDEX && index < PLAYER_HOTBAR_END_INDEX && !moveItemStackTo(stack, PLAYER_HOTBAR_END_INDEX, PLAYER_INV_END_INDEX, false)) { return ItemStack.EMPTY; diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/vendor/VendorBlockEntity.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/vendor/VendorBlockEntity.java index 5b747752..d8f54e26 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/vendor/VendorBlockEntity.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/vendor/VendorBlockEntity.java @@ -27,17 +27,15 @@ import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; import com.simibubi.create.foundation.utility.Lang; -import dan200.computercraft.api.ComputerCraftAPI; -import dan200.computercraft.api.ComputerCraftTags; import dev.ithundxr.createnumismatics.Numismatics; import dev.ithundxr.createnumismatics.compat.computercraft.ComputerCraftProxy; -import dev.ithundxr.createnumismatics.content.backend.BankAccount; -import dev.ithundxr.createnumismatics.content.backend.Coin; -import dev.ithundxr.createnumismatics.content.backend.Trusted; +import dev.ithundxr.createnumismatics.content.backend.*; import dev.ithundxr.createnumismatics.content.backend.behaviours.SliderStylePriceBehaviour; import dev.ithundxr.createnumismatics.content.backend.trust_list.TrustListContainer; import dev.ithundxr.createnumismatics.content.backend.trust_list.TrustListHolder; import dev.ithundxr.createnumismatics.content.backend.trust_list.TrustListMenu; +import dev.ithundxr.createnumismatics.content.bank.AuthorizedCardItem; +import dev.ithundxr.createnumismatics.content.bank.AuthorizedCardItem.AuthorizationPair; import dev.ithundxr.createnumismatics.content.bank.CardItem; import dev.ithundxr.createnumismatics.content.coins.CoinItem; import dev.ithundxr.createnumismatics.content.coins.DiscreteCoinBag; @@ -127,11 +125,10 @@ public int getCoinCount(Coin coin) { return this.inventory.getDiscrete(coin); } - public @Nullable UUID getCardId() { + public @Nullable IDeductable getDeductable() { ItemStack card = cardContainer.getItem(0); - if (!(card.getItem() instanceof CardItem)) - return null; - return CardItem.get(card); + + return IDeductable.getAutomated(card, owner, ReasonHolder.IGNORED); } @Override @@ -236,15 +233,23 @@ public void addCoin(Coin coin, int count) { setChanged(); } + /** + * NOTE: this account is ONLY for deposits, for withdrawals, use getDeductable() + */ @Nullable public UUID getDepositAccount() { ItemStack cardStack = cardContainer.getItem(0); if (cardStack.isEmpty()) return null; - if (!NumismaticsTags.AllItemTags.CARDS.matches(cardStack)) - return null; - return CardItem.get(cardStack); + if (NumismaticsTags.AllItemTags.CARDS.matches(cardStack)) { + return CardItem.get(cardStack); + } else if (NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(cardStack)) { + AuthorizationPair authorizationPair = AuthorizedCardItem.get(cardStack); + return authorizationPair == null ? null : authorizationPair.accountID(); + } else { + return null; + } } @Override @@ -325,7 +330,7 @@ public boolean addToTooltip(List tooltip, boolean isPlayerSneaking) { } } else if (!hasEnoughMoney()) { Lang.builder() - .add(Components.translatable("gui.numismatics.vendor.insufficient_funds")) + .add(Components.translatable("gui.numismatics.vendor.out_of_stock.funds")) .style(ChatFormatting.DARK_RED) .forGoggles(tooltip); @@ -636,11 +641,8 @@ private boolean hasEnoughMoney() { if (price.canPayOut()) return true; - if (getCardId() != null) { - BankAccount account = Numismatics.BANK.getAccount(getCardId()); - return account != null && account.isAuthorized(owner) && account.getBalance() >= price.getTotalPrice(); - } - return false; + IDeductable deductable = getDeductable(); + return deductable != null && deductable.getMaxWithdrawal() >= price.getTotalPrice(); } public void tryTransaction(Player player, InteractionHand hand) { @@ -662,7 +664,8 @@ private void trySellTo(Player player, InteractionHand hand) { condenseItems(); if (isCreativeVendor()) { - if (price.deduct(player, hand, false)) { + ReasonHolder reasonHolder = new ReasonHolder(); + if (price.deduct(player, hand, false, reasonHolder)) { ItemStack output = selling.copy(); ItemUtil.givePlayerItem(player, output); giveSellingAdvancements(player); @@ -671,14 +674,15 @@ private void trySellTo(Player player, InteractionHand hand) { notifyUpdate(); } else { // insufficient funds - player.displayClientMessage(Components.translatable("gui.numismatics.vendor.insufficient_funds") + player.displayClientMessage(reasonHolder.getMessageOrDefault() .withStyle(ChatFormatting.DARK_RED), true); level.playSound(null, getBlockPos(), AllSoundEvents.DENY.getMainEvent(), SoundSource.BLOCKS, 0.5f, 1.0f); } } else { for (ItemStack stack : items) { if (matchesSellingItem(stack) && stack.getCount() >= selling.getCount()) { - if (price.deduct(player, hand, true)) { + ReasonHolder reasonHolder = new ReasonHolder(); + if (price.deduct(player, hand, true, reasonHolder)) { ItemStack output = stack.split(selling.getCount()); ItemUtil.givePlayerItem(player, output); giveSellingAdvancements(player); @@ -687,7 +691,7 @@ private void trySellTo(Player player, InteractionHand hand) { notifyUpdate(); } else { // insufficient funds - player.displayClientMessage(Components.translatable("gui.numismatics.vendor.insufficient_funds") + player.displayClientMessage(reasonHolder.getMessageOrDefault() .withStyle(ChatFormatting.DARK_RED), true); level.playSound(null, getBlockPos(), AllSoundEvents.DENY.getMainEvent(), SoundSource.BLOCKS, 0.5f, 1.0f); } @@ -787,9 +791,9 @@ private void tryBuyFrom(Player player, InteractionHand hand) { notifyUpdate(); return; - } else if (getCardId() != null) { - BankAccount account = Numismatics.BANK.getAccount(getCardId()); - if (account != null && account.isAuthorized(owner) && account.deduct(price.getTotalPrice())) { + } else { + IDeductable deductable = getDeductable(); + if (deductable != null && deductable.deduct(price.getTotalPrice(), ReasonHolder.IGNORED)) { handStack.shrink(buying.getCount()); player.setItemInHand(hand, handStack); @@ -807,10 +811,10 @@ private void tryBuyFrom(Player player, InteractionHand hand) { // insufficient funds (return early on success) String ownerName = UsernameUtils.INSTANCE.getName(owner, null); if (ownerName != null) { - player.displayClientMessage(Components.translatable("gui.numismatics.vendor.insufficient_funds.named", ownerName) + player.displayClientMessage(Components.translatable("gui.numismatics.vendor.out_of_stock.funds.named", ownerName) .withStyle(ChatFormatting.DARK_RED), true); } else { - player.displayClientMessage(Components.translatable("gui.numismatics.vendor.insufficient_funds") + player.displayClientMessage(Components.translatable("gui.numismatics.vendor.out_of_stock.funds") .withStyle(ChatFormatting.DARK_RED), true); } level.playSound(null, getBlockPos(), AllSoundEvents.DENY.getMainEvent(), SoundSource.BLOCKS, 0.5f, 1.0f); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/vendor/VendorMenu.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/vendor/VendorMenu.java index 59b23187..a1720331 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/vendor/VendorMenu.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/vendor/VendorMenu.java @@ -19,9 +19,9 @@ package dev.ithundxr.createnumismatics.content.vendor; import com.simibubi.create.foundation.gui.menu.MenuBase; -import dev.ithundxr.createnumismatics.content.backend.Coin; import dev.ithundxr.createnumismatics.content.backend.BigStackSizeContainerSynchronizer; -import dev.ithundxr.createnumismatics.content.bank.CardSlot; +import dev.ithundxr.createnumismatics.content.backend.Coin; +import dev.ithundxr.createnumismatics.content.bank.AnyCardSlot; import dev.ithundxr.createnumismatics.content.coins.CoinDisplaySlot; import dev.ithundxr.createnumismatics.content.coins.CoinItem; import dev.ithundxr.createnumismatics.content.coins.SlotDiscreteCoinBag; @@ -80,7 +80,7 @@ protected void addSlots() { addSlot(new SlotDiscreteCoinBag(contentHolder.inventory, coin, x, y, true, true)); x += 18; } - addSlot(new CardSlot.BoundCardSlot(contentHolder.cardContainer, 0, 170+4, y)); // make here to preserve slot order + addSlot(new AnyCardSlot.BoundAnyCardSlot(contentHolder.cardContainer, 0, 170+4, y)); // make here to preserve slot order addSlot(new Slot(contentHolder.sellingContainer, 0, 142+5, y)); for (int i = 0; i < 3; ++i) { diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/events/CommonEvents.java b/common/src/main/java/dev/ithundxr/createnumismatics/events/CommonEvents.java index 36c98c0a..752732a2 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/events/CommonEvents.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/events/CommonEvents.java @@ -25,13 +25,11 @@ import dev.ithundxr.createnumismatics.base.block.NotifyFailedBreak; import dev.ithundxr.createnumismatics.content.backend.BankAccount; import dev.ithundxr.createnumismatics.content.backend.TrustedBlock; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.SubAccount; import dev.ithundxr.createnumismatics.content.vendor.VendorBlock; -import dev.ithundxr.createnumismatics.content.vendor.VendorBlockEntity; import dev.ithundxr.createnumismatics.registry.NumismaticsPackets; import dev.ithundxr.createnumismatics.registry.packets.BankAccountLabelPacket; import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.Options; import net.minecraft.core.BlockPos; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; @@ -43,6 +41,8 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; +import java.util.Collection; + public class CommonEvents { public static void onLoadWorld(LevelAccessor world) { Numismatics.BANK.levelLoaded(world); @@ -81,6 +81,13 @@ public static boolean onBlockBreak(LevelAccessor level, BlockPos pos, BlockState public static void onPlayerJoin(ServerPlayer player) { for (BankAccount account : Numismatics.BANK.accounts.values()) { NumismaticsPackets.PACKETS.sendTo(player, new BankAccountLabelPacket(account)); + + Collection subAccounts = account.getSubAccounts(); + if (subAccounts != null) { + for (SubAccount subAccount : subAccounts) { + NumismaticsPackets.PACKETS.sendTo(player, new BankAccountLabelPacket(subAccount)); + } + } } } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/CommonTags.java b/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/CommonTags.java index 41f51f23..64d62526 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/CommonTags.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/CommonTags.java @@ -19,7 +19,6 @@ package dev.ithundxr.createnumismatics.multiloader; import net.minecraft.Util; -import net.minecraft.core.Registry; import net.minecraft.core.registries.Registries; import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.Item; @@ -35,6 +34,7 @@ public class CommonTags { ZINC_NUGGETS = item("nuggets/zinc_nuggets", "zinc_nuggets", "nuggets/zinc"), BRASS_NUGGETS = item("nuggets/brass_nuggets", "brass_nuggets", "nuggets/brass"), IRON_PLATES = item("plates/iron_plates", "iron_plates", "plates/iron"), + GOLD_PLATES = item("plates/gold_plates", "gold_plates", "plates/gold"), COPPER_INGOTS = item("ingots/copper_ingots", "copper_ingots", "ingots/copper"), IRON_INGOTS = item("ingots/iron_ingots", "iron_ingots", "ingots/iron"); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/PlayerSelection.java b/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/PlayerSelection.java index 8973294d..f9fd7553 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/PlayerSelection.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/PlayerSelection.java @@ -27,6 +27,8 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.entity.BlockEntity; +import java.util.function.Predicate; + /** * Find players to send S2C packets to. */ @@ -38,6 +40,11 @@ public static PlayerSelection all() { throw new AssertionError(); } + @ExpectPlatform + public static PlayerSelection allWith(Predicate condition) { + throw new AssertionError(); + } + @ExpectPlatform public static PlayerSelection of(ServerPlayer player) { throw new AssertionError(); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsCreativeModeTabs.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsCreativeModeTabs.java index 33e63e4a..3d6be195 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsCreativeModeTabs.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsCreativeModeTabs.java @@ -24,6 +24,7 @@ import com.tterrag.registrate.util.entry.RegistryEntry; import dev.architectury.injectables.annotations.ExpectPlatform; import dev.ithundxr.createnumismatics.Numismatics; +import dev.ithundxr.createnumismatics.content.bank.AuthorizedCardItem; import dev.ithundxr.createnumismatics.content.bank.CardItem; import dev.ithundxr.createnumismatics.content.bank.IDCardItem; import dev.ithundxr.createnumismatics.multiloader.Env; @@ -186,6 +187,13 @@ private static Function makeVisibilityFunc() { } } + for (ItemEntry entry : NumismaticsItems.AUTHORIZED_CARDS) { + AuthorizedCardItem item = entry.get(); + if (item.color != DyeColor.RED) { + visibilities.put(item, TabVisibility.SEARCH_TAB_ONLY); + } + } + return item -> { TabVisibility visibility = visibilities.get(item); if (visibility != null) { diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsGuiTextures.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsGuiTextures.java index f910a32f..179a0bba 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsGuiTextures.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsGuiTextures.java @@ -36,6 +36,16 @@ public enum NumismaticsGuiTextures implements ScreenElement { ANDESITE_DEPOSITOR("andesite_depositor", 182, 79), BRASS_DEPOSITOR("brass_depositor", 208, 145), BANK_TERMINAL("bank_terminal",200, 132), + SUB_ACCOUNT_LIST("bank_terminal_sub_account_list",234, 220), + SUB_ACCOUNT_LIST_DELETE("bank_terminal_sub_account_list", 0, 220, 12, 12), + SUB_ACCOUNT_LIST_DELETE_COLORABLE("bank_terminal_sub_account_list", 12, 220, 12, 12), + SUB_ACCOUNT_LIST_RESET("bank_terminal_sub_account_list", 0, 232, 12, 12), + SUB_ACCOUNT_LIST_EDIT("bank_terminal_sub_account_list", 0, 244, 12, 12), + VALUE_SETTINGS_LABEL_BG_TALL("bank_terminal_sub_account_list", 12, 242, 81, 14), + SUB_ACCOUNT_LIST_POPUP("bank_terminal_sub_account_list_popup", 250, 193), + SUB_ACCOUNT_MODE_TRUSTED_PLAYERS("bank_terminal_sub_account_list_popup", 0, 240, 16, 16), + SUB_ACCOUNT_MODE_TRUSTED_AUTOMATION("bank_terminal_sub_account_list_popup", 20, 240, 16, 16), + SUB_ACCOUNT_MODE_ANY("bank_terminal_sub_account_list_popup", 40, 240, 16, 16), TRUST_LIST("trust_list",200, 110), BLAZE_BANKER("blaze_banker",200, 110), VENDOR("vendor", 236, 145), diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsIcons.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsIcons.java index 23a86cc1..92ca927c 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsIcons.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsIcons.java @@ -60,7 +60,8 @@ public class NumismaticsIcons extends AllIcons { I_COIN_COG = next(), I_COIN_CROWN = next(), I_COIN_SUN = next(), - I_HOPPER = next() + I_HOPPER = next(), + I_OPEN_SUB_LIST = next() ; public NumismaticsIcons(int x, int y) { diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsItems.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsItems.java index b6344f39..419286c7 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsItems.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsItems.java @@ -23,8 +23,9 @@ import com.tterrag.registrate.util.entry.ItemEntry; import dev.ithundxr.createnumismatics.Numismatics; import dev.ithundxr.createnumismatics.base.item.DyedItemList; -import dev.ithundxr.createnumismatics.content.bank.CardItem; import dev.ithundxr.createnumismatics.content.backend.Coin; +import dev.ithundxr.createnumismatics.content.bank.AuthorizedCardItem; +import dev.ithundxr.createnumismatics.content.bank.CardItem; import dev.ithundxr.createnumismatics.content.bank.IDCardItem; import dev.ithundxr.createnumismatics.content.bank.blaze_banker.BankingGuideItem; import dev.ithundxr.createnumismatics.content.coins.CoinItem; @@ -39,7 +40,7 @@ public class NumismaticsItems { private static ItemEntry makeCoin(Coin coin) { return REGISTRATE.item(coin.getName(), CoinItem.create(coin)) .tag(NumismaticsTags.AllItemTags.COINS.tag) - .lang(coin.getDisplayName()) + .lang(coin.getDefaultLangName()) .properties(p -> p.rarity(coin.rarity)) .model((c, p) -> p.generated(c, p.modLoc("item/coin/" + coin.getName()))) .register(); @@ -79,6 +80,17 @@ public static ItemEntry getCoin(Coin coin) { .register(); }); + public static final DyedItemList AUTHORIZED_CARDS = new DyedItemList<>(color -> { + String colorName = color.getSerializedName(); + return REGISTRATE.item(colorName+"_authorized_card", p -> new AuthorizedCardItem(p, color)) + .properties(p -> p.stacksTo(1)) + .tag(NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.tag) + .lang(TextUtils.titleCaseConversion(color.getName()) + " Authorized Card") + .model((c, p) -> p.generated(c, Numismatics.asResource("item/authorized_card/"+colorName+"_authorized_card"))) + .onRegisterAfter(Registries.ITEM, v -> ItemDescription.useKey(v, "item.numismatics.authorized_bank_card")) + .register(); + }); + public static final ItemEntry BANKING_GUIDE = REGISTRATE.item("banking_guide", BankingGuideItem::new) .lang("Banking Guide") .register(); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsMenuTypes.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsMenuTypes.java index c866276f..38c51ecc 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsMenuTypes.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsMenuTypes.java @@ -25,6 +25,8 @@ import dev.ithundxr.createnumismatics.Numismatics; import dev.ithundxr.createnumismatics.content.backend.trust_list.TrustListMenu; import dev.ithundxr.createnumismatics.content.backend.trust_list.TrustListScreen; +import dev.ithundxr.createnumismatics.content.bank.SubAccountListMenu; +import dev.ithundxr.createnumismatics.content.bank.SubAccountListScreen; import dev.ithundxr.createnumismatics.content.bank.blaze_banker.BlazeBankerMenu; import dev.ithundxr.createnumismatics.content.bank.blaze_banker.BlazeBankerScreen; import dev.ithundxr.createnumismatics.content.depositor.AndesiteDepositorMenu; @@ -78,6 +80,12 @@ public class NumismaticsMenuTypes { () -> VendorScreen::new ); + public static final MenuEntry SUB_ACCOUNT_LIST = register( + "sub_account_list", + SubAccountListMenu::new, + () -> SubAccountListScreen::new + ); + private static > MenuEntry register( String name, MenuBuilder.ForgeMenuFactory factory, NonNullSupplier> screenFactory) { return REGISTRATE diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsPackets.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsPackets.java index 99fefd07..25817d77 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsPackets.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsPackets.java @@ -23,21 +23,29 @@ import dev.ithundxr.createnumismatics.content.backend.behaviours.SliderStylePriceConfigurationPacket; import dev.ithundxr.createnumismatics.multiloader.PacketSet; import dev.ithundxr.createnumismatics.registry.packets.*; +import dev.ithundxr.createnumismatics.registry.packets.sub_account.*; public class NumismaticsPackets { - public static final PacketSet PACKETS = PacketSet.builder(Numismatics.MOD_ID, 3) // increment version on changes + public static final PacketSet PACKETS = PacketSet.builder(Numismatics.MOD_ID, 4) // increment version on changes .c2s(SliderStylePriceConfigurationPacket.class, SliderStylePriceConfigurationPacket::new) .c2s(BlazeBankerEditPacket.class, BlazeBankerEditPacket::new) .c2s(AndesiteDepositorConfigurationPacket.class, AndesiteDepositorConfigurationPacket::new) .c2s(OpenTrustListPacket.class, OpenTrustListPacket::new) .c2s(VendorConfigurationPacket.class, VendorConfigurationPacket::new) + .c2s(OpenSubAccountsMenuPacket.class, OpenSubAccountsMenuPacket::new) + .c2s(OpenSubAccountEditScreenPacket.class, OpenSubAccountEditScreenPacket::new) + .c2s(RemoveSubAccountPacket.class, RemoveSubAccountPacket::new) + .c2s(ResetSubAccountSpendingPacket.class, ResetSubAccountSpendingPacket::new) + .c2s(ConfigureSubAccountPacket.class, ConfigureSubAccountPacket::new) + .c2s(AddSubAccountPacket.class, AddSubAccountPacket::new) .s2c(BankAccountLabelPacket.class, BankAccountLabelPacket::new) .s2c(VarIntContainerSetDataPacket.class, VarIntContainerSetDataPacket::new) .s2c(BigStackSizeContainerSetSlotPacket.class, BigStackSizeContainerSetSlotPacket::new) .s2c(BigStackSizeContainerSetContentPacket.class, BigStackSizeContainerSetContentPacket::new) + .s2c(UpdateSubAccountsPacket.class, UpdateSubAccountsPacket::new) .build(); } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsTags.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsTags.java index 07c96c52..1190eb5e 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsTags.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsTags.java @@ -22,7 +22,6 @@ import dev.ithundxr.createnumismatics.Numismatics; import net.minecraft.core.Registry; import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.core.registries.Registries; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagKey; import net.minecraft.world.item.BlockItem; @@ -106,7 +105,8 @@ public enum AllItemTags { NUMISMATICS_ITEMS, COINS, CARDS, - ID_CARDS + ID_CARDS, + AUTHORIZED_CARDS ; public final TagKey tag; diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/BankAccountLabelPacket.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/BankAccountLabelPacket.java index 81ef8c39..e2ec31ff 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/BankAccountLabelPacket.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/BankAccountLabelPacket.java @@ -20,6 +20,7 @@ import dev.ithundxr.createnumismatics.NumismaticsClient; import dev.ithundxr.createnumismatics.content.backend.BankAccount; +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.SubAccount; import dev.ithundxr.createnumismatics.multiloader.S2CPacket; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -28,27 +29,51 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Map; import java.util.UUID; public class BankAccountLabelPacket implements S2CPacket { + private final boolean isSubAccount; + @NotNull private final UUID id; @Nullable private final String label; public BankAccountLabelPacket(FriendlyByteBuf buf) { - id = buf.readUUID(); - label = buf.readBoolean() ? buf.readUtf(256) : null; + this( + buf.readBoolean(), // isSubAccount + buf.readUUID(), // id + buf.readBoolean() ? buf.readUtf(256) : null // label + ); } public BankAccountLabelPacket(BankAccount account) { - this.id = account.id; - this.label = account.getLabel(); + this(false, account.id, account.getLabel()); + } + + public BankAccountLabelPacket(SubAccount subAccount) { + this(true, subAccount.getAuthorizationID(), subAccount.getLabel()); + } + + private BankAccountLabelPacket(boolean isSubAccount, @NotNull UUID id, @Nullable String label) { + this.isSubAccount = isSubAccount; + this.id = id; + this.label = label; + } + + public static BankAccountLabelPacket remove(BankAccount account) { + return new BankAccountLabelPacket(false, account.id, null); + } + + public static BankAccountLabelPacket remove(SubAccount subAccount) { + return new BankAccountLabelPacket(true, subAccount.getAuthorizationID(), null); } @Override public void write(FriendlyByteBuf buffer) { + buffer.writeBoolean(isSubAccount); buffer.writeUUID(id); buffer.writeBoolean(label != null); if (label != null) @@ -58,10 +83,11 @@ public void write(FriendlyByteBuf buffer) { @Override @Environment(EnvType.CLIENT) public void handle(Minecraft mc) { + Map labelMap = isSubAccount ? NumismaticsClient.subAccountLabels : NumismaticsClient.bankAccountLabels; if (label == null) { - NumismaticsClient.bankAccountLabels.remove(id); + labelMap.remove(id); } else { - NumismaticsClient.bankAccountLabels.put(id, label); + labelMap.put(id, label); } } } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/AddSubAccountPacket.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/AddSubAccountPacket.java new file mode 100644 index 00000000..6ab662fc --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/AddSubAccountPacket.java @@ -0,0 +1,44 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.registry.packets.sub_account; + +import dev.ithundxr.createnumismatics.content.bank.SubAccountListMenu; +import dev.ithundxr.createnumismatics.multiloader.C2SPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.NotNull; + +public record AddSubAccountPacket(@NotNull String label) implements C2SPacket { + + public AddSubAccountPacket(FriendlyByteBuf buf) { + this(buf.readUtf()); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeUtf(label); + } + + @Override + public void handle(ServerPlayer sender) { + if (sender.containerMenu instanceof SubAccountListMenu subAccountListMenu) { + subAccountListMenu.addSubAccount(label); + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/ConfigureSubAccountPacket.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/ConfigureSubAccountPacket.java new file mode 100644 index 00000000..2f5fe301 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/ConfigureSubAccountPacket.java @@ -0,0 +1,123 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.registry.packets.sub_account; + +import dev.ithundxr.createnumismatics.content.backend.sub_authorization.AuthorizationType; +import dev.ithundxr.createnumismatics.content.bank.SubAccountListMenu; +import dev.ithundxr.createnumismatics.multiloader.C2SPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public class ConfigureSubAccountPacket implements C2SPacket { + + private final @NotNull UUID subAccountID; + private final @NotNull Type type; + + private @Nullable Integer limit; + private @Nullable AuthorizationType authorizationType; + private @Nullable String label; + + public ConfigureSubAccountPacket(@NotNull UUID subAccountID, @Nullable Integer limit) { + this(subAccountID, Type.LIMIT); + + this.limit = limit; + } + + public ConfigureSubAccountPacket(@NotNull UUID subAccountID, @NotNull AuthorizationType authorizationType) { + this(subAccountID, Type.AUTHORIZATION_TYPE); + + this.authorizationType = authorizationType; + } + + public ConfigureSubAccountPacket(@NotNull UUID subAccountID, @NotNull String label) { + this(subAccountID, Type.LABEL); + + this.label = label; + } + + private ConfigureSubAccountPacket(@NotNull UUID subAccountID, @NotNull Type type) { + this.subAccountID = subAccountID; + this.type = type; + } + + public ConfigureSubAccountPacket(FriendlyByteBuf buf) { + this(buf.readUUID(), buf.readEnum(Type.class)); + + switch (type) { + case LIMIT: + if (buf.readBoolean()) + limit = buf.readVarInt(); + break; + case AUTHORIZATION_TYPE: + authorizationType = AuthorizationType.values()[buf.readByte()]; + break; + case LABEL: + label = buf.readUtf(); + break; + } + } + + @Override + @SuppressWarnings("DataFlowIssue") // IntelliJ complains about nullability of limit, authorizationType, and label + public void write(FriendlyByteBuf buffer) { + buffer.writeUUID(subAccountID); + buffer.writeEnum(type); + + switch (type) { + case LIMIT: + buffer.writeBoolean(limit != null); + if (limit != null) + buffer.writeVarInt(limit); + break; + case AUTHORIZATION_TYPE: + buffer.writeByte(authorizationType.ordinal()); + break; + case LABEL: + buffer.writeUtf(label); + break; + } + } + + @Override + public void handle(ServerPlayer sender) { + if (sender.containerMenu instanceof SubAccountListMenu subAccountListMenu) { + switch (type) { + case LIMIT: + subAccountListMenu.setLimit(subAccountID, limit); + break; + case AUTHORIZATION_TYPE: + subAccountListMenu.setAuthorizationType(subAccountID, authorizationType); + break; + case LABEL: + subAccountListMenu.setLabel(subAccountID, label); + break; + } + } + } + + private enum Type { + LIMIT, + AUTHORIZATION_TYPE, + LABEL + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/OpenSubAccountEditScreenPacket.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/OpenSubAccountEditScreenPacket.java new file mode 100644 index 00000000..b4ce0c6f --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/OpenSubAccountEditScreenPacket.java @@ -0,0 +1,48 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.registry.packets.sub_account; + +import dev.ithundxr.createnumismatics.content.bank.SubAccountListMenu; +import dev.ithundxr.createnumismatics.multiloader.C2SPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.Nullable; + +import java.util.UUID; + +public record OpenSubAccountEditScreenPacket(@Nullable UUID subAccountID) implements C2SPacket { + + public OpenSubAccountEditScreenPacket(FriendlyByteBuf buf) { + this(buf.readBoolean() ? buf.readUUID() : null); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeBoolean(subAccountID != null); + if (subAccountID != null) + buffer.writeUUID(subAccountID); + } + + @Override + public void handle(ServerPlayer sender) { + if (sender.containerMenu instanceof SubAccountListMenu subAccountListMenu) { + subAccountListMenu.openSubAccountEditScreen(subAccountID); + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/OpenSubAccountsMenuPacket.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/OpenSubAccountsMenuPacket.java new file mode 100644 index 00000000..8092ad34 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/OpenSubAccountsMenuPacket.java @@ -0,0 +1,66 @@ +/* + * Numismatics + * Copyright (c) 2023-2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.registry.packets.sub_account; + +import dev.ithundxr.createnumismatics.Numismatics; +import dev.ithundxr.createnumismatics.content.backend.BankAccount; +import dev.ithundxr.createnumismatics.multiloader.C2SPacket; +import dev.ithundxr.createnumismatics.util.Utils; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; + +import java.util.UUID; + +public class OpenSubAccountsMenuPacket implements C2SPacket { + + private final UUID accountID; + private final boolean open; + + public OpenSubAccountsMenuPacket(BankAccount bankAccount) { + this(bankAccount, true); + } + + public OpenSubAccountsMenuPacket(BankAccount bankAccount, boolean open) { + this.accountID = bankAccount.id; + this.open = open; + } + + public OpenSubAccountsMenuPacket(FriendlyByteBuf buf) { + accountID = buf.readUUID(); + open = buf.readBoolean(); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeUUID(accountID); + buffer.writeBoolean(open); + } + + @Override + public void handle(ServerPlayer sender) { + BankAccount account = Numismatics.BANK.getAccount(accountID); + if (account != null && account.isAuthorized(sender)) { + if (open) { + account.openSubAccountsMenu(sender); + } else { + Utils.openScreen(sender, account, account::sendToMenu); + } + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/RemoveSubAccountPacket.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/RemoveSubAccountPacket.java new file mode 100644 index 00000000..e7dca8ad --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/RemoveSubAccountPacket.java @@ -0,0 +1,46 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.registry.packets.sub_account; + +import dev.ithundxr.createnumismatics.content.bank.SubAccountListMenu; +import dev.ithundxr.createnumismatics.multiloader.C2SPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public record RemoveSubAccountPacket(@NotNull UUID subAccountID) implements C2SPacket { + + public RemoveSubAccountPacket(FriendlyByteBuf buf) { + this(buf.readUUID()); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeUUID(subAccountID); + } + + @Override + public void handle(ServerPlayer sender) { + if (sender.containerMenu instanceof SubAccountListMenu subAccountListMenu) { + subAccountListMenu.removeSubAccount(subAccountID); + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/ResetSubAccountSpendingPacket.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/ResetSubAccountSpendingPacket.java new file mode 100644 index 00000000..d971660f --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/ResetSubAccountSpendingPacket.java @@ -0,0 +1,46 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.registry.packets.sub_account; + +import dev.ithundxr.createnumismatics.content.bank.SubAccountListMenu; +import dev.ithundxr.createnumismatics.multiloader.C2SPacket; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import org.jetbrains.annotations.NotNull; + +import java.util.UUID; + +public record ResetSubAccountSpendingPacket(@NotNull UUID subAccountID) implements C2SPacket { + + public ResetSubAccountSpendingPacket(FriendlyByteBuf buf) { + this(buf.readUUID()); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeUUID(subAccountID); + } + + @Override + public void handle(ServerPlayer sender) { + if (sender.containerMenu instanceof SubAccountListMenu subAccountListMenu) { + subAccountListMenu.resetSubAccountSpending(subAccountID); + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/UpdateSubAccountsPacket.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/UpdateSubAccountsPacket.java new file mode 100644 index 00000000..b1d5df4b --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/UpdateSubAccountsPacket.java @@ -0,0 +1,63 @@ +/* + * Numismatics + * Copyright (c) 2024 The Railways Team + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package dev.ithundxr.createnumismatics.registry.packets.sub_account; + +import dev.ithundxr.createnumismatics.content.backend.BankAccount; +import dev.ithundxr.createnumismatics.content.bank.SubAccountListScreen; +import dev.ithundxr.createnumismatics.multiloader.S2CPacket; +import io.netty.buffer.Unpooled; +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; + +import java.util.UUID; + +/** Only works for players who have a SubAccountListMenu open */ +public class UpdateSubAccountsPacket implements S2CPacket { + + private final UUID accountID; + private final FriendlyByteBuf data = new FriendlyByteBuf(Unpooled.buffer());; + + public UpdateSubAccountsPacket(BankAccount account) { + this.accountID = account.id; + account.sendSubAccountsOnlyToMenu(data); + } + + public UpdateSubAccountsPacket(FriendlyByteBuf buf) { + accountID = buf.readUUID(); + int length = buf.readVarInt(); + buf.readBytes(data, length); + } + + @Override + public void write(FriendlyByteBuf buffer) { + buffer.writeUUID(accountID); + buffer.writeVarInt(data.readableBytes()); + buffer.writeBytes(data); + } + + @Override + public void handle(Minecraft mc) { + if (mc.screen instanceof SubAccountListScreen sal) { + BankAccount account = sal.getMenu().contentHolder; + if (account.id.equals(accountID)) { + account.updateSubAccountsFrom(data); + } + } + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/util/TextUtils.java b/common/src/main/java/dev/ithundxr/createnumismatics/util/TextUtils.java index c3cbcb1c..b813617e 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/util/TextUtils.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/util/TextUtils.java @@ -29,6 +29,7 @@ import org.apache.commons.lang3.StringUtils; import org.joml.Matrix4f; +import java.util.Locale; import java.util.Optional; import java.util.stream.Stream; @@ -130,4 +131,11 @@ public static String leftPad(String s, char c, int width) { if (s.length() >= width) return s; return String.valueOf(c).repeat(width - s.length()) + s; } + + public static boolean isLeftToRight() { + return Components.translatable("numismatics.special.ltr") + .getString() + .toLowerCase(Locale.ROOT) + .equals("true"); + } } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/util/Utils.java b/common/src/main/java/dev/ithundxr/createnumismatics/util/Utils.java index 78e13dc8..3ab314a2 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/util/Utils.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/util/Utils.java @@ -19,8 +19,11 @@ package dev.ithundxr.createnumismatics.util; import dev.architectury.injectables.annotations.ExpectPlatform; +import dev.ithundxr.createnumismatics.Numismatics; import dev.ithundxr.createnumismatics.multiloader.Env; +import net.minecraft.core.Registry; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceKey; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.MenuProvider; import net.minecraft.world.entity.player.Player; @@ -45,4 +48,12 @@ public static boolean testClientPlayerOrElse(Predicate predicate, boolea public static void openScreen(ServerPlayer player, MenuProvider factory, Consumer extraDataWriter) { throw new AssertionError(); } + + public static void runOnceRegistered(ResourceKey> registryType, Runnable callback) { + if (Numismatics.registrate().isRegistered(registryType)) { + callback.run(); + } else { + Numismatics.registrate().addRegisterCallback(registryType, callback); + } + } } diff --git a/common/src/main/resources/assets/numismatics/lang/default/interface.json b/common/src/main/resources/assets/numismatics/lang/default/interface.json index 6977591f..9286127e 100644 --- a/common/src/main/resources/assets/numismatics/lang/default/interface.json +++ b/common/src/main/resources/assets/numismatics/lang/default/interface.json @@ -1,18 +1,28 @@ { "numismatics.andesite_depositor.price": "Price", - "item.numismatics.spur": "Spur", - "item.numismatics.spur.plural": "Spurs", - "item.numismatics.bevel": "Bevel", - "item.numismatics.bevel.plural": "Bevels", - "item.numismatics.sprocket": "Sprocket", - "item.numismatics.sprocket.plural": "Sprockets", - "item.numismatics.cog": "Cog", - "item.numismatics.cog.plural": "Cogs", - "item.numismatics.crown": "Crown", - "item.numismatics.crown.plural": "Crowns", - "item.numismatics.sun": "Sun", - "item.numismatics.sun.plural": "Suns", + "gui.numismatics.bank_terminal.balance": "Balance: %s %s, %s¤", + + "gui.numismatics.bank_terminal.sub_accounts": "Sub Accounts", + "gui.numismatics.bank_terminal.sub_accounts.named": "%s: Sub Accounts", + "gui.numismatics.bank_terminal.sub_accounts.edit": "Edit Sub Account", + "gui.numismatics.bank_terminal.sub_accounts.remove": "Remove Sub Account", + "gui.numismatics.bank_terminal.sub_accounts.remove.confirm": "Are you sure? Click again to actually remove", + "gui.numismatics.bank_terminal.sub_accounts.reset_spending": "Reset Spending", + "gui.numismatics.bank_terminal.sub_accounts.authorization_type": "Authorization Type", + "gui.numismatics.bank_terminal.sub_accounts.name_box": "Name", + "gui.numismatics.bank_terminal.sub_accounts.help": "No Sub Accounts", + "gui.numismatics.bank_terminal.sub_accounts.help.line.1": "Enter a name and then click the add", + "gui.numismatics.bank_terminal.sub_accounts.help.line.2": "button to create a new Sub Account.", + "gui.numismatics.bank_terminal.sub_accounts.help.line.3": "Sub Accounts can be used to provide", + "gui.numismatics.bank_terminal.sub_accounts.help.line.4": "limited access to selected players or", + "gui.numismatics.bank_terminal.sub_accounts.help.line.5": "enable safer automated transactions.", + "gui.numismatics.bank_terminal.sub_accounts.help.line.6": "", + + "gui.numismatics.limit": "Spent %s of %s", + "gui.numismatics.limit.none": "No limit", + "gui.numismatics.limit.monetary": "Spent %s %s, %s¤ of %s %s, %s¤", + "command.numismatics.arguments.enum.invalid": "Error: Invalid enum value '%s'. Valid values are: %s", "itemGroup.numismatics": "Create: Numismatics", "gui.numismatics.trust_list": "Trust List", @@ -22,7 +32,8 @@ "gui.numismatics.vendor.out_of_stock": "Out of stock", "gui.numismatics.vendor.out_of_stock.named": "Out of stock, contact %s for a refill", "gui.numismatics.vendor.insufficient_funds": "Insufficient funds", - "gui.numismatics.vendor.insufficient_funds.named": "Insufficient funds, contact %s for a refill", + "gui.numismatics.vendor.out_of_stock.funds": "Vendor has insufficient funds", + "gui.numismatics.vendor.out_of_stock.funds.named": "Vendor has insufficient funds, contact %s for a refill", "gui.numismatics.vendor.generic_named": "Contact %s", "gui.numismatics.vendor.mode.sell": "Sell", "gui.numismatics.vendor.mode.buy": "Buy", @@ -34,5 +45,11 @@ "gui.numismatics.vendor.full.named": "Vendor is full, contact %s to empty it", "gui.numismatics.vendor.no_item_in_hand": "Hold the stack of items you want to sell", - "block.numismatics.trusted_block.attempt_break": "Hold %1$s to break this block" + "block.numismatics.trusted_block.attempt_break": "Hold %1$s to break this block", + + "error.numismatics.card.not_bound": "Card not bound", + "error.numismatics.card.account_not_found": "Account not found", + "error.numismatics.card.not_authorized": "Not authorized", + "error.numismatics.authorized_card.limit_reached": "Spending limit reached", + "error.numismatics.authorized_card.account_not_found": "Sub Account not found" } \ No newline at end of file diff --git a/common/src/main/resources/assets/numismatics/lang/default/tooltips.json b/common/src/main/resources/assets/numismatics/lang/default/tooltips.json index 19661ec2..2699a173 100644 --- a/common/src/main/resources/assets/numismatics/lang/default/tooltips.json +++ b/common/src/main/resources/assets/numismatics/lang/default/tooltips.json @@ -6,6 +6,9 @@ "item.numismatics.card.tooltip.bound": "Bound", "item.numismatics.card.tooltip.bound.to": "Bound to: %s", "item.numismatics.card.tooltip.blank": "Blank", + "item.numismatics.authorized_card.tooltip.bound.no_label": "Sub Account: Unknown", + "item.numismatics.authorized_card.tooltip.bound.with_label": "Sub Account: %s", + "item.numismatics.authorized_card.tooltip.hold_shift": "Hold sneak to clear. Bind in a Bank Terminal", "block.numismatics.brass_depositor.tooltip.price": "Price: %s %s, %s¤", "item.numismatics.id_card.tooltip.already_bound": "Already bound, Sneak + Use to Unbind", "item.numismatics.id_card.tooltip.cleared": "Cleared", @@ -19,7 +22,10 @@ "item.numismatics.banking_guide.tooltip.summary": "Use on a _Blaze Burner_ to convert it into a _Blaze Banker_.", "item.numismatics.bank_card.tooltip": "BANK CARD", - "item.numismatics.bank_card.tooltip.summary": "_Right Click_ to bind, _shift click_ to clear. Allows Access to the bound Bank Account when used in a _Bank Terminal_, or can be placed in a _Vendor/Depositor_ to automatically collect the coins and add them to the bound account.", + "item.numismatics.bank_card.tooltip.summary": "_Right Click_ to bind, _shift click_ to clear. Allows access to the bound Bank Account when used in a _Bank Terminal_, or can be placed in a _Vendor/Depositor_ to automatically collect the coins and add them to the bound account.", + + "item.numismatics.authorized_bank_card.tooltip": "AUTHORIZED BANK CARD", + "item.numismatics.authorized_bank_card.tooltip.summary": "Put in Bank Terminal _Sub Account menu_ to bind, _shift click_ to clear. Allows providing limited Bank Account access to trusted players or automation. Can be placed in a _Vendor/Depositor_ to automatically collect the coins and add them to the bound account.", "item.numismatics.id_card.tooltip": "ID CARD", "item.numismatics.id_card.tooltip.summary": "_Right Click_ to bind, _shift click_ to clear. Can be placed in the _Trusted Menu_ of many Numismatics blocks to give the bound player access to that block.", diff --git a/common/src/main/resources/assets/numismatics/textures/gui/andesite_depositor.xcf b/common/src/main/resources/assets/numismatics/textures/gui/andesite_depositor.xcf index 67da8e25..de0498b3 100644 Binary files a/common/src/main/resources/assets/numismatics/textures/gui/andesite_depositor.xcf and b/common/src/main/resources/assets/numismatics/textures/gui/andesite_depositor.xcf differ diff --git a/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal.png b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal.png index f9df5ce9..5189f068 100644 Binary files a/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal.png and b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal.xcf b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal.xcf index a33b0e78..639bfbef 100644 Binary files a/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal.xcf and b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal.xcf differ diff --git a/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list.png b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list.png new file mode 100644 index 00000000..67299d3e Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list.xcf b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list.xcf new file mode 100644 index 00000000..22dd8c6e Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list.xcf differ diff --git a/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list_popup.png b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list_popup.png new file mode 100644 index 00000000..340a00ed Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list_popup.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list_popup.xcf b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list_popup.xcf new file mode 100644 index 00000000..8e67b06c Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list_popup.xcf differ diff --git a/common/src/main/resources/assets/numismatics/textures/gui/icons.png b/common/src/main/resources/assets/numismatics/textures/gui/icons.png index 0e6a5085..a6862b7f 100644 Binary files a/common/src/main/resources/assets/numismatics/textures/gui/icons.png and b/common/src/main/resources/assets/numismatics/textures/gui/icons.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/gui/icons.xcf b/common/src/main/resources/assets/numismatics/textures/gui/icons.xcf index 3d0c1741..f89bc6f2 100644 Binary files a/common/src/main/resources/assets/numismatics/textures/gui/icons.xcf and b/common/src/main/resources/assets/numismatics/textures/gui/icons.xcf differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/any_card_outline.png b/common/src/main/resources/assets/numismatics/textures/item/any_card_outline.png new file mode 100644 index 00000000..10eb0260 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/any_card_outline.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/any_card_outline.png.mcmeta b/common/src/main/resources/assets/numismatics/textures/item/any_card_outline.png.mcmeta new file mode 100644 index 00000000..0ebf05c9 --- /dev/null +++ b/common/src/main/resources/assets/numismatics/textures/item/any_card_outline.png.mcmeta @@ -0,0 +1,9 @@ +{ + "animation": { + "frametime": 16, + "frames": [ + 0, + 1 + ] + } +} diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/black_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/black_authorized_card.png new file mode 100644 index 00000000..ec220da8 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/black_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/blue_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/blue_authorized_card.png new file mode 100644 index 00000000..47a5b098 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/blue_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/brown_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/brown_authorized_card.png new file mode 100644 index 00000000..4954a75d Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/brown_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/cyan_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/cyan_authorized_card.png new file mode 100644 index 00000000..25aef3b4 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/cyan_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/gray_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/gray_authorized_card.png new file mode 100644 index 00000000..4d22f495 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/gray_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/green_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/green_authorized_card.png new file mode 100644 index 00000000..71c902c7 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/green_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/light_blue_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/light_blue_authorized_card.png new file mode 100644 index 00000000..26b0fe76 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/light_blue_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/light_gray_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/light_gray_authorized_card.png new file mode 100644 index 00000000..d153da1c Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/light_gray_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/lime_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/lime_authorized_card.png new file mode 100644 index 00000000..5615e341 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/lime_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/magenta_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/magenta_authorized_card.png new file mode 100644 index 00000000..3b9ee158 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/magenta_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/orange_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/orange_authorized_card.png new file mode 100644 index 00000000..a18816ab Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/orange_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/orange_authorized_card.xcf b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/orange_authorized_card.xcf new file mode 100644 index 00000000..ae31c4f3 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/orange_authorized_card.xcf differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/outline.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/outline.png new file mode 100644 index 00000000..80c3a493 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/outline.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/pink_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/pink_authorized_card.png new file mode 100644 index 00000000..5cb5aaea Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/pink_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/purple_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/purple_authorized_card.png new file mode 100644 index 00000000..c23c6f4f Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/purple_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/red_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/red_authorized_card.png new file mode 100644 index 00000000..896a9277 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/red_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/white_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/white_authorized_card.png new file mode 100644 index 00000000..2ed96f0c Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/white_authorized_card.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/item/authorized_card/yellow_authorized_card.png b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/yellow_authorized_card.png new file mode 100644 index 00000000..46f596e8 Binary files /dev/null and b/common/src/main/resources/assets/numismatics/textures/item/authorized_card/yellow_authorized_card.png differ diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/fabric/ComputerCraftProxyImpl.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/fabric/ComputerCraftProxyImpl.java index bfa9b123..1e4ddc4b 100644 --- a/fabric/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/fabric/ComputerCraftProxyImpl.java +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/fabric/ComputerCraftProxyImpl.java @@ -18,11 +18,25 @@ package dev.ithundxr.createnumismatics.compat.computercraft.fabric; +import com.google.common.collect.ImmutableMap; import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import dan200.computercraft.api.detail.VanillaDetailRegistries; import dan200.computercraft.api.peripheral.PeripheralLookup; import dev.ithundxr.createnumismatics.compat.computercraft.ComputerCraftProxy; import dev.ithundxr.createnumismatics.compat.computercraft.implementation.ComputerBehaviour; +import dev.ithundxr.createnumismatics.compat.computercraft.implementation.peripherals.BankTerminalPeripheral; +import dev.ithundxr.createnumismatics.content.bank.AuthorizedCardItem; +import dev.ithundxr.createnumismatics.content.bank.CardItem; +import dev.ithundxr.createnumismatics.content.bank.IDCardItem; +import dev.ithundxr.createnumismatics.registry.NumismaticsBlocks; +import dev.ithundxr.createnumismatics.registry.NumismaticsTags; +import dev.ithundxr.createnumismatics.util.Utils; +import net.minecraft.core.registries.Registries; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.UUID; public class ComputerCraftProxyImpl { public static void registerWithDependency() { @@ -30,6 +44,45 @@ public static void registerWithDependency() { ComputerCraftProxy.computerFactory = ComputerBehaviour::new; PeripheralLookup.get().registerFallback((level, blockPos, blockState, blockEntity, direction) -> ComputerBehaviour.peripheralProvider(level, blockPos)); + + Utils.runOnceRegistered(Registries.BLOCK, () -> { + PeripheralLookup.get().registerForBlocks( + (world, pos, state, blockEntity, context) -> BankTerminalPeripheral.INSTANCE, + NumismaticsBlocks.BANK_TERMINAL.get() + ); + }); + + VanillaDetailRegistries.ITEM_STACK.addProvider((detailMap, stack) -> { + Map cardDetails = null; + if (NumismaticsTags.AllItemTags.CARDS.matches(stack)) { + UUID accountID = CardItem.get(stack); + if (accountID != null) { + cardDetails = Map.of( + "AccountID", accountID.toString() + ); + } + } else if (NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(stack)) { + AuthorizedCardItem.AuthorizationPair authorizationPair = AuthorizedCardItem.get(stack); + if (authorizationPair != null) { + UUID accountID = authorizationPair.accountID(); + UUID authorizationID = authorizationPair.authorizationID(); + cardDetails = Map.of( + "AccountID", accountID.toString(), + "AuthorizationID", authorizationID.toString() + ); + } + } else if (NumismaticsTags.AllItemTags.ID_CARDS.matches(stack)) { + UUID id = IDCardItem.get(stack); + if (id != null) { + cardDetails = Map.of( + "ID", id.toString() + ); + } + } + + if (cardDetails != null) + detailMap.put("numismatics", ImmutableMap.of("card", cardDetails)); + }); } public static AbstractComputerBehaviour behaviour(SmartBlockEntity sbe) { diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/multiloader/fabric/PlayerSelectionImpl.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/multiloader/fabric/PlayerSelectionImpl.java index b3a5613a..c335d3e2 100644 --- a/fabric/src/main/java/dev/ithundxr/createnumismatics/multiloader/fabric/PlayerSelectionImpl.java +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/multiloader/fabric/PlayerSelectionImpl.java @@ -34,6 +34,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.function.Predicate; public class PlayerSelectionImpl extends PlayerSelection { @@ -55,6 +56,11 @@ public static PlayerSelection all() { return new PlayerSelectionImpl(PlayerLookup.all(ServerLifecycleHooks.getCurrentServer())); } + public static PlayerSelection allWith(Predicate condition) { + return new PlayerSelectionImpl(PlayerLookup.all(ServerLifecycleHooks.getCurrentServer()).stream() + .filter(condition).toList()); + } + public static PlayerSelection of(ServerPlayer player) { return new PlayerSelectionImpl(Collections.singleton(player)); } diff --git a/forge/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/forge/ComputerCraftProxyImpl.java b/forge/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/forge/ComputerCraftProxyImpl.java index 8b542e3d..97f00cf0 100644 --- a/forge/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/forge/ComputerCraftProxyImpl.java +++ b/forge/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/forge/ComputerCraftProxyImpl.java @@ -18,15 +18,72 @@ package dev.ithundxr.createnumismatics.compat.computercraft.forge; +import com.google.common.collect.ImmutableMap; import com.simibubi.create.compat.computercraft.AbstractComputerBehaviour; import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import dan200.computercraft.api.ForgeComputerCraftAPI; +import dan200.computercraft.api.detail.VanillaDetailRegistries; import dev.ithundxr.createnumismatics.compat.computercraft.ComputerCraftProxy; import dev.ithundxr.createnumismatics.compat.computercraft.implementation.ComputerBehaviour; +import dev.ithundxr.createnumismatics.compat.computercraft.implementation.peripherals.BankTerminalPeripheral; +import dev.ithundxr.createnumismatics.content.bank.AuthorizedCardItem; +import dev.ithundxr.createnumismatics.content.bank.CardItem; +import dev.ithundxr.createnumismatics.content.bank.IDCardItem; +import dev.ithundxr.createnumismatics.registry.NumismaticsBlocks; +import dev.ithundxr.createnumismatics.registry.NumismaticsTags; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; +import java.util.UUID; public class ComputerCraftProxyImpl { public static void registerWithDependency() { /* Comment if computercraft.implementation is not in the source set */ ComputerCraftProxy.computerFactory = ComputerBehaviour::new; + + ForgeComputerCraftAPI.registerPeripheralProvider((level, pos, direction) -> { + BlockState state = level.getBlockState(pos); + + if (NumismaticsBlocks.BANK_TERMINAL.has(state)) { + return LazyOptional.of(() -> BankTerminalPeripheral.INSTANCE); + } + + return LazyOptional.empty(); + }); + + VanillaDetailRegistries.ITEM_STACK.addProvider((detailMap, stack) -> { + Map cardDetails = null; + if (NumismaticsTags.AllItemTags.CARDS.matches(stack)) { + UUID accountID = CardItem.get(stack); + if (accountID != null) { + cardDetails = Map.of( + "AccountID", accountID.toString() + ); + } + } else if (NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(stack)) { + AuthorizedCardItem.AuthorizationPair authorizationPair = AuthorizedCardItem.get(stack); + if (authorizationPair != null) { + UUID accountID = authorizationPair.accountID(); + UUID authorizationID = authorizationPair.authorizationID(); + cardDetails = Map.of( + "AccountID", accountID.toString(), + "AuthorizationID", authorizationID.toString() + ); + } + } else if (NumismaticsTags.AllItemTags.ID_CARDS.matches(stack)) { + UUID id = IDCardItem.get(stack); + if (id != null) { + cardDetails = Map.of( + "ID", id.toString() + ); + } + } + + if (cardDetails != null) + detailMap.put("numismatics", ImmutableMap.of("card", cardDetails)); + }); } public static AbstractComputerBehaviour behaviour(SmartBlockEntity sbe) { if (ComputerCraftProxy.computerFactory == null) diff --git a/forge/src/main/java/dev/ithundxr/createnumismatics/multiloader/forge/PlayerSelectionImpl.java b/forge/src/main/java/dev/ithundxr/createnumismatics/multiloader/forge/PlayerSelectionImpl.java index 51e67919..617bc470 100644 --- a/forge/src/main/java/dev/ithundxr/createnumismatics/multiloader/forge/PlayerSelectionImpl.java +++ b/forge/src/main/java/dev/ithundxr/createnumismatics/multiloader/forge/PlayerSelectionImpl.java @@ -21,6 +21,7 @@ import dev.ithundxr.createnumismatics.multiloader.PlayerSelection; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.ClientboundCustomPayloadPacket; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerLevel; @@ -28,11 +29,32 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraftforge.network.NetworkDirection; import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor.PacketTarget; +import net.minecraftforge.server.ServerLifecycleHooks; + +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.Supplier; public class PlayerSelectionImpl extends PlayerSelection { + private static Consumer> playerListAllWith(final PacketDistributor> distributor, + final Supplier> predicateSupplier) { + return p -> { + Predicate predicate = predicateSupplier.get(); + for (ServerPlayer player : ServerLifecycleHooks.getCurrentServer().getPlayerList().getPlayers()) { + if (predicate.test(player)) { + player.connection.send(p); + } + } + }; + } + + private static final PacketDistributor> ALL_WITH = + new PacketDistributor<>(PlayerSelectionImpl::playerListAllWith, NetworkDirection.PLAY_TO_CLIENT); + final PacketTarget target; private PlayerSelectionImpl(PacketTarget target) { @@ -49,6 +71,10 @@ public static PlayerSelection all() { return new PlayerSelectionImpl(PacketDistributor.ALL.noArg()); } + public static PlayerSelection allWith(Predicate condition) { + return new PlayerSelectionImpl(ALL_WITH.with(() -> condition)); + } + public static PlayerSelection of(ServerPlayer player) { return new PlayerSelectionImpl(PacketDistributor.PLAYER.with(() -> player)); }