Added Stalinium Cache block with shared party inventory functionality. Updated loot tables, block entities, menus, and localized translations. Bumped version to 0.2.0.

This commit is contained in:
IM23a-spirgif
2025-06-10 14:46:49 +02:00
parent ea5084653d
commit 7da7dddafa
9 changed files with 190 additions and 11 deletions
@@ -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.StaliniumCacheBlock;
import net.krituximon.stalinium.block.custom.StaliniumPressBlock;
import net.krituximon.stalinium.item.ModItems;
import net.minecraft.util.valueproviders.UniformInt;
@@ -46,6 +47,10 @@ public class ModBlocks {
public static final DeferredBlock<Block> STALINIUM_PRESS = registerBlock("stalinium_press",
() -> new StaliniumPressBlock(BlockBehaviour.Properties.of()));
public static final DeferredBlock<StaliniumCacheBlock> STALINIUM_CACHE = registerBlock(
"stalinium_cache",
() -> new StaliniumCacheBlock(Block.Properties.of()));
private static <T extends Block> DeferredBlock<T> registerBlock(String name, Supplier<T> block) {
DeferredBlock<T> toReturn = BLOCKS.register(name, block);
registerBlockItem(name, toReturn);
@@ -0,0 +1,82 @@
package net.krituximon.stalinium.block.custom;
import com.mojang.serialization.MapCodec;
import net.krituximon.stalinium.block.entity.ModBlockEntities;
import net.krituximon.stalinium.block.entity.StaliniumCacheBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.*;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.ChestMenu;
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 StaliniumCacheBlock extends BaseEntityBlock {
// 1) supply a real codec so the block actually constructs from your registry
public static final MapCodec<StaliniumCacheBlock> CODEC =
simpleCodec(StaliniumCacheBlock::new);
public StaliniumCacheBlock(Properties props) {
super(props);
}
@Override
protected MapCodec<? extends BaseEntityBlock> codec() {
return CODEC;
}
@Nullable
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState state) {
return ModBlockEntities.STALINIUM_CACHE_BE.get().create(pos, state);
}
@Override
protected RenderShape getRenderShape(BlockState state) {
return RenderShape.MODEL;
}
@Override
protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level level,
BlockPos pos, Player player, InteractionHand hand,
BlockHitResult hit) {
if (!level.isClientSide() && player instanceof ServerPlayer sp) {
var container = StaliniumCacheBlockEntity.getPartyInventory(sp);
sp.openMenu(new SimpleMenuProvider(
(id, inv, p) -> ChestMenu.threeRows(id, inv, container),
Component.translatable("container.stalinium.cache")
), pos);
}
return ItemInteractionResult.sidedSuccess(level.isClientSide());
}
@Override
@SuppressWarnings("unchecked")
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(
Level level, BlockState state, BlockEntityType<T> type) {
return null;
}
@Override
public void onRemove(BlockState oldSt, Level world, BlockPos pos,
BlockState newSt, boolean moving) {
if (!oldSt.is(newSt.getBlock())) {
var be = world.getBlockEntity(pos);
if (be instanceof StaliniumCacheBlockEntity cache) {
cache.drops();
}
}
super.onRemove(oldSt, world, pos, newSt, moving);
}
}
@@ -64,7 +64,6 @@ public class StaliniumPressBlock extends BaseEntityBlock {
throw new IllegalStateException("Our Container provider is missing!");
}
}
return ItemInteractionResult.sidedSuccess(pLevel.isClientSide());
}
@@ -19,6 +19,14 @@ public class ModBlockEntities {
BLOCK_ENTITIES.register("stalinium_press_be", () -> BlockEntityType.Builder.of(
StaliniumPressBlockEntity::new, ModBlocks.STALINIUM_PRESS.get()).build(null));
public static final Supplier<BlockEntityType<StaliniumCacheBlockEntity>> STALINIUM_CACHE_BE =
BLOCK_ENTITIES.register("stalinium_cache", () ->
BlockEntityType.Builder.of(
StaliniumCacheBlockEntity::new,
ModBlocks.STALINIUM_CACHE.get()
).build(null)
);
public static void register(IEventBus eventBus) {
BLOCK_ENTITIES.register(eventBus);
}
@@ -0,0 +1,70 @@
// StaliniumCacheBlockEntity.java
package net.krituximon.stalinium.block.entity;
import net.krituximon.stalinium.event.ComradeHandler;
import net.minecraft.core.BlockPos;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.Registries;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.Containers;
import net.minecraft.world.SimpleContainer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.ContainerData;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import javax.annotation.Nullable;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
public class StaliniumCacheBlockEntity extends BlockEntity {
private static final int SIZE = 27;
// each party → shared 27slot inventory
private static final Map<UUID, SimpleContainer> PARTY_INVENTORIES = new ConcurrentHashMap<>();
public StaliniumCacheBlockEntity(BlockPos pos, BlockState state) {
super(ModBlockEntities.STALINIUM_CACHE_BE.get(), pos, state);
}
/**
* Grab (or create) the shared SimpleContainer for this player's party
*/
public static SimpleContainer getPartyInventory(Player who) {
Optional<ComradeHandler.Party> opt = ComradeHandler.findPartyOf(who.getUUID());
UUID key = opt.map(p -> p.leader).orElse(who.getUUID());
return PARTY_INVENTORIES.computeIfAbsent(key, __ -> new SimpleContainer(SIZE));
}
/** Drop everything, using that same shared container */
public void drops() {
SimpleContainer inv = getPartyInventory((ServerPlayer) null);
// actually, we don't know "who" here—just drop all slots
SimpleContainer tmp = new SimpleContainer(SIZE);
for (int i = 0; i < SIZE; i++) {
tmp.setItem(i, inv.getItem(i));
}
Containers.dropContents(level, worldPosition, tmp);
}
@Override
protected void saveAdditional(CompoundTag tag, HolderLookup.Provider prov) {
super.saveAdditional(tag, prov);
}
@Override
@Nullable
public Packet<ClientGamePacketListener> getUpdatePacket() {
return ClientboundBlockEntityDataPacket.create(this);
}
}
@@ -38,6 +38,7 @@ public class ModBlockLootTableProvider extends BlockLootSubProvider {
dropSelf(ModBlocks.STALINIUM_BLOCK.get());
dropSelf(ModBlocks.COMPRESSED_BEDROCK.get());
dropSelf(ModBlocks.STALINIUM_PRESS.get());
dropSelf(ModBlocks.STALINIUM_CACHE.get());
}
@@ -3,7 +3,9 @@ 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.SimpleContainer;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ChestMenu;
import net.minecraft.world.inventory.MenuType;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.common.extensions.IMenuTypeExtension;
@@ -15,15 +17,24 @@ 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));
@SuppressWarnings("unchecked")
private static <T extends AbstractContainerMenu> DeferredHolder<MenuType<T>, MenuType<T>>
registerMenuType(String name, IContainerFactory<T> factory) {
return (DeferredHolder<MenuType<T>, MenuType<T>>) (Object) MENUS.register(name, () -> IMenuTypeExtension.create(factory));
}
public static void register(IEventBus eventBus) {
MENUS.register(eventBus);
// press menu
public static final DeferredHolder<MenuType<StaliniumPressMenu>,MenuType<StaliniumPressMenu>>
STALINIUM_PRESS_MENU = registerMenuType("stalinium_press_menu", StaliniumPressMenu::new);
// cache menu — *also* use registerMenuType so the generics line up:
public static final DeferredHolder<MenuType<ChestMenu>,MenuType<ChestMenu>>
STALINIUM_CACHE_MENU = registerMenuType(
"stalinium_cache",
(windowId, inv, buf) -> ChestMenu.threeRows(windowId, inv, new SimpleContainer(27))
);
public static void register(IEventBus bus) {
MENUS.register(bus);
}
}