diff --git a/src/main/java/com/simibubi/create/AllMenuTypes.java b/src/main/java/com/simibubi/create/AllMenuTypes.java index 9ebd08fe2b..92244483fb 100644 --- a/src/main/java/com/simibubi/create/AllMenuTypes.java +++ b/src/main/java/com/simibubi/create/AllMenuTypes.java @@ -4,6 +4,8 @@ import com.simibubi.create.content.equipment.blueprint.BlueprintMenu; import com.simibubi.create.content.equipment.blueprint.BlueprintScreen; import com.simibubi.create.content.equipment.toolbox.ToolboxMenu; import com.simibubi.create.content.equipment.toolbox.ToolboxScreen; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelSetItemMenu; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelSetItemScreen; import com.simibubi.create.content.logistics.filter.AttributeFilterMenu; import com.simibubi.create.content.logistics.filter.AttributeFilterScreen; import com.simibubi.create.content.logistics.filter.FilterMenu; @@ -76,6 +78,9 @@ public class AllMenuTypes { public static final MenuEntry REDSTONE_REQUESTER = register("redstone_requester", RedstoneRequesterMenu::new, () -> RedstoneRequesterScreen::new); + public static final MenuEntry FACTORY_PANEL_SET_ITEM = + register("factory_panel_set_item", FactoryPanelSetItemMenu::new, () -> FactoryPanelSetItemScreen::new); + private static > MenuEntry register( String name, ForgeMenuFactory factory, NonNullSupplier> screenFactory) { return Create.REGISTRATE diff --git a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java index 1df3820a45..c36ee88ba5 100644 --- a/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java +++ b/src/main/java/com/simibubi/create/compat/jei/CreateJEI.java @@ -59,6 +59,7 @@ import com.simibubi.create.content.kinetics.fan.processing.SplashingRecipe; import com.simibubi.create.content.kinetics.press.MechanicalPressBlockEntity; import com.simibubi.create.content.kinetics.press.PressingRecipe; import com.simibubi.create.content.kinetics.saw.CuttingRecipe; +import com.simibubi.create.content.logistics.factoryBoard.FactoryPanelSetItemScreen; import com.simibubi.create.content.logistics.filter.AbstractFilterScreen; import com.simibubi.create.content.logistics.redstoneRequester.RedstoneRequesterScreen; import com.simibubi.create.content.processing.basin.BasinRecipe; @@ -396,6 +397,7 @@ public class CreateJEI implements IModPlugin { registration.addGhostIngredientHandler(LinkedControllerScreen.class, new GhostIngredientHandler()); registration.addGhostIngredientHandler(ScheduleScreen.class, new GhostIngredientHandler()); registration.addGhostIngredientHandler(RedstoneRequesterScreen.class, new GhostIngredientHandler()); + registration.addGhostIngredientHandler(FactoryPanelSetItemScreen.class, new GhostIngredientHandler()); } private class CategoryBuilder> { diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java index 185f2893e4..249e6a74e6 100644 --- a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelBehaviour.java @@ -13,7 +13,6 @@ import java.util.UUID; import javax.annotation.Nullable; -import net.minecraft.network.chat.Component; import org.joml.Math; import com.google.common.collect.HashMultimap; @@ -57,12 +56,16 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.Tag; +import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionHand; +import net.minecraft.world.MenuProvider; +import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Player; +import net.minecraft.world.inventory.AbstractContainerMenu; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.BlockAndTintGetter; import net.minecraft.world.level.Level; @@ -71,8 +74,9 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.fml.DistExecutor; +import net.minecraftforge.network.NetworkHooks; -public class FactoryPanelBehaviour extends FilteringBehaviour { +public class FactoryPanelBehaviour extends FilteringBehaviour implements MenuProvider { public static final BehaviourType TOP_LEFT = new BehaviourType<>(); public static final BehaviourType TOP_RIGHT = new BehaviourType<>(); @@ -526,6 +530,7 @@ public class FactoryPanelBehaviour extends FilteringBehaviour { @Override public void onShortInteract(Player player, InteractionHand hand, Direction side, BlockHitResult hitResult) { + // Network is protected if (!Create.LOGISTICS.mayInteract(network, player)) { player.displayClientMessage(CreateLang.translate("logistically_linked.protected") .style(ChatFormatting.RED) @@ -533,6 +538,9 @@ public class FactoryPanelBehaviour extends FilteringBehaviour { return; } + boolean isClientSide = player.level().isClientSide; + + // Wrench cycles through arrow bending if (targeting.size() + targetedByLinks.size() > 0 && AllItemTags.WRENCH.matches(player.getItemInHand(hand))) { int sharedMode = -1; boolean notifySelf = false; @@ -547,7 +555,7 @@ public class FactoryPanelBehaviour extends FilteringBehaviour { if (sharedMode == -1) sharedMode = (connection.arrowBendMode + 1) % 4; connection.arrowBendMode = sharedMode; - if (!player.level().isClientSide) + if (!isClientSide) at.blockEntity.notifyUpdate(); } @@ -555,7 +563,7 @@ public class FactoryPanelBehaviour extends FilteringBehaviour { if (sharedMode == -1) sharedMode = (connection.arrowBendMode + 1) % 4; connection.arrowBendMode = sharedMode; - if (!player.level().isClientSide) + if (!isClientSide) notifySelf = true; } @@ -572,23 +580,34 @@ public class FactoryPanelBehaviour extends FilteringBehaviour { return; } - if (player.level().isClientSide) + // Client might be in the process of connecting a panel + if (isClientSide) if (FactoryPanelConnectionHandler.panelClicked(getWorld(), player, this)) return; + ItemStack heldItem = player.getItemInHand(hand); if (getFilter().isEmpty()) { + // Open screen for setting an item through JEI + if (heldItem.isEmpty()) { + if (!isClientSide && player instanceof ServerPlayer sp) + NetworkHooks.openScreen(sp, this, buf -> getPanelPosition().send(buf)); + return; + } + + // Use regular filter interaction for setting the item super.onShortInteract(player, hand, side, hitResult); return; } - ItemStack heldItem = player.getItemInHand(hand); + // Bind logistics items to this panels' frequency if (heldItem.getItem() instanceof LogisticallyLinkedBlockItem) { - if (!player.level().isClientSide) + if (!isClientSide) LogisticallyLinkedBlockItem.assignFrequency(heldItem, player, network); return; } - if (player.level().isClientSide) + // Open configuration screen + if (isClientSide) DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> displayScreen(player)); } @@ -1008,4 +1027,16 @@ public class FactoryPanelBehaviour extends FilteringBehaviour { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> LogisticallyLinkedClientHandler.tickPanel(this)); } + @Override + public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) { + return FactoryPanelSetItemMenu.create(containerId, playerInventory, this); + } + + @Override + public Component getDisplayName() { + return blockEntity.getBlockState() + .getBlock() + .getName(); + } + } diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemMenu.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemMenu.java new file mode 100644 index 0000000000..c68c094b0c --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemMenu.java @@ -0,0 +1,72 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import com.simibubi.create.AllMenuTypes; +import com.simibubi.create.AllSoundEvents; +import com.simibubi.create.foundation.gui.menu.GhostItemMenu; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.MenuType; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.items.ItemStackHandler; +import net.minecraftforge.items.SlotItemHandler; + +public class FactoryPanelSetItemMenu extends GhostItemMenu { + + public FactoryPanelSetItemMenu(MenuType type, int id, Inventory inv, FactoryPanelBehaviour contentHolder) { + super(type, id, inv, contentHolder); + } + + public FactoryPanelSetItemMenu(MenuType type, int id, Inventory inv, FriendlyByteBuf extraData) { + super(type, id, inv, extraData); + } + + public static FactoryPanelSetItemMenu create(int id, Inventory inv, FactoryPanelBehaviour be) { + return new FactoryPanelSetItemMenu(AllMenuTypes.FACTORY_PANEL_SET_ITEM.get(), id, inv, be); + } + + @Override + protected ItemStackHandler createGhostInventory() { + return new ItemStackHandler(1); + } + + @Override + protected boolean allowRepeats() { + return true; + } + + @Override + @OnlyIn(Dist.CLIENT) + protected FactoryPanelBehaviour createOnClient(FriendlyByteBuf extraData) { + FactoryPanelPosition pos = FactoryPanelPosition.receive(extraData); + return FactoryPanelBehaviour.at(Minecraft.getInstance().level, pos); + } + + @Override + protected void addSlots() { + int playerX = 13; + int playerY = 112; + int slotX = 74; + int slotY = 28; + + addPlayerSlots(playerX, playerY); + addSlot(new SlotItemHandler(ghostInventory, 0, slotX, slotY)); + } + + @Override + protected void saveData(FactoryPanelBehaviour contentHolder) { + if (!contentHolder.setFilter(ghostInventory.getStackInSlot(0))) { + player.displayClientMessage(CreateLang.translateDirect("logistics.filter.invalid_item"), true); + AllSoundEvents.DENY.playOnServer(player.level(), player.blockPosition(), 1, 1); + return; + } + player.level() + .playSound(null, contentHolder.getPos(), SoundEvents.ITEM_FRAME_ADD_ITEM, SoundSource.BLOCKS, .25f, .1f); + } + +} diff --git a/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemScreen.java b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemScreen.java new file mode 100644 index 0000000000..6becd82492 --- /dev/null +++ b/src/main/java/com/simibubi/create/content/logistics/factoryBoard/FactoryPanelSetItemScreen.java @@ -0,0 +1,69 @@ +package com.simibubi.create.content.logistics.factoryBoard; + +import java.util.Collections; +import java.util.List; + +import com.simibubi.create.AllBlocks; +import com.simibubi.create.foundation.gui.AllGuiTextures; +import com.simibubi.create.foundation.gui.AllIcons; +import com.simibubi.create.foundation.gui.menu.AbstractSimiContainerScreen; +import com.simibubi.create.foundation.gui.widget.IconButton; +import com.simibubi.create.foundation.utility.CreateLang; + +import net.createmod.catnip.gui.element.GuiGameElement; +import net.minecraft.client.gui.GuiGraphics; +import net.minecraft.client.renderer.Rect2i; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.item.ItemStack; + +public class FactoryPanelSetItemScreen extends AbstractSimiContainerScreen { + + private IconButton confirmButton; + private List extraAreas = Collections.emptyList(); + + public FactoryPanelSetItemScreen(FactoryPanelSetItemMenu container, Inventory inv, Component title) { + super(container, inv, title); + } + + @Override + protected void init() { + int bgHeight = AllGuiTextures.FACTORY_GAUGE_SET_ITEM.getHeight(); + int bgWidth = AllGuiTextures.FACTORY_GAUGE_SET_ITEM.getWidth(); + setWindowSize(bgWidth, bgHeight + AllGuiTextures.PLAYER_INVENTORY.getHeight()); + super.init(); + clearWidgets(); + int x = getGuiLeft(); + int y = getGuiTop(); + + + confirmButton = new IconButton(x + bgWidth - 40, y + bgHeight - 25, AllIcons.I_CONFIRM); + confirmButton.withCallback(() -> minecraft.player.closeContainer()); + addRenderableWidget(confirmButton); + + extraAreas = List.of(new Rect2i(x + bgWidth, y + bgHeight - 30, 40, 20)); + } + + @Override + protected void renderBg(GuiGraphics pGuiGraphics, float pPartialTick, int pMouseX, int pMouseY) { + int x = getGuiLeft(); + int y = getGuiTop(); + AllGuiTextures.FACTORY_GAUGE_SET_ITEM.render(pGuiGraphics, x - 5, y); + renderPlayerInventory(pGuiGraphics, x + 5, y + 94); + + ItemStack stack = AllBlocks.FACTORY_GAUGE.asStack(); + Component title = CreateLang.translate("gui.factory_panel.place_item_to_monitor") + .component(); + pGuiGraphics.drawString(font, title, x + imageWidth / 2 - font.width(title) / 2 - 5, y + 4, 0x3D3C48, false); + + GuiGameElement.of(stack) + .scale(3) + .render(pGuiGraphics, x + 180, y + 48); + } + + @Override + public List getExtraAreas() { + return extraAreas; + } + +} diff --git a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java index 31bcdd9da2..f899d35872 100644 --- a/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java +++ b/src/main/java/com/simibubi/create/foundation/gui/AllGuiTextures.java @@ -157,6 +157,7 @@ public enum AllGuiTextures implements ScreenElement, TextureSheetSegment { FACTORY_GAUGE_RECIPE("factory_gauge", 32, 0, 192, 96), FACTORY_GAUGE_RESTOCK("factory_gauge", 32, 112, 192, 40), FACTORY_GAUGE_BOTTOM("factory_gauge", 32, 176, 200, 64), + FACTORY_GAUGE_SET_ITEM("requester", 16, 160, 184, 88), STOCK_KEEPER_REQUEST_HEADER("stock_keeper", 0, 0, 256, 36), STOCK_KEEPER_REQUEST_BODY("stock_keeper", 0, 48, 256, 20), diff --git a/src/main/resources/assets/create/lang/default/interface.json b/src/main/resources/assets/create/lang/default/interface.json index 37f5ea64eb..09e12fc909 100644 --- a/src/main/resources/assets/create/lang/default/interface.json +++ b/src/main/resources/assets/create/lang/default/interface.json @@ -1094,6 +1094,7 @@ "create.gui.factory_panel.address_missing": "Inactive: missing a target address", "create.gui.factory_panel.no_target_amount_set": "Inactive: no target amount set", "create.gui.factory_panel.has_link_connections": "Gauge has connected links", + "create.gui.factory_panel.place_item_to_monitor": "Place Item to Monitor", "create.gui.redstone_requester.allow_partial": "Allow partial orders", "create.gui.redstone_requester.dont_allow_partial": "Must send all items", diff --git a/src/main/resources/assets/create/textures/gui/requester.png b/src/main/resources/assets/create/textures/gui/requester.png index 39567ab429..76a7fbd678 100644 Binary files a/src/main/resources/assets/create/textures/gui/requester.png and b/src/main/resources/assets/create/textures/gui/requester.png differ