Skip to content

Commit 14f6e2c

Browse files
KaupenjoeKaupenjoe
authored andcommitted
block entity menu
1 parent 4ea5faf commit 14f6e2c

7 files changed

Lines changed: 202 additions & 1 deletion

File tree

src/main/java/net/kaupenjoe/tutorialmod/TutorialMod.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@
1616
import net.kaupenjoe.tutorialmod.particle.BismuthParticles;
1717
import net.kaupenjoe.tutorialmod.particle.ModParticles;
1818
import net.kaupenjoe.tutorialmod.potion.ModPotions;
19+
import net.kaupenjoe.tutorialmod.screen.ModMenuTypes;
20+
import net.kaupenjoe.tutorialmod.screen.custom.PedestalScreen;
1921
import net.kaupenjoe.tutorialmod.sound.ModSounds;
2022
import net.kaupenjoe.tutorialmod.util.ModItemProperties;
2123
import net.kaupenjoe.tutorialmod.villager.ModVillagers;
2224
import net.minecraft.client.renderer.entity.EntityRenderers;
2325
import net.minecraft.world.item.CreativeModeTabs;
2426
import net.neoforged.neoforge.client.event.EntityRenderersEvent;
27+
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
2528
import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent;
2629
import org.slf4j.Logger;
2730

@@ -77,6 +80,8 @@ public TutorialMod(IEventBus modEventBus, ModContainer modContainer) {
7780
ModLootModifiers.register(modEventBus);
7881
ModBlockEntities.register(modEventBus);
7982

83+
ModMenuTypes.register(modEventBus);
84+
8085
// Register the item to a creative tab
8186
modEventBus.addListener(this::addCreative);
8287
// Register our mod's ModConfigSpec so that FML can create and load the config file for us
@@ -128,5 +133,10 @@ public static void registerParticleFactories(RegisterParticleProvidersEvent even
128133
public static void registerBER(EntityRenderersEvent.RegisterRenderers event) {
129134
event.registerBlockEntityRenderer(ModBlockEntities.PEDESTAL_BE.get(), PedestalBlockEntityRenderer::new);
130135
}
136+
137+
@SubscribeEvent
138+
public static void registerScreens(RegisterMenuScreensEvent event) {
139+
event.register(ModMenuTypes.PEDESTAL_MENU.get(), PedestalScreen::new);
140+
}
131141
}
132142
}

src/main/java/net/kaupenjoe/tutorialmod/block/custom/PedestalBlock.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,14 @@
33
import com.mojang.serialization.MapCodec;
44
import net.kaupenjoe.tutorialmod.block.entity.PedestalBlockEntity;
55
import net.minecraft.core.BlockPos;
6+
import net.minecraft.network.chat.Component;
7+
import net.minecraft.server.level.ServerPlayer;
68
import net.minecraft.sounds.SoundEvent;
79
import net.minecraft.sounds.SoundEvents;
810
import net.minecraft.sounds.SoundSource;
911
import net.minecraft.world.InteractionHand;
1012
import net.minecraft.world.ItemInteractionResult;
13+
import net.minecraft.world.SimpleMenuProvider;
1114
import net.minecraft.world.entity.player.Player;
1215
import net.minecraft.world.item.ItemStack;
1316
import net.minecraft.world.level.BlockGetter;
@@ -68,6 +71,11 @@ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState
6871
protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level, BlockPos pos,
6972
Player player, InteractionHand hand, BlockHitResult hitResult) {
7073
if(level.getBlockEntity(pos) instanceof PedestalBlockEntity pedestalBlockEntity) {
74+
if(player.isCrouching() && !level.isClientSide()) {
75+
((ServerPlayer) player).openMenu(new SimpleMenuProvider(pedestalBlockEntity, Component.literal("Pedestal")), pos);
76+
return ItemInteractionResult.SUCCESS;
77+
}
78+
7179
if(pedestalBlockEntity.inventory.getStackInSlot(0).isEmpty() && !stack.isEmpty()) {
7280
pedestalBlockEntity.inventory.insertItem(0, stack.copy(), false);
7381
stack.shrink(1);

src/main/java/net/kaupenjoe/tutorialmod/block/entity/PedestalBlockEntity.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,26 @@
11
package net.kaupenjoe.tutorialmod.block.entity;
22

3+
import net.kaupenjoe.tutorialmod.screen.custom.PedestalMenu;
34
import net.minecraft.core.BlockPos;
45
import net.minecraft.core.HolderLookup;
56
import net.minecraft.nbt.CompoundTag;
7+
import net.minecraft.network.chat.Component;
68
import net.minecraft.network.protocol.Packet;
79
import net.minecraft.network.protocol.game.ClientGamePacketListener;
810
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
911
import net.minecraft.world.Containers;
12+
import net.minecraft.world.MenuProvider;
1013
import net.minecraft.world.SimpleContainer;
14+
import net.minecraft.world.entity.player.Inventory;
15+
import net.minecraft.world.entity.player.Player;
16+
import net.minecraft.world.inventory.AbstractContainerMenu;
1117
import net.minecraft.world.item.ItemStack;
1218
import net.minecraft.world.level.block.entity.BlockEntity;
1319
import net.minecraft.world.level.block.state.BlockState;
1420
import net.neoforged.neoforge.items.ItemStackHandler;
1521
import org.jetbrains.annotations.Nullable;
1622

17-
public class PedestalBlockEntity extends BlockEntity {
23+
public class PedestalBlockEntity extends BlockEntity implements MenuProvider {
1824
public final ItemStackHandler inventory = new ItemStackHandler(1) {
1925
@Override
2026
protected int getStackLimit(int slot, ItemStack stack) {
@@ -68,6 +74,18 @@ protected void loadAdditional(CompoundTag tag, HolderLookup.Provider registries)
6874
inventory.deserializeNBT(registries, tag.getCompound("inventory"));
6975
}
7076

77+
@Override
78+
public Component getDisplayName() {
79+
return Component.literal("Pedestal");
80+
}
81+
82+
@Nullable
83+
@Override
84+
public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
85+
return new PedestalMenu(i, inventory, this);
86+
}
87+
88+
7189
@Nullable
7290
@Override
7391
public Packet<ClientGamePacketListener> getUpdatePacket() {
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package net.kaupenjoe.tutorialmod.screen;
2+
3+
import net.kaupenjoe.tutorialmod.TutorialMod;
4+
import net.kaupenjoe.tutorialmod.screen.custom.PedestalMenu;
5+
import net.minecraft.core.registries.Registries;
6+
import net.minecraft.world.inventory.AbstractContainerMenu;
7+
import net.minecraft.world.inventory.MenuType;
8+
import net.neoforged.bus.api.IEventBus;
9+
import net.neoforged.neoforge.common.extensions.IMenuTypeExtension;
10+
import net.neoforged.neoforge.network.IContainerFactory;
11+
import net.neoforged.neoforge.registries.DeferredHolder;
12+
import net.neoforged.neoforge.registries.DeferredRegister;
13+
14+
public class ModMenuTypes {
15+
public static final DeferredRegister<MenuType<?>> MENUS =
16+
DeferredRegister.create(Registries.MENU, TutorialMod.MOD_ID);
17+
18+
public static final DeferredHolder<MenuType<?>, MenuType<PedestalMenu>> PEDESTAL_MENU =
19+
registerMenuType("pedestal_menu", PedestalMenu::new);
20+
21+
private static <T extends AbstractContainerMenu>DeferredHolder<MenuType<?>, MenuType<T>> registerMenuType(String name,
22+
IContainerFactory<T> factory) {
23+
return MENUS.register(name, () -> IMenuTypeExtension.create(factory));
24+
}
25+
26+
public static void register(IEventBus eventBus) {
27+
MENUS.register(eventBus);
28+
}
29+
}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package net.kaupenjoe.tutorialmod.screen.custom;
2+
3+
import net.kaupenjoe.tutorialmod.block.ModBlocks;
4+
import net.kaupenjoe.tutorialmod.block.entity.PedestalBlockEntity;
5+
import net.kaupenjoe.tutorialmod.screen.ModMenuTypes;
6+
import net.minecraft.network.FriendlyByteBuf;
7+
import net.minecraft.world.entity.player.Inventory;
8+
import net.minecraft.world.entity.player.Player;
9+
import net.minecraft.world.inventory.AbstractContainerMenu;
10+
import net.minecraft.world.inventory.ContainerLevelAccess;
11+
import net.minecraft.world.inventory.Slot;
12+
import net.minecraft.world.item.ItemStack;
13+
import net.minecraft.world.level.Level;
14+
import net.minecraft.world.level.block.entity.BlockEntity;
15+
import net.neoforged.neoforge.items.SlotItemHandler;
16+
17+
public class PedestalMenu extends AbstractContainerMenu {
18+
public final PedestalBlockEntity blockEntity;
19+
private final Level level;
20+
21+
public PedestalMenu(int containerId, Inventory inv, FriendlyByteBuf extraData) {
22+
this(containerId, inv, inv.player.level().getBlockEntity(extraData.readBlockPos()));
23+
}
24+
25+
public PedestalMenu(int containerId, Inventory inv, BlockEntity blockEntity) {
26+
super(ModMenuTypes.PEDESTAL_MENU.get(), containerId);
27+
this.blockEntity = ((PedestalBlockEntity) blockEntity);
28+
this.level = inv.player.level();
29+
30+
addPlayerInventory(inv);
31+
addPlayerHotbar(inv);
32+
33+
this.addSlot(new SlotItemHandler(this.blockEntity.inventory, 0, 80, 35));
34+
}
35+
36+
// CREDIT GOES TO: diesieben07 | https://github.com/diesieben07/SevenCommons
37+
// must assign a slot number to each of the slots used by the GUI.
38+
// For this container, we can see both the tile inventory's slots as well as the player inventory slots and the hotbar.
39+
// Each time we add a Slot to the container, it automatically increases the slotIndex, which means
40+
// 0 - 8 = hotbar slots (which will map to the InventoryPlayer slot numbers 0 - 8)
41+
// 9 - 35 = player inventory slots (which map to the InventoryPlayer slot numbers 9 - 35)
42+
// 36 - 44 = TileInventory slots, which map to our TileEntity slot numbers 0 - 8)
43+
private static final int HOTBAR_SLOT_COUNT = 9;
44+
private static final int PLAYER_INVENTORY_ROW_COUNT = 3;
45+
private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9;
46+
private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT;
47+
private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT;
48+
private static final int VANILLA_FIRST_SLOT_INDEX = 0;
49+
private static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT;
50+
51+
// THIS YOU HAVE TO DEFINE!
52+
private static final int TE_INVENTORY_SLOT_COUNT = 1; // must be the number of slots you have!
53+
@Override
54+
public ItemStack quickMoveStack(Player playerIn, int pIndex) {
55+
Slot sourceSlot = slots.get(pIndex);
56+
if (sourceSlot == null || !sourceSlot.hasItem()) return ItemStack.EMPTY; //EMPTY_ITEM
57+
ItemStack sourceStack = sourceSlot.getItem();
58+
ItemStack copyOfSourceStack = sourceStack.copy();
59+
60+
// Check if the slot clicked is one of the vanilla container slots
61+
if (pIndex < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) {
62+
// This is a vanilla container slot so merge the stack into the tile inventory
63+
if (!moveItemStackTo(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX
64+
+ TE_INVENTORY_SLOT_COUNT, false)) {
65+
return ItemStack.EMPTY; // EMPTY_ITEM
66+
}
67+
} else if (pIndex < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) {
68+
// This is a TE slot so merge the stack into the players inventory
69+
if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) {
70+
return ItemStack.EMPTY;
71+
}
72+
} else {
73+
System.out.println("Invalid slotIndex:" + pIndex);
74+
return ItemStack.EMPTY;
75+
}
76+
// If stack size == 0 (the entire stack was moved) set slot contents to null
77+
if (sourceStack.getCount() == 0) {
78+
sourceSlot.set(ItemStack.EMPTY);
79+
} else {
80+
sourceSlot.setChanged();
81+
}
82+
sourceSlot.onTake(playerIn, sourceStack);
83+
return copyOfSourceStack;
84+
}
85+
86+
@Override
87+
public boolean stillValid(Player player) {
88+
return stillValid(ContainerLevelAccess.create(level, blockEntity.getBlockPos()),
89+
player, ModBlocks.PEDESTAL.get());
90+
}
91+
92+
private void addPlayerInventory(Inventory playerInventory) {
93+
for (int i = 0; i < 3; ++i) {
94+
for (int l = 0; l < 9; ++l) {
95+
this.addSlot(new Slot(playerInventory, l + i * 9 + 9, 8 + l * 18, 84 + i * 18));
96+
}
97+
}
98+
}
99+
100+
private void addPlayerHotbar(Inventory playerInventory) {
101+
for (int i = 0; i < 9; ++i) {
102+
this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
103+
}
104+
}
105+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package net.kaupenjoe.tutorialmod.screen.custom;
2+
3+
import com.mojang.blaze3d.systems.RenderSystem;
4+
import net.kaupenjoe.tutorialmod.TutorialMod;
5+
import net.minecraft.client.gui.GuiGraphics;
6+
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
7+
import net.minecraft.client.renderer.GameRenderer;
8+
import net.minecraft.network.chat.Component;
9+
import net.minecraft.resources.ResourceLocation;
10+
import net.minecraft.world.entity.player.Inventory;
11+
12+
public class PedestalScreen extends AbstractContainerScreen<PedestalMenu> {
13+
private static final ResourceLocation GUI_TEXTURE =
14+
ResourceLocation.fromNamespaceAndPath(TutorialMod.MOD_ID, "textures/gui/pedestal/pedestal_gui.png");
15+
16+
public PedestalScreen(PedestalMenu menu, Inventory playerInventory, Component title) {
17+
super(menu, playerInventory, title);
18+
}
19+
20+
@Override
21+
protected void renderBg(GuiGraphics guiGraphics, float pPartialTick, int pMouseX, int pMouseY) {
22+
RenderSystem.setShader(GameRenderer::getPositionTexShader);
23+
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
24+
RenderSystem.setShaderTexture(0, GUI_TEXTURE);
25+
26+
int x = (width - imageWidth) / 2;
27+
int y = (height - imageHeight) / 2;
28+
29+
guiGraphics.blit(GUI_TEXTURE, x, y, 0, 0, imageWidth, imageHeight);
30+
}
31+
}
1.19 KB
Loading

0 commit comments

Comments
 (0)