diff --git a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 index 87b0f4c9..5b7280f2 100644 --- a/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 +++ b/common/src/generated/resources/.cache/630af4bded938901e0e1fd57c58a2ac245292828 @@ -1,4 +1,4 @@ -// 1.20.1 2024-08-04T19:37:15.035886867 Create: Numismatics/Numismatics' Advancements +// 1.20.1 2024-08-05T17:31:05.743168034 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 1b9b97e0..1cba9f94 100644 --- a/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 +++ b/common/src/generated/resources/.cache/6ba62358bf8e130d42215f5f9edbedd611809677 @@ -1,4 +1,4 @@ -// 1.20.1 2024-08-04T19:37:15.034619492 Create: Numismatics/Numismatics Standard Recipes +// 1.20.1 2024-08-05T17:31:05.737487381 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 @@ -26,8 +26,8 @@ ce32a3a7c2a5564e84b30bb1b71007ca4adc985d data/numismatics/recipes/crafting/lime_ 501f27ee03faeb675a05b63b0c8058f1473f02d5 data/numismatics/advancements/recipes/misc/crafting/purple_id_card.json 8d863132d01d516db98d228e9038425923b7354d data/numismatics/recipes/crafting/black_card.json 78af0a7f17e04133eae7172df3255aaa34034537 data/numismatics/advancements/recipes/misc/crafting/red_id_card.json -86ccf10cd1549f633f99674b002c543bd46aefd0 data/numismatics/recipes/crafting/yellow_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 diff --git a/common/src/generated/resources/.cache/816056b233c115f7af92c9ed2c207f096721f5cf b/common/src/generated/resources/.cache/816056b233c115f7af92c9ed2c207f096721f5cf index 2472653a..c72f27cc 100644 --- a/common/src/generated/resources/.cache/816056b233c115f7af92c9ed2c207f096721f5cf +++ b/common/src/generated/resources/.cache/816056b233c115f7af92c9ed2c207f096721f5cf @@ -1,2 +1,2 @@ -// 1.20.1 2024-08-04T19:37:15.031552342 Create: Numismatics/Numismatics EMI excluded tags +// 1.20.1 2024-08-05T17:31:05.725976583 Create: Numismatics/Numismatics EMI excluded tags b57edab6f7e7a6e1b1211daa4c3b217ffd09ce62 assets/emi/tag/exclusions/numismatics.json diff --git a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 index 1dcddd2b..db363452 100644 --- a/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 +++ b/common/src/generated/resources/.cache/c6e4c19894bc5aece2976a0277ba8e1dbf023865 @@ -1 +1 @@ -// 1.20.1 2024-08-04T19:37:15.035644417 Create: Numismatics/Numismatics' Sequenced Assembly Recipes +// 1.20.1 2024-08-05T17:31:05.741816291 Create: Numismatics/Numismatics' Sequenced Assembly Recipes diff --git a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 index 907cb1b4..993e65dc 100644 --- a/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 +++ b/common/src/generated/resources/.cache/d6a1ec2d08c6d6d7facbde77dda6f0158c00bbd6 @@ -1,4 +1,4 @@ -// 1.20.1 2024-08-04T19:37:15.03270554 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-08-05T17:31:05.729416827 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 -7792957fb81474e92aea29bb69c435866fcc25ae assets/numismatics/lang/en_us.json +3346bd25775d94025b9cc65c03d9a7151d316355 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 -d780766e58a270fc111ee7517399d209168b8e8f assets/numismatics/lang/en_ud.json +8343a58fb3d5ce9eeecabdeaa911eccae29409d1 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 @@ -56,8 +56,8 @@ d048d04208faa63f0014d614d6026a66fe118c11 data/numismatics/loot_tables/blocks/bra 790ff3c5da6a67a5de1ceb7138fa3e1c0fe97f80 data/numismatics/tags/items/internal/dyes/lime_dyes.json 5cfb64f42dbeaa0720a7dd952e47d638c17a1056 assets/numismatics/models/block/salepoint.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 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 df1f8458..1e646614 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_ud.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_ud.json @@ -66,10 +66,14 @@ "gui.numismatics.limit.none": "ʇıɯıן oN", "gui.numismatics.salepoint.cancel": "uoıʇɔɐsuɐɹʇ ןǝɔuɐƆ", "gui.numismatics.salepoint.count": "sʇıu∩", + "gui.numismatics.salepoint.fluid_empty": "ʎʇdɯƎ", + "gui.numismatics.salepoint.fluid_filter_empty.0": "ɹǝʇןıℲ pınןℲ", + "gui.numismatics.salepoint.fluid_filter_empty.1": "ǝןʇʇoq ɐ ɹo ʇǝʞɔnq ɐ sɐ ɥɔns ɯǝʇı buıpןoɥ-pınןɟ ɐ ɥʇıʍ ʞɔıןƆ", "gui.numismatics.salepoint.go": "uoıʇɔɐsuɐɹʇ ʇɹɐʇS", "gui.numismatics.salepoint.insufficient_space": "ןןnɟ sı ʇǝbɹɐ⟘", "gui.numismatics.salepoint.invalid_state": "ǝʇɐʇs pıןɐʌuI", "gui.numismatics.salepoint.no_card": "pɹɐɔ oN", + "gui.numismatics.salepoint.no_filter": "ɹǝʇןıɟ oN", "gui.numismatics.salepoint.no_state": "pǝɹnbıɟuoɔ ʇoN", "gui.numismatics.salepoint.no_target": "punoɟ ʇou ʇǝbɹɐ⟘", "gui.numismatics.salepoint.price": "¤%s '%s %s :ʇıu∩/ǝɔıɹԀ", 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 db19c046..1d65fe92 100644 --- a/common/src/generated/resources/assets/numismatics/lang/en_us.json +++ b/common/src/generated/resources/assets/numismatics/lang/en_us.json @@ -66,10 +66,14 @@ "gui.numismatics.limit.none": "No limit", "gui.numismatics.salepoint.cancel": "Cancel transaction", "gui.numismatics.salepoint.count": "Units", + "gui.numismatics.salepoint.fluid_empty": "Empty", + "gui.numismatics.salepoint.fluid_filter_empty.0": "Fluid Filter", + "gui.numismatics.salepoint.fluid_filter_empty.1": "Click with a fluid-holding item such as a bucket or a bottle", "gui.numismatics.salepoint.go": "Start transaction", "gui.numismatics.salepoint.insufficient_space": "Target is full", "gui.numismatics.salepoint.invalid_state": "Invalid state", "gui.numismatics.salepoint.no_card": "No card", + "gui.numismatics.salepoint.no_filter": "No filter", "gui.numismatics.salepoint.no_state": "Not configured", "gui.numismatics.salepoint.no_target": "Target not found", "gui.numismatics.salepoint.price": "Price/Unit: %s %s, %s¤", diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/base/client/rendering/IItemApplicableWidget.java b/common/src/main/java/dev/ithundxr/createnumismatics/base/client/rendering/IItemApplicableWidget.java new file mode 100644 index 00000000..fb01429d --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/client/rendering/IItemApplicableWidget.java @@ -0,0 +1,25 @@ +/* + * 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 net.minecraft.world.item.ItemStack; + +public interface IItemApplicableWidget { + void onItemApplied(ItemStack stack); +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/base/client/rendering/ISalepointStateUpdatingWidget.java b/common/src/main/java/dev/ithundxr/createnumismatics/base/client/rendering/ISalepointStateUpdatingWidget.java new file mode 100644 index 00000000..9b287e04 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/base/client/rendering/ISalepointStateUpdatingWidget.java @@ -0,0 +1,25 @@ +/* + * 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 dev.ithundxr.createnumismatics.content.salepoint.states.ISalepointState; + +public interface ISalepointStateUpdatingWidget { + void updateState(ISalepointState state); +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointConfigMenu.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointConfigMenu.java index bb8a877c..1a646dc1 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointConfigMenu.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointConfigMenu.java @@ -61,6 +61,7 @@ public SalepointConfigMenu(MenuType type, int id, Inventory inv, SalepointBlo } @Override + @SuppressWarnings("DataFlowIssue") protected SalepointBlockEntity createOnClient(FriendlyByteBuf extraData) { ClientLevel world = Minecraft.getInstance().level; BlockEntity blockEntity = world.getBlockEntity(extraData.readBlockPos()); @@ -122,7 +123,7 @@ public boolean canTakeItemForPickAll(@NotNull ItemStack stack, Slot slot) { } @Override - public void clicked(int slotId, int button, ClickType clickType, Player player) { + public void clicked(int slotId, int button, @NotNull ClickType clickType, Player player) { ItemStack held = getCarried(); Inventory inventory = player.getInventory(); ISalepointState salepointState = getSalepointState(); @@ -217,7 +218,7 @@ public void setSynchronizer(@NotNull ContainerSynchronizer synchronizer) { super.setSynchronizer(synchronizer); } - protected @Nullable ISalepointState getSalepointState() { + public @Nullable ISalepointState getSalepointState() { if (contentHolder.salepointState == null) return null; return contentHolder.salepointState.state(); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointConfigScreen.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointConfigScreen.java index f23ac541..1f12c423 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointConfigScreen.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointConfigScreen.java @@ -29,6 +29,8 @@ import com.simibubi.create.foundation.gui.widget.ScrollInput; import com.simibubi.create.foundation.utility.Components; import com.simibubi.create.foundation.utility.Couple; +import dev.ithundxr.createnumismatics.base.client.rendering.IItemApplicableWidget; +import dev.ithundxr.createnumismatics.base.client.rendering.ISalepointStateUpdatingWidget; import dev.ithundxr.createnumismatics.config.NumismaticsConfig; import dev.ithundxr.createnumismatics.content.backend.Coin; import dev.ithundxr.createnumismatics.content.backend.behaviours.SliderStylePriceConfigurationPacket; @@ -39,6 +41,10 @@ import dev.ithundxr.createnumismatics.registry.packets.ScrollSlotPacket; import dev.ithundxr.createnumismatics.util.TextUtils; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.components.Renderable; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.renderer.Rect2i; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.player.Inventory; @@ -62,6 +68,8 @@ public class SalepointConfigScreen extends AbstractSimiContainerScreen extraAreas = Collections.emptyList(); public SalepointConfigScreen(SalepointConfigMenu container, Inventory inv, Component title) { @@ -82,9 +90,7 @@ protected void init() { int y = topPos; trustListButton = new IconButton(x + 16, y + background.height - 24, AllIcons.I_VIEW_SCHEDULE); - trustListButton.withCallback(() -> { - menu.contentHolder.openTrustList(); - }); + trustListButton.withCallback(() -> menu.contentHolder.openTrustList()); addRenderableWidget(trustListButton); confirmButton = new IconButton(x + background.width - 33, y + background.height - 24, AllIcons.I_CONFIRM); @@ -118,11 +124,19 @@ protected void init() { ISalepointState salepointState = getSalepointState(); if (salepointState != null) - salepointState.createConfigWidgets(this::addRenderableWidget); + salepointState.createConfigWidgets(this::addRenderableWidgetOffset); extraAreas = ImmutableList.of(new Rect2i(x + background.width, y + background.height - 68, 84, 84)); } + private T addRenderableWidgetOffset(T widget) { + if (widget instanceof AbstractWidget abstractWidget) { + abstractWidget.setX(abstractWidget.getX() + leftPos); + abstractWidget.setY(abstractWidget.getY() + topPos); + } + return addRenderableWidget(widget); + } + @Override public List getExtraAreas() { return extraAreas; @@ -185,6 +199,50 @@ public boolean mouseScrolled(double mouseX, double mouseY, double delta) { return super.mouseScrolled(mouseX, mouseY, delta); } + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + if (button == 0 && !menu.getCarried().isEmpty()) { + for (GuiEventListener widget : this.children()) { + if (widget.isMouseOver(mouseX, mouseY) && widget instanceof IItemApplicableWidget itemApplicableWidget) { + itemApplicableWidget.onItemApplied(menu.getCarried()); + } + } + } + + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public boolean mouseDragged(double mouseX, double mouseY, int button, double dragX, double dragY) { + wasDragging = true; + return super.mouseDragged(mouseX, mouseY, button, dragX, dragY); + } + + @Override + public boolean mouseReleased(double mouseX, double mouseY, int button) { + if (button == 0 && wasDragging && !menu.getCarried().isEmpty()) { + for (GuiEventListener widget : this.children()) { + if (widget.isMouseOver(mouseX, mouseY) && widget instanceof IItemApplicableWidget itemApplicableWidget) { + itemApplicableWidget.onItemApplied(menu.getCarried()); + } + } + } + + wasDragging = false; + + return super.mouseReleased(mouseX, mouseY, button); + } + + @Override + protected void containerTick() { + super.containerTick(); + for (GuiEventListener widget : this.children()) { + if (widget instanceof ISalepointStateUpdatingWidget salepointStateUpdatingWidget) { + salepointStateUpdatingWidget.updateState(getSalepointState()); + } + } + } + @Override public void removed() { NumismaticsPackets.PACKETS.send(new SliderStylePriceConfigurationPacket(menu.contentHolder)); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointPurchaseScreen.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointPurchaseScreen.java index 2f4b888a..bfbe5c0a 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointPurchaseScreen.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/SalepointPurchaseScreen.java @@ -40,6 +40,10 @@ import dev.ithundxr.createnumismatics.registry.packets.SalepointPurchasePacket; import dev.ithundxr.createnumismatics.util.TextUtils; import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.gui.components.AbstractWidget; +import net.minecraft.client.gui.components.Renderable; +import net.minecraft.client.gui.components.events.GuiEventListener; +import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.renderer.Rect2i; import net.minecraft.network.chat.Component; import net.minecraft.util.FormattedCharSequence; @@ -107,12 +111,20 @@ protected void init() { ISalepointState salepointState = getSalepointState(); if (salepointState != null) - salepointState.createPurchaseWidgets(this::addRenderableWidget); + salepointState.createPurchaseWidgets(this::addRenderableWidgetOffset); extraAreas = ImmutableList.of(new Rect2i(x + background.width, y + background.height - 68, 84, 84)); updateAction(); } + private T addRenderableWidgetOffset(T widget) { + if (widget instanceof AbstractWidget abstractWidget) { + abstractWidget.setX(abstractWidget.getX() + leftPos); + abstractWidget.setY(abstractWidget.getY() + topPos); + } + return addRenderableWidget(widget); + } + @Override public List getExtraAreas() { return extraAreas; @@ -233,7 +245,6 @@ private void onAction() { } } - @SuppressWarnings("DataFlowIssue") private void updateAction() { action = Action.GO; Component alert = Components.translatable("gui.numismatics.salepoint.go"); diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/behaviours/FluidSalepointTargetBehaviour.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/behaviours/FluidSalepointTargetBehaviour.java new file mode 100644 index 00000000..688c58fd --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/behaviours/FluidSalepointTargetBehaviour.java @@ -0,0 +1,42 @@ +/* + * 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.salepoint.behaviours; + +import com.simibubi.create.foundation.blockEntity.SmartBlockEntity; +import dev.ithundxr.createnumismatics.content.salepoint.states.ISalepointState; +import dev.ithundxr.createnumismatics.content.salepoint.states.SalepointTypes; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class FluidSalepointTargetBehaviour extends SalepointTargetBehaviour { + public FluidSalepointTargetBehaviour(SmartBlockEntity be) { + super(be); + } + + @Override + protected @Nullable ISalepointState tryBindToSalepointInternal() { + return SalepointTypes.FLUID.create(); + } + + @Override + protected @NotNull Class getContentType() { + return MultiloaderFluidStack.class; + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/behaviours/ItemSalepointTargetBehaviour.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/behaviours/ItemSalepointTargetBehaviour.java index ea3fc790..e970a964 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/behaviours/ItemSalepointTargetBehaviour.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/behaviours/ItemSalepointTargetBehaviour.java @@ -22,6 +22,7 @@ import dev.ithundxr.createnumismatics.content.salepoint.states.ISalepointState; import dev.ithundxr.createnumismatics.content.salepoint.states.SalepointTypes; import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; public abstract class ItemSalepointTargetBehaviour extends SalepointTargetBehaviour { @@ -36,7 +37,7 @@ public ItemSalepointTargetBehaviour(SmartBlockEntity be) { } @Override - protected Class getContentType() { + protected @NotNull Class getContentType() { return ItemStack.class; } } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/InvalidatableAbstractBuffer.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/InvalidatableAbstractBuffer.java index 1021810a..73d2c160 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/InvalidatableAbstractBuffer.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/InvalidatableAbstractBuffer.java @@ -68,4 +68,14 @@ public final int copyToBuffer(C source, boolean simulate) { * @return The number of elements copied. */ protected abstract int copyToBufferInternal(C source, boolean simulate); + + /** + * Remove as much as possible of the source element from the buffer, up to maxAmount, i.e. ignoring source's size.
+ * Note: It is the caller's responsibility to modify the source, + * the implementor MUST NOT modify the source argument + * @param source The source to remove. + * @param simulate If true, the caller MUST NOT actually remove the element from its buffer + * @return The number of elements removed. + */ + protected abstract int removeFromBufferInternal(C source, boolean simulate, final int maxAmount); } diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/InvalidatableWrappingItemBuffer.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/InvalidatableWrappingItemBuffer.java index 3466448d..094dde35 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/InvalidatableWrappingItemBuffer.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/InvalidatableWrappingItemBuffer.java @@ -67,6 +67,7 @@ public boolean canPlaceItem(int index, @NotNull ItemStack stack) { return 0; } + @Override protected int removeFromBufferInternal(ItemStack source, boolean simulate, final int maxAmount) { SimpleContainer buffer = this.buffer; if (simulate) { // lazy but it works diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/FluidSalepointState.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/FluidSalepointState.java new file mode 100644 index 00000000..c44a7bf6 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/FluidSalepointState.java @@ -0,0 +1,233 @@ +/* + * 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.salepoint.states; + +import com.simibubi.create.foundation.utility.Components; +import dev.architectury.injectables.annotations.ExpectPlatform; +import dev.ithundxr.createnumismatics.content.backend.ReasonHolder; +import dev.ithundxr.createnumismatics.content.salepoint.behaviours.SalepointTargetBehaviour; +import dev.ithundxr.createnumismatics.content.salepoint.widgets.SalepointFluidConfigWidget; +import dev.ithundxr.createnumismatics.content.salepoint.widgets.SalepointFluidDisplayWidget; +import dev.ithundxr.createnumismatics.multiloader.fluid.FluidUnits; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; +import java.util.UUID; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +public abstract class FluidSalepointState implements ISalepointState { + + private UUID uuid; + private @NotNull MultiloaderFluidStack filter = MultiloaderFluidStack.EMPTY; + private @Nullable Runnable changedCallback; + + @ExpectPlatform + public static FluidSalepointState create() { + throw new AssertionError(); + } + + @Override + public void init() { + uuid = UUID.randomUUID(); + } + + @Override + public final SalepointTypes getType() { + return SalepointTypes.FLUID; + } + + @Override + public final UUID getId() { + return uuid; + } + + @Override + public final boolean canChangeFilterTo(MultiloaderFluidStack filter) { + return (this.filter.isFluidEqual(filter) && !filter.isEmpty()) || canChangeFilterToInternal(filter); + } + + protected abstract boolean canChangeFilterToInternal(MultiloaderFluidStack filter); + + @Override + public final boolean setFilter(MultiloaderFluidStack filter, Level salepointLevel, BlockPos salepointPos, @Nullable Player player) { + if (!canChangeFilterTo(filter)) + return false; + + setFilterInternal(filter, salepointLevel, salepointPos, player); + this.filter = filter.copy(); + + setChanged(); + + return true; + } + + protected abstract void setFilterInternal(MultiloaderFluidStack filter, Level salepointLevel, BlockPos salepointPos, @Nullable Player player); + + @Override + public final MultiloaderFluidStack getFilter() { + return filter.copy(); + } + + @Override + public boolean filterMatches(MultiloaderFluidStack object) { + return filter.isFluidEqual(object); + } + + @Override + public final CompoundTag save() { + CompoundTag tag = new CompoundTag(); + tag.putString("id", getType().getId()); + tag.putUUID("UUID", uuid); + + saveInternal(tag); + + if (!filter.isEmpty()) + tag.put("Filter", filter.writeToNBT(new CompoundTag())); + + return tag; + } + + protected abstract void saveInternal(CompoundTag tag); + + @Override + public final void load(CompoundTag tag) { + uuid = tag.getUUID("UUID"); + + loadInternal(tag); + + if (tag.contains("Filter", CompoundTag.TAG_COMPOUND)) + filter = MultiloaderFluidStack.loadFluidStackFromNBT(tag.getCompound("Filter")); + else + filter = MultiloaderFluidStack.EMPTY; + } + + protected abstract void loadInternal(CompoundTag tag); + + @Override + public final boolean isValidForPurchase(Level level, BlockPos targetedPos, ReasonHolder reasonHolder) { + SalepointTargetBehaviour behaviour = getBehaviour(level, targetedPos); + return isValidForPurchase(behaviour, reasonHolder); + } + + protected abstract boolean hasBufferFluidForPurchase(); + + protected abstract List removeBufferFluidForPurchase(); + + private boolean isValidForPurchase(@Nullable SalepointTargetBehaviour behaviour, ReasonHolder reasonHolder) { + if (behaviour == null) { + reasonHolder.setMessage(Components.translatable("gui.numismatics.salepoint.no_target")); + return false; + } + + if (!behaviour.isUnderControl(this)) { + reasonHolder.setMessage(Components.translatable("gui.numismatics.salepoint.target_not_controlled")); + return false; + } + + if (filter.isEmpty()) { + reasonHolder.setMessage(Components.translatable("gui.numismatics.salepoint.no_filter")); + return false; + } + + if (!hasBufferFluidForPurchase()) { + reasonHolder.setMessage(Components.translatable("gui.numismatics.vendor.out_of_stock")); + return false; + } + + if (!behaviour.hasSpaceFor(filter.copy())) { + reasonHolder.setMessage(Components.translatable("gui.numismatics.salepoint.insufficient_space")); + return false; + } + + return true; + } + + @Override + public final boolean doPurchase(Level level, BlockPos targetedPos, ReasonHolder reasonHolder) { + SalepointTargetBehaviour behaviour = getBehaviour(level, targetedPos); + if (behaviour == null) { + reasonHolder.setMessage(Components.translatable("gui.numismatics.salepoint.no_target")); + return false; + } + + if (!isValidForPurchase(behaviour, reasonHolder)) + return false; + + if (!behaviour.doPurchase(filter.copy(), this::removeBufferFluidForPurchase)) { + reasonHolder.setMessage(Components.translatable("gui.numismatics.salepoint.target_failed_purchase")); + return false; + } + + return true; + } + + @Override + public final void ensureUnderControl(Level level, BlockPos targetedPos) { + SalepointTargetBehaviour behaviour = getBehaviour(level, targetedPos); + if (behaviour == null) + return; + + behaviour.ensureUnderControl(this); + } + + @Override + public final void relinquishControl(Level level, BlockPos targetedPos) { + SalepointTargetBehaviour behaviour = getBehaviour(level, targetedPos); + if (behaviour == null) + return; + + behaviour.relinquishControl(this); + } + + @Override + public void setChangedCallback(Runnable callback) { + this.changedCallback = callback; + } + + protected void setChanged() { + if (changedCallback != null) + changedCallback.run(); + } + + @Override + @Environment(EnvType.CLIENT) + public void createConfigWidgets(WidgetConsumer widgetConsumer) { + widgetConsumer.addRenderableWidget(new SalepointFluidConfigWidget(100, 54, this)); + } + + @Override + public void createPurchaseWidgets(WidgetConsumer widgetConsumer) { + widgetConsumer.addRenderableWidget(new SalepointFluidDisplayWidget(68, 55, this)); + } + + public static long getFilterCapacity() { + return FluidUnits.bucket() * 4; + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/ItemSalepointState.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/ItemSalepointState.java index e9b3ad73..8a35602f 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/ItemSalepointState.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/ItemSalepointState.java @@ -70,9 +70,7 @@ public boolean canPlaceItem(int index, ItemStack stack) { private @Nullable Runnable changedCallback; ItemSalepointState() { - buffer.addListener($ -> { - setChanged(); - }); + buffer.addListener($ -> setChanged()); } @ExpectPlatform @@ -139,7 +137,7 @@ public boolean setFilter(ItemStack filter, Level salepointLevel, BlockPos salepo } setChanged(); - return false; + return true; } @Override @@ -390,6 +388,11 @@ private boolean isValidForPurchase(@Nullable SalepointTargetBehaviour return false; } + if (filter.isEmpty()) { + reasonHolder.setMessage(Components.translatable("gui.numismatics.salepoint.no_filter")); + return false; + } + if (!hasBufferItemsForPurchase()) { reasonHolder.setMessage(Components.translatable("gui.numismatics.vendor.out_of_stock")); return false; diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/SalepointTypes.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/SalepointTypes.java index 25736d3d..e462f29c 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/SalepointTypes.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/SalepointTypes.java @@ -18,6 +18,7 @@ package dev.ithundxr.createnumismatics.content.salepoint.states; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; import org.jetbrains.annotations.Contract; @@ -26,6 +27,7 @@ public enum SalepointTypes { ITEM(ItemSalepointState::new, ItemStack.class), + FLUID(FluidSalepointState::create, MultiloaderFluidStack.class), ; @NotNull diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/SalepointFluidConfigWidget.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/SalepointFluidConfigWidget.java new file mode 100644 index 00000000..45a85ece --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/SalepointFluidConfigWidget.java @@ -0,0 +1,138 @@ +/* + * 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.salepoint.widgets; + +import com.simibubi.create.AllKeys; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.foundation.utility.Components; +import dev.architectury.injectables.annotations.ExpectPlatform; +import dev.ithundxr.createnumismatics.base.client.rendering.IItemApplicableWidget; +import dev.ithundxr.createnumismatics.content.salepoint.states.FluidSalepointState; +import dev.ithundxr.createnumismatics.multiloader.fluid.FluidUnits; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import dev.ithundxr.createnumismatics.registry.NumismaticsGuiTextures; +import dev.ithundxr.createnumismatics.registry.NumismaticsPackets; +import dev.ithundxr.createnumismatics.registry.packets.SalepointFluidFilterPacket; +import dev.ithundxr.createnumismatics.util.TextUtils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.sounds.SimpleSoundInstance; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +public class SalepointFluidConfigWidget extends SalepointFluidDisplayWidget implements IItemApplicableWidget { + + private boolean soundPlayed; + + public SalepointFluidConfigWidget(int x, int y, @NotNull FluidSalepointState state) { + super(x, y, state); + } + + @Override + protected NumismaticsGuiTextures getBackground() { + return NumismaticsGuiTextures.SALEPOINT_CONFIG_FLUID_BG; + } + + @Override + protected NumismaticsGuiTextures getForeground() { + return NumismaticsGuiTextures.SALEPOINT_CONFIG_FLUID_FG; + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double delta) { + MultiloaderFluidStack filter = state.getFilter(); + if (filter.isEmpty()) + return false; + + int offset = delta > 0 ? 1 : -1; + + if (AllKeys.shiftDown() && AllKeys.ctrlDown()) + //noinspection DataFlowIssue + offset *= 1; + else if (AllKeys.ctrlDown()) + offset *= 10; + else if (AllKeys.shiftDown()) + offset *= 1000; + else + offset *= 100; + + offset = (int) ((long) offset * FluidUnits.bucket() / 1000); + + long oldAmount = filter.getAmount(); + long min = 0; + long max = FluidSalepointState.getFilterCapacity(); + long amount = Math.max(min, Math.min(oldAmount + offset, max)); + if (oldAmount != amount) { + NumismaticsPackets.PACKETS.send(new SalepointFluidFilterPacket(filter.copy().setAmount(amount))); + if (!soundPlayed) { + Minecraft.getInstance() + .getSoundManager() + .play(SimpleSoundInstance.forUI(AllSoundEvents.SCROLL_VALUE.getMainEvent(), + 1.5f + 0.1f * (amount - min) / (max - min))); + soundPlayed = true; + } + return true; + } + + return false; + } + + @Override + public void tick() { + super.tick(); + soundPlayed = false; + } + + @Override + public void onItemApplied(ItemStack stack) { + MultiloaderFluidStack fluidStack = getFluidFrom(stack); + if (fluidStack != null) { + NumismaticsPackets.PACKETS.send(new SalepointFluidFilterPacket(fluidStack)); + this.playDownSound(Minecraft.getInstance().getSoundManager()); + } + } + + @ExpectPlatform + @Environment(EnvType.CLIENT) + protected static @Nullable MultiloaderFluidStack getFluidFrom(@NotNull ItemStack stack) { + throw new AssertionError(); + } + + @Override + public List getToolTip() { + MultiloaderFluidStack filter = state.getFilter(); + if (filter.isEmpty()) + return List.of( + Components.translatable("gui.numismatics.salepoint.fluid_filter_empty.0"), + Components.translatable("gui.numismatics.salepoint.fluid_filter_empty.1") + ); + + return List.of( + filter.getDisplayName(), + Components.literal(TextUtils.formatFluid(filter.getAmount())), + Components.translatable("create.gui.scrollInput.scrollToAdjustAmount"), + Components.translatable("create.gui.scrollInput.shiftScrollsFaster") + ); + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/SalepointFluidDisplayWidget.java b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/SalepointFluidDisplayWidget.java new file mode 100644 index 00000000..b337d6ad --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/SalepointFluidDisplayWidget.java @@ -0,0 +1,178 @@ +/* + * 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.salepoint.widgets; + +import com.mojang.blaze3d.platform.Lighting; +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.gui.CustomLightingSettings; +import com.simibubi.create.foundation.gui.ILightingSettings; +import com.simibubi.create.foundation.gui.widget.AbstractSimiWidget; +import com.simibubi.create.foundation.utility.Components; +import dev.architectury.injectables.annotations.ExpectPlatform; +import dev.ithundxr.createnumismatics.base.client.rendering.ISalepointStateUpdatingWidget; +import dev.ithundxr.createnumismatics.content.salepoint.states.FluidSalepointState; +import dev.ithundxr.createnumismatics.content.salepoint.states.ISalepointState; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import dev.ithundxr.createnumismatics.registry.NumismaticsGuiTextures; +import dev.ithundxr.createnumismatics.util.TextUtils; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.LightTexture; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +public class SalepointFluidDisplayWidget extends AbstractSimiWidget implements ISalepointStateUpdatingWidget { + + public static final ILightingSettings DEFAULT_LIGHTING = CustomLightingSettings.builder() + .firstLightRotation(12.5f, 135.0f) + .secondLightRotation(-20.0f, 140.0f) + .build(); + + protected @NotNull FluidSalepointState state; + + public SalepointFluidDisplayWidget(int x, int y, @NotNull FluidSalepointState state) { + super(x, y, 28, 28); + this.state = state; + } + + protected NumismaticsGuiTextures getBackground() { + return NumismaticsGuiTextures.SALEPOINT_PURCHASE_FLUID_BG; + } + + protected NumismaticsGuiTextures getForeground() { + return NumismaticsGuiTextures.SALEPOINT_PURCHASE_FLUID_FG; + } + + @Override + protected void doRender(@NotNull GuiGraphics graphics, int mouseX, int mouseY, float partialTicks) { + int x = getX(); + int y = getY(); + PoseStack ms = graphics.pose(); + + getBackground().render(graphics, x, y); + + MultiloaderFluidStack filter = state.getFilter(); + if (!filter.isEmpty()) { + ms.pushPose(); + ms.translate(0, 0, 10); + + boolean top = filter.isLighterThanAir(); + + float level = (float) filter.getAmount() / (float) FluidSalepointState.getFilterCapacity(); + + float xMin = x; + float xMax = x + getWidth(); + float yMin = y + (1.0f - level) * (getHeight() - 4) + 2; + float yMax = y + getHeight() - 2; + + if (top) { + yMin = y + 2; + yMax = y + level * (getHeight() - 4) - 2; + } + + float zMin = 1; + float zMax = 9; + + xMin /= 16f; + xMax /= 16f; + yMin /= 16f; + yMax /= 16f; + zMin /= 16f; + zMax /= 16f; + + { + DEFAULT_LIGHTING.applyLighting(); + + ms.pushPose(); + ms.scale(16, 16, 16); + + float xOffset = (xMin + xMax) / 2; + float yOffset = (yMin + yMax) / 2; + float zOffset = (zMin + zMax) / 2; + + ms.translate(xOffset, yOffset, zOffset); + + xMin -= xOffset; + xMax -= xOffset; + yMin -= yOffset; + yMax -= yOffset; + zMin -= zOffset; + zMax -= zOffset; + + DEFAULT_LIGHTING.applyLighting(); + + renderFluidBox(filter, xMin, yMin, zMin, xMax, yMax, zMax, graphics.bufferSource(), ms, LightTexture.FULL_BRIGHT, false); + graphics.bufferSource().endBatch(); + + ms.popPose(); + + Lighting.setupFor3DItems(); + } + + ms.popPose(); + } + + { + ms.pushPose(); + ms.translate(0, 0, 20); + + getForeground().render(graphics, x, y); + + ms.popPose(); + } + } + + @Override + public void updateState(ISalepointState state) { + if (state instanceof FluidSalepointState fluidSalepointState) + this.state = fluidSalepointState; + } + + @Override + protected boolean clicked(double mouseX, double mouseY) { + return false; + } + + @Override + public List getToolTip() { + MultiloaderFluidStack filter = state.getFilter(); + if (filter.isEmpty()) + return List.of( + Components.translatable("gui.numismatics.salepoint.fluid_empty") + ); + + return List.of( + filter.getDisplayName(), + Components.literal(TextUtils.formatFluid(filter.getAmount())) + ); + } + + @ExpectPlatform + @Environment(EnvType.CLIENT) + @SuppressWarnings("SameParameterValue") + protected static void renderFluidBox(@NotNull MultiloaderFluidStack fluidStack, float xMin, float yMin, float zMin, + float xMax, float yMax, float zMax, @NotNull MultiBufferSource buffer, + @NotNull PoseStack ms, int light, boolean renderBottom) { + throw new AssertionError(); + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/FluidUnits.java b/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/FluidUnits.java new file mode 100644 index 00000000..cd6db110 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/FluidUnits.java @@ -0,0 +1,28 @@ +/* + * 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.multiloader.fluid; + +import dev.architectury.injectables.annotations.ExpectPlatform; + +public class FluidUnits { + @ExpectPlatform + public static long bucket() { + throw new AssertionError(); + } +} diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/MultiloaderFluidStack.java b/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/MultiloaderFluidStack.java new file mode 100644 index 00000000..bcee4017 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/MultiloaderFluidStack.java @@ -0,0 +1,162 @@ +/* + * 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.multiloader.fluid; + +import com.mojang.serialization.Codec; +import dev.architectury.injectables.annotations.ExpectPlatform; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.material.Fluid; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public abstract class MultiloaderFluidStack { + + @ExpectPlatform + private static Codec makeCodec() { + throw new AssertionError(); + } + + @ExpectPlatform + private static MultiloaderFluidStack makeEmpty() { + throw new AssertionError(); + } + + public static final Codec CODEC = makeCodec(); + + public static final MultiloaderFluidStack EMPTY = makeEmpty(); + + public static MultiloaderFluidStack create(Fluid fluid, long amount) { + return create(fluid, amount, null); + } + + @ExpectPlatform + public static MultiloaderFluidStack create(Fluid fluid, long amount, @Nullable CompoundTag nbt) { + throw new AssertionError(); + } + + public abstract MultiloaderFluidStack setAmount(long amount); + + public void grow(long amount) { + setAmount(getAmount() + amount); + } + + public abstract Fluid getFluid(); + + public abstract long getAmount(); + + public abstract boolean isEmpty(); + + public void shrink(int amount) { + setAmount(getAmount() - amount); + } + + public void shrink(long amount) { + setAmount(getAmount() - amount); + } + + /** + * Determines if the FluidIDs and NBT Tags are equal. This does not check amounts. + * + * @param other + * The FluidStack for comparison + * @return true if the Fluids (IDs and NBT Tags) are the same + */ + public abstract boolean isFluidEqual(MultiloaderFluidStack other); + + public abstract CompoundTag writeToNBT(CompoundTag nbt); + + @ExpectPlatform + public static MultiloaderFluidStack loadFluidStackFromNBT(CompoundTag tag) { + throw new AssertionError(); + } + + public abstract void setTag(CompoundTag tag); + + @Nullable + public abstract CompoundTag getTag(); + + public CompoundTag getOrCreateTag() { + if (getTag() == null) setTag(new CompoundTag()); + return getTag(); + } + + public void removeChildTag(String key) { + if (getTag() == null) return; + getTag().remove(key); + } + + public abstract Component getDisplayName(); + + public boolean hasTag() { + return getTag() != null; + } + + @ExpectPlatform + public static MultiloaderFluidStack readFromPacket(FriendlyByteBuf buffer) { + throw new AssertionError(); + } + + public abstract FriendlyByteBuf writeToPacket(FriendlyByteBuf buffer); + + public abstract MultiloaderFluidStack copy(); + + private boolean isFluidStackTagEqual(MultiloaderFluidStack other) { + CompoundTag tag = getTag(); + CompoundTag other$tag = other.getTag(); + return tag == null ? other$tag == null : other$tag != null && tag.equals(other$tag); + } + + /** + * Determines if the NBT Tags are equal. Useful if the FluidIDs are known to be equal. + */ + public static boolean areFluidStackTagsEqual(@NotNull MultiloaderFluidStack stack1, @NotNull MultiloaderFluidStack stack2) { + return stack1.isFluidStackTagEqual(stack2); + } + + /** + * Determines if the Fluids are equal and this stack is larger. + * + * @return true if this FluidStack contains the other FluidStack (same fluid and >= amount) + */ + public abstract boolean containsFluid(@NotNull MultiloaderFluidStack other); + + /** + * Determines if the FluidIDs, Amounts, and NBT Tags are all equal. + * + * @param other + * - the FluidStack for comparison + * @return true if the two FluidStacks are exactly the same + */ + public abstract boolean isFluidStackIdentical(MultiloaderFluidStack other); + + /** + * Determines if the FluidIDs and NBT Tags are equal compared to a registered container + * ItemStack. This does not check amounts. + * + * @param other + * The ItemStack for comparison + * @return true if the Fluids (IDs and NBT Tags) are the same + */ + public abstract boolean isFluidEqual(@NotNull ItemStack other); + + public abstract boolean isLighterThanAir(); +} 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 1546a91b..ec3e306a 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsPackets.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/NumismaticsPackets.java @@ -42,6 +42,7 @@ public class NumismaticsPackets { .c2s(ScrollSlotPacket.class, ScrollSlotPacket::new) .c2s(GhostItemSubmitPacket.class, GhostItemSubmitPacket::new) .c2s(SalepointPurchasePacket.class, SalepointPurchasePacket::new) + .c2s(SalepointFluidFilterPacket.class, SalepointFluidFilterPacket::new) .s2c(BankAccountLabelPacket.class, BankAccountLabelPacket::new) .s2c(VarIntContainerSetDataPacket.class, VarIntContainerSetDataPacket::new) diff --git a/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/SalepointFluidFilterPacket.java b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/SalepointFluidFilterPacket.java new file mode 100644 index 00000000..472902e4 --- /dev/null +++ b/common/src/main/java/dev/ithundxr/createnumismatics/registry/packets/SalepointFluidFilterPacket.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; + +import dev.ithundxr.createnumismatics.content.salepoint.SalepointConfigMenu; +import dev.ithundxr.createnumismatics.content.salepoint.states.FluidSalepointState; +import dev.ithundxr.createnumismatics.multiloader.C2SPacket; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; + +public record SalepointFluidFilterPacket(MultiloaderFluidStack filter) implements C2SPacket { + + public SalepointFluidFilterPacket(FriendlyByteBuf buf) { + this(MultiloaderFluidStack.readFromPacket(buf)); + } + + @Override + public void write(FriendlyByteBuf buffer) { + filter.writeToPacket(buffer); + } + + @Override + @SuppressWarnings("DataFlowIssue") + public void handle(ServerPlayer sender) { + if (sender.containerMenu instanceof SalepointConfigMenu salepointConfigMenu) { + if (salepointConfigMenu.getSalepointState() instanceof FluidSalepointState fluidSalepointState) { + fluidSalepointState.setFilter(filter, salepointConfigMenu.contentHolder.getLevel(), salepointConfigMenu.contentHolder.getBlockPos(), sender); + } + } + } +} 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 b813617e..4a49f093 100644 --- a/common/src/main/java/dev/ithundxr/createnumismatics/util/TextUtils.java +++ b/common/src/main/java/dev/ithundxr/createnumismatics/util/TextUtils.java @@ -20,6 +20,7 @@ import com.mojang.blaze3d.vertex.PoseStack; import com.simibubi.create.foundation.utility.Components; +import dev.architectury.injectables.annotations.ExpectPlatform; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.Font; import net.minecraft.client.renderer.MultiBufferSource; @@ -138,4 +139,9 @@ public static boolean isLeftToRight() { .toLowerCase(Locale.ROOT) .equals("true"); } + + @ExpectPlatform + public static String formatFluid(long amount) { + throw new AssertionError(); + } } 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 1840a44c..765913de 100644 --- a/common/src/main/resources/assets/numismatics/lang/default/interface.json +++ b/common/src/main/resources/assets/numismatics/lang/default/interface.json @@ -21,6 +21,9 @@ "gui.numismatics.salepoint.price": "Price/Unit: %s %s, %s¤", "gui.numismatics.salepoint.count": "Units", + "gui.numismatics.salepoint.fluid_filter_empty.0": "Fluid Filter", + "gui.numismatics.salepoint.fluid_filter_empty.1": "Click with a fluid-holding item such as a bucket or a bottle", + "gui.numismatics.salepoint.fluid_empty": "Empty", "gui.numismatics.salepoint.go": "Start transaction", "gui.numismatics.salepoint.cancel": "Cancel transaction", @@ -30,6 +33,7 @@ "gui.numismatics.salepoint.invalid_state": "Invalid state", "gui.numismatics.salepoint.no_target": "Target not found", "gui.numismatics.salepoint.target_not_controlled": "Target not under salepoint control", + "gui.numismatics.salepoint.no_filter": "No filter", "gui.numismatics.salepoint.insufficient_space": "Target is full", "gui.numismatics.salepoint.target_failed_purchase": "Target could not execute the purchase", @@ -66,5 +70,139 @@ "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" + "error.numismatics.authorized_card.account_not_found": "Sub Account not found", + "advancement.numismatics.is_this_legal": "Is This Legal?", + "advancement.numismatics.is_this_legal.desc": "Buy coins for less than they are worth\n§7(Hidden Advancement)", + "advancement.numismatics.money_laundering": "Money Laundering", + "advancement.numismatics.money_laundering.desc": "Buy coins in a vendor\n§7(Hidden Advancement)", + "advancement.numismatics.questionable_investment": "Questionable Investment", + "advancement.numismatics.questionable_investment.desc": "Buy coins for more than they are worth\n§7(Hidden Advancement)", + "advancement.numismatics.root": "Welcome to Numismatics", + "advancement.numismatics.root.desc": "Here Be Riches", + "block.numismatics.andesite_depositor": "Andesite Depositor", + "block.numismatics.andesite_depositor.tooltip": "ANDESITE DEPOSITOR", + "block.numismatics.andesite_depositor.tooltip.price": "Price: %s %s (%s¤)", + "block.numismatics.andesite_depositor.tooltip.summary": "_Shift click_ the _top_ to configure, _right click_ to pay the given amount either with either the card or coins in your hand, at which point a redstone pulse is emmited.", + "block.numismatics.bank_terminal": "Bank Terminal", + "block.numismatics.bank_terminal.tooltip": "BANK TERMINAL", + "block.numismatics.bank_terminal.tooltip.summary": "Allows you to access your own bank account or any account you are _Trusted_ with.", + "block.numismatics.blaze_banker": "Blaze Banker", + "block.numismatics.blaze_banker.tooltip": "BLAZE BANKER", + "block.numismatics.blaze_banker.tooltip.summary": "Creates a bank account in the Banker's name, useful for sharing an account with multiple people. You can assign a _Bank Card_ to the banker by placing it in the appropriate slot.", + "block.numismatics.brass_depositor": "Brass Depositor", + "block.numismatics.brass_depositor.tooltip": "BRASS DEPOSITOR", + "block.numismatics.brass_depositor.tooltip.price": "Price: %s %s, %s¤", + "block.numismatics.brass_depositor.tooltip.summary": "_Shift click_ the _top_ to configure, _right click_ to pay the given amount either with either the card in your hand or the coins in your inventory, at which point a redstone pulse is emmited.", + "block.numismatics.creative_vendor": "Creative Vendor", + "block.numismatics.creative_vendor.tooltip": "CREATIVE VENDOR", + "block.numismatics.creative_vendor.tooltip.summary": "_Creative_ version of the vendor, once configured will never fill up or run out of stock.", + "block.numismatics.salepoint": "Salepoint", + "block.numismatics.salepoint.tooltip.clear": "Cleared interface selection", + "block.numismatics.salepoint.tooltip.missing": "Right-click the targeted interface first", + "block.numismatics.salepoint.tooltip.not_found": "Targeted interface not found", + "block.numismatics.salepoint.tooltip.set": "Interface selected", + "block.numismatics.salepoint.tooltip.success": "Successfully bound to targeted interface", + "block.numismatics.salepoint.tooltip.too_far": "Targeted interface is too far from here", + "block.numismatics.vendor": "Vendor", + "block.numismatics.vendor.tooltip": "VENDOR", + "block.numismatics.vendor.tooltip.mode": "Mode", + "block.numismatics.vendor.tooltip.price": "For: %s %s, %s¤", + "block.numismatics.vendor.tooltip.stock": "Stock", + "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", + "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.banking_guide": "Banking Guide", + "item.numismatics.banking_guide.tooltip": "BANKING GUIDE", + "item.numismatics.banking_guide.tooltip.summary": "Use on a _Blaze Burner_ to convert it into a _Blaze Banker_.", + "item.numismatics.bevel": "Bevel", + "item.numismatics.bevel.plural": "Bevels", + "item.numismatics.black_authorized_card": "Black Authorized Card", + "item.numismatics.black_card": "Black Bank Card", + "item.numismatics.black_id_card": "Black ID Card", + "item.numismatics.blue_authorized_card": "Blue Authorized Card", + "item.numismatics.blue_card": "Blue Bank Card", + "item.numismatics.blue_id_card": "Blue ID Card", + "item.numismatics.brown_authorized_card": "Brown Authorized Card", + "item.numismatics.brown_card": "Brown Bank Card", + "item.numismatics.brown_id_card": "Brown ID Card", + "item.numismatics.card.tooltip.blank": "Blank", + "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 Bank Card", + "item.numismatics.cyan_id_card": "Cyan ID Card", + "item.numismatics.gray_authorized_card": "Gray Authorized Card", + "item.numismatics.gray_card": "Gray Bank Card", + "item.numismatics.gray_id_card": "Gray ID Card", + "item.numismatics.green_authorized_card": "Green Authorized Card", + "item.numismatics.green_card": "Green Bank Card", + "item.numismatics.green_id_card": "Green ID Card", + "item.numismatics.id_card.tooltip": "ID CARD", + "item.numismatics.id_card.tooltip.already_bound": "Already bound, Sneak + Use to Unbind", + "item.numismatics.id_card.tooltip.bound": "Bound to self", + "item.numismatics.id_card.tooltip.cleared": "Cleared", + "item.numismatics.id_card.tooltip.summary": "_Right Click_ to bind, _shift click_ to clear. Can be placed in the _Trusted Menu_ of many Numismatics blocks to give the bound player access to that block.", + "item.numismatics.light_blue_authorized_card": "Light Blue Authorized Card", + "item.numismatics.light_blue_card": "Light Blue Bank Card", + "item.numismatics.light_blue_id_card": "Light Blue ID Card", + "item.numismatics.light_gray_authorized_card": "Light Gray Authorized Card", + "item.numismatics.light_gray_card": "Light Gray Bank Card", + "item.numismatics.light_gray_id_card": "Light Gray ID Card", + "item.numismatics.lime_authorized_card": "Lime Authorized Card", + "item.numismatics.lime_card": "Lime Bank Card", + "item.numismatics.lime_id_card": "Lime ID Card", + "item.numismatics.magenta_authorized_card": "Magenta Authorized Card", + "item.numismatics.magenta_card": "Magenta Bank Card", + "item.numismatics.magenta_id_card": "Magenta ID Card", + "item.numismatics.orange_authorized_card": "Orange Authorized Card", + "item.numismatics.orange_card": "Orange Bank Card", + "item.numismatics.orange_id_card": "Orange ID Card", + "item.numismatics.pink_authorized_card": "Pink Authorized Card", + "item.numismatics.pink_card": "Pink Bank Card", + "item.numismatics.pink_id_card": "Pink ID Card", + "item.numismatics.purple_authorized_card": "Purple Authorized Card", + "item.numismatics.purple_card": "Purple Bank Card", + "item.numismatics.purple_id_card": "Purple ID Card", + "item.numismatics.red_authorized_card": "Red Authorized Card", + "item.numismatics.red_card": "Red Bank Card", + "item.numismatics.red_id_card": "Red ID Card", + "item.numismatics.sprocket": "Sprocket", + "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 Bank Card", + "item.numismatics.white_id_card": "White ID Card", + "item.numismatics.yellow_authorized_card": "Yellow Authorized Card", + "item.numismatics.yellow_card": "Yellow Bank Card", + "item.numismatics.yellow_id_card": "Yellow ID Card", + "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", + "tag.block.numismatics.numismatics_blocks": "Numismatics Blocks", + "tag.item.forge.string": "String", + "tag.item.numismatics.authorized_cards": "Authorized Cards", + "tag.item.numismatics.cards": "Cards", + "tag.item.numismatics.coins": "Coins", + "tag.item.numismatics.id_cards": "Id Cards", + "tag.item.numismatics.numismatics_items": "Numismatics Items" } \ No newline at end of file diff --git a/common/src/main/resources/assets/numismatics/textures/gui/salepoint_config.png b/common/src/main/resources/assets/numismatics/textures/gui/salepoint_config.png index dec58117..d0fae384 100644 Binary files a/common/src/main/resources/assets/numismatics/textures/gui/salepoint_config.png and b/common/src/main/resources/assets/numismatics/textures/gui/salepoint_config.png differ diff --git a/common/src/main/resources/assets/numismatics/textures/gui/salepoint_config.xcf b/common/src/main/resources/assets/numismatics/textures/gui/salepoint_config.xcf index f3e4d49c..d744cb59 100644 Binary files a/common/src/main/resources/assets/numismatics/textures/gui/salepoint_config.xcf and b/common/src/main/resources/assets/numismatics/textures/gui/salepoint_config.xcf differ diff --git a/fabric/build.gradle.kts b/fabric/build.gradle.kts index b58312cd..11547e5d 100644 --- a/fabric/build.gradle.kts +++ b/fabric/build.gradle.kts @@ -81,6 +81,7 @@ dependencies { // Development QOL modLocalRuntime("maven.modrinth:lazydfu:${"lazydfu_version"()}") modLocalRuntime("com.terraformersmc:modmenu:${"modmenu_version"()}") + modLocalRuntime("maven.modrinth:jade:${"jade_version"()}") modCompileOnly("dev.emi:emi-fabric:${"emi_version"()}:api") modLocalRuntime("dev.emi:emi-fabric:${"emi_version"()}") diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/fabric/InvalidatableWrappingFluidBufferTank.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/fabric/InvalidatableWrappingFluidBufferTank.java new file mode 100644 index 00000000..47a8a788 --- /dev/null +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/containers/fabric/InvalidatableWrappingFluidBufferTank.java @@ -0,0 +1,95 @@ +/* + * 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.salepoint.containers.fabric; + +import dev.ithundxr.createnumismatics.content.salepoint.containers.InvalidatableAbstractBuffer; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import dev.ithundxr.createnumismatics.multiloader.fluid.fabric.MultiloaderFluidStackImpl; +import io.github.fabricators_of_create.porting_lib.transfer.fluid.FluidTank; +import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; +import net.fabricmc.fabric.api.transfer.v1.storage.Storage; +import net.fabricmc.fabric.api.transfer.v1.storage.StorageView; +import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; +import net.fabricmc.fabric.api.transfer.v1.transaction.TransactionContext; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.Iterator; + +@SuppressWarnings("UnstableApiUsage") +public class InvalidatableWrappingFluidBufferTank extends InvalidatableAbstractBuffer implements Storage { + + protected FluidTank buffer; + + public InvalidatableWrappingFluidBufferTank(FluidTank buffer) { + this.buffer = buffer; + } + + @Override + protected void afterInvalidate() { + super.afterInvalidate(); + buffer = null; + } + + @Override + protected int copyToBufferInternal(MultiloaderFluidStack source, boolean simulate) { + try (Transaction transaction = Transaction.openOuter()) { + long inserted = buffer.insert(((MultiloaderFluidStackImpl) source).getType(), source.getAmount(), transaction); + if (!simulate) { + transaction.commit(); + } + return (int) inserted; + } + } + + @Override + protected int removeFromBufferInternal(MultiloaderFluidStack source, boolean simulate, int maxAmount) { + try (Transaction transaction = Transaction.openOuter()) { + long extracted = buffer.extract(((MultiloaderFluidStackImpl) source).getType(), maxAmount, transaction); + if (!simulate) { + transaction.commit(); + } + return (int) extracted; + } + } + + @Override + public long insert(FluidVariant resource, long maxAmount, TransactionContext transaction) { + if (!isValid()) + return 0; + + return buffer.insert(resource, maxAmount, transaction); + } + + @Override + public long extract(FluidVariant resource, long maxAmount, TransactionContext transaction) { + if (!isValid()) + return 0; + + return buffer.extract(resource, maxAmount, transaction); + } + + @Override + public @NotNull Iterator> iterator() { + if (!isValid()) + return Collections.emptyListIterator(); + + return buffer.iterator(); + } +} diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/fabric/FluidSalepointStateImpl.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/fabric/FluidSalepointStateImpl.java new file mode 100644 index 00000000..c1751754 --- /dev/null +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/fabric/FluidSalepointStateImpl.java @@ -0,0 +1,126 @@ +/* + * 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.salepoint.states.fabric; + +import com.simibubi.create.foundation.fluid.SmartFluidTank; +import dev.ithundxr.createnumismatics.content.salepoint.containers.InvalidatableAbstractBuffer; +import dev.ithundxr.createnumismatics.content.salepoint.containers.fabric.InvalidatableWrappingFluidBufferTank; +import dev.ithundxr.createnumismatics.content.salepoint.states.FluidSalepointState; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import dev.ithundxr.createnumismatics.multiloader.fluid.fabric.MultiloaderFluidStackImpl; +import io.github.fabricators_of_create.porting_lib.fluids.FluidStack; +import io.github.fabricators_of_create.porting_lib.transfer.fluid.FluidTank; +import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; +import net.minecraft.MethodsReturnNonnullByDefault; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.Tag; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.annotation.ParametersAreNonnullByDefault; +import java.util.List; + +@ParametersAreNonnullByDefault +@MethodsReturnNonnullByDefault +@SuppressWarnings("UnstableApiUsage") +public class FluidSalepointStateImpl extends FluidSalepointState { + + private final @NotNull FluidTank buffer = new SmartFluidTank(4 * getFilterCapacity(), $ -> this.setChanged()) + .setValidator(fs -> this.filterMatches(new MultiloaderFluidStackImpl(fs))); + private @NotNull InvalidatableAbstractBuffer bufferWrapper = createBufferWrapper(buffer); + + private static InvalidatableAbstractBuffer createBufferWrapper(FluidTank buffer) { + return new InvalidatableWrappingFluidBufferTank(buffer); + } + + public static FluidSalepointState create() { + return new FluidSalepointStateImpl(); + } + + @Override + protected boolean canChangeFilterToInternal(MultiloaderFluidStack filter) { + return buffer.isEmpty(); + } + + @Override + protected void setFilterInternal(MultiloaderFluidStack filter, Level salepointLevel, BlockPos salepointPos, @Nullable Player player) { + // buffer gets cleared when filter is set, but the filter *should* only be set when the buffer is empty + if (!getFilter().isFluidEqual(filter)) + buffer.setFluid(FluidStack.EMPTY); + } + + @Override + protected void saveInternal(CompoundTag tag) { + CompoundTag bufferTag = new CompoundTag(); + buffer.writeToNBT(bufferTag); + tag.put("Buffer", bufferTag); + } + + @Override + protected void loadInternal(CompoundTag tag) { + buffer.setFluid(FluidStack.EMPTY); + + if (tag.contains("Buffer", Tag.TAG_COMPOUND)) { + buffer.readFromNBT(tag.getCompound("Buffer")); + } + } + + @Override + protected boolean hasBufferFluidForPurchase() { + return getFilter().isFluidEqual(new MultiloaderFluidStackImpl(buffer.getFluid())) + && buffer.getAmount() >= getFilter().getAmount(); + } + + @Override + protected List removeBufferFluidForPurchase() { + try (Transaction transaction = Transaction.openOuter()) { + long amount = buffer.extract(((MultiloaderFluidStackImpl) getFilter()).getType(), getFilter().getAmount(), transaction); + transaction.commit(); + + return List.of( + new MultiloaderFluidStackImpl(buffer.getFluid().copy().setAmount(amount)) + ); + } + } + + @Override + public InvalidatableAbstractBuffer getBuffer() { + return bufferWrapper; + } + + @Override + public void onDestroy(Level level, BlockPos pos) { + onUnload(); + buffer.setFluid(FluidStack.EMPTY); + } + + @Override + public void onUnload() { + bufferWrapper.invalidate(); + } + + @Override + public void keepAlive() { + if (!bufferWrapper.isValid()) + bufferWrapper = createBufferWrapper(buffer); + } +} diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/fabric/SalepointFluidConfigWidgetImpl.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/fabric/SalepointFluidConfigWidgetImpl.java new file mode 100644 index 00000000..009844c5 --- /dev/null +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/fabric/SalepointFluidConfigWidgetImpl.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.content.salepoint.widgets.fabric; + +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import dev.ithundxr.createnumismatics.multiloader.fluid.fabric.MultiloaderFluidStackImpl; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.Minecraft; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class SalepointFluidConfigWidgetImpl { + @Environment(EnvType.CLIENT) + public static @Nullable MultiloaderFluidStack getFluidFrom(@NotNull ItemStack stack) { + Level level = Minecraft.getInstance().level; + if (level == null) + return null; + + if (!GenericItemEmptying.canItemBeEmptied(level, stack)) + return null; + + return new MultiloaderFluidStackImpl(GenericItemEmptying.emptyItem(level, stack, true).getFirst()); + } +} diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/fabric/SalepointFluidDisplayWidgetImpl.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/fabric/SalepointFluidDisplayWidgetImpl.java new file mode 100644 index 00000000..e91fd612 --- /dev/null +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/fabric/SalepointFluidDisplayWidgetImpl.java @@ -0,0 +1,37 @@ +/* + * 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.salepoint.widgets.fabric; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.fluid.FluidRenderer; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import dev.ithundxr.createnumismatics.multiloader.fluid.fabric.MultiloaderFluidStackImpl; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.renderer.MultiBufferSource; +import org.jetbrains.annotations.NotNull; + +public class SalepointFluidDisplayWidgetImpl { + @Environment(EnvType.CLIENT) + public static void renderFluidBox(@NotNull MultiloaderFluidStack fluidStack, float xMin, float yMin, float zMin, + float xMax, float yMax, float zMax, @NotNull MultiBufferSource buffer, + @NotNull PoseStack ms, int light, boolean renderBottom) { + FluidRenderer.renderFluidBox(((MultiloaderFluidStackImpl) fluidStack).getWrapped(), xMin, yMin, zMin, xMax, yMax, zMax, buffer, ms, light, renderBottom); + } +} diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/fabric/mixin/PortableFluidInterfaceBlockEntityMixin.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/fabric/mixin/PortableFluidInterfaceBlockEntityMixin.java new file mode 100644 index 00000000..a5ea0518 --- /dev/null +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/fabric/mixin/PortableFluidInterfaceBlockEntityMixin.java @@ -0,0 +1,212 @@ +/* + * 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.fabric.mixin; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.simibubi.create.content.contraptions.actors.psi.PortableFluidInterfaceBlockEntity; +import com.simibubi.create.content.contraptions.actors.psi.PortableFluidInterfaceBlockEntity.InterfaceFluidHandler; +import com.simibubi.create.content.contraptions.actors.psi.PortableStorageInterfaceBlockEntity; +import com.simibubi.create.foundation.blockEntity.behaviour.BlockEntityBehaviour; +import dev.ithundxr.createnumismatics.Numismatics; +import dev.ithundxr.createnumismatics.content.salepoint.behaviours.FluidSalepointTargetBehaviour; +import dev.ithundxr.createnumismatics.content.salepoint.behaviours.SalepointTargetBehaviour; +import dev.ithundxr.createnumismatics.content.salepoint.containers.fabric.InvalidatableWrappingFluidBufferTank; +import dev.ithundxr.createnumismatics.content.salepoint.states.ISalepointState; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import dev.ithundxr.createnumismatics.multiloader.fluid.fabric.MultiloaderFluidStackImpl; +import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; +import net.fabricmc.fabric.api.transfer.v1.storage.Storage; +import net.fabricmc.fabric.api.transfer.v1.transaction.Transaction; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; + +import java.util.List; + +@Mixin(PortableFluidInterfaceBlockEntity.class) +@SuppressWarnings("UnstableApiUsage") +public abstract class PortableFluidInterfaceBlockEntityMixin extends PortableStorageInterfaceBlockEntity { + + @Shadow protected InterfaceFluidHandler capability; + @Unique + private FluidSalepointTargetBehaviour railway$salepointBehaviour; + + @Unique + @Nullable + private Storage railway$contraptionStorage; + + private PortableFluidInterfaceBlockEntityMixin(BlockEntityType type, BlockPos pos, BlockState state) { + super(type, pos, state); + } + + @WrapOperation( + method = "startTransferringTo", + at = @At( + value = "INVOKE", + target = "Lcom/simibubi/create/content/contraptions/actors/psi/PortableFluidInterfaceBlockEntity$InterfaceFluidHandler;setWrapped(Lnet/fabricmc/fabric/api/transfer/v1/storage/Storage;)V" + ), + remap = false + ) + @SuppressWarnings("unchecked") + private void keepControl(InterfaceFluidHandler instance, Storage wrapped, Operation original) { + Storage existingWrapped = ((WrappedStorageAccessor) capability).getWrapped(); + if (!(existingWrapped instanceof InvalidatableWrappingFluidBufferTank)) { + original.call(instance, wrapped); + } + railway$contraptionStorage = wrapped; + } + + @WrapOperation( + method = "stopTransferring", + at = @At( + value = "INVOKE", + target = "Lcom/simibubi/create/content/contraptions/actors/psi/PortableFluidInterfaceBlockEntity$InterfaceFluidHandler;setWrapped(Lnet/fabricmc/fabric/api/transfer/v1/storage/Storage;)V" + ), + remap = false + ) + @SuppressWarnings("unchecked") + private void keepControl2(InterfaceFluidHandler instance, Storage wrapped, Operation original) { + Storage existingWrapped = ((WrappedStorageAccessor) capability).getWrapped(); + if (!(existingWrapped instanceof InvalidatableWrappingFluidBufferTank)) { + original.call(instance, wrapped); + } + railway$contraptionStorage = null; + } + + @Override + public boolean canTransfer() { + return super.canTransfer() || railway$salepointBehaviour.isControlledBySalepoint(); + } + + @Override + public void addBehaviours(List behaviours) { + super.addBehaviours(behaviours); + railway$salepointBehaviour = new FluidSalepointTargetBehaviour(this) { + private boolean underControl = false; + + @Override + protected boolean isUnderControlInternal(@NotNull ISalepointState state) { + return underControl; // id checks done by super + } + + @Override + @SuppressWarnings("unchecked") + protected void ensureUnderControlInternal(@NotNull ISalepointState state) { + ((WrappedStorageAccessor) capability).setWrapped((InvalidatableWrappingFluidBufferTank) state.getBuffer()); + + if (!underControl) { + underControl = true; + notifyUpdate(); + } + } + + @Override + @SuppressWarnings("unchecked") + protected void relinquishControlInternal(@NotNull ISalepointState state) { + if (railway$contraptionStorage != null) { + ((WrappedStorageAccessor) capability).setWrapped(railway$contraptionStorage); + } else { + ((WrappedStorageAccessor) capability).setWrapped(Storage.empty()); + } + + if (underControl) { + underControl = false; + notifyUpdate(); + } + } + + @Override + public boolean hasSpaceFor(@NotNull MultiloaderFluidStack object) { + if (railway$contraptionStorage == null) + return false; + + if (!railway$contraptionStorage.supportsInsertion()) + return false; + + try (Transaction transaction = Transaction.openOuter()) { + if (railway$contraptionStorage.insert(((MultiloaderFluidStackImpl) object).getType(), object.getAmount(), transaction) != object.getAmount()) { + return false; + } + } + + return true; + } + + @Override + public boolean doPurchase(@NotNull MultiloaderFluidStack object, @NotNull PurchaseProvider purchaseProvider) { + if (railway$contraptionStorage == null) + return false; + + if (!hasSpaceFor(object)) + return false; + + List extracted = purchaseProvider.extract(); + try (Transaction transaction = Transaction.openOuter()) { + for (MultiloaderFluidStack stack : extracted) { + if (railway$contraptionStorage.insert(((MultiloaderFluidStackImpl) stack).getType(), stack.getAmount(), transaction) != stack.getAmount()) { + Numismatics.LOGGER.error("Failed to insert fluid into contraption storage, despite having space."); + return false; + } + } + transaction.commit(); + } + + return true; + } + + @Override + public void read(@NotNull CompoundTag nbt, boolean clientPacket) { + super.read(nbt, clientPacket); + + underControl = nbt.getBoolean("SalepointUnderControl"); + } + + @Override + public void write(@NotNull CompoundTag nbt, boolean clientPacket) { + super.write(nbt, clientPacket); + + nbt.putBoolean("SalepointUnderControl", underControl); + } + }; + + behaviours.add(railway$salepointBehaviour); + } + + @Mixin(InterfaceFluidHandler.class) + private static class InterfaceFluidHandlerMixin { + @WrapOperation( + method = "insert(Lnet/fabricmc/fabric/api/transfer/v1/fluid/FluidVariant;JLnet/fabricmc/fabric/api/transfer/v1/transaction/TransactionContext;)J", + at = @At( + value = "INVOKE", + target = "Lcom/simibubi/create/content/contraptions/actors/psi/PortableFluidInterfaceBlockEntity;isConnected()Z" + ) + ) + private boolean fakeConnect(PortableFluidInterfaceBlockEntity instance, Operation original) { + return original.call(instance) || instance.getBehaviour(SalepointTargetBehaviour.TYPE).isControlledBySalepoint(); + } + } +} diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/fabric/mixin/WrappedStorageAccessor.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/fabric/mixin/WrappedStorageAccessor.java new file mode 100644 index 00000000..e0f524a6 --- /dev/null +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/fabric/mixin/WrappedStorageAccessor.java @@ -0,0 +1,34 @@ +/* + * 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.fabric.mixin; + +import io.github.fabricators_of_create.porting_lib.transfer.WrappedStorage; +import net.fabricmc.fabric.api.transfer.v1.storage.Storage; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(WrappedStorage.class) +@SuppressWarnings("UnstableApiUsage") +public interface WrappedStorageAccessor extends Storage { + @Accessor("wrapped") + Storage getWrapped(); + + @Accessor("wrapped") + void setWrapped(Storage wrapped); +} diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/fabric/FluidUnitsImpl.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/fabric/FluidUnitsImpl.java new file mode 100644 index 00000000..f73be2fa --- /dev/null +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/fabric/FluidUnitsImpl.java @@ -0,0 +1,28 @@ +/* + * 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.multiloader.fluid.fabric; + +import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants; + +public class FluidUnitsImpl { + @SuppressWarnings("UnstableApiUsage") + public static long bucket() { + return FluidConstants.BUCKET; + } +} diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/fabric/MultiloaderFluidStackImpl.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/fabric/MultiloaderFluidStackImpl.java new file mode 100644 index 00000000..6399f2a9 --- /dev/null +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/fabric/MultiloaderFluidStackImpl.java @@ -0,0 +1,213 @@ +/* + * 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.multiloader.fluid.fabric; + +import com.mojang.serialization.Codec; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import io.github.fabricators_of_create.porting_lib.fluids.FluidStack; +import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; +import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariantAttributes; +import net.fabricmc.fabric.api.transfer.v1.storage.StorageView; +import net.fabricmc.fabric.api.transfer.v1.storage.base.ResourceAmount; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.material.Fluid; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +@SuppressWarnings("UnstableApiUsage") +public class MultiloaderFluidStackImpl extends MultiloaderFluidStack { + + public static Codec makeCodec() { + return FluidStack.CODEC.xmap(MultiloaderFluidStackImpl::new, fs -> ((MultiloaderFluidStackImpl) fs).wrapped); + } + + public static MultiloaderFluidStack makeEmpty() { + return new MultiloaderFluidStackImpl(FluidStack.EMPTY); + } + + private final FluidStack wrapped; + + public MultiloaderFluidStackImpl(FluidStack wrapped) { + this.wrapped = wrapped; + } + + public MultiloaderFluidStackImpl(FluidVariant type, long amount) { + this(new FluidStack(type, amount)); + } + + public MultiloaderFluidStackImpl(FluidVariant type, long amount, @Nullable CompoundTag tag) { + this(new FluidStack(type, amount, tag)); + } + + public MultiloaderFluidStackImpl(StorageView view) { + this(new FluidStack(view)); + } + + public MultiloaderFluidStackImpl(ResourceAmount resource) { + this(new FluidStack(resource)); + } + + /** + * Avoid this constructor when possible, may result in NBT loss + */ + public MultiloaderFluidStackImpl(Fluid fluid, long amount) { + this(new FluidStack(fluid, amount)); + } + + public MultiloaderFluidStackImpl(Fluid fluid, long amount, @Nullable CompoundTag nbt) { + this(new FluidStack(fluid, amount, nbt)); + } + + public MultiloaderFluidStackImpl(FluidStack copy, long amount) { + this(new FluidStack(copy, amount)); + } + + public MultiloaderFluidStackImpl(MultiloaderFluidStack copy, long amount) { + this(((MultiloaderFluidStackImpl) copy).wrapped, amount); + } + + @Override + public MultiloaderFluidStack setAmount(long amount) { + wrapped.setAmount(amount); + return this; + } + + public FluidVariant getType() { + return wrapped.getType(); + } + + @Override + public Fluid getFluid() { + return wrapped.getFluid(); + } + + @Override + public long getAmount() { + return wrapped.getAmount(); + } + + @Override + public boolean isEmpty() { + return wrapped.isEmpty(); + } + + @Override + public boolean isFluidEqual(MultiloaderFluidStack other) { + return wrapped.isFluidEqual(((MultiloaderFluidStackImpl) other).wrapped); + } + + public boolean isFluidEqual(FluidVariant other) { + return wrapped.isFluidEqual(other); + } + + public static boolean isFluidEqual(FluidVariant mine, FluidVariant other) { + return FluidStack.isFluidEqual(mine, other); + } + + public boolean canFill(FluidVariant var) { + return wrapped.canFill(var); + } + + @Override + public CompoundTag writeToNBT(CompoundTag nbt) { + return wrapped.writeToNBT(nbt); + } + + public static MultiloaderFluidStack loadFluidStackFromNBT(CompoundTag tag) { + return new MultiloaderFluidStackImpl(FluidStack.loadFluidStackFromNBT(tag)); + } + + @Override + public void setTag(CompoundTag tag) { + wrapped.setTag(tag); + } + + @Override + public @Nullable CompoundTag getTag() { + return wrapped.getTag(); + } + + @Override + public Component getDisplayName() { + return wrapped.getDisplayName(); + } + + public static MultiloaderFluidStack readFromPacket(FriendlyByteBuf buffer) { + return new MultiloaderFluidStackImpl(FluidStack.readFromPacket(buffer)); + } + + @Override + public FriendlyByteBuf writeToPacket(FriendlyByteBuf buffer) { + return wrapped.writeToPacket(buffer); + } + + @Override + public MultiloaderFluidStack copy() { + return new MultiloaderFluidStackImpl(wrapped.copy()); + } + + @Override + public boolean containsFluid(@NotNull MultiloaderFluidStack other) { + return wrapped.containsFluid(((MultiloaderFluidStackImpl) other).wrapped); + } + + @Override + public boolean isFluidStackIdentical(MultiloaderFluidStack other) { + return wrapped.isFluidStackIdentical(((MultiloaderFluidStackImpl) other).wrapped); + } + + @Override + public boolean isFluidEqual(@NotNull ItemStack other) { + return wrapped.isFluidEqual(other); + } + + @Override + public boolean isLighterThanAir() { + return FluidVariantAttributes.isLighterThanAir(wrapped.getType()); + } + + public FluidStack getWrapped() { + return wrapped; + } + + @Override + public final int hashCode() { + return wrapped.hashCode(); + } + + /** + * Default equality comparison for a FluidStack. Same functionality as isFluidEqual(). + * + * This is included for use in data structures. + */ + @Override + public final boolean equals(Object obj) { + if (!(obj instanceof MultiloaderFluidStack fs)) + return false; + + return isFluidEqual(fs); + } + + public static MultiloaderFluidStack create(Fluid fluid, long amount, @Nullable CompoundTag nbt) { + return new MultiloaderFluidStackImpl(fluid, amount, nbt); + } +} diff --git a/fabric/src/main/java/dev/ithundxr/createnumismatics/util/fabric/TextUtilsImpl.java b/fabric/src/main/java/dev/ithundxr/createnumismatics/util/fabric/TextUtilsImpl.java new file mode 100644 index 00000000..48d3348b --- /dev/null +++ b/fabric/src/main/java/dev/ithundxr/createnumismatics/util/fabric/TextUtilsImpl.java @@ -0,0 +1,39 @@ +/* + * 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.util.fabric; + +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.LangBuilder; +import com.simibubi.create.infrastructure.config.AllConfigs; +import io.github.fabricators_of_create.porting_lib.util.FluidTextUtil; +import io.github.fabricators_of_create.porting_lib.util.FluidUnit; + +public class TextUtilsImpl { + public static String formatFluid(long amount) { + FluidUnit unit = AllConfigs.client().fluidUnitType.get(); + boolean simplify = AllConfigs.client().simplifyFluidUnit.get(); + LangBuilder mb = Lang.translate(unit.getTranslationKey()); + + String amountStr = FluidTextUtil.getUnicodeMillibuckets(amount, unit, simplify); + + return Lang.text(amountStr) + .add(mb) + .string(); + } +} diff --git a/fabric/src/main/resources/numismatics.mixins.json b/fabric/src/main/resources/numismatics.mixins.json index cbb80188..ccae7e84 100644 --- a/fabric/src/main/resources/numismatics.mixins.json +++ b/fabric/src/main/resources/numismatics.mixins.json @@ -9,7 +9,10 @@ ], "mixins": [ "ItemHandlerWrapperAccessor", - "PortableItemInterfaceBlockEntityMixin" + "PortableFluidInterfaceBlockEntityMixin", + "PortableFluidInterfaceBlockEntityMixin$InterfaceFluidHandlerMixin", + "PortableItemInterfaceBlockEntityMixin", + "WrappedStorageAccessor" ], "injectors": { "defaultRequire": 1 diff --git a/forge/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/forge/FluidSalepointStateImpl.java b/forge/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/forge/FluidSalepointStateImpl.java new file mode 100644 index 00000000..a29d037f --- /dev/null +++ b/forge/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/states/forge/FluidSalepointStateImpl.java @@ -0,0 +1,27 @@ +/* + * 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.salepoint.states.forge; + +import dev.ithundxr.createnumismatics.content.salepoint.states.FluidSalepointState; + +public class FluidSalepointStateImpl { + public static FluidSalepointState create() { + throw new AssertionError(); + } +} diff --git a/forge/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/forge/SalepointFluidConfigWidgetImpl.java b/forge/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/forge/SalepointFluidConfigWidgetImpl.java new file mode 100644 index 00000000..aec9cc8c --- /dev/null +++ b/forge/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/forge/SalepointFluidConfigWidgetImpl.java @@ -0,0 +1,45 @@ +/* + * 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.salepoint.widgets.forge; + +import com.simibubi.create.content.fluids.transfer.GenericItemEmptying; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import dev.ithundxr.createnumismatics.multiloader.fluid.forge.MultiloaderFluidStackImpl; +import net.minecraft.client.Minecraft; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class SalepointFluidConfigWidgetImpl { + @OnlyIn(Dist.CLIENT) + @Nullable + public static MultiloaderFluidStack getFluidFrom(@NotNull ItemStack stack) { + Level level = Minecraft.getInstance().level; + if (level == null) + return null; + + if (!GenericItemEmptying.canItemBeEmptied(level, stack)) + return null; + + return new MultiloaderFluidStackImpl(GenericItemEmptying.emptyItem(level, stack, true).getFirst()); + } +} diff --git a/forge/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/forge/SalepointFluidDisplayWidgetImpl.java b/forge/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/forge/SalepointFluidDisplayWidgetImpl.java new file mode 100644 index 00000000..5426ac85 --- /dev/null +++ b/forge/src/main/java/dev/ithundxr/createnumismatics/content/salepoint/widgets/forge/SalepointFluidDisplayWidgetImpl.java @@ -0,0 +1,37 @@ +/* + * 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.salepoint.widgets.forge; + +import com.mojang.blaze3d.vertex.PoseStack; +import com.simibubi.create.foundation.fluid.FluidRenderer; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import dev.ithundxr.createnumismatics.multiloader.fluid.forge.MultiloaderFluidStackImpl; +import net.minecraft.client.renderer.MultiBufferSource; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import org.jetbrains.annotations.NotNull; + +public class SalepointFluidDisplayWidgetImpl { + @OnlyIn(Dist.CLIENT) + public static void renderFluidBox(@NotNull MultiloaderFluidStack fluidStack, float xMin, float yMin, float zMin, + float xMax, float yMax, float zMax, @NotNull MultiBufferSource buffer, + @NotNull PoseStack ms, int light, boolean renderBottom) { + FluidRenderer.renderFluidBox(((MultiloaderFluidStackImpl) fluidStack).getWrapped(), xMin, yMin, zMin, xMax, yMax, zMax, buffer, ms, light, renderBottom); + } +} diff --git a/forge/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/forge/FluidUnitsImpl.java b/forge/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/forge/FluidUnitsImpl.java new file mode 100644 index 00000000..8dae0573 --- /dev/null +++ b/forge/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/forge/FluidUnitsImpl.java @@ -0,0 +1,25 @@ +/* + * 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.multiloader.fluid.forge; + +public class FluidUnitsImpl { + public static long bucket() { + return 1000L; + } +} diff --git a/forge/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/forge/MultiloaderFluidStackImpl.java b/forge/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/forge/MultiloaderFluidStackImpl.java new file mode 100644 index 00000000..eb25f4c9 --- /dev/null +++ b/forge/src/main/java/dev/ithundxr/createnumismatics/multiloader/fluid/forge/MultiloaderFluidStackImpl.java @@ -0,0 +1,190 @@ +/* + * 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.multiloader.fluid.forge; + +import com.mojang.serialization.Codec; +import dev.ithundxr.createnumismatics.multiloader.fluid.MultiloaderFluidStack; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.material.Fluid; +import net.minecraftforge.fluids.FluidStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class MultiloaderFluidStackImpl extends MultiloaderFluidStack { + + public static Codec makeCodec() { + return FluidStack.CODEC.xmap(MultiloaderFluidStackImpl::new, fs -> ((MultiloaderFluidStackImpl) fs).wrapped); + } + + public static MultiloaderFluidStack makeEmpty() { + return new MultiloaderFluidStackImpl(FluidStack.EMPTY); + } + + private final FluidStack wrapped; + + public MultiloaderFluidStackImpl(FluidStack wrapped) { + this.wrapped = wrapped; + } + + public MultiloaderFluidStackImpl(Fluid fluid, int amount) { + this(new FluidStack(fluid, amount)); + } + + public MultiloaderFluidStackImpl(Fluid fluid, int amount, CompoundTag nbt) { + this(new FluidStack(fluid, amount, nbt)); + } + + public MultiloaderFluidStackImpl(FluidStack stack, int amount) { + this(new FluidStack(stack, amount)); + } + + public MultiloaderFluidStackImpl(MultiloaderFluidStack stack, int amount) { + this(((MultiloaderFluidStackImpl) stack).wrapped, amount); + } + + @Override + public MultiloaderFluidStack setAmount(long amount) { + wrapped.setAmount((int) amount); + return this; + } + + @Override + public Fluid getFluid() { + return wrapped.getFluid(); + } + + public final Fluid getRawFluid() { + return wrapped.getRawFluid(); + } + + @Override + public long getAmount() { + return wrapped.getAmount(); + } + + @Override + public boolean isEmpty() { + return wrapped.isEmpty(); + } + + @Override + public boolean isFluidEqual(MultiloaderFluidStack other) { + return wrapped.isFluidEqual(((MultiloaderFluidStackImpl) other).wrapped); + } + + @Override + public CompoundTag writeToNBT(CompoundTag nbt) { + return wrapped.writeToNBT(nbt); + } + + public static MultiloaderFluidStack loadFluidStackFromNBT(CompoundTag tag) { + return new MultiloaderFluidStackImpl(FluidStack.loadFluidStackFromNBT(tag)); + } + + @Override + public void setTag(CompoundTag tag) { + wrapped.setTag(tag); + } + + @Override + public @Nullable CompoundTag getTag() { + return wrapped.getTag(); + } + + public @Nullable CompoundTag getChildTag(String childName) { + return wrapped.getChildTag(childName); + } + + public @Nullable CompoundTag getOrCreateChildTag(String childName) { + return wrapped.getOrCreateChildTag(childName); + } + + @Override + public Component getDisplayName() { + return wrapped.getDisplayName(); + } + + public String getTranslationKey() { + return wrapped.getTranslationKey(); + } + + public static MultiloaderFluidStack readFromPacket(FriendlyByteBuf buffer) { + return new MultiloaderFluidStackImpl(FluidStack.readFromPacket(buffer)); + } + + @Override + public FriendlyByteBuf writeToPacket(FriendlyByteBuf buffer) { + wrapped.writeToPacket(buffer); + return buffer; + } + + @Override + public MultiloaderFluidStack copy() { + return new MultiloaderFluidStackImpl(wrapped.copy()); + } + + @Override + public boolean containsFluid(@NotNull MultiloaderFluidStack other) { + return wrapped.containsFluid(((MultiloaderFluidStackImpl) other).wrapped); + } + + @Override + public boolean isFluidStackIdentical(MultiloaderFluidStack other) { + return wrapped.isFluidStackIdentical(((MultiloaderFluidStackImpl) other).wrapped); + } + + @Override + public boolean isFluidEqual(@NotNull ItemStack other) { + return wrapped.isFluidEqual(other); + } + + @Override + public boolean isLighterThanAir() { + return getFluid().getFluidType().isLighterThanAir(); + } + + @Override + public final int hashCode() { + return wrapped.hashCode(); + } + + /** + * Default equality comparison for a FluidStack. Same functionality as isFluidEqual(). + * + * This is included for use in data structures. + */ + @Override + public final boolean equals(Object obj) { + if (!(obj instanceof MultiloaderFluidStack fs)) + return false; + + return isFluidEqual(fs); + } + + public static MultiloaderFluidStack create(Fluid fluid, long amount, @Nullable CompoundTag nbt) { + return new MultiloaderFluidStackImpl(fluid, (int) amount, nbt); + } + + public FluidStack getWrapped() { + return wrapped; + } +} diff --git a/forge/src/main/java/dev/ithundxr/createnumismatics/util/forge/TextUtilsImpl.java b/forge/src/main/java/dev/ithundxr/createnumismatics/util/forge/TextUtilsImpl.java new file mode 100644 index 00000000..c5d1880f --- /dev/null +++ b/forge/src/main/java/dev/ithundxr/createnumismatics/util/forge/TextUtilsImpl.java @@ -0,0 +1,32 @@ +/* + * 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.util.forge; + +import com.simibubi.create.foundation.utility.Lang; +import com.simibubi.create.foundation.utility.LangBuilder; + +public class TextUtilsImpl { + public static String formatFluid(long amount) { + LangBuilder mb = Lang.translate("generic.unit.millibuckets"); + + return Lang.number(amount) + .add(mb) + .string(); + } +} diff --git a/gradle.properties b/gradle.properties index 925f8bc8..f925e402 100644 --- a/gradle.properties +++ b/gradle.properties @@ -48,6 +48,8 @@ jei_version = 15.8.0.16 modmenu_version = 7.2.2 # LazyDFU - https://modrinth.com/mod/lazydfu/versions lazydfu_version = 0.1.3 +# Jade - https://modrinth.com/mod/jade/versions +jade_version = 11.10.0+fabric # Carry On - https://github.com/Tschipp/CarryOn carryon_forge_version = 2.1.2.7