Add Stalinium Press block and its functionality

This commit is contained in:
IM23a-spirgif
2025-05-15 11:29:05 +02:00
parent 4bd30f9215
commit 51fa5f6f34
10 changed files with 496 additions and 2 deletions
@@ -1,9 +1,13 @@
package net.krituximon.stalinium;
import net.krituximon.stalinium.block.ModBlocks;
import net.krituximon.stalinium.block.entity.ModBlockEntities;
import net.krituximon.stalinium.item.ModItems;
import net.krituximon.stalinium.particle.BloodParticle;
import net.krituximon.stalinium.particle.ModParticles;
import net.krituximon.stalinium.screen.ModMenuTypes;
import net.krituximon.stalinium.screen.custom.StaliniumPressMenu;
import net.krituximon.stalinium.screen.custom.StaliniumPressScreen;
import net.krituximon.stalinium.sound.ModSounds;
import net.krituximon.stalinium.worldgen.ModFeatures;
import net.krituximon.stalinium.worldgen.StaliniumVeinFeature;
@@ -11,6 +15,7 @@ import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.levelgen.feature.Feature;
import net.minecraft.world.level.levelgen.feature.configurations.NoneFeatureConfiguration;
import net.neoforged.neoforge.client.event.RegisterMenuScreensEvent;
import net.neoforged.neoforge.client.event.RegisterParticleProvidersEvent;
import org.slf4j.Logger;
@@ -67,6 +72,8 @@ public class Stalinium
// Register our mod's ModConfigSpec so that FML can create and load the config file for us
modContainer.registerConfig(ModConfig.Type.COMMON, Config.SPEC);
ModFeatures.register(modEventBus);
ModBlockEntities.register(modEventBus);
ModMenuTypes.register(modEventBus);
}
private void commonSetup(final FMLCommonSetupEvent event)
@@ -111,5 +118,9 @@ public class Stalinium
public static void registerParticleFactories(RegisterParticleProvidersEvent event) {
event.registerSpriteSet(ModParticles.BLOOD_PARTICLE.get(), BloodParticle.Provider::new);
}
@SubscribeEvent
public static void registerScreens(RegisterMenuScreensEvent event) {
event.register(ModMenuTypes.STALINIUM_PRESS_MENU.get(), StaliniumPressScreen::new);
}
}
}
@@ -2,6 +2,7 @@ package net.krituximon.stalinium.block;
import net.krituximon.stalinium.Stalinium;
import net.krituximon.stalinium.block.custom.CompressedBedrock;
import net.krituximon.stalinium.block.custom.StaliniumPressBlock;
import net.krituximon.stalinium.item.ModItems;
import net.minecraft.util.valueproviders.UniformInt;
import net.minecraft.world.item.BlockItem;
@@ -42,7 +43,8 @@ public class ModBlocks {
.requiresCorrectToolForDrops()
.sound(SoundType.NETHERITE_BLOCK)));
public static final DeferredBlock<Block> STALINIUM_PRESS = registerBlock("stalinium_press",
() -> new StaliniumPressBlock(BlockBehaviour.Properties.of()));
private static <T extends Block> DeferredBlock<T> registerBlock(String name, Supplier<T> block) {
DeferredBlock<T> toReturn = BLOCKS.register(name, block);
@@ -0,0 +1,81 @@
package net.krituximon.stalinium.block.custom;
import com.mojang.serialization.MapCodec;
import net.krituximon.stalinium.block.entity.StaliniumPressBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.ItemInteractionResult;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.RenderShape;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import org.jetbrains.annotations.Nullable;
public class StaliniumPressBlock extends BaseEntityBlock {
public static final MapCodec<StaliniumPressBlock> CODEC = simpleCodec(StaliniumPressBlock::new);
public StaliniumPressBlock(Properties properties) {
super(properties);
}
@Override
protected MapCodec<? extends BaseEntityBlock> codec() {
return CODEC;
}
@Override
public @Nullable BlockEntity newBlockEntity(BlockPos blockPos, BlockState blockState) {
return net.krituximon.stalinium.block.entity.ModBlockEntities.STALINIUM_PRESS_BE.get().create(blockPos, blockState) ;
}
@Override
protected RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
@Override
public void onRemove(BlockState pState, Level pLevel, BlockPos pPos, BlockState pNewState, boolean pIsMoving) {
if (pState.getBlock() != pNewState.getBlock()) {
BlockEntity blockEntity = pLevel.getBlockEntity(pPos);
if (blockEntity instanceof StaliniumPressBlockEntity StaliniumPressBlockEntity) {
StaliniumPressBlockEntity.drops();
}
}
super.onRemove(pState, pLevel, pPos, pNewState, pIsMoving);
}
@Override
protected ItemInteractionResult useItemOn(ItemStack pStack, BlockState pState, Level pLevel, BlockPos pPos,
Player pPlayer, InteractionHand pHand, BlockHitResult pHitResult) {
if (!pLevel.isClientSide()) {
BlockEntity entity = pLevel.getBlockEntity(pPos);
if(entity instanceof StaliniumPressBlockEntity staliniumPressBlockEntity) {
((ServerPlayer) pPlayer).openMenu(new SimpleMenuProvider(staliniumPressBlockEntity, Component.literal("Stalinium Press")), pPos);
} else {
throw new IllegalStateException("Our Container provider is missing!");
}
}
return ItemInteractionResult.sidedSuccess(pLevel.isClientSide());
}
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state, BlockEntityType<T> blockEntityType) {
if(level.isClientSide()) {
return null;
}
return createTickerHelper(blockEntityType, net.krituximon.stalinium.block.entity.ModBlockEntities.STALINIUM_PRESS_BE.get(),
(level1, blockPos, blockState, blockEntity) -> blockEntity.tick(level1, blockPos, blockState));
}
}
@@ -0,0 +1,25 @@
package net.krituximon.stalinium.block.entity;
import net.krituximon.stalinium.Stalinium;
import net.krituximon.stalinium.block.ModBlocks;
import net.krituximon.stalinium.block.entity.StaliniumPressBlockEntity;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredRegister;
import java.util.function.Supplier;
public class ModBlockEntities {
public static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES =
DeferredRegister.create(BuiltInRegistries.BLOCK_ENTITY_TYPE, Stalinium.MODID);
public static final Supplier<BlockEntityType<StaliniumPressBlockEntity>> STALINIUM_PRESS_BE =
BLOCK_ENTITIES.register("stalinium_press_be", () -> BlockEntityType.Builder.of(
StaliniumPressBlockEntity::new, ModBlocks.STALINIUM_PRESS.get()).build(null));
public static void register(IEventBus eventBus) {
BLOCK_ENTITIES.register(eventBus);
}
}
@@ -0,0 +1,176 @@
package net.krituximon.stalinium.block.entity;
import net.krituximon.stalinium.item.ModItems;
import net.krituximon.stalinium.screen.custom.StaliniumPressMenu;
import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.world.Containers;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.neoforged.neoforge.items.ItemStackHandler;
import org.jetbrains.annotations.Nullable;
import javax.swing.plaf.basic.BasicComboBoxUI;
public class StaliniumPressBlockEntity extends BlockEntity implements MenuProvider {
public final ItemStackHandler itemHandler = new ItemStackHandler(2) {
@Override
protected void onContentsChanged(int slot) {
setChanged();
if (!level.isClientSide()) {
level.sendBlockUpdated(getBlockPos(), getBlockState(), getBlockState(), 3);
}
}
};
private static final int INPUT_SLOT = 0;
private static final int OUTPUT_SLOT = 1;
protected final ContainerData data;
private int progress = 0;
private int maxProgress = 72;
public StaliniumPressBlockEntity(BlockPos pos, BlockState blockState) {
super(ModBlockEntities.STALINIUM_PRESS_BE.get(), pos, blockState);
data = new ContainerData() {
@Override
public int get(int i) {
return switch (i) {
case 0 -> net.krituximon.stalinium.block.entity.StaliniumPressBlockEntity.this.progress;
case 1 -> net.krituximon.stalinium.block.entity.StaliniumPressBlockEntity.this.maxProgress;
default -> 0;
};
}
@Override
public void set(int i, int value) {
switch (i) {
case 0:
net.krituximon.stalinium.block.entity.StaliniumPressBlockEntity.this.progress = value;
case 1:
net.krituximon.stalinium.block.entity.StaliniumPressBlockEntity.this.maxProgress = value;
}
}
@Override
public int getCount() {
return 2;
}
};
}
@Override
public Component getDisplayName() {
return Component.translatable("block.stalinium.stalinium_press");
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int i, Inventory inventory, Player player) {
return new StaliniumPressMenu(i, inventory, this, this.data);
}
public void drops() {
SimpleContainer inventory = new SimpleContainer(itemHandler.getSlots());
for (int i = 0; i < itemHandler.getSlots(); i++) {
inventory.setItem(i, itemHandler.getStackInSlot(i));
}
Containers.dropContents(this.level, this.worldPosition, inventory);
}
@Override
protected void saveAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
pTag.put("inventory", itemHandler.serializeNBT(pRegistries));
pTag.putInt("growth_chamber.progress", progress);
pTag.putInt("growth_chamber.max_progress", maxProgress);
super.saveAdditional(pTag, pRegistries);
}
@Override
protected void loadAdditional(CompoundTag pTag, HolderLookup.Provider pRegistries) {
super.loadAdditional(pTag, pRegistries);
itemHandler.deserializeNBT(pRegistries, pTag.getCompound("inventory"));
progress = pTag.getInt("growth_chamber.progress");
maxProgress = pTag.getInt("growth_chamber.max_progress");
}
public void tick(Level level, BlockPos blockPos, BlockState blockState) {
if (hasRecipe()) {
increaseCraftingProgress();
setChanged(level, blockPos, blockState);
if (hasCraftingFinished()) {
craftItem();
resetProgress();
}
} else {
resetProgress();
}
}
private void craftItem() {
if (itemHandler.getStackInSlot(INPUT_SLOT).getCount() < 9) return;
ItemStack output = new ItemStack(ModItems.STALINIUM_INGOT.get(), 1);
itemHandler.extractItem(INPUT_SLOT, 9, false);
itemHandler.setStackInSlot(OUTPUT_SLOT, new ItemStack(output.getItem(),
itemHandler.getStackInSlot(OUTPUT_SLOT).getCount() + output.getCount()));
}
private void resetProgress() {
progress = 0;
maxProgress = 600;
}
private boolean hasCraftingFinished() {
return this.progress >= this.maxProgress;
}
private void increaseCraftingProgress() {
progress++;
}
private boolean hasRecipe() {
ItemStack output = new ItemStack(ModItems.STALINIUM_INGOT.get(), 1);
return itemHandler.getStackInSlot(INPUT_SLOT).is(ModItems.STALINIUM_NUGGET) &&
canInsertAmountIntoOutputSlot(output.getCount()) && canInsertItemIntoOutputSlot(output);
}
private boolean canInsertItemIntoOutputSlot(ItemStack output) {
return itemHandler.getStackInSlot(OUTPUT_SLOT).isEmpty() ||
itemHandler.getStackInSlot(OUTPUT_SLOT).getItem() == output.getItem();
}
private boolean canInsertAmountIntoOutputSlot(int count) {
int maxCount = itemHandler.getStackInSlot(OUTPUT_SLOT).isEmpty() ? 64 : itemHandler.getStackInSlot(OUTPUT_SLOT).getMaxStackSize();
int currentCount = itemHandler.getStackInSlot(OUTPUT_SLOT).getCount();
return maxCount >= currentCount + count;
}
@Override
public CompoundTag getUpdateTag(HolderLookup.Provider pRegistries) {
return saveWithoutMetadata(pRegistries);
}
@Nullable
@Override
public Packet<ClientGamePacketListener> getUpdatePacket() {
return ClientboundBlockEntityDataPacket.create(this);
}
}
@@ -37,6 +37,7 @@ public class ModBlockLootTableProvider extends BlockLootSubProvider {
);
dropSelf(ModBlocks.STALINIUM_BLOCK.get());
dropSelf(ModBlocks.COMPRESSED_BEDROCK.get());
dropSelf(ModBlocks.STALINIUM_PRESS.get());
}
@@ -0,0 +1,29 @@
package net.krituximon.stalinium.screen;
import net.krituximon.stalinium.Stalinium;
import net.krituximon.stalinium.screen.custom.StaliniumPressMenu;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.MenuType;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.common.extensions.IMenuTypeExtension;
import net.neoforged.neoforge.network.IContainerFactory;
import net.neoforged.neoforge.registries.DeferredHolder;
import net.neoforged.neoforge.registries.DeferredRegister;
public class ModMenuTypes {
public static final DeferredRegister<MenuType<?>> MENUS =
DeferredRegister.create(Registries.MENU, Stalinium.MODID);
public static final DeferredHolder<MenuType<?>, MenuType<StaliniumPressMenu>> STALINIUM_PRESS_MENU =
registerMenuType("stalinium_press_menu", StaliniumPressMenu::new);
private static <T extends AbstractContainerMenu> DeferredHolder<MenuType<?>, MenuType<T>> registerMenuType(String name,
IContainerFactory<T> factory) {
return MENUS.register(name, () -> IMenuTypeExtension.create(factory));
}
public static void register(IEventBus eventBus) {
MENUS.register(eventBus);
}
}
@@ -0,0 +1,121 @@
package net.krituximon.stalinium.screen.custom;
import net.krituximon.stalinium.block.ModBlocks;
import net.krituximon.stalinium.block.entity.StaliniumPressBlockEntity;
import net.krituximon.stalinium.screen.ModMenuTypes;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.*;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.neoforged.neoforge.items.SlotItemHandler;
public class StaliniumPressMenu extends AbstractContainerMenu {
public final StaliniumPressBlockEntity blockEntity;
private final Level level;
private final ContainerData data;
public StaliniumPressMenu(int pContainerId, Inventory inv, FriendlyByteBuf extraData) {
this(pContainerId, inv, inv.player.level().getBlockEntity(extraData.readBlockPos()), new SimpleContainerData(2));
}
public StaliniumPressMenu(int pContainerId, Inventory inv, BlockEntity entity, ContainerData data) {
super(ModMenuTypes.STALINIUM_PRESS_MENU.get(), pContainerId);
this.blockEntity = ((StaliniumPressBlockEntity) entity);
this.level = inv.player.level();
this.data = data;
addPlayerInventory(inv);
addPlayerHotbar(inv);
this.addSlot(new SlotItemHandler(blockEntity.itemHandler, 0, 54, 34));
this.addSlot(new SlotItemHandler(blockEntity.itemHandler, 1, 104, 34));
addDataSlots(data);
}
public boolean isCrafting() {
return data.get(0) > 0;
}
public int getScaledArrowProgress() {
int progress = this.data.get(0);
int maxProgress = this.data.get(1);
int arrowPixelSize = 24;
return maxProgress != 0 && progress != 0 ? progress * arrowPixelSize / maxProgress : 0;
}
// CREDIT GOES TO: diesieben07 | https://github.com/diesieben07/SevenCommons
// must assign a slot number to each of the slots used by the GUI.
// For this container, we can see both the tile inventory's slots as well as the player inventory slots and the hotbar.
// Each time we add a Slot to the container, it automatically increases the slotIndex, which means
// 0 - 8 = hotbar slots (which will map to the InventoryPlayer slot numbers 0 - 8)
// 9 - 35 = player inventory slots (which map to the InventoryPlayer slot numbers 9 - 35)
// 36 - 44 = TileInventory slots, which map to our TileEntity slot numbers 0 - 8)
private static final int HOTBAR_SLOT_COUNT = 9;
private static final int PLAYER_INVENTORY_ROW_COUNT = 3;
private static final int PLAYER_INVENTORY_COLUMN_COUNT = 9;
private static final int PLAYER_INVENTORY_SLOT_COUNT = PLAYER_INVENTORY_COLUMN_COUNT * PLAYER_INVENTORY_ROW_COUNT;
private static final int VANILLA_SLOT_COUNT = HOTBAR_SLOT_COUNT + PLAYER_INVENTORY_SLOT_COUNT;
private static final int VANILLA_FIRST_SLOT_INDEX = 0;
private static final int TE_INVENTORY_FIRST_SLOT_INDEX = VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT;
// THIS YOU HAVE TO DEFINE!
private static final int TE_INVENTORY_SLOT_COUNT = 2; // must be the number of slots you have!
@Override
public ItemStack quickMoveStack(Player playerIn, int pIndex) {
Slot sourceSlot = slots.get(pIndex);
if (sourceSlot == null || !sourceSlot.hasItem()) return ItemStack.EMPTY; //EMPTY_ITEM
ItemStack sourceStack = sourceSlot.getItem();
ItemStack copyOfSourceStack = sourceStack.copy();
// Check if the slot clicked is one of the vanilla container slots
if (pIndex < VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT) {
// This is a vanilla container slot so merge the stack into the tile inventory
if (!moveItemStackTo(sourceStack, TE_INVENTORY_FIRST_SLOT_INDEX, TE_INVENTORY_FIRST_SLOT_INDEX
+ TE_INVENTORY_SLOT_COUNT, false)) {
return ItemStack.EMPTY; // EMPTY_ITEM
}
} else if (pIndex < TE_INVENTORY_FIRST_SLOT_INDEX + TE_INVENTORY_SLOT_COUNT) {
// This is a TE slot so merge the stack into the players inventory
if (!moveItemStackTo(sourceStack, VANILLA_FIRST_SLOT_INDEX, VANILLA_FIRST_SLOT_INDEX + VANILLA_SLOT_COUNT, false)) {
return ItemStack.EMPTY;
}
} else {
System.out.println("Invalid slotIndex:" + pIndex);
return ItemStack.EMPTY;
}
// If stack size == 0 (the entire stack was moved) set slot contents to null
if (sourceStack.getCount() == 0) {
sourceSlot.set(ItemStack.EMPTY);
} else {
sourceSlot.setChanged();
}
sourceSlot.onTake(playerIn, sourceStack);
return copyOfSourceStack;
}
@Override
public boolean stillValid(Player pPlayer) {
return stillValid(ContainerLevelAccess.create(level, blockEntity.getBlockPos()),
pPlayer, ModBlocks.STALINIUM_PRESS.get());
}
private void addPlayerInventory(Inventory playerInventory) {
for (int i = 0; i < 3; ++i) {
for (int l = 0; l < 9; ++l) {
this.addSlot(new Slot(playerInventory, l + i * 9 + 9, 8 + l * 18, 84 + i * 18));
}
}
}
private void addPlayerHotbar(Inventory playerInventory) {
for (int i = 0; i < 9; ++i) {
this.addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
}
}
}
@@ -0,0 +1,47 @@
package net.krituximon.stalinium.screen.custom;
import com.mojang.blaze3d.systems.RenderSystem;
import net.krituximon.stalinium.Stalinium;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
public class StaliniumPressScreen extends AbstractContainerScreen<StaliniumPressMenu> {
private static final ResourceLocation GUI_TEXTURE =
ResourceLocation.fromNamespaceAndPath(Stalinium.MODID,"textures/gui/growth_chamber/growth_chamber_gui.png");
private static final ResourceLocation ARROW_TEXTURE =
ResourceLocation.fromNamespaceAndPath(Stalinium.MODID, "textures/gui/arrow_progress.png");
public StaliniumPressScreen(StaliniumPressMenu menu, Inventory playerInventory, Component title) {
super(menu, playerInventory, title);
}
@Override
protected void renderBg(GuiGraphics guiGraphics, float v, int i, int i1) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.setShaderTexture(0, GUI_TEXTURE);
int x = (width - imageWidth) / 2;
int y = (height - imageHeight) / 2;
guiGraphics.blit(GUI_TEXTURE, x, y, 0, 0, imageWidth, imageHeight);
renderProgressArrow(guiGraphics, x, y);
}
private void renderProgressArrow(GuiGraphics guiGraphics, int x, int y) {
if(menu.isCrafting()) {
guiGraphics.blit(ARROW_TEXTURE,x + 73, y + 35, 0, 0, menu.getScaledArrowProgress(), 16, 24, 16);
}
}
@Override
public void render(GuiGraphics pGuiGraphics, int pMouseX, int pMouseY, float pPartialTick) {
super.render(pGuiGraphics, pMouseX, pMouseY, pPartialTick);
this.renderTooltip(pGuiGraphics, pMouseX, pMouseY);
}
}
@@ -7,5 +7,6 @@
"block.stalinium.stalinium_block": "Block of Stalinium",
"block.stalinium.stalinium_ore": "Stalinium Ore",
"block.stalinium.compressed_bedrock": "Compressed Bedrock"
"block.stalinium.compressed_bedrock": "Compressed Bedrock",
"block.stalinium.stalinium_press": "Stalinium Press"
}