Gauges and JEI

- Added the ability to pull in items from JEI when configuring gauges initially (empty hand on empty panel)
This commit is contained in:
simibubi 2025-02-07 14:35:04 +01:00
parent 728efc0a84
commit c1268da86a
8 changed files with 189 additions and 8 deletions

View file

@ -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<RedstoneRequesterMenu> REDSTONE_REQUESTER =
register("redstone_requester", RedstoneRequesterMenu::new, () -> RedstoneRequesterScreen::new);
public static final MenuEntry<FactoryPanelSetItemMenu> FACTORY_PANEL_SET_ITEM =
register("factory_panel_set_item", FactoryPanelSetItemMenu::new, () -> FactoryPanelSetItemScreen::new);
private static <C extends AbstractContainerMenu, S extends Screen & MenuAccess<C>> MenuEntry<C> register(
String name, ForgeMenuFactory<C> factory, NonNullSupplier<ScreenFactory<C, S>> screenFactory) {
return Create.REGISTRATE

View file

@ -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<T extends Recipe<?>> {

View file

@ -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<FactoryPanelBehaviour> TOP_LEFT = new BehaviourType<>();
public static final BehaviourType<FactoryPanelBehaviour> 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();
}
}

View file

@ -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<FactoryPanelBehaviour> {
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);
}
}

View file

@ -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<FactoryPanelSetItemMenu> {
private IconButton confirmButton;
private List<Rect2i> 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<Rect2i> getExtraAreas() {
return extraAreas;
}
}

View file

@ -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),

View file

@ -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",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB