From 0ab43f1f96c4913d509f5de190edefe91d7fbf00 Mon Sep 17 00:00:00 2001 From: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Sat, 20 Jul 2024 22:02:17 +0200 Subject: [PATCH 1/8] begin authorized cards --- .../630af4bded938901e0e1fd57c58a2ac245292828 | 6 +- .../6ba62358bf8e130d42215f5f9edbedd611809677 | 150 ++-- .../c6e4c19894bc5aece2976a0277ba8e1dbf023865 | 2 +- .../d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 | 176 +++-- .../assets/numismatics/lang/en_ud.json | 50 ++ .../assets/numismatics/lang/en_us.json | 50 ++ .../models/item/black_authorized_card.json | 6 + .../models/item/blue_authorized_card.json | 6 + .../models/item/brown_authorized_card.json | 6 + .../models/item/cyan_authorized_card.json | 6 + .../models/item/gray_authorized_card.json | 6 + .../models/item/green_authorized_card.json | 6 + .../item/light_blue_authorized_card.json | 6 + .../item/light_gray_authorized_card.json | 6 + .../models/item/lime_authorized_card.json | 6 + .../models/item/magenta_authorized_card.json | 6 + .../models/item/orange_authorized_card.json | 6 + .../models/item/pink_authorized_card.json | 6 + .../models/item/purple_authorized_card.json | 6 + .../models/item/red_authorized_card.json | 6 + .../models/item/white_authorized_card.json | 6 + .../models/item/yellow_authorized_card.json | 6 + .../misc/crafting/black_authorized_card.json | 35 + .../misc/crafting/blue_authorized_card.json | 35 + .../misc/crafting/brown_authorized_card.json | 35 + .../misc/crafting/cyan_authorized_card.json | 35 + .../misc/crafting/gray_authorized_card.json | 35 + .../misc/crafting/green_authorized_card.json | 35 + .../crafting/light_blue_authorized_card.json | 35 + .../crafting/light_gray_authorized_card.json | 35 + .../misc/crafting/lime_authorized_card.json | 35 + .../crafting/magenta_authorized_card.json | 35 + .../misc/crafting/orange_authorized_card.json | 35 + .../misc/crafting/pink_authorized_card.json | 35 + .../misc/crafting/purple_authorized_card.json | 35 + .../misc/crafting/red_authorized_card.json | 35 + .../misc/crafting/white_authorized_card.json | 35 + .../misc/crafting/yellow_authorized_card.json | 35 + .../crafting/black_authorized_card.json | 22 + .../crafting/blue_authorized_card.json | 22 + .../crafting/brown_authorized_card.json | 22 + .../crafting/cyan_authorized_card.json | 22 + .../crafting/gray_authorized_card.json | 22 + .../crafting/green_authorized_card.json | 22 + .../crafting/light_blue_authorized_card.json | 22 + .../crafting/light_gray_authorized_card.json | 22 + .../crafting/lime_authorized_card.json | 22 + .../crafting/magenta_authorized_card.json | 22 + .../crafting/orange_authorized_card.json | 22 + .../crafting/pink_authorized_card.json | 22 + .../crafting/purple_authorized_card.json | 22 + .../recipes/crafting/red_authorized_card.json | 22 + .../crafting/white_authorized_card.json | 22 + .../crafting/yellow_authorized_card.json | 22 + .../tags/items/authorized_cards.json | 21 + .../items/internal/plates/gold_plates.json | 13 + .../tags/items/numismatics_items.json | 16 + .../createnumismatics/NumismaticsClient.java | 3 +- .../base/client/rendering/UIRenderHelper.java | 61 ++ .../base/data/NumismaticsTagGen.java | 4 +- .../base/data/lang/NumismaticsLangGen.java | 11 + .../recipe/NumismaticsRecipeProvider.java | 4 + .../recipe/NumismaticsStandardRecipeGen.java | 9 + .../base/item/DelegatingContainer.java | 89 +++ .../base/item/DynamicContainer.java | 36 + .../base/item/SingleCallbackContainer.java | 44 ++ .../content/backend/BankAccount.java | 189 ++++- .../content/backend/Coin.java | 31 +- .../content/backend/IDeductable.java | 85 +++ .../content/backend/ItemWritingContainer.java | 98 +++ .../behaviours/SliderStylePriceBehaviour.java | 31 +- .../sub_authorization/Authorization.java | 117 +++ .../sub_authorization/AuthorizationType.java | 108 +++ .../backend/sub_authorization/Limit.java | 151 ++++ .../backend/sub_authorization/SubAccount.java | 271 +++++++ .../backend/trust_list/TrustListMenu.java | 2 +- .../content/bank/AuthorizedCardItem.java | 161 +++++ .../content/bank/AuthorizedCardSlot.java | 69 ++ .../content/bank/BankScreen.java | 7 +- .../content/bank/ScrollingLabel.java | 75 ++ .../content/bank/SubAccountListMenu.java | 408 +++++++++++ .../content/bank/SubAccountListScreen.java | 683 ++++++++++++++++++ .../content/bank/TripleCoinSliderWidget.java | 328 +++++++++ .../bank/blaze_banker/BlazeBankerMenu.java | 69 +- .../bank/blaze_banker/BlazeBankerScreen.java | 6 +- .../depositor/AndesiteDepositorBlock.java | 23 +- .../events/CommonEvents.java | 8 +- .../multiloader/CommonTags.java | 2 +- .../multiloader/PlayerSelection.java | 7 + .../registry/NumismaticsCreativeModeTabs.java | 8 + .../registry/NumismaticsGuiTextures.java | 10 + .../registry/NumismaticsIcons.java | 3 +- .../registry/NumismaticsItems.java | 16 +- .../registry/NumismaticsMenuTypes.java | 8 + .../registry/NumismaticsPackets.java | 10 +- .../registry/NumismaticsTags.java | 4 +- .../packets/BankAccountLabelPacket.java | 18 +- .../sub_account/AddSubAccountPacket.java | 44 ++ .../ConfigureSubAccountPacket.java | 123 ++++ .../OpenSubAccountEditScreenPacket.java | 48 ++ .../OpenSubAccountsMenuPacket.java | 66 ++ .../sub_account/RemoveSubAccountPacket.java | 46 ++ .../ResetSubAccountSpendingPacket.java | 46 ++ .../sub_account/UpdateSubAccountsPacket.java | 63 ++ .../createnumismatics/util/TextUtils.java | 8 + .../numismatics/lang/default/interface.json | 18 + .../numismatics/lang/default/tooltips.json | 3 + .../textures/gui/andesite_depositor.xcf | Bin 28638 -> 28098 bytes .../textures/gui/bank_terminal.png | Bin 2464 -> 14778 bytes .../textures/gui/bank_terminal.xcf | Bin 30085 -> 57098 bytes .../gui/bank_terminal_sub_account_list.png | Bin 0 -> 10577 bytes .../gui/bank_terminal_sub_account_list.xcf | Bin 0 -> 134262 bytes .../bank_terminal_sub_account_list_popup.png | Bin 0 -> 12384 bytes .../bank_terminal_sub_account_list_popup.xcf | Bin 0 -> 86128 bytes .../assets/numismatics/textures/gui/icons.png | Bin 7871 -> 8233 bytes .../assets/numismatics/textures/gui/icons.xcf | Bin 10357 -> 11898 bytes .../authorized_card/black_authorized_card.png | Bin 0 -> 442 bytes .../authorized_card/blue_authorized_card.png | Bin 0 -> 460 bytes .../authorized_card/brown_authorized_card.png | Bin 0 -> 478 bytes .../authorized_card/cyan_authorized_card.png | Bin 0 -> 479 bytes .../authorized_card/gray_authorized_card.png | Bin 0 -> 468 bytes .../authorized_card/green_authorized_card.png | Bin 0 -> 471 bytes .../light_blue_authorized_card.png | Bin 0 -> 465 bytes .../light_gray_authorized_card.png | Bin 0 -> 470 bytes .../authorized_card/lime_authorized_card.png | Bin 0 -> 473 bytes .../magenta_authorized_card.png | Bin 0 -> 475 bytes .../orange_authorized_card.png | Bin 0 -> 5588 bytes .../orange_authorized_card.xcf | Bin 0 -> 2516 bytes .../textures/item/authorized_card/outline.png | Bin 0 -> 5322 bytes .../authorized_card/pink_authorized_card.png | Bin 0 -> 469 bytes .../purple_authorized_card.png | Bin 0 -> 471 bytes .../authorized_card/red_authorized_card.png | Bin 0 -> 479 bytes .../authorized_card/white_authorized_card.png | Bin 0 -> 463 bytes .../yellow_authorized_card.png | Bin 0 -> 470 bytes .../fabric/PlayerSelectionImpl.java | 6 + .../forge/PlayerSelectionImpl.java | 26 + 136 files changed, 4990 insertions(+), 266 deletions(-) create mode 100644 common/src/generated/resources/assets/numismatics/models/item/black_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/blue_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/brown_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/cyan_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/gray_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/green_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/light_blue_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/light_gray_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/lime_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/magenta_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/orange_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/pink_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/purple_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/red_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/white_authorized_card.json create mode 100644 common/src/generated/resources/assets/numismatics/models/item/yellow_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/black_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/blue_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/brown_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/cyan_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/gray_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/green_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/light_blue_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/light_gray_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/lime_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/magenta_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/orange_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/pink_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/purple_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/red_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/white_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/advancements/recipes/misc/crafting/yellow_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/black_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/blue_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/brown_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/cyan_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/gray_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/green_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/light_blue_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/light_gray_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/lime_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/magenta_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/orange_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/pink_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/purple_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/red_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/white_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/recipes/crafting/yellow_authorized_card.json create mode 100644 common/src/generated/resources/data/numismatics/tags/items/authorized_cards.json create mode 100644 common/src/generated/resources/data/numismatics/tags/items/internal/plates/gold_plates.json create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/base/client/rendering/UIRenderHelper.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/base/item/DelegatingContainer.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/base/item/DynamicContainer.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/base/item/SingleCallbackContainer.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/backend/IDeductable.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/backend/ItemWritingContainer.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/Authorization.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/AuthorizationType.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/Limit.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/SubAccount.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AuthorizedCardItem.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AuthorizedCardSlot.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/bank/ScrollingLabel.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListMenu.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListScreen.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/bank/TripleCoinSliderWidget.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/AddSubAccountPacket.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/ConfigureSubAccountPacket.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/OpenSubAccountEditScreenPacket.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/OpenSubAccountsMenuPacket.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/RemoveSubAccountPacket.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/ResetSubAccountSpendingPacket.java create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/sub_account/UpdateSubAccountsPacket.java create mode 100644 common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list.png create mode 100644 common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list.xcf create mode 100644 common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list_popup.png create mode 100644 common/src/main/resources/assets/numismatics/textures/gui/bank_terminal_sub_account_list_popup.xcf create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/black_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/blue_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/brown_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/cyan_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/gray_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/green_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/light_blue_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/light_gray_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/lime_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/magenta_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/orange_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/orange_authorized_card.xcf create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/outline.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/pink_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/purple_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/red_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/white_authorized_card.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/authorized_card/yellow_authorized_card.png diff --git a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 index 3614284e..77023634 100644 --- a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 +++ b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 @@ -1,5 +1,5 @@ -// 1.20.1 2024-06-15T09:57:05.592624451 Create: Numismatics/Numismatics' Advancements -8f32fb49ef81058e2e660fac983dbef2f554db38 data/numismatics/advancements/root.json +// 1.20.1 2024-07-20T21:35:42.063798491 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 7217a008..9dd22c63 100644 --- a/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 +++ b/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 @@ -1,75 +1,107 @@ -// 1.20.1 2024-06-15T09:57:05.591802125 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-20T21:35:42.062261717 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 6cffc9d1..0105cd38 100644 --- a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 +++ b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 @@ -1 +1 @@ -// 1.20.1 2024-06-15T09:57:05.592492659 Create: Numismatics/Numismatics' Sequenced Assembly Recipes +// 1.20.1 2024-07-20T21:35:42.063465261 Create: Numismatics/Numismatics' Sequenced Assembly Recipes diff --git a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 index 5a38533b..5a674b9c 100644 --- a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 +++ b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 @@ -1,101 +1,119 @@ -// 1.20.1 2024-06-15T09:57:05.589915157 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-20T21:35:42.058853357 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 +26be219740f21ea416f940849471f2f8d1393bb4 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 +a0136be8293c4a1563a69cfe90ee10075d775e53 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 +cca7e7be961c6ed6272f19211bb17707b7934155 assets/numismatics/models/item/creative_vendor.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 +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 +c09892d2d189f147997d77f4ce39b0570729f030 assets/numismatics/models/item/lime_authorized_card.json +e1087e56db7b4d8812ab4617344f0ac8b0f0e6c7 assets/numismatics/models/item/light_gray_authorized_card.json +390db78c5393fca4f90018df51d1a79d11a64f72 assets/numismatics/models/item/light_blue_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 -52659db3242553289a2cb1268eb469a48a477f3a 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 -cbbdd36d74d48d2ff03629264e405a790dd1697f 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 -266d9b0eb6fdecc4bcf6da465078d059009a3b54 data/numismatics/loot_tables/blocks/blaze_banker.json +b6efde0135fab023b1b51f219254e5e9d7439f6a assets/numismatics/models/item/cog.json +b1f339ffecbae2c812e18a1286162d31429ce356 data/numismatics/tags/items/internal/dyes/gray_dyes.json +88219edf7b658e79cfaeead5e314dab8db133f79 assets/numismatics/models/item/blue_authorized_card.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 -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 56c24c0e..385e50d9 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_ud.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_ud.json @@ -34,6 +34,24 @@ "block.numismatics.vendor.tooltip.trade_item": "ǝpɐɹ⟘ oʇ ɯǝʇI", "command.numismatics.arguments.enum.invalid": "%s :ǝɹɐ sǝnןɐʌ pıןɐΛ ˙,%s, ǝnןɐʌ ɯnuǝ pıןɐʌuI :ɹoɹɹƎ", "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ǝΛ", @@ -50,30 +68,42 @@ "gui.numismatics.vendor.out_of_stock": "ʞɔoʇs ɟo ʇnO", "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_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.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ɹɐƆ ʞɔɐןᗺ", "item.numismatics.black_id_card": "pɹɐƆ ᗡI ʞɔɐןᗺ", + "item.numismatics.blue_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ǝnןᗺ", "item.numismatics.blue_card": "pɹɐƆ ǝ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ʍoɹᗺ", "item.numismatics.brown_id_card": "pɹɐƆ ᗡI uʍoɹᗺ", "item.numismatics.card.tooltip.blank": "ʞuɐןᗺ", "item.numismatics.card.tooltip.bound": "punoᗺ", "item.numismatics.card.tooltip.bound.to": "%s :oʇ punoᗺ", "item.numismatics.cog": "boƆ", + "item.numismatics.cog.plural": "sboƆ", "item.numismatics.coin.tooltip.count": "%s %s :ʇunoƆ", "item.numismatics.coin.tooltip.value": ")¤%s( %s %s :ǝnןɐΛ", "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ɐʎƆ", "item.numismatics.cyan_id_card": "pɹɐƆ ᗡI uɐʎƆ", + "item.numismatics.gray_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ʎɐɹ⅁", "item.numismatics.gray_card": "pɹɐƆ ʎɐɹ⅁", "item.numismatics.gray_id_card": "pɹɐƆ ᗡI ʎɐɹ⅁", + "item.numismatics.green_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ uǝǝɹ⅁", "item.numismatics.green_card": "pɹɐƆ uǝǝɹ⅁", "item.numismatics.green_id_card": "pɹɐƆ ᗡI uǝǝɹ⅁", "item.numismatics.id_card.tooltip": "ᗡᴚⱯƆ ᗡI", @@ -81,30 +111,50 @@ "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ɹɐƆ ǝ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ɹɐƆ ʎɐɹ⅁ ʇɥ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ɹɐƆ ǝɯıꞀ", "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ǝ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ɹɐƆ ǝ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ıԀ", "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ɹɐƆ ǝן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ɹɐƆ pǝᴚ", "item.numismatics.red_id_card": "pɹɐƆ ᗡI pǝᴚ", "item.numismatics.sprocket": "ʇǝʞɔoɹdS", + "item.numismatics.sprocket.plural": "sʇǝʞɔoɹdS", "item.numismatics.spur": "ɹndS", + "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ɹɐƆ ǝʇıɥ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ɹɐƆ ʍ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 e8f945a2..fbda1ea9 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_us.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_us.json @@ -34,6 +34,24 @@ "block.numismatics.vendor.tooltip.trade_item": "Item to Trade", "command.numismatics.arguments.enum.invalid": "Error: Invalid enum value '%s'. Valid values are: %s", "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", @@ -50,30 +68,42 @@ "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.too_few_items": "Too few items", + "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.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 Card", "item.numismatics.black_id_card": "Black ID Card", + "item.numismatics.blue_authorized_card": "Blue Authorized Card", "item.numismatics.blue_card": "Blue Card", "item.numismatics.blue_id_card": "Blue ID Card", + "item.numismatics.brown_authorized_card": "Brown Authorized Card", "item.numismatics.brown_card": "Brown Card", "item.numismatics.brown_id_card": "Brown ID Card", "item.numismatics.card.tooltip.blank": "Blank", "item.numismatics.card.tooltip.bound": "Bound", "item.numismatics.card.tooltip.bound.to": "Bound to: %s", "item.numismatics.cog": "Cog", + "item.numismatics.cog.plural": "Cogs", "item.numismatics.coin.tooltip.count": "Count: %s %s", "item.numismatics.coin.tooltip.value": "Value: %s %s (%s¤)", "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 Card", "item.numismatics.cyan_id_card": "Cyan ID Card", + "item.numismatics.gray_authorized_card": "Gray Authorized Card", "item.numismatics.gray_card": "Gray Card", "item.numismatics.gray_id_card": "Gray ID Card", + "item.numismatics.green_authorized_card": "Green Authorized Card", "item.numismatics.green_card": "Green Card", "item.numismatics.green_id_card": "Green ID Card", "item.numismatics.id_card.tooltip": "ID CARD", @@ -81,30 +111,50 @@ "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 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 Card", "item.numismatics.light_gray_id_card": "Light Gray ID Card", + "item.numismatics.lime_authorized_card": "Lime Authorized Card", "item.numismatics.lime_card": "Lime Card", "item.numismatics.lime_id_card": "Lime ID Card", + "item.numismatics.magenta_authorized_card": "Magenta Authorized Card", "item.numismatics.magenta_card": "Magenta Card", "item.numismatics.magenta_id_card": "Magenta ID Card", + "item.numismatics.orange_authorized_card": "Orange Authorized Card", "item.numismatics.orange_card": "Orange Card", "item.numismatics.orange_id_card": "Orange ID Card", + "item.numismatics.pink_authorized_card": "Pink Authorized Card", "item.numismatics.pink_card": "Pink Card", "item.numismatics.pink_id_card": "Pink ID Card", + "item.numismatics.purple_authorized_card": "Purple Authorized Card", "item.numismatics.purple_card": "Purple Card", "item.numismatics.purple_id_card": "Purple ID Card", + "item.numismatics.red_authorized_card": "Red Authorized Card", "item.numismatics.red_card": "Red Card", "item.numismatics.red_id_card": "Red ID Card", "item.numismatics.sprocket": "Sprocket", + "item.numismatics.sprocket.plural": "Sprockets", "item.numismatics.spur": "Spur", + "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 Card", "item.numismatics.white_id_card": "White ID Card", + "item.numismatics.yellow_authorized_card": "Yellow Authorized Card", "item.numismatics.yellow_card": "Yellow 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..0c54b1de --- /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/content/backend/BankAccount.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/BankAccount.java index dc4897b0..81eb1480 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,10 +213,12 @@ public void deposit(int amount) { setBalance(getBalance() + amount); } + @Override public boolean deduct(Coin coin, int amount) { return deduct(coin, amount, false); } + @Override public boolean deduct(int amount) { return deduct(amount, false); } @@ -214,6 +269,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 +298,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 +349,41 @@ 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); + markDirty(); + return subAccount.getAuthorizationID(); + } + + public void removeSubAccount(UUID subAccountID) { + if (subAccounts == null) + return; + + SubAccount subAccount = subAccounts.remove(subAccountID); + subAccount.setRemoved(); + markDirty(); + } + public boolean isClientSide() { return clientSide; } @@ -299,6 +404,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 +418,83 @@ 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) { + if (!isAuthorized(authorization.getPersonalID())) + return null; + + if (subAccounts == null) + return null; + + SubAccount subAccount = subAccounts.get(authorization.getAuthorizationID()); + if (subAccount == null) + return null; + + if (!subAccount.isAuthorized(authorization)) + 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 cbf08317..0cef80e3 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 @@ -23,7 +23,6 @@ import com.simibubi.create.foundation.gui.AllIcons; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; -import com.simibubi.create.foundation.utility.Pair; import dev.ithundxr.createnumismatics.registry.NumismaticsIcons; import dev.ithundxr.createnumismatics.registry.NumismaticsItems; import dev.ithundxr.createnumismatics.util.TextUtils; @@ -32,6 +31,7 @@ import net.minecraft.world.item.Rarity; import java.util.*; +import java.util.function.BiConsumer; import static dev.ithundxr.createnumismatics.registry.NumismaticsIcons.*; @@ -94,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); } @@ -103,10 +120,12 @@ public String getTranslatedName() { } public String getName(int amount) { - return getTranslatedName() + (amount != 1 ? "s" : ""); + return Components.translatable(getTranslationKey() + (amount != 1 ? ".plural" : "")) + .getString() + .toLowerCase(Locale.ROOT); } - public String getDisplayName() { + public String getDefaultLangName() { return TextUtils.titleCaseConversion(getName()); } @@ -165,4 +184,10 @@ 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"); + } + } } 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..7e5976c7 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/IDeductable.java @@ -0,0 +1,85 @@ +/* + * 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.content.kinetics.deployer.DeployerFakePlayer; +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.UUID; + +public interface IDeductable { + boolean deduct(Coin coin, int amount); + boolean deduct(int spurs); + + @Nullable + static IDeductable get(ItemStack stack, @Nullable Player player) { + if (NumismaticsTags.AllItemTags.CARDS.matches(stack)) { + if (player == null) + return null; + + 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 (NumismaticsTags.AllItemTags.AUTHORIZED_CARDS.matches(stack)) { + AuthorizationPair authorizedPair = AuthorizedCardItem.get(stack); + + if (authorizedPair == null) + return null; + + Authorization authorization; + if (player == null) { + authorization = new Authorization.Anonymous(authorizedPair.authorizationID()); + } else if (player instanceof DeployerFakePlayer) { + authorization = new Authorization.Deployer(player.getUUID(), authorizedPair.authorizationID()); + } else { + authorization = new Authorization.Player(player, authorizedPair.authorizationID()); + } + + BankAccount account = Numismatics.BANK.getAccount(authorizedPair.accountID()); + + if (account == null) + return null; + + SubAccount subAccount = account.getSubAccount(authorization); + + if (subAccount != null) { + return subAccount.getDeductor(authorization); + } + } + + 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/behaviours/SliderStylePriceBehaviour.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/behaviours/SliderStylePriceBehaviour.java index 7851635a..3a3608f9 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,9 @@ 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.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 +35,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; @@ -116,21 +116,16 @@ public boolean deduct(@NotNull Player player, @NotNull InteractionHand hand, boo 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); + if (deductable != null) { + if (deductable.deduct(totalPrice)) { + //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..77383db2 --- /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 Deployer implements Authorization { + + @Nullable + private final UUID uuid; + + @NotNull + private final UUID authorizationID; + + public Deployer(@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..20913548 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/Limit.java @@ -0,0 +1,151 @@ +/* + * 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 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..d17b8328 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/sub_authorization/SubAccount.java @@ -0,0 +1,271 @@ +/* + * 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 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.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) { + 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) { + return spend(authorization, coin, count, false); + } + + public boolean spend(Authorization authorization, Coin coin, int count, boolean simulate) { + return spend(authorization, coin.toSpurs(count), simulate); + } + + public boolean spend(Authorization authorization, int spurs) { + return spend(authorization, spurs, false); + } + + public boolean spend(Authorization authorization, int spurs, boolean simulate) { + if (!isAuthorized(authorization)) + return false; + + if (parentAccount.getBalance() < spurs) { + return false; + } + + if (!totalLimit.spend(spurs, simulate)) { + return false; + } + + if (!simulate) { + markDirty(); + parentAccount.deduct(spurs); + } + + 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) { + return spend(authorization, coin, amount); + } + + @Override + public boolean deduct(int spurs) { + return spend(authorization, spurs); + } + } +} 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/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..8cbce42f --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListMenu.java @@ -0,0 +1,408 @@ +/* + * 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; + contentHolder.removeSubAccount(subAccountID); + + if (player instanceof ServerPlayer) { + 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..a13b7d51 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListScreen.java @@ -0,0 +1,683 @@ +/* + * 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(); + + 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) { + 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/AndesiteDepositorBlock.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/depositor/AndesiteDepositorBlock.java index 8cd0e6d3..6a4e8db2 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 @@ -20,18 +20,14 @@ 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.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,16 +82,11 @@ 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); - } - } + IDeductable deductable = IDeductable.get(handStack, player); + if (deductable != null) { + if (deductable.deduct(coin, 1)) { + activate(state, level, pos); + andesiteDepositor.addCoin(coin, 1); } } else if (CoinItem.extract(player, hand, coin, true)) { activate(state, level, pos); 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..e544f5c4 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; @@ -81,6 +79,10 @@ 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)); + + for (SubAccount subAccount : account.getSubAccounts()) { + 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 ec96b6cb..608ea9df 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..699b9b24 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,39 @@ 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) { + isSubAccount = buf.readBoolean(); id = buf.readUUID(); label = buf.readBoolean() ? buf.readUtf(256) : null; } public BankAccountLabelPacket(BankAccount account) { + this.isSubAccount = false; this.id = account.id; this.label = account.getLabel(); } + public BankAccountLabelPacket(SubAccount subAccount) { + this.isSubAccount = true; + this.id = subAccount.getAuthorizationID(); + this.label = subAccount.getLabel(); + } + @Override public void write(FriendlyByteBuf buffer) { + buffer.writeBoolean(isSubAccount); buffer.writeUUID(id); buffer.writeBoolean(label != null); if (label != null) @@ -58,10 +71,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/resources/assets/numismatics/lang/default/interface.json b/common/src/main/resources/assets/numismatics/lang/default/interface.json index c1fd2d01..9a0c7fe2 100644 --- a/common/src/main/resources/assets/numismatics/lang/default/interface.json +++ b/common/src/main/resources/assets/numismatics/lang/default/interface.json @@ -7,6 +7,24 @@ "item.numismatics.crown": "Crown", "item.numismatics.sun": "Sun", "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", 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..fd8eb911 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", 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 67da8e25412fe8b62f0520797bad39df716bf1cd..de0498b3cfde3d68d79ca9dd741839ee591d99fb 100644 GIT binary patch delta 480 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

MzcI)A+ym_^THGiyq+6|8?>o@%vx8 z{!7ylosyiij@R7& z;;`KUlnU)=*pFW+b&i^xz;|o$Y-F5Lhpr(+W*E%UEuMCdgk3(AhsNr2MBA5;k@&MS z5?RI=4*@TDQAI<`NnM=b0YQe8SL=&0gVO1FRr>6FG@`Nwac6Q zhu+o+Npy6%Sy|DqU%&od!x0k`Lq}&}Ys+?Vd1)M&0x@i1KM}k1RMot#n`?<_e%U{` zOv7H-VqF;i{WOrX(MR!c_0fp)8bOmQx$W-q@$}HR0u!_HVaQ^y;VB>p0q}nu zh|K|BYM_FT3wPak?f0S|5&G1ET!69RE$Phn`fSN3rKP3(kKXMtnv4CH-{#T0+a22v zFAoI==9|Ln_Wartr*<5st#9X>Tg=8X%rKH9{jPXCJUmq8Fb{9ecbyNHS}%5&WrNbw z)35pu1E~^!ap2;{7I4_NJ!VQ~gk;123}I1|)g5R?{cT;2)%2h}p~k6?73t^CBbFbA ztW3-`4Sw5E5v&lc6Up4e-d`$^=C*mVj-DR*y9*o1$kr#f&ig-f_F89RU4T(vztXcV zU;9;NbwA?9uC}_6*2O*$*Ta@QQ1Pj_kwGG2kr5FINum80`~dZ*fNV4-B15GgU5v$o zK^%!SPNfKEqkx(#tWoiazdj|4AjJ&-km71+X9G5S zcFnMU`i89Rf(dnFj%s(5+%{AFypQb6C>k3Zx6AU5Qc_bnW$O6>w4JC`O-LH z`9kH8;>ZEyK@$LM0FIO`05u4eRuF*G@th8Rlv2i#LW6ic$6~1%x=NE);z`?c6YdS8a?-$nrV4~t0KUn&as)WN7&I+FB#}*2 zo=?5Djy3}IAK+uM;z&<>EF0m<8o3hgqVx^fwPH-vlVm}tnn9=?&4syx@Fp8458?+z z=_B9UKN#0L0^xaanA+mxHC_*|Ng2Sep01&ev|ZmqamnE}qH_R{a64)qf>y_!iPY0p z1u=(H;nw~A#g@C46?ec8;OQmm(e}`RqGT>V04Io76zOVx&F1)?#;<<2_kO<;rxJMr z9#i}LSc!jFGFa(2! zp5-AFR{zYo?BXqxop3rVwYKQfWeI4Si%<_PNay#;Lj9NIhhCy z4W}xF>(f8$Dp6(@7Tk1sT>AU_kFSo`;$H^FQj6DY_426zPyyxuKwl1mTT|fULq~3& zQF+ha-lt@)APQkeY(ENic6MH2Vd0eAVSor23Gcn$N1zEuTyk=9utWe9T3U?bos$dm zy`|yhKYb@g7{FGwmr$f16%|E5pjA0N{Of*r{_f6CRU`1+3*EkVU_iA-wu1~HZYMx4 z?y%w0O8rjW^3wxObMs@&hTYE?GqSYxD6jy)N3T@J!oi{3eRzoyGg3JsaeD(ha)Z6O=xIn&JeCP4I(PQzuEWlfa3CIk-W2n`c_yt zuw9LI_;fui2tjIjYHCWo^)1b>*1+41!_D;9i;Ig59{Wb?-qgm%#?Gf3gA8FovQnsH zVrZ`<@wP5()>^JJFD@>O+Lz|$A{Bp{Ya*HF4K9l(0xzw$=zb}zUWii71+n_-hzzJav z?*T+}ntOH&ZX@=3O0m507*dR|ZCI$iz0KOz-QE3S7=tSWK81LGT0Wlo1ZD=RqDs{n zy)!D`h%DA^O-)I`JiXRlzJpN#YHMrT($P3wU0vz#4?rIt{8(L3|LlhCY=lo074mZ5 zZf=@LR%8|$U3=+F0Fso%zVOfF|5uNo>Wjcdf1Xa1#ii2UF(^G(m#dI55BdK9d+dZB literal 2464 zcmc&$`9IX#8~+TADf@IO`<^wW5Eo@+O0w^li;*?i*Rjr^$Z}0ueSKfA?_Y4wFX#O{&-*#&JkRqw=Q%0nrUqQ>LhJwla2ei# zTLJ)x2|>VVHs<6QT;a(S9(wERn;YuuO9Tc7czXMK0DwF;7JL0p4@`uFu)^I^Ep*f*QqX&y&c3(kCzSvg#}rLV$U*i z`5cH5feRVPeKF)VP;BAxd`g}D{u@6}OT#O<2&jJDX-Q5OPK!MI-f9`#vi938=*LZ` z1TR|QVaV<)a2g1NjYtwKGwCqZY4R2>*iUh*zF0-15T#|EFh8-IseJ(jMwd8rR6RXa zLx@*g>nFSJLK+(?p=M|MY)r~yBq{X+k!g*#HTBciX&lnv*vOPkH3+tw<(#D6qXZ$v zitgJ9wlDZN1n0~SenK1x@Joq~{3^lk-B^X(Kkytw2<=U&zpOf2%A5%$Xb$)B^3H*u zhxO5Jgcq!z;f-Od-EBs{1R0|BQCTU-5o2E+o}Sa)>=8x-0tF=gf#S+>1) zO(G?tICiU}@J)L`2Y`EJ)h<_H;AzfW`RE}Ed3kv8`1-`gHbf5`oTVP0HUR*T8AG_9 zbwmM`tQ#QmyCCEvvd@R2CU1SU4=i= zT%pFcA!)Fx%r4UuTX<+Y!=W-t#Qe>4t~NC9d|Y@{HtHCCOtnwcj}NA=JvMtK);(Ea zhTt(SU;zZJ00}pCz}*-W_lE+2xdH~RmI1I{KH%MN%LSqD?ArH9`vls&Vjsx5nCy>~ zE}0)h9{DsmklWhY;u+}4O*uSXu~wWCF6Sf`=9sl$%TE|wZHfM{z41D>k#X>ge{R#F zQv4g_)Q8BCrz5ANE_DDVMO9ZC0z}annh|=RaG`T_Z~#tJSFI30I#mAGk_C& zdvD_&f(AUGm<10!Z{V6}Jc|CZkVHy5ztTA3e0O$+PP&ZV5{>5;v1fgj1Th$BG|iL- zy9kMiD2!+sh5}dHWyVgTfI}o2jn0b3y}$GiDUJI5zxF1kQHIq5V(4SARY~uCL`9Sw zc4&y>{0M1$d^~UK{R>mM<6W24$sNpRz+J&UN3U1kl?#@W>5*6FY7Nmx0$EYDp4y*$ zy@X^5+%8dEcs7+3N-)z)Oeexc`+~0*hC=jMV{X!WV9%y*LaN|S+5#$aEo3+CE+NK2 z?yjHJfenwR{pcSXHarig=GZ#cYw(T$7$dxA2by`?c> z{l|t&>EA#_29q@6{h@Geih`~SC5(YM`-EUU_{|{tE-k!rsqUgy-128YXe%~@vT9(q z(!O-Km$HAji7-7jy76EGD9hq5S~iW=5!a2nI({SqzRzX=67t9NM_NJy`6PI>;*x|z zGsP~mXvOI;SMh&lIEOeD3Phd+_g7Yv-3b;rknc>-&`mWhSKZTac5rBTakg1?z&)1! zxu2*F7=X$qM!i@TkB$zAi|*aw1GB?wrK+Ivto>6@aqjkPf;=fma1IldRSHbSkAN|_ zwbJP)rvJ`Zk~1qN_-Vn~+*qq2vs9kBGSh&2xM2w^X7)k~_lc|pe|&h z3Pub2`1sVfwra+YsZB(4z=-*0be@=&y9HsfH8nNqVT|nTY~;DPni@2bPPc2v?i6=g zaR6#V>B1T-l8|(GRrjZZhUW#@DjMyQhVw`lv&t; z^oEWOk-@=1)}|Y8w+@sdFSjcGs4{+#iv#9TNwY6fXSjO>DGUqTC z(>3w<3@Qe|M~*{M=-o)3a`EC GlJGBs!D{dT 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 a33b0e78e372854a0589989c1d5e172c9c531cdb..639bfbef747487b50539301c2362922667597a9d 100644 GIT binary patch literal 57098 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 literal 30085 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 S>VMpX;yBhUPvNBH+5Z7%Dw&)B 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 0000000000000000000000000000000000000000..67299d3e00def2feb8ab1868e849d3f83ef6892b GIT binary patch literal 10577 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..22dd8c6ed4b9584bd34875553d11edf378c03a47 GIT binary patch literal 134262 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..340a00ed5a420c100bcaf9aa9817f36304fb4489 GIT binary patch literal 12384 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 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..8e67b06cafea0494a48977657dad9a7c063f1ef4 GIT binary patch literal 86128 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 literal 0 HcmV?d00001 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 0e6a5085c1b71b78686c8862184f32b027ad6e2a..a6862b7fb184a9edc5228b4a7eba573c3ac0e108 100644 GIT binary patch delta 4849 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 V6ii`Yr;RHhEp^@dWvVve{{xHkvG@Q0 delta 4485 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 X82bNhUT#rU00000NkvXXu0mjfD-jOi 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 3d0c174190819bd577a15095ce22213d7233fa5e..f89bc6f2c1df0d81f143c3c9b5ef75d598b7f330 100644 GIT binary patch delta 1717 zcmcJP-%C_M6vyYz{k6NU;<~V{8n<2dhq}5;81#@2hC%dDXhkm(A@&d!m}CY~aG`&o zaDt$hpeU#pv5N!+{d}t-P@-Oh;`-2&BvEN@I-U8k+ZB6|%7K~BnK|D%bLPjr-};x2 zUG3GzCif)tgO89X_65oCL&>NinS3s}bwM(9Q!?{ZGCwcbeqXZV4!NOks|z0<8%*sV z8a>BHG5Od)v=MSV+Y>t_WtG-=Nn*)(SS@CJfL_8i7Ax+0gjon_OhX!7VU!w7qdyr% z$Y6}>Y>_g=5CYp~OH`RA`$3r)$KWv8vJ_cd9dPI{1NwXt*IBGA0)XvSJA4&f4JUiw zRSZg57_C4mGQ)cG-*R;k+IX^?kgK~{2fM*s-E{}6!3ci@jMbnrzi`?JCi zPQhx28?y3t{j@;Xj^6^YZasgEyx~=Y8W}oqW_YwTGJFz|H<=8X&1Ff+*=LS$4VkpM zW2eCil+eZCD-T^4uRJtSQFK9Sb!e5swOeSFA)A^UCbKy#DhAj34EQWyf=O+d+l~Gr zg8T0w{u}`^R@-1}wjl?rzPNCT5OS-q4{}e>k?Bl7iRPo^lC_--8htqOEO>a4S$=pp z^40rfr10L_MCA~H15o)LslQ3>F0i2_rzAx?04>)*sXZzg-|Zc+$7?hlep5bfoDMG6 zI4_oKGQFjEQU^(Fi;o=~lsJx%I6J-e^WHT_v8ltlI=q}K zR9Txl`Wq2h3~blsad42cgoS;;p^IC5X;+@3J$OtyJLeif}_zc)s;TK?IMHn{!m6Tv+Wdtf`oV-t4 zc{0CB&g7M{{!HS3!RjO=!RjOoH|xnwVFIgTf~yNt^kuv zP<6YRarFOO!w)PelR{jSqZ2SWjcG~y{>;zE|T(gAW zBZwFbB)s}!34A314RrkQJ$8gID-n(W|!nGTv5_EQce*(4(eiHcg z7^>Dk%G(R-J%iRiTHOPH@rCt@ k=dpzYfaKMoH~S}i0H@ft%6e7+egFUf07*qoM6N<$f|v)wIsgCw literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..47a5b098bb5831ce309307391118fc18ca52dcd9 GIT binary patch literal 460 zcmV;-0W@P0N>&#m$P;9E3*GA@J=oFBgC zXghPS1|o2!*tm0mmR)uRV`p`tGfPaGs4JzgQ%L}1J(!8WNSHjcEE-ax$Lu^|zr@Yc zHMG=dN4E>{_}??o2_Z&_n4L#A=9g&yhL3NnZ0^1TI}gDHy{q!*Im>u%lbn;pbDLC( z4Nfnw`BYuSm|q(H1Avzs9|n=eDGC6}UydW}qv9515V*};+*XeO00001gh6oo%0GrL)DytZUZi4YM*LKNXZ3QH7}(9u%R(o;}S@eWX=$qS@N2MsTf4hazn ziH%p5l^-i0EO{k+?8RP>y-Tsq#`%#Fl!DXTJ9FpUd*;l*|3>D)qe>hO2LD9TTBo@v zMKN}14jqn>=4@IhIySxvC^|L(z6ug@IA$1{7-qyUoI(5?hAbG1sJ^1#`g1m>H8>xq zVA)xSW>G;00nq&Q8_Uj;D>z6gua!U2BUHPScmS}xT8x_jQ99_j&iZi)wdh9M&>oy7QAa`;*mvx+kSX>yt@L%!|g+nTc09dr>mLmrpN< z8dW^k=jDfkv_5m1NGbWcwZZo5yO(kxB{!y>1s_I2EFCjp5uwGKI;BFa*=QIs$_T3~Cro1!0wz=(k|=X_Mz~pMg^W z^^MVSee#@jJU3vioX2wm8r2@VdnbHsu49#!l79fO^7vJpYP?1PK>hnp%Dol-0``@^ Us8C8B2LJ#707*qoM6N<$f=qk-vJL^_yQid!No7Y&4g$| z!qQD?P#R)rV#9X3+ds^9>tX9qp$QlcJeT*KdFOfGXPz0jZKRf-6#Lyy=f6lwDV>Wb z{|M`D78S(E?3gZ?_7ni2cZz9G5qhTyIf%K_Zjm-JoV8ns-a!c?oJBQ!{II1P_(Kzi za{$B40MPLo2!PtJ6AUv$&bE+JUMW9P5x&<*JOG$mDD>~$pJjV(KDpP!Wul`!09>ce zVqqHBsRQt{Qs={$Ccf98`lFl@!=0bK+aIj<^`4XxrH%(NF)!}L=O&JF_M&8fuUoH( zt0i2g&g+kdx~^@PQnIuDl+SM;T*?7Wu9kv-2BhW|3jM#%3Mse_hD{VoDJ**ufTnlx z!A8R{Gh}l)f@Twuwu;2PGG`Mjr0l_oZWqSKM@OI&Lz*&atB5dW^0a@$r{^_ZzJCE$ z5&UmNN0q^IR&bq=#lj@66H+Y&Y=1vyv$l*elTZEuz~j|7eXa2d1pt-Z4b8m~{s8sx VyrvOM!SMh9002ovPDHLkV1kal+a&-1 literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..4d22f4957c5244fc6fa3e5b53fd42c4afd1b91b0 GIT binary patch literal 468 zcmV;_0W1EAP)ez=5QV=(yAFHC7mFAXP%Mf-6yX4cB?`*WrA?7GJq1Oo{0As#_yZJl(C`P+A)z24 zaq-Dm#IYiTrC74>e7knmIj69F7y*hA1=Gyz&b~Kq-!A;`aPHnO5Bt5|UxBQ(X)SIn z7P)$@fQdCK>!uCmDvUNLR{>zO8Rb}Gv_`ouMr%a9{snUy5q3gMtY=a%85FiV2!Q6d z@2IRxF7F|wyioqY4hY*F033kjmD2F~%|-T}-5K5M)*6GO&j18|i`CKsf!_k4UTd-Y zE+TAqXdG4@G0ptw>A`q)knTw-vG#bJN9HAG$qy5!3H~G*;QiZ8l17EVZ?X0KYudjw zDWsHqc=>==PnLeEffU@RbblJ)EU%P?6K91K%o5Wk3TrK1ejb3R9nM6cvMyJ0Il57V z$arOvvnr>T@8RUfC;EMuoBMqRdI@BxlJUw2RVZRk;Kh2Ajh)Bfl_A_`a8w&VXN|y* zSuM>I_%V%2m%We2ylJkX3dPYs0J!~ddzfmxKmkDQ)9V!bPjL=@^}KrWHtX*I0000< KMNUMnLSTaWpVlS- literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..71c902c7097a17886deed9ec0dcd1330ef996175 GIT binary patch literal 471 zcmV;|0Vw{7P)E|RK`M8ckEZz?rdU6hc&Q$|FIY;NJ0f6f$NN*Z3(?fdGDCwna|MC12?3T^7+nGp# z7SjQ+n=Mp;+QlVWOedZ&5JKE5-9*3&vN*cV*o6(PA2;h%d7)% zR<5)2&B1QAsGgP-b)0$QU17K?gnL2=q&y$yfq6kMxHWN{;7^hP_P@R&s1~uzIeA%x)j$2C5^efnDsgy3qi{mTVPdMVoxRC~}uonOT N002ovPDHLkV1l-l*%kl* literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..26b0fe762aa58e82100dbf3da2c95a2261a4f278 GIT binary patch literal 465 zcmV;?0WSWDP)cuqDm$Vwqp$Lqm34pBn z=m3@L8;qn$Dq|spcoM&>y2xrsqyh9P4)+(rcg^MKUVaC_bv%}`Hm>6V@T26h_qB$s z`jjt3M195S=Q2*ruZGJJ^>np1ZondTHL|rL`l?i8EtIDAo7)g`yREm17hMutU z1P?{-$6ldjq7$7CjE?@<1ML736iHZlbYpUs)-8P4sIaxW305BDG2P2jG|m#P(_kr^ z#&sH$3v~`pt~jXVFeYcie*p0E^-eEle1ZU=box22{V#h2);zfH_fwc600000NkvXX Hu0mjf4({5> literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..d153da1c733ce9846786673a2c1065de06125495 GIT binary patch literal 470 zcmV;{0V)28P)fv zpYxx{WYRcJfN92~Mk=LKtNEl-Ismnr4}jwYxNbl)8OL=4l-Y%B_rAgXoRuzEr zQk9K^I-cWF{#8`eVdi&V&ibpfXio@%l$ZV7GcUXe?@SyfcuF$B_x+EAW>WyAp}2mR@hyieozAuxLj!58=%ZCWV-`rRiQFU44bG*DKX3>0CmS3i9pliOePXE z>UGqZkt4h*ay{`H#q6JGw_$wz@eH&=h*2bFw7SA;2qJqDD|JS zgl+jOW|P>KPr1;M1& M07*qoM6N<$f) literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5615e341d6293504ea7af2cc532cf203c694bb85 GIT binary patch literal 473 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 Py>kj0$nzLzpg8p}4af~m literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..80c3a49315675d58b96b00d555dbf083052e1a46 GIT binary patch literal 5322 zcmeHKd0Z3M77p@2MZj7r;DUrux5^}w$v(0t0U`!zKn0=7WM%>bWHAX4mbL;_5q}gn z6c-e6qqe1JD`m7UP055-9&UC9cPu9mB%&<-Sz3xznahmVKLoM#Do3d$}8r=9D>n{)CPv`1XsaiH?2{=%L`>4^t2SC`7(z5S@A#rN6O zb1fUEGs{nn7BB7l`0+8%)z`l{?t0CwCod$Ns@YvTMbU>E(S$gzh z+xQIknC$f5Y8K^%5_tu%?XmT^Yo6|gwBXYd)xA&bE9`QXmwQ)*tg3vVQhxlj@9hf{ zzf#6Yj;UR$s-~=v=-ejQ&l$5~a?-5^;r51NkGO9Zx9}v%Que zoa*FLS8{_FXnx&UM>OY)IX`WJGS3}*>vylp*n27UD-^1&DUOD{qO<(|9X~4$WhIs$ z+MjqOsbZh3Wz~Z{`&4IRG~_>QLaDK#v6qxI?nsR8*rp_Zfk4OjT#qr{z>bSrf)mo;|?~PLAeV3*i8@^f7^{(@^uE#m8 zi!Nn0<=$DHIQ5}#V(;awrJ^U%Yj$NF7e#0G+zNINHj0q1g(ZcasN1Bv{8S!-9Ebf2S++mzJJO z$B$L|aW3DFpV{JG{P@w7t3i`LqS35YQettqOe}t0hoJg)yuaQj=O?z6{3ipYSWsN>%Mm3XqWi+++uA4?pZgq)ypnQ z=RIAfNSM%7zufPK>zN&O)*mfd^NFfmSem$beSTBJ{8XuZZJD*W`=o2xo1BMj1Y&jm ze#&_FWp^3gXZkyK?TKmLYJYD{182U#t23qZ6M5**wF{;yr7{oSnbUaPISqxeTi*Mi zD^?eEbE}7E$u>{N32Rq6Z;mOR=ul+ZApER+@{i*tZJBs3X2%u9O5U%{%Ur*s&VEo*tEV;oy2DL)y{H2Q zxn1LmM=tHpTy00y_}3-2-)O3O&(G@V`4dG~d$%N==$+YfWxuoUsEn%Ywg22dqn7aq}SGbd8GQo z^V}!>R((18j?=BTooF=2n-o|WqvZ2ZT&recgjPv1O==xjIB7I*Ka&o_lSm_7Nybwe zAI9C9;|w}Q_%IgpPCKITT3_Tf<5f+JOB;g{0;pc1TZ9)Nnnlxf`lR8;rKutaj z3oZ)o&CM(Z-C|-)@?k{D!|7tJo}_b`TqX=jO;jqv@U^3R>j@RAkOU1ufF~bDg3+i$ zS**0QG-euysny4`*dmdL1tTm3fq(^MNY@xK6QnVCnjr=;B%}e?Q#vE1)zHnDm{OZ! z^kFbSKmB=pYMosE0$yVnQUU0}GGRIvn+dbjYSwTMgHf6aK!yVPQx8KV*k4!*(x6Sz z+5GdvLB{sMP|^>gkPV_+qhqY^EiVh&Fx@nM+9M+q%X5vb*st>j}$E}svP z9JUJLvN=2mgV_kgAviD_6LM5S3>gL`(-@4H1}Du>0Gvqy92{n=R6LOq!Z8j8ad8d@ z5~fVk=1= zm&Zl~9GGW;B5*WFt5;)SIw>_4PqK8HcuR*_a5NxX=EFdk@XMC)WXz}n4nB}g4Fy7%Cugir=xk#5fTp`4E(mk&M-mOwIP>7vsuX^Ud` z;2;Jpl_V?!0l&d6JOR_hlc2tb66$$7^(T|1BKQI!$yGrFpHxCzK7vC^J|E0Hhd>CW zfX^2x@sa2Tt;(2&>B)e2z!b0n31neIpJkD9_DJir1k$V%jBp@W06vjyK8o;BjtJbN zFw9{6^%M~fAK~GI658 zdM(#0Dey|hue0laCYRmIV=Jiv|7Fv_p)?|^um~JzZIz+H654?IU0QcwBWM|`3yC(+ zXyd?1c$||JZQBl4&^X#ClS@Z;+q$`M+%unSDgjLjnIs@mcm|JiO*k>@lhWQ@45wLa ze?>r#pVO7vdr#|q%Ib1=J2!eX(u_ym%EWFu#0B&TW?y{AY}#o&5va+@cy@D|XAnxC gX~R+69+huJ`>uATl}pzCTL7IVlZHtu0^@T21?XMJ=Kufz literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..5cb5aaea1aa69814c715f92362f9f4fed4a681dc GIT binary patch literal 469 zcmV;`0V@89P))?Gxe5XBmEuf?Oi7b79bzmj7P`|9X9yYr7wumoDX>#X z0D^i00Z{w?13Q%@opq2>-YdVOI|TIx00zK7#oqSg-o56R=$sq?;JH5e!UUe{1Mscl zv-Pn_P;XE@E*oN)dHMBWzdMZAq?BlV+Rr`nqO0h}#9@NFBm;c~75cQ3El!T5A1vfU&Sx=nk9}QZPykn<%u_IN1yU&3Z5rft^Y+mQK@Z zHW3M@NOV=^(t3)K?e7RfFwNUDpdv_6CgBtj_GFHWpYY~ojn&N+aEcIop>tB{KW7Ec zZIdr#@Z2`lQj5K>r@XH%VNd3I{{Z08i}h}-@g4;LmHl@y_MhS!i^90w`c|nx00000 LNkvXXu0mjf+wRtS literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..c23c6f4f9ca6483b1ffb3e61289647f6cc9946d0 GIT binary patch literal 471 zcmV;|0Vw{7P)?y3phW+(kl( z6e){W)`}ks0fSh{yS8JSvDYbVZyY5NMk%<>y?5@MGiS~W+;?az>xEvs)w&Z%DHYfH zmi>a2rFHy3GHu!MV9v?{a1nUSSy?Uu4*)-q$Sa9GYa_2D+F~x>v*#ZY1|iMHkFgXO zsU!elH9!ZD=a(3%B;IrRq5 z>ESvJmh%>_)1XqSQ~Y|yN4bhIv(Wzs0NKrFy;$Qd3IM!sdolLE;wOHzxg#&pI-URk N002ovPDHLkV1f>f&tw1q literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..896a92773a912d231ed359792862b175b10cd85e GIT binary patch literal 479 zcmV<50U-W~P)db6K`|&x@3T_pI#GH zir7|-H`{-b`oIN{Qu6KnD?YrNx`Ba&Tq)MC4A5rh@?8KUokB>#eWKq)p_IbRWdZOV z?_Ldzbc&HohPv+~bhALzDG?06K+DA^+HDvbx;+D}2y{y5W&vSLOw&Atos}wU8>?Uz z!23>kSdO2wjBPcT&u6i%29;u+y&p&HRu?cPrhESY;OWxaZlduH1pwur9~16>#W{qE Vyp%j6hw%Ua002ovPDHLkV1l7B*5UvF literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..2ed96f0cb3e74b67658a0a2778315b70dba5da14 GIT binary patch literal 463 zcmV;=0WkiFP)^!D5Im6W@?5;@GwpPK;ga3{0dAa|bWjwdVVrCrA zZBZ#UIrx6TXPL#Coay}ofLCwU!-(+-0)X<5Pf_oG*&koUyM)$1p^pFn002ovPDHLk FV1oVZ)nWhu literal 0 HcmV?d00001 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 0000000000000000000000000000000000000000..46f596e8cc439c4ad6b7ad54a6b589f763e54eea GIT binary patch literal 470 zcmV;{0V)28P)9cl6cbV!Iu zNE|*{76c0-Te6XF?ZY-}&MD45j7WqL1=Gyz&d%(&|13PWX>ZnDHmN5rp^1@+kGREbF13 z!T`vsgAP#oQ^bgbiN;NY5D((FRU29Li8O#7#qQc`|6SAbw9k$Ju&oMn>6h461%TiA z3adYB$f`r(G^gqPoj-j$?yio5Js|{2op-%2o_FKjirC-af5-rPKNj%{S!}Dq()vk| zf6)ts5bSThXY1?Ky%-3J3)%Xe3$&S3y3?%;`u_l6_TzFVV0?f8Ab+?W)IQ1n0ylZN5FHNLn+a literal 0 HcmV?d00001 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/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)); } From 26ce42b1a6bc8bda4b70d961ea1dcbcc5663b177 Mon Sep 17 00:00:00 2001 From: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Sun, 21 Jul 2024 00:01:45 +0200 Subject: [PATCH 2/8] various authorized card fixes --- .../630af4bded938901e0e1fd57c58a2ac245292828 | 2 +- .../6ba62358bf8e130d42215f5f9edbedd611809677 | 2 +- .../c6e4c19894bc5aece2976a0277ba8e1dbf023865 | 2 +- .../d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 | 14 ++--- .../assets/numismatics/lang/en_ud.json | 8 ++- .../assets/numismatics/lang/en_us.json | 8 ++- .../content/backend/BankAccount.java | 29 ++++++--- .../content/backend/IDeductable.java | 31 ++++++--- .../content/backend/ReasonHolder.java | 63 +++++++++++++++++++ .../behaviours/SliderStylePriceBehaviour.java | 7 ++- .../backend/sub_authorization/SubAccount.java | 34 ++++++---- .../content/bank/SubAccountListMenu.java | 4 +- .../depositor/AndesiteDepositorBlock.java | 15 +++-- .../depositor/BrassDepositorBlock.java | 18 ++---- .../content/vendor/VendorBlockEntity.java | 21 ++++--- .../events/CommonEvents.java | 9 ++- .../packets/BankAccountLabelPacket.java | 30 ++++++--- .../numismatics/lang/default/interface.json | 25 +++++--- 18 files changed, 224 insertions(+), 98 deletions(-) create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/backend/ReasonHolder.java diff --git a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 index 77023634..229a2f09 100644 --- a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 +++ b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 @@ -1,4 +1,4 @@ -// 1.20.1 2024-07-20T21:35:42.063798491 Create: Numismatics/Numismatics' Advancements +// 1.20.1 2024-07-20T23:00:35.820097013 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 diff --git a/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 b/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 index 9dd22c63..accf55aa 100644 --- a/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 +++ b/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 @@ -1,4 +1,4 @@ -// 1.20.1 2024-07-20T21:35:42.062261717 Create: Numismatics/Numismatics Standard Recipes +// 1.20.1 2024-07-20T23:00:35.818533487 Create: Numismatics/Numismatics Standard Recipes 0e1680b878cfa51c04809504b3542cb6312027a1 data/numismatics/recipes/crafting/gray_id_card.json 61954216f844eecdbee266da7e517a983993d2f8 data/numismatics/advancements/recipes/misc/crafting/brown_card.json 2c732f9c3bc02a29a4d86a0552f4dbbae986a34a data/numismatics/recipes/crafting/blue_authorized_card.json diff --git a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 index 0105cd38..416e9075 100644 --- a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 +++ b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 @@ -1 +1 @@ -// 1.20.1 2024-07-20T21:35:42.063465261 Create: Numismatics/Numismatics' Sequenced Assembly Recipes +// 1.20.1 2024-07-20T23:00:35.819703997 Create: Numismatics/Numismatics' Sequenced Assembly Recipes diff --git a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 index 5a674b9c..582dac20 100644 --- a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 +++ b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 @@ -1,4 +1,4 @@ -// 1.20.1 2024-07-20T21:35:42.058853357 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-20T23:00:35.815987106 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 @@ -8,7 +8,7 @@ a96d3d02794064cd9be1bca25a9ba6217675e6c5 assets/numismatics/models/item/white_id 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 -26be219740f21ea416f940849471f2f8d1393bb4 assets/numismatics/lang/en_us.json +1d27f892fbc5e7c13c50ba96fadd0051c89f73a6 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 @@ -18,13 +18,13 @@ ad712dd2a2a7268dfa773f38a50d526952758d5c data/numismatics/tags/items/internal/dy 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 -a0136be8293c4a1563a69cfe90ee10075d775e53 assets/numismatics/lang/en_ud.json +ab0fe4f0e989b51dc7500a539f4cca32f703424c 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 -cca7e7be961c6ed6272f19211bb17707b7934155 assets/numismatics/models/item/creative_vendor.json ad693bfb3bb45d661f989071bd896e3020fcbe87 assets/numismatics/models/item/pink_card.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 @@ -53,9 +53,9 @@ bde18ccd9c21484154597c6271750c0406082f61 data/c/tags/blocks/relocation_not_suppo 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 -c09892d2d189f147997d77f4ce39b0570729f030 assets/numismatics/models/item/lime_authorized_card.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 95ef415a564eba1d212053195d25b199427b94e3 assets/numismatics/blockstates/creative_vendor.json 9fdcd12c871f136e66973a8c02be94a675a4b727 data/numismatics/tags/items/internal/dyes/yellow_dyes.json @@ -79,8 +79,8 @@ a2ff135c1fea203b49dbbf4cae010664aa1cf909 assets/numismatics/models/item/magenta_ 56973a6ce09377c8f235f46aa4d71a2a9fabf587 assets/numismatics/models/item/red_card.json 4a6ca666740b098929798ad132260f288cc228c0 data/numismatics/tags/items/internal/ingots/copper_ingots.json 36e1dad2803241c11c646b9737be8af6d67ef8fe data/forge/tags/items/string.json -b6efde0135fab023b1b51f219254e5e9d7439f6a assets/numismatics/models/item/cog.json b1f339ffecbae2c812e18a1286162d31429ce356 data/numismatics/tags/items/internal/dyes/gray_dyes.json +b6efde0135fab023b1b51f219254e5e9d7439f6a assets/numismatics/models/item/cog.json 88219edf7b658e79cfaeead5e314dab8db133f79 assets/numismatics/models/item/blue_authorized_card.json edd6109002439af0f15959debe4cb9cca254add8 data/minecraft/tags/blocks/mineable/pickaxe.json 36e1dad2803241c11c646b9737be8af6d67ef8fe data/c/tags/items/string.json @@ -95,8 +95,8 @@ b60a4818cad76e2fecad9750f7d576cf5528b5a8 assets/numismatics/models/item/red_auth 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 -0d06a3a44565e63cf98c451e7a4a6c28681d49be assets/numismatics/models/item/red_id_card.json fa326874015c5f24f6a65390c31f96324eecc96d assets/numismatics/models/item/blue_card.json +0d06a3a44565e63cf98c451e7a4a6c28681d49be assets/numismatics/models/item/red_id_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 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 385e50d9..600f8d28 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_ud.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_ud.json @@ -33,6 +33,11 @@ "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Ɐ", @@ -59,13 +64,14 @@ "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_card.tooltip.bound.no_label": "uʍouʞu∩ :ʇunoɔɔⱯ qnS", 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 fbda1ea9..e3cfdeef 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_us.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_us.json @@ -33,6 +33,11 @@ "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", @@ -59,13 +64,14 @@ "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_card.tooltip.bound.no_label": "Sub Account: Unknown", 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 81eb1480..8ea7d7d5 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 @@ -214,12 +214,12 @@ public void deposit(int amount) { } @Override - public boolean deduct(Coin coin, int amount) { + public boolean deduct(Coin coin, int amount, ReasonHolder reasonHolder) { return deduct(coin, amount, false); } @Override - public boolean deduct(int amount) { + public boolean deduct(int amount, ReasonHolder reasonHolder) { return deduct(amount, false); } @@ -371,17 +371,20 @@ public void sendSubAccountsOnlyToMenu(FriendlyByteBuf buf) { 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 void removeSubAccount(UUID subAccountID) { + public @Nullable SubAccount removeSubAccount(UUID subAccountID) { if (subAccounts == null) - return; + return null; SubAccount subAccount = subAccounts.remove(subAccountID); subAccount.setRemoved(); + NumismaticsPackets.PACKETS.sendTo(PlayerSelection.all(), BankAccountLabelPacket.remove(subAccount)); markDirty(); + return subAccount; } public boolean isClientSide() { @@ -440,19 +443,27 @@ public boolean hasSubAccounts() { return subAccounts == null ? null : subAccounts.get(subAccountID); } - public @Nullable SubAccount getSubAccount(Authorization authorization) { - if (!isAuthorized(authorization.getPersonalID())) + public @Nullable SubAccount getSubAccount(Authorization authorization, ReasonHolder reasonHolder) { + if (!isAuthorized(authorization.getPersonalID())) { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.not_authorized")); return null; + } - if (subAccounts == null) + 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) + if (subAccount == null) { + reasonHolder.setMessage(Components.translatable("error.numismatics.authorized_card.account_not_found")); return null; + } - if (!subAccount.isAuthorized(authorization)) + if (!subAccount.isAuthorized(authorization)) { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.not_authorized")); return null; + } return subAccount; } 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 index 7e5976c7..1de05b04 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/IDeductable.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/IDeductable.java @@ -19,6 +19,7 @@ package dev.ithundxr.createnumismatics.content.backend; 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; @@ -33,11 +34,11 @@ import java.util.UUID; public interface IDeductable { - boolean deduct(Coin coin, int amount); - boolean deduct(int spurs); + boolean deduct(Coin coin, int amount, ReasonHolder reasonHolder); + boolean deduct(int spurs, ReasonHolder reasonHolder); @Nullable - static IDeductable get(ItemStack stack, @Nullable Player player) { + static IDeductable get(ItemStack stack, @Nullable Player player, ReasonHolder reasonHolder) { if (NumismaticsTags.AllItemTags.CARDS.matches(stack)) { if (player == null) return null; @@ -51,13 +52,21 @@ static IDeductable get(ItemStack stack, @Nullable Player player) { 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) + if (authorizedPair == null) { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.not_bound")); return null; + } Authorization authorization; if (player == null) { @@ -70,13 +79,21 @@ static IDeductable get(ItemStack stack, @Nullable Player player) { BankAccount account = Numismatics.BANK.getAccount(authorizedPair.accountID()); - if (account == null) + if (account == null) { + reasonHolder.setMessage(Components.translatable("error.numismatics.card.account_not_found")); return null; + } - SubAccount subAccount = account.getSubAccount(authorization); + SubAccount subAccount = account.getSubAccount(authorization, reasonHolder); if (subAccount != null) { - return subAccount.getDeductor(authorization); + 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")); } } 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 3a3608f9..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 @@ -24,6 +24,7 @@ import com.simibubi.create.foundation.utility.Components; 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.coins.CoinItem; import dev.ithundxr.createnumismatics.util.ItemUtil; import dev.ithundxr.createnumismatics.util.TextUtils; @@ -112,13 +113,13 @@ 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); - IDeductable deductable = IDeductable.get(handStack, player); + IDeductable deductable = IDeductable.get(handStack, player, reasonHolder); if (deductable != null) { - if (deductable.deduct(totalPrice)) { + if (deductable.deduct(totalPrice, reasonHolder)) { //activate(state, level, pos); if (addToSource) { for (Map.Entry entry : prices.entrySet()) { 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 index d17b8328..9505ec41 100644 --- 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 @@ -18,10 +18,12 @@ 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; @@ -66,6 +68,9 @@ public SubAccount(BankAccount parentAccount, @NotNull String label, @NotNull UUI } public void setLabel(@NotNull String label) { + if (this.label.equals(label)) + return; + this.label = label; markDirty(); @@ -99,33 +104,36 @@ public void setAuthorizationType(@NotNull AuthorizationType authorizationType) { markDirty(); } - public boolean spend(Authorization authorization, Coin coin, int count) { - return spend(authorization, coin, count, false); + 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) { - return spend(authorization, coin.toSpurs(count), simulate); + 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) { - return spend(authorization, spurs, false); + public boolean spend(Authorization authorization, int spurs, ReasonHolder reasonHolder) { + return spend(authorization, spurs, false, reasonHolder); } - public boolean spend(Authorization authorization, int spurs, boolean simulate) { - if (!isAuthorized(authorization)) + 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); + parentAccount.deduct(spurs, reasonHolder); } return true; @@ -259,13 +267,13 @@ private PreAuthorizedDeductor(Authorization authorization) { } @Override - public boolean deduct(Coin coin, int amount) { - return spend(authorization, coin, amount); + public boolean deduct(Coin coin, int amount, ReasonHolder reasonHolder) { + return spend(authorization, coin, amount, reasonHolder); } @Override - public boolean deduct(int spurs) { - return spend(authorization, spurs); + public boolean deduct(int spurs, ReasonHolder reasonHolder) { + return spend(authorization, spurs, reasonHolder); } } } 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 index 8cbce42f..434199e2 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListMenu.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListMenu.java @@ -265,9 +265,11 @@ public void addSubAccount(@NotNull String label) { public void removeSubAccount(@NotNull UUID subAccountID) { if (contentHolder == null) return; - contentHolder.removeSubAccount(subAccountID); + SubAccount subAccount = contentHolder.removeSubAccount(subAccountID); if (player instanceof ServerPlayer) { + if (subAccount != null) + clearContainer(player, subAccount.getTrustListContainer()); sendUpdateToOthers(); } else { NumismaticsPackets.PACKETS.send(new RemoveSubAccountPacket(subAccountID)); 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 6a4e8db2..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,9 +19,9 @@ package dev.ithundxr.createnumismatics.content.depositor; import com.simibubi.create.AllSoundEvents; -import com.simibubi.create.foundation.utility.Components; 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.coins.CoinItem; import dev.ithundxr.createnumismatics.registry.NumismaticsBlockEntities; import dev.ithundxr.createnumismatics.util.Utils; @@ -82,17 +82,16 @@ public BlockEntityType getBlockEntityType() { Coin coin = andesiteDepositor.getCoin(); ItemStack handStack = player.getItemInHand(hand); - IDeductable deductable = IDeductable.get(handStack, player); - if (deductable != null) { - if (deductable.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/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/vendor/VendorBlockEntity.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/vendor/VendorBlockEntity.java index 5b747752..2019ed6a 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,12 +27,11 @@ 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.ReasonHolder; import dev.ithundxr.createnumismatics.content.backend.Trusted; import dev.ithundxr.createnumismatics.content.backend.behaviours.SliderStylePriceBehaviour; import dev.ithundxr.createnumismatics.content.backend.trust_list.TrustListContainer; @@ -325,7 +324,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); @@ -662,7 +661,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 +671,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 +688,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); } @@ -789,7 +790,7 @@ private void tryBuyFrom(Player player, InteractionHand hand) { return; } else if (getCardId() != null) { BankAccount account = Numismatics.BANK.getAccount(getCardId()); - if (account != null && account.isAuthorized(owner) && account.deduct(price.getTotalPrice())) { + if (account != null && account.isAuthorized(owner) && account.deduct(price.getTotalPrice(), ReasonHolder.IGNORED)) { handStack.shrink(buying.getCount()); player.setItemInHand(hand, handStack); @@ -807,10 +808,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/events/CommonEvents.java b/common/src/main/java/dev/ithundxr/createnumismatics/events/CommonEvents.java index e544f5c4..752732a2 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/events/CommonEvents.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/events/CommonEvents.java @@ -41,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); @@ -80,8 +82,11 @@ public static void onPlayerJoin(ServerPlayer player) { for (BankAccount account : Numismatics.BANK.accounts.values()) { NumismaticsPackets.PACKETS.sendTo(player, new BankAccountLabelPacket(account)); - for (SubAccount subAccount : account.getSubAccounts()) { - NumismaticsPackets.PACKETS.sendTo(player, new BankAccountLabelPacket(subAccount)); + 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/registry/packets/BankAccountLabelPacket.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/BankAccountLabelPacket.java index 699b9b24..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 @@ -42,21 +42,33 @@ public class BankAccountLabelPacket implements S2CPacket { private final String label; public BankAccountLabelPacket(FriendlyByteBuf buf) { - isSubAccount = buf.readBoolean(); - 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.isSubAccount = false; - this.id = account.id; - this.label = account.getLabel(); + this(false, account.id, account.getLabel()); } public BankAccountLabelPacket(SubAccount subAccount) { - this.isSubAccount = true; - this.id = subAccount.getAuthorizationID(); - this.label = subAccount.getLabel(); + 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 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 9a0c7fe2..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,12 +1,8 @@ { "numismatics.andesite_depositor.price": "Price", - "item.numismatics.spur": "Spur", - "item.numismatics.bevel": "Bevel", - "item.numismatics.sprocket": "Sprocket", - "item.numismatics.cog": "Cog", - "item.numismatics.crown": "Crown", - "item.numismatics.sun": "Sun", + "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", @@ -17,14 +13,16 @@ "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.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", @@ -34,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", @@ -46,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 From d6936abca5496604b7e6506db39460326ee64941 Mon Sep 17 00:00:00 2001 From: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Sun, 21 Jul 2024 07:19:34 +0200 Subject: [PATCH 3/8] more blocks now accept authorized cards --- .../content/backend/BankAccount.java | 10 +-- .../content/backend/IDeductable.java | 31 ++++++-- .../sub_authorization/Authorization.java | 4 +- .../backend/sub_authorization/Limit.java | 4 + .../backend/sub_authorization/SubAccount.java | 15 ++++ .../content/bank/AnyCardSlot.java | 69 ++++++++++++++++++ .../AbstractDepositorBlockEntity.java | 25 +++---- .../depositor/AndesiteDepositorMenu.java | 6 +- .../content/depositor/BrassDepositorMenu.java | 6 +- .../content/vendor/VendorBlockEntity.java | 41 ++++++----- .../content/vendor/VendorMenu.java | 6 +- .../textures/item/any_card_outline.png | Bin 0 -> 5827 bytes .../textures/item/any_card_outline.png.mcmeta | 9 +++ 13 files changed, 172 insertions(+), 54 deletions(-) create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/content/bank/AnyCardSlot.java create mode 100644 common/src/main/resources/assets/numismatics/textures/item/any_card_outline.png create mode 100644 common/src/main/resources/assets/numismatics/textures/item/any_card_outline.png.mcmeta 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 8ea7d7d5..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 @@ -223,6 +223,11 @@ 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); } @@ -444,11 +449,6 @@ public boolean hasSubAccounts() { } public @Nullable SubAccount getSubAccount(Authorization authorization, ReasonHolder reasonHolder) { - if (!isAuthorized(authorization.getPersonalID())) { - reasonHolder.setMessage(Components.translatable("error.numismatics.card.not_authorized")); - return null; - } - if (subAccounts == null) { 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/IDeductable.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/IDeductable.java index 1de05b04..ec46cdff 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/IDeductable.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/backend/IDeductable.java @@ -18,6 +18,7 @@ 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; @@ -31,26 +32,43 @@ 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; - if (player instanceof DeployerFakePlayer) + 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)) { + if (account != null && account.isAuthorized(player$)) { return account; } else if (account == null) { reasonHolder.setMessage(Components.translatable("error.numismatics.card.account_not_found")); @@ -71,10 +89,13 @@ static IDeductable get(ItemStack stack, @Nullable Player player, ReasonHolder re Authorization authorization; if (player == null) { authorization = new Authorization.Anonymous(authorizedPair.authorizationID()); - } else if (player instanceof DeployerFakePlayer) { - authorization = new Authorization.Deployer(player.getUUID(), authorizedPair.authorizationID()); } else { - authorization = new Authorization.Player(player, authorizedPair.authorizationID()); + 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()); 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 index 77383db2..63380b5f 100644 --- 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 @@ -61,7 +61,7 @@ public boolean isHuman() { } } - final class Deployer implements Authorization { + final class Automation implements Authorization { @Nullable private final UUID uuid; @@ -69,7 +69,7 @@ final class Deployer implements Authorization { @NotNull private final UUID authorizationID; - public Deployer(@Nullable UUID uuid, @NotNull UUID authorizationID) { + public Automation(@Nullable UUID uuid, @NotNull UUID authorizationID) { this.uuid = uuid; this.authorizationID = authorizationID; } 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 index 20913548..1b42fba9 100644 --- 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 @@ -54,6 +54,10 @@ public int getSpent() { return spent; } + public boolean hasLimit() { + return limit != null; + } + public boolean spend(int amount) { return spend(amount, false); } 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 index 9505ec41..e2750938 100644 --- 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 @@ -275,5 +275,20 @@ public boolean deduct(Coin coin, int amount, ReasonHolder reasonHolder) { 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/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/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/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/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 2019ed6a..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 @@ -29,14 +29,13 @@ import com.simibubi.create.foundation.utility.Lang; 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.ReasonHolder; -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; @@ -126,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 @@ -235,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 @@ -635,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) { @@ -788,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(), ReasonHolder.IGNORED)) { + } else { + IDeductable deductable = getDeductable(); + if (deductable != null && deductable.deduct(price.getTotalPrice(), ReasonHolder.IGNORED)) { handStack.shrink(buying.getCount()); player.setItemInHand(hand, handStack); 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/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 0000000000000000000000000000000000000000..10eb0260d877f17163a66c65dc38f97b882943b9 GIT binary patch literal 5827 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 Date: Sun, 21 Jul 2024 07:23:57 +0200 Subject: [PATCH 4/8] authorized card tooltips --- .../.cache/630af4bded938901e0e1fd57c58a2ac245292828 | 2 +- .../.cache/6ba62358bf8e130d42215f5f9edbedd611809677 | 2 +- .../.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 | 2 +- .../.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 | 10 +++++----- .../resources/assets/numismatics/lang/en_ud.json | 8 +++++--- .../resources/assets/numismatics/lang/en_us.json | 8 +++++--- .../assets/numismatics/lang/default/tooltips.json | 5 ++++- 7 files changed, 22 insertions(+), 15 deletions(-) diff --git a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 index 229a2f09..a22b117c 100644 --- a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 +++ b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 @@ -1,4 +1,4 @@ -// 1.20.1 2024-07-20T23:00:35.820097013 Create: Numismatics/Numismatics' Advancements +// 1.20.1 2024-07-21T07:23:40.160955478 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 diff --git a/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 b/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 index accf55aa..f63cf88a 100644 --- a/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 +++ b/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 @@ -1,4 +1,4 @@ -// 1.20.1 2024-07-20T23:00:35.818533487 Create: Numismatics/Numismatics Standard Recipes +// 1.20.1 2024-07-21T07:23:40.157651281 Create: Numismatics/Numismatics Standard Recipes 0e1680b878cfa51c04809504b3542cb6312027a1 data/numismatics/recipes/crafting/gray_id_card.json 61954216f844eecdbee266da7e517a983993d2f8 data/numismatics/advancements/recipes/misc/crafting/brown_card.json 2c732f9c3bc02a29a4d86a0552f4dbbae986a34a data/numismatics/recipes/crafting/blue_authorized_card.json diff --git a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 index 416e9075..f9c3ba50 100644 --- a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 +++ b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 @@ -1 +1 @@ -// 1.20.1 2024-07-20T23:00:35.819703997 Create: Numismatics/Numismatics' Sequenced Assembly Recipes +// 1.20.1 2024-07-21T07:23:40.160622716 Create: Numismatics/Numismatics' Sequenced Assembly Recipes diff --git a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 index 582dac20..aa76839c 100644 --- a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 +++ b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 @@ -1,4 +1,4 @@ -// 1.20.1 2024-07-20T23:00:35.815987106 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:23:40.153681082 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 @@ -8,7 +8,7 @@ a96d3d02794064cd9be1bca25a9ba6217675e6c5 assets/numismatics/models/item/white_id 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 -1d27f892fbc5e7c13c50ba96fadd0051c89f73a6 assets/numismatics/lang/en_us.json +2009b99f5ce622e62c2e6e92d423cc74105bdd99 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 @@ -18,7 +18,7 @@ ad712dd2a2a7268dfa773f38a50d526952758d5c data/numismatics/tags/items/internal/dy 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 -ab0fe4f0e989b51dc7500a539f4cca32f703424c assets/numismatics/lang/en_ud.json +52c516365097cefcb3dcef4967358c25b7da1185 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 @@ -53,8 +53,8 @@ bde18ccd9c21484154597c6271750c0406082f61 data/c/tags/blocks/relocation_not_suppo 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 -e1087e56db7b4d8812ab4617344f0ac8b0f0e6c7 assets/numismatics/models/item/light_gray_authorized_card.json 390db78c5393fca4f90018df51d1a79d11a64f72 assets/numismatics/models/item/light_blue_authorized_card.json +e1087e56db7b4d8812ab4617344f0ac8b0f0e6c7 assets/numismatics/models/item/light_gray_authorized_card.json c09892d2d189f147997d77f4ce39b0570729f030 assets/numismatics/models/item/lime_authorized_card.json 06ecd28cd97f4e8200dc396858695cad57b871c8 assets/numismatics/blockstates/blaze_banker.json 95ef415a564eba1d212053195d25b199427b94e3 assets/numismatics/blockstates/creative_vendor.json @@ -95,8 +95,8 @@ b60a4818cad76e2fecad9750f7d576cf5528b5a8 assets/numismatics/models/item/red_auth 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 -fa326874015c5f24f6a65390c31f96324eecc96d assets/numismatics/models/item/blue_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 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 600f8d28..a4557fbf 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_ud.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_ud.json @@ -44,8 +44,8 @@ "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.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": "", @@ -74,11 +74,13 @@ "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∩", 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 e3cfdeef..edd06136 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_us.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_us.json @@ -44,8 +44,8 @@ "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.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": "", @@ -74,11 +74,13 @@ "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_.", 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 fd8eb911..2699a173 100644 --- a/common/src/main/resources/assets/numismatics/lang/default/tooltips.json +++ b/common/src/main/resources/assets/numismatics/lang/default/tooltips.json @@ -22,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.", From 80702c670462f5864dbcb4102f9c8bfed6f29218 Mon Sep 17 00:00:00 2001 From: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Sun, 21 Jul 2024 07:29:50 +0200 Subject: [PATCH 5/8] data gen --- .../630af4bded938901e0e1fd57c58a2ac245292828 | 2 +- .../6ba62358bf8e130d42215f5f9edbedd611809677 | 2 +- .../c6e4c19894bc5aece2976a0277ba8e1dbf023865 | 2 +- .../d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 | 10 +++--- .../assets/numismatics/lang/en_ud.json | 32 +++++++++---------- .../assets/numismatics/lang/en_us.json | 32 +++++++++---------- 6 files changed, 40 insertions(+), 40 deletions(-) diff --git a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 index a22b117c..d80d9ce3 100644 --- a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 +++ b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 @@ -1,4 +1,4 @@ -// 1.20.1 2024-07-21T07:23:40.160955478 Create: Numismatics/Numismatics' Advancements +// 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 diff --git a/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 b/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 index f63cf88a..631a847c 100644 --- a/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 +++ b/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 @@ -1,4 +1,4 @@ -// 1.20.1 2024-07-21T07:23:40.157651281 Create: Numismatics/Numismatics Standard Recipes +// 1.20.1 2024-07-21T07:28:28.808884081 Create: Numismatics/Numismatics Standard Recipes 0e1680b878cfa51c04809504b3542cb6312027a1 data/numismatics/recipes/crafting/gray_id_card.json 61954216f844eecdbee266da7e517a983993d2f8 data/numismatics/advancements/recipes/misc/crafting/brown_card.json 2c732f9c3bc02a29a4d86a0552f4dbbae986a34a data/numismatics/recipes/crafting/blue_authorized_card.json diff --git a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 index f9c3ba50..6dd8ed86 100644 --- a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 +++ b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 @@ -1 +1 @@ -// 1.20.1 2024-07-21T07:23:40.160622716 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 aa76839c..c832c265 100644 --- a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 +++ b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 @@ -1,4 +1,4 @@ -// 1.20.1 2024-07-21T07:23:40.153681082 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 @@ -8,7 +8,7 @@ a96d3d02794064cd9be1bca25a9ba6217675e6c5 assets/numismatics/models/item/white_id 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 -2009b99f5ce622e62c2e6e92d423cc74105bdd99 assets/numismatics/lang/en_us.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 @@ -18,7 +18,7 @@ ad712dd2a2a7268dfa773f38a50d526952758d5c data/numismatics/tags/items/internal/dy 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 -52c516365097cefcb3dcef4967358c25b7da1185 assets/numismatics/lang/en_ud.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 @@ -53,8 +53,8 @@ bde18ccd9c21484154597c6271750c0406082f61 data/c/tags/blocks/relocation_not_suppo 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 -390db78c5393fca4f90018df51d1a79d11a64f72 assets/numismatics/models/item/light_blue_authorized_card.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 95ef415a564eba1d212053195d25b199427b94e3 assets/numismatics/blockstates/creative_vendor.json @@ -80,8 +80,8 @@ a2ff135c1fea203b49dbbf4cae010664aa1cf909 assets/numismatics/models/item/magenta_ 4a6ca666740b098929798ad132260f288cc228c0 data/numismatics/tags/items/internal/ingots/copper_ingots.json 36e1dad2803241c11c646b9737be8af6d67ef8fe data/forge/tags/items/string.json b1f339ffecbae2c812e18a1286162d31429ce356 data/numismatics/tags/items/internal/dyes/gray_dyes.json -b6efde0135fab023b1b51f219254e5e9d7439f6a assets/numismatics/models/item/cog.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 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 a4557fbf..b7768cb3 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_ud.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_ud.json @@ -87,13 +87,13 @@ "item.numismatics.bevel": "ןǝʌǝᗺ", "item.numismatics.bevel.plural": "sןǝʌǝᗺ", "item.numismatics.black_authorized_card": "pɹɐƆ pǝzıɹoɥʇnⱯ ʞɔɐןᗺ", - "item.numismatics.black_card": "pɹɐƆ ʞɔɐןᗺ", + "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ɹɐƆ ǝ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ʍoɹᗺ", + "item.numismatics.brown_card": "pɹɐƆ ʞuɐᗺ uʍoɹᗺ", "item.numismatics.brown_id_card": "pɹɐƆ ᗡI uʍoɹᗺ", "item.numismatics.card.tooltip.blank": "ʞuɐןᗺ", "item.numismatics.card.tooltip.bound": "punoᗺ", @@ -106,13 +106,13 @@ "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ɐʎƆ", + "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ɹɐƆ ʎɐɹ⅁", + "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ǝǝɹ⅁", + "item.numismatics.green_card": "pɹɐƆ ʞuɐᗺ uǝǝɹ⅁", "item.numismatics.green_id_card": "pɹɐƆ ᗡI uǝǝɹ⅁", "item.numismatics.id_card.tooltip": "ᗡᴚⱯƆ ᗡI", "item.numismatics.id_card.tooltip.already_bound": "puıqu∩ oʇ ǝs∩ + ʞɐǝuS 'punoq ʎpɐǝɹןⱯ", @@ -120,28 +120,28 @@ "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ɹɐƆ ǝ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ɹɐƆ ʎɐɹ⅁ ʇɥ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ɹɐƆ ǝɯıꞀ", + "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ǝ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ɹɐƆ ǝ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ıԀ", + "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ɹɐƆ ǝן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ɹɐƆ pǝᴚ", + "item.numismatics.red_card": "pɹɐƆ ʞuɐᗺ pǝᴚ", "item.numismatics.red_id_card": "pɹɐƆ ᗡI pǝᴚ", "item.numismatics.sprocket": "ʇǝʞɔoɹdS", "item.numismatics.sprocket.plural": "sʇǝʞɔoɹdS", @@ -150,10 +150,10 @@ "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ɹɐƆ ǝʇıɥ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ɹɐƆ ʍ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": "ǝɔıɹԀ", 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 edd06136..9ec7ed19 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_us.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_us.json @@ -87,13 +87,13 @@ "item.numismatics.bevel": "Bevel", "item.numismatics.bevel.plural": "Bevels", "item.numismatics.black_authorized_card": "Black Authorized Card", - "item.numismatics.black_card": "Black 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 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 Card", + "item.numismatics.brown_card": "Brown Bank Card", "item.numismatics.brown_id_card": "Brown ID Card", "item.numismatics.card.tooltip.blank": "Blank", "item.numismatics.card.tooltip.bound": "Bound", @@ -106,13 +106,13 @@ "item.numismatics.crown": "Crown", "item.numismatics.crown.plural": "Crowns", "item.numismatics.cyan_authorized_card": "Cyan Authorized Card", - "item.numismatics.cyan_card": "Cyan 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 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 Card", + "item.numismatics.green_card": "Green Bank Card", "item.numismatics.green_id_card": "Green ID Card", "item.numismatics.id_card.tooltip": "ID CARD", "item.numismatics.id_card.tooltip.already_bound": "Already bound, Sneak + Use to Unbind", @@ -120,28 +120,28 @@ "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 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 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 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 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 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 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 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 Card", + "item.numismatics.red_card": "Red Bank Card", "item.numismatics.red_id_card": "Red ID Card", "item.numismatics.sprocket": "Sprocket", "item.numismatics.sprocket.plural": "Sprockets", @@ -150,10 +150,10 @@ "item.numismatics.sun": "Sun", "item.numismatics.sun.plural": "Suns", "item.numismatics.white_authorized_card": "White Authorized Card", - "item.numismatics.white_card": "White 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 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", From d751b6a09a89a5dd627b88f7e62515ac25b3be38 Mon Sep 17 00:00:00 2001 From: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Sun, 21 Jul 2024 11:22:12 +0200 Subject: [PATCH 6/8] ComputerCraft API peripheral for Bank Terminal --- .../peripherals/BankTerminalPeripheral.java | 150 ++++++++++++++++++ .../createnumismatics/util/Utils.java | 11 ++ .../fabric/ComputerCraftProxyImpl.java | 53 +++++++ .../forge/ComputerCraftProxyImpl.java | 57 +++++++ 4 files changed, 271 insertions(+) create mode 100644 common/src/main/java/dev/ithundxr/createnumismatics/compat/computercraft/implementation/peripherals/BankTerminalPeripheral.java 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/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/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/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) From 271f481fbbd5454a9d1a911ebd04de1c45e7e3c5 Mon Sep 17 00:00:00 2001 From: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Sun, 21 Jul 2024 11:49:29 +0200 Subject: [PATCH 7/8] sync account label more enthusiastically --- .../createnumismatics/content/bank/SubAccountListScreen.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) 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 index a13b7d51..d6b53e88 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListScreen.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/bank/SubAccountListScreen.java @@ -211,7 +211,7 @@ protected void stopPopup() { sliders.clear(); removeWidget(editorConfirm); editorConfirm = null; - syncName(); + // syncName(); - this doesn't do anything because there's no open sub account anymore by the time this gets called hasPopup = false; init(); @@ -537,6 +537,8 @@ protected void endStencil() { @Override public boolean mouseClicked(double pMouseX, double pMouseY, int pButton) { + syncName(); + if (editorConfirm != null && editorConfirm.isMouseOver(pMouseX, pMouseY)) { editSubAccount(null); return true; From 5d95ddc08e7324e98fd03033f20d9472f3056030 Mon Sep 17 00:00:00 2001 From: techno-sam <77073745+techno-sam@users.noreply.github.com> Date: Sun, 21 Jul 2024 16:46:50 +0200 Subject: [PATCH 8/8] Update common/src/main/java/dev/ithundxr/createnumismatics/base/item/SingleCallbackContainer.java add space Co-authored-by: IThundxr --- .../createnumismatics/base/item/SingleCallbackContainer.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 index 0c54b1de..0d40e7ea 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/base/item/SingleCallbackContainer.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/item/SingleCallbackContainer.java @@ -21,7 +21,7 @@ import net.minecraft.world.Container; import net.minecraft.world.ContainerListener; -public class SingleCallbackContainer extends DelegatingContainer{ +public class SingleCallbackContainer extends DelegatingContainer { private final Container container; private final ContainerListener onChanged;