Make InventoryBlock more general

Uses item capabilities for item dropping and a new interface for renaming
This commit is contained in:
KnightMiner committed 2021-01-16 12:59:20 -05:00
1 parent 61d251d45a
commit dfcf3b4146
4 files changed
+148 -42

No files matched your search

@@ -15,8 +15,13 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.IBlockReader;
import net.minecraft.world.World;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import slimeknights.mantle.inventory.BaseContainer;
import slimeknights.mantle.inventory.EmptyItemHandler;
import slimeknights.mantle.tileentity.IRenamableContainerProvider;
import slimeknights.mantle.tileentity.InventoryTileEntity;
import javax.annotation.Nullable;
@@ -87,8 +92,8 @@ public abstract class InventoryBlock extends Block {
// set custom name from named stack
if (stack.hasDisplayName()) {
TileEntity tileentity = worldIn.getTileEntity(pos);
if (tileentity instanceof InventoryTileEntity) {
((InventoryTileEntity) tileentity).setCustomName(stack.getDisplayName());
if (tileentity instanceof IRenamableContainerProvider) {
((IRenamableContainerProvider) tileentity).setCustomName(stack.getDisplayName());
}
}
}
@@ -110,9 +115,15 @@ public abstract class InventoryBlock extends Block {
@Override
public void onReplaced(BlockState state, World worldIn, BlockPos pos, BlockState newState, boolean isMoving) {
if (state.getBlock() != newState.getBlock()) {
TileEntity tileentity = worldIn.getTileEntity(pos);
if (tileentity instanceof InventoryTileEntity) {
dropInventoryItems(state, worldIn, pos, (InventoryTileEntity) tileentity);
TileEntity te = worldIn.getTileEntity(pos);
if (te != null) {
// FIXME legacy support, switch to non-deprecated method in 1.17
if (te instanceof InventoryTileEntity) {
dropInventoryItems(state, worldIn, pos, (InventoryTileEntity) te);
} else {
te.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY)
.ifPresent(inventory -> dropInventoryItems(state, worldIn, pos, inventory));
}
worldIn.updateComparatorOutputLevel(pos, this);
}
}
@@ -126,9 +137,42 @@ public abstract class InventoryBlock extends Block {
* @param worldIn Tile world
* @param pos Tile position
* @param inventory Tile entity instance
* @deprecated Will remove in 1.17, use {@link #dropInventoryItems(BlockState, World, BlockPos, IItemHandler)}
*/
@Deprecated
protected void dropInventoryItems(BlockState state, World worldIn, BlockPos pos, InventoryTileEntity inventory) {
InventoryHelper.dropInventoryItems(worldIn, pos, inventory);
LazyOptional<IItemHandler> itemCapability = inventory.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY);
if (itemCapability.isPresent()) {
dropInventoryItems(state, worldIn, pos, itemCapability.orElse(EmptyItemHandler.INSTANCE));
} else {
InventoryHelper.dropInventoryItems(worldIn, pos, inventory);
}
}
/**
* Called when the block is replaced to drop contained items.
* @param state Block state
* @param worldIn Tile world
* @param pos Tile position
* @param inventory Item handler
*/
protected void dropInventoryItems(BlockState state, World worldIn, BlockPos pos, IItemHandler inventory) {
dropInventoryItems(worldIn, pos, inventory);
}
/**
* Drops all items from the given inventory in world
* @param world World instance
* @param pos Position to drop
* @param inventory Inventory instance
*/
public static void dropInventoryItems(World world, BlockPos pos, IItemHandler inventory) {
double x = pos.getX();
double y = pos.getY();
double z = pos.getZ();
for(int i = 0; i < inventory.getSlots(); ++i) {
InventoryHelper.spawnItemStack(world, x, y, z, inventory.getStackInSlot(i));
}
}
@SuppressWarnings("deprecation")
@@ -0,0 +1,44 @@
package slimeknights.mantle.inventory;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import net.minecraft.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
/**
* Item handler that contains no items. Use similarly to {@link net.minecraftforge.fluids.capability.templates.EmptyFluidHandler}
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class EmptyItemHandler implements IItemHandler {
public static final EmptyItemHandler INSTANCE = new EmptyItemHandler();
@Override
public int getSlots() {
return 0;
}
@Override
public int getSlotLimit(int slot) {
return 0;
}
@Override
public ItemStack getStackInSlot(int slot) {
return ItemStack.EMPTY;
}
@Override
public boolean isItemValid(int slot, ItemStack stack) {
return false;
}
@Override
public ItemStack insertItem(int slot, ItemStack stack, boolean simulate) {
return stack;
}
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
return ItemStack.EMPTY;
}
}
@@ -0,0 +1,44 @@
package slimeknights.mantle.tileentity;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.util.INameable;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nullable;
/**
* Interface for containers that can be renamed. Used in {@link slimeknights.mantle.block.InventoryBlock} to set the name on placement
*/
public interface IRenamableContainerProvider extends INamedContainerProvider, INameable {
/**
* Gets the default name of this tile entity
* @return Default name
*/
ITextComponent getDefaultName();
/**
* Gets the custom name for this tile entity
* @return Custom name
*/
@Override
@Nullable
ITextComponent getCustomName();
/**
* Sets the name for this tile entity
* @param name New custom name
*/
void setCustomName(ITextComponent name);
@Override
default ITextComponent getName() {
ITextComponent customTitle = getCustomName();
return customTitle != null ? customTitle : getDefaultName();
}
@Override
default ITextComponent getDisplayName() {
return getName();
}
}
@@ -1,62 +1,36 @@
package slimeknights.mantle.tileentity;
import lombok.Getter;
import lombok.Setter;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.INameable;
import net.minecraft.util.text.ITextComponent;
import net.minecraftforge.common.util.Constants.NBT;
import javax.annotation.Nullable;
/**
* Extension of tile entity to make it namable
*/
public abstract class NamableTileEntity extends MantleTileEntity implements INamedContainerProvider, INameable {
public abstract class NamableTileEntity extends MantleTileEntity implements IRenamableContainerProvider {
private static final String TAG_CUSTOM_NAME = "CustomName";
/** Default title for this tile entity */
private final ITextComponent defaultTitle;
@Getter
private final ITextComponent defaultName;
/** Title set to this tile entity */
private ITextComponent customTitle;
@Getter @Setter
private ITextComponent customName;
public NamableTileEntity(TileEntityType<?> tileEntityTypeIn, ITextComponent defaultTitle) {
super(tileEntityTypeIn);
this.defaultTitle = defaultTitle;
}
@Override
public ITextComponent getName() {
return customTitle != null ? customTitle : defaultTitle;
}
@Nullable
public ITextComponent getCustomName() {
return customTitle;
}
/**
* Sets the name for this tile entity
* @param customName New custom name
*/
public void setCustomName(ITextComponent customName) {
this.customTitle = customName;
}
@Override
public ITextComponent getDisplayName() {
return getName();
this.defaultName = defaultTitle;
}
@Override
public void read(BlockState blockState, CompoundNBT tags) {
super.read(blockState, tags);
if (tags.contains(TAG_CUSTOM_NAME, NBT.TAG_STRING)) {
this.customTitle = ITextComponent.Serializer.getComponentFromJson(tags.getString(TAG_CUSTOM_NAME));
this.customName = ITextComponent.Serializer.getComponentFromJson(tags.getString(TAG_CUSTOM_NAME));
}
}
@@ -64,7 +38,7 @@ public abstract class NamableTileEntity extends MantleTileEntity implements INam
public void writeSynced(CompoundNBT tags) {
super.writeSynced(tags);
if (this.hasCustomName()) {
tags.putString(TAG_CUSTOM_NAME, ITextComponent.Serializer.toJson(this.customTitle));
tags.putString(TAG_CUSTOM_NAME, ITextComponent.Serializer.toJson(this.customName));
}
}
}