filter for the block stacker

This commit is contained in:
Jottyfan 2022-11-28 23:22:22 +01:00
parent 7992e5d9ba
commit 4ff86faf91
15 changed files with 817 additions and 16 deletions

View File

@ -9,7 +9,7 @@
loader_version=0.14.9
# Mod Properties
mod_version = 1.19.2.0
mod_version = 1.19.2.1
maven_group = de.jottyfan.minecraft
archives_base_name = quickiefabric

View File

@ -2,24 +2,26 @@ package de.jottyfan.minecraft.quickiefabric;
import de.jottyfan.minecraft.quickiefabric.blocks.QuickieBlocks;
import de.jottyfan.minecraft.quickiefabric.container.BackpackScreen;
import de.jottyfan.minecraft.quickiefabric.container.BlockStackerScreen;
import de.jottyfan.minecraft.quickiefabric.init.RegistryManager;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.screenhandler.v1.ScreenRegistry;
import net.minecraft.client.gui.screen.ingame.HandledScreens;
import net.minecraft.client.render.RenderLayer;
/**
*
*
* @author jotty
*
*/
@Environment(EnvType.CLIENT)
public class QuickieFabricClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
ScreenRegistry.register(RegistryManager.BACKPACK_SCREEN_HANDLER, BackpackScreen::new);
public void onInitializeClient() {
HandledScreens.register(RegistryManager.BACKPACK_SCREEN_HANDLER, BackpackScreen::new);
HandledScreens.register(RegistryManager.BLOCKSTACKER_SCREEN_HANDLER, BlockStackerScreen::new);
// make cotton plant block transparent
BlockRenderLayerMap.INSTANCE.putBlock(QuickieBlocks.COTTONPLANT, RenderLayer.getCutout());
}

View File

@ -1,14 +1,28 @@
package de.jottyfan.minecraft.quickiefabric.blockentity;
import java.util.ArrayList;
import java.util.List;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.jottyfan.minecraft.quickiefabric.blocks.help.BlockStacker;
import de.jottyfan.minecraft.quickiefabric.container.BlockStackerScreenHandler;
import de.jottyfan.minecraft.quickiefabric.container.ImplementedInventory;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.LootableContainerBlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventories;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.text.Text;
import net.minecraft.util.collection.DefaultedList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
@ -17,13 +31,55 @@ import net.minecraft.world.World;
* @author jotty
*
*/
public class BlockStackerEntity extends BlockEntity {
public class BlockStackerEntity extends BlockEntity implements NamedScreenHandlerFactory, ImplementedInventory {
private static final Logger LOGGER = LogManager.getLogger(BlockStackerEntity.class);
private final DefaultedList<ItemStack> inventory = DefaultedList.ofSize(9, ItemStack.EMPTY);
public BlockStackerEntity(BlockPos blockPos, BlockState blockState) {
super(QuickieFabricBlockEntity.BLOCKSTACKER_ENTITY, blockPos, blockState);
}
@Override
public DefaultedList<ItemStack> getItems() {
return inventory;
}
@Override
public ScreenHandler createMenu(int syncId, PlayerInventory playerInventory, PlayerEntity player) {
return new BlockStackerScreenHandler(syncId, playerInventory, this);
}
@Override
public Text getDisplayName() {
return Text.translatable(getCachedState().getBlock().getTranslationKey());
}
@Override
public void readNbt(NbtCompound nbt) {
super.readNbt(nbt);
Inventories.readNbt(nbt, inventory);
}
@Override
public void writeNbt(NbtCompound nbt) {
Inventories.writeNbt(nbt, inventory);
super.writeNbt(nbt);
}
/**
* if whitelist, return true if current == pattern; return false otherwise
*
* @param current the current item stack
* @param pattern the item stack to compare with
* @param whitelist if true, filter only current == pattern, if false, filter
* all but that
* @return true or false
*/
public static final Boolean filter(ItemStack current, ItemStack pattern, Boolean whitelist) {
Boolean matches = pattern.getItem().equals(current.getItem());
return whitelist ? matches : !matches;
}
public static void tick(World world, BlockPos pos, BlockState state, BlockStackerEntity entity) {
if (!world.isClient) {
pos.down();
@ -35,13 +91,23 @@ public class BlockStackerEntity extends BlockEntity {
if (sourceIsLootable && destIsLootable) {
LootableContainerBlockEntity lootableSource = (LootableContainerBlockEntity) source;
LootableContainerBlockEntity lootableDest = (LootableContainerBlockEntity) dest;
transferOneStack(lootableSource, lootableDest);
List<Item> checked = new ArrayList<>();
Boolean found = false;
Item item = findNextItem(entity.getItems(), checked);
while(!found && item != null) {
checked.add(item);
Boolean whitelist = true;
found = transferOneStack(lootableSource, lootableDest, item, whitelist);
item = findNextItem(entity.getItems(), checked);
}
}
}
}
private static final void transferOneStack(LootableContainerBlockEntity source, LootableContainerBlockEntity dest) {
Integer sourceSlot = findItemStackPos(source, false);
private static final Boolean transferOneStack(LootableContainerBlockEntity source, LootableContainerBlockEntity dest,
Item filterItem, Boolean whitelist) {
Boolean result = false;
Integer sourceSlot = findItemStackPos(source, filterItem, whitelist);
if (sourceSlot != null && !Items.AIR.equals(source.getStack(sourceSlot).getItem())) {
ItemStack sourceStack = source.getStack(sourceSlot);
Integer destSlot = findItemStackPos(dest, sourceStack);
@ -51,21 +117,38 @@ public class BlockStackerEntity extends BlockEntity {
Integer candidates = source.getStack(sourceSlot).getCount();
Integer travellers = candidates > free ? free : candidates;
if (travellers > 0) {
LOGGER.debug("transfer {}/{} of {} from slot {} to slot {} on top of {} ones", travellers, candidates, source.getStack(sourceSlot).getItem().toString(), sourceSlot, destSlot, occupied);
LOGGER.debug("transfer {}/{} of {} from slot {} to slot {} on top of {} ones", travellers, candidates,
source.getStack(sourceSlot).getItem().toString(), sourceSlot, destSlot, occupied);
source.getStack(sourceSlot).decrement(travellers);
if (source.getStack(sourceSlot).getCount() < 1) {
source.removeStack(sourceSlot); // make empty slots really empty
}
dest.getStack(destSlot).increment(travellers);
result = true;
}
} else {
Integer destFreeSlot = findItemStackPos(dest, true);
if (destFreeSlot != null) {
LOGGER.debug("transfer all of {} from slot {} to slot {}", source.getStack(sourceSlot).getItem().toString(), sourceSlot, destSlot);
LOGGER.debug("transfer all of {} from slot {} to slot {}", source.getStack(sourceSlot).getItem().toString(),
sourceSlot, destSlot);
dest.setStack(destFreeSlot, source.removeStack(sourceSlot));
result = true;
}
}
}
return result;
}
private static final Item findNextItem(List<ItemStack> inventory, List<Item> exclude) {
for (ItemStack stack : inventory) {
if (!stack.isEmpty()) {
Item item = stack.getItem();
if (!exclude.contains(item)) {
return item;
}
}
}
return null;
}
private static final Integer findItemStackPos(LootableContainerBlockEntity lcbe, ItemStack sourceStack) {
@ -73,7 +156,7 @@ public class BlockStackerEntity extends BlockEntity {
while (counter > 0) {
counter--;
ItemStack stack = lcbe.getStack(counter);
if (stack.getItem().equals(sourceStack.getItem())) {
if (sourceStack.getItem().equals(stack.getItem())) {
if (stack.getCount() < stack.getMaxCount()) {
return counter;
}
@ -93,4 +176,30 @@ public class BlockStackerEntity extends BlockEntity {
}
return null;
}
private static final Integer findItemStackPos(LootableContainerBlockEntity lcbe, Item item, Boolean whitelist) {
if (item == null) {
return findItemStackPos(lcbe, false);
} else {
if (whitelist == null) {
whitelist = true;
LOGGER.error("whitelist is null");
}
Integer counter = lcbe.size();
while (counter > 0) {
counter--;
ItemStack stack = lcbe.getStack(counter);
Boolean found = item.equals(stack.getItem());
if (whitelist ? found : !found) {
return counter;
}
}
return null;
}
}
@Override
public int size() {
return inventory.size();
}
}

View File

@ -14,8 +14,15 @@ import net.minecraft.block.Material;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContext.Builder;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
@ -64,4 +71,39 @@ public class BlockStackerDown extends BlockWithEntity implements BlockStacker {
return checkType(type, QuickieFabricBlockEntity.BLOCKSTACKER_ENTITY,
(world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockHitResult hit) {
if (!world.isClient) {
NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos);
if (screenHandlerFactory != null) {
player.openHandledScreen(screenHandlerFactory);
}
}
return ActionResult.SUCCESS;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof BlockStackerEntity) {
ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity);
// update comparators
world.updateComparators(pos, this);
}
super.onStateReplaced(state, world, pos, newState, moved);
}
}
@Override
public boolean hasComparatorOutput(BlockState state) {
return true;
}
@Override
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos));
}
}

View File

@ -14,8 +14,15 @@ import net.minecraft.block.Material;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContext.Builder;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
@ -64,4 +71,39 @@ public class BlockStackerEast extends BlockWithEntity implements BlockStacker {
return checkType(type, QuickieFabricBlockEntity.BLOCKSTACKER_ENTITY,
(world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockHitResult hit) {
if (!world.isClient) {
NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos);
if (screenHandlerFactory != null) {
player.openHandledScreen(screenHandlerFactory);
}
}
return ActionResult.SUCCESS;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof BlockStackerEntity) {
ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity);
// update comparators
world.updateComparators(pos, this);
}
super.onStateReplaced(state, world, pos, newState, moved);
}
}
@Override
public boolean hasComparatorOutput(BlockState state) {
return true;
}
@Override
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos));
}
}

View File

@ -14,8 +14,15 @@ import net.minecraft.block.Material;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContext.Builder;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
@ -64,4 +71,39 @@ public class BlockStackerNorth extends BlockWithEntity implements BlockStacker {
return checkType(type, QuickieFabricBlockEntity.BLOCKSTACKER_ENTITY,
(world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockHitResult hit) {
if (!world.isClient) {
NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos);
if (screenHandlerFactory != null) {
player.openHandledScreen(screenHandlerFactory);
}
}
return ActionResult.SUCCESS;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof BlockStackerEntity) {
ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity);
// update comparators
world.updateComparators(pos, this);
}
super.onStateReplaced(state, world, pos, newState, moved);
}
}
@Override
public boolean hasComparatorOutput(BlockState state) {
return true;
}
@Override
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos));
}
}

View File

@ -14,8 +14,15 @@ import net.minecraft.block.Material;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContext.Builder;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
@ -64,4 +71,39 @@ public class BlockStackerSouth extends BlockWithEntity implements BlockStacker {
return checkType(type, QuickieFabricBlockEntity.BLOCKSTACKER_ENTITY,
(world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockHitResult hit) {
if (!world.isClient) {
NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos);
if (screenHandlerFactory != null) {
player.openHandledScreen(screenHandlerFactory);
}
}
return ActionResult.SUCCESS;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof BlockStackerEntity) {
ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity);
// update comparators
world.updateComparators(pos, this);
}
super.onStateReplaced(state, world, pos, newState, moved);
}
}
@Override
public boolean hasComparatorOutput(BlockState state) {
return true;
}
@Override
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos));
}
}

View File

@ -14,8 +14,15 @@ import net.minecraft.block.Material;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContext.Builder;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
@ -64,4 +71,39 @@ public class BlockStackerUp extends BlockWithEntity implements BlockStacker {
return checkType(type, QuickieFabricBlockEntity.BLOCKSTACKER_ENTITY,
(world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockHitResult hit) {
if (!world.isClient) {
NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos);
if (screenHandlerFactory != null) {
player.openHandledScreen(screenHandlerFactory);
}
}
return ActionResult.SUCCESS;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof BlockStackerEntity) {
ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity);
// update comparators
world.updateComparators(pos, this);
}
super.onStateReplaced(state, world, pos, newState, moved);
}
}
@Override
public boolean hasComparatorOutput(BlockState state) {
return true;
}
@Override
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos));
}
}

View File

@ -14,8 +14,15 @@ import net.minecraft.block.Material;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.context.LootContext.Builder;
import net.minecraft.screen.NamedScreenHandlerFactory;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.ItemScatterer;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.world.World;
@ -64,4 +71,39 @@ public class BlockStackerWest extends BlockWithEntity implements BlockStacker {
return checkType(type, QuickieFabricBlockEntity.BLOCKSTACKER_ENTITY,
(world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand,
BlockHitResult hit) {
if (!world.isClient) {
NamedScreenHandlerFactory screenHandlerFactory = state.createScreenHandlerFactory(world, pos);
if (screenHandlerFactory != null) {
player.openHandledScreen(screenHandlerFactory);
}
}
return ActionResult.SUCCESS;
}
@Override
public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) {
if (state.getBlock() != newState.getBlock()) {
BlockEntity blockEntity = world.getBlockEntity(pos);
if (blockEntity instanceof BlockStackerEntity) {
ItemScatterer.spawn(world, pos, (BlockStackerEntity) blockEntity);
// update comparators
world.updateComparators(pos, this);
}
super.onStateReplaced(state, world, pos, newState, moved);
}
}
@Override
public boolean hasComparatorOutput(BlockState state) {
return true;
}
@Override
public int getComparatorOutput(BlockState state, World world, BlockPos pos) {
return ScreenHandler.calculateComparatorOutput(world.getBlockEntity(pos));
}
}

View File

@ -1,5 +1,6 @@
package de.jottyfan.minecraft.quickiefabric.blocks.help;
import net.minecraft.block.BlockEntityProvider;
import net.minecraft.util.math.Direction;
/**
@ -7,7 +8,7 @@ import net.minecraft.util.math.Direction;
* @author jotty
*
*/
public interface BlockStacker {
public interface BlockStacker extends BlockEntityProvider {
/**
* define the source offset
*

View File

@ -0,0 +1,176 @@
package de.jottyfan.minecraft.quickiefabric.container;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import de.jottyfan.minecraft.quickiefabric.items.ItemBackpack;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.nbt.NbtList;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Hand;
/**
*
* @author jotty
*
*/
public class BlockStackerInventory extends SimpleInventory {
private static final String NBT_BLOCKSTACKER = "blockstacer";
private static final String NBT_SLOT = "slot";
private static final String NBT_ITEMS = "items";
private Hand hand;
private BlockStackerInventory(NbtCompound tag, BlockStackerScreenHandler handler) {
super(1);
readItemsFromTag(super.size(), tag);
}
public BlockStackerInventory(ItemStack stack) {
this(init(stack).getOrCreateNbt().getCompound(NBT_BLOCKSTACKER), null);
}
public static final BlockStackerInventory getInventory(BlockStackerScreenHandler handler, PlayerEntity player,
ItemStack stack) {
return new BlockStackerInventory(init(stack).getOrCreateNbt().getCompound(NBT_BLOCKSTACKER), handler);
}
private final static ItemStack init(ItemStack stack) {
if (stack != null) {
if (!stack.getOrCreateNbt().contains(NBT_BLOCKSTACKER)) {
stack.getOrCreateNbt().put(NBT_BLOCKSTACKER, new NbtCompound());
}
}
return stack;
}
@Override
public void onOpen(PlayerEntity player) {
super.onOpen(player);
player.playSound(SoundEvents.BLOCK_CHEST_OPEN, SoundCategory.PLAYERS, 1f, 1f);
}
@Override
public void onClose(PlayerEntity player) {
super.onClose(player);
ItemStack stack = player.getStackInHand(hand);
if (stack != null) {
stack.getOrCreateNbt().put(NBT_BLOCKSTACKER, writeItemsToTag(super.size()));
}
player.getStackInHand(hand).setNbt(stack.getNbt());
player.playSound(SoundEvents.BLOCK_CHEST_CLOSE, SoundCategory.PLAYERS, 1f, 1f);
}
private void readItemsFromTag(Integer size, NbtCompound tag) {
NbtList listTag = tag.getList(NBT_ITEMS, NbtElement.COMPOUND_TYPE);
for (int i = 0; i < listTag.size(); ++i) {
NbtCompound compoundTag = listTag.getCompound(i);
int slot = compoundTag.getInt(NBT_SLOT);
if (slot >= 0 && slot < size) {
super.setStack(slot, ItemStack.fromNbt(compoundTag));
}
}
}
private NbtCompound writeItemsToTag(int slotsize) {
NbtList listTag = new NbtList();
for (int slot = 0; slot < slotsize; ++slot) {
ItemStack itemStack = super.getStack(slot);
if (!(itemStack == null) && !itemStack.isEmpty()) {
listTag.add(prepareCompoundTag(slot, itemStack));
}
}
NbtCompound tag = new NbtCompound();
tag.put(NBT_ITEMS, listTag);
return tag;
}
private static final NbtCompound prepareCompoundTag(Integer slot, ItemStack stack) {
NbtCompound compoundTag = new NbtCompound();
compoundTag.putInt(NBT_SLOT, slot);
stack.writeNbt(compoundTag);
return compoundTag;
}
public void setHand(Hand hand) {
this.hand = hand;
}
/**
* get the items from the itemStack that contains the backpack
*
* @param itemStack the itemStack of the backpack
* @return the list of found itemStacks in the backpack
*/
public static List<ItemStack> getItemsFromBackpack(ItemStack itemStack) {
NbtCompound backpackNbt = init(itemStack).getOrCreateNbt().getCompound(NBT_BLOCKSTACKER);
NbtList listTag = backpackNbt.getList(NBT_ITEMS, NbtElement.COMPOUND_TYPE);
List<ItemStack> items = new ArrayList<>();
for (int i = 0; i < listTag.size(); ++i) {
NbtCompound compoundTag = listTag.getCompound(i);
int slot = compoundTag.getInt(NBT_SLOT);
if (slot >= 0 && slot < ItemBackpack.SLOTSIZE) {
ItemStack stack = ItemStack.fromNbt(compoundTag);
items.add(stack);
}
}
return items;
}
/**
* set the items in the itemStack that contains the backpack
*
* @param itemStack the backpack's itemStack
* @param itemStacks the collection of lists of itemStacks for the backpack
*/
public static void setItemsToBackpack(ItemStack itemStack, Collection<List<ItemStack>> itemStacks) {
NbtList listTag = new NbtList();
Integer slot = 0;
for (List<ItemStack> stacks : itemStacks) {
if (stacks != null && stacks.size() > 0) {
ItemStack stack = stacks.get(0);
Integer leftCount = 0;
for (ItemStack is : stacks) {
leftCount += is.getCount();
}
while (leftCount > 0) {
if (leftCount > stack.getMaxCount()) {
stack.setCount(stack.getMaxCount());
leftCount = leftCount - stack.getMaxCount();
} else {
stack.setCount(leftCount);
leftCount = 0;
}
listTag.add(prepareCompoundTag(slot, stack));
slot++;
}
}
}
NbtCompound tag = new NbtCompound();
tag.put(NBT_ITEMS, listTag);
itemStack.getOrCreateNbt().put(NBT_BLOCKSTACKER, tag);
}
/**
* replace every slot of the backpack with the content of backpackInventory
*
* @param itemStack the backpack's itemStack
* @param backpackInventory the replacement inventory
*/
public static void setItemsToBackpack(ItemStack itemStack, BlockStackerInventory backpackInventory) {
Collection<List<ItemStack>> itemStacks = new ArrayList<>();
for (int i = 0; i < backpackInventory.size(); i++) {
ItemStack stack = backpackInventory.getStack(i);
List<ItemStack> list = new ArrayList<>();
list.add(stack);
itemStacks.add(list);
}
setItemsToBackpack(itemStack, itemStacks);
}
}

View File

@ -0,0 +1,51 @@
package de.jottyfan.minecraft.quickiefabric.container;
import com.mojang.blaze3d.systems.RenderSystem;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.gui.screen.ingame.HandledScreen;
import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider;
import net.minecraft.client.render.GameRenderer;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
/**
*
* @author jotty
*
*/
@Environment(EnvType.CLIENT)
public class BlockStackerScreen extends HandledScreen<BlockStackerScreenHandler>
implements ScreenHandlerProvider<BlockStackerScreenHandler> {
private final static Identifier TEXTURE = new Identifier("minecraft", "textures/gui/container/dispenser.png");
public BlockStackerScreen(BlockStackerScreenHandler handler, PlayerInventory inventory, Text text) {
super(handler, inventory, text);
}
@Override
protected void init() {
super.init();
this.titleX = (backgroundWidth - textRenderer.getWidth(title)) / 2;
}
@Override
public void render(MatrixStack matrices, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(matrices);
super.render(matrices, mouseX, mouseY, partialTicks);
this.drawMouseoverTooltip(matrices, mouseX, mouseY);
}
@Override
protected void drawBackground(MatrixStack matrices, float delta, int mouseX, int mouseY) {
RenderSystem.setShader(GameRenderer::getPositionTexShader);
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
RenderSystem.setShaderTexture(0, TEXTURE);
int x = (width - backgroundWidth) / 2;
int y = (height - backgroundHeight) / 2;
drawTexture(matrices, x, y, 0, 0, backgroundWidth, backgroundHeight);
}
}

View File

@ -0,0 +1,76 @@
package de.jottyfan.minecraft.quickiefabric.container;
import de.jottyfan.minecraft.quickiefabric.init.RegistryManager;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.screen.slot.Slot;
/**
*
* @author jotty
*
*/
public class BlockStackerScreenHandler extends ScreenHandler {
public static final Integer SLOTSIZE = 9;
private final Inventory inventory;
public BlockStackerScreenHandler(int syncId, PlayerInventory playerInventory) {
this(syncId, playerInventory, new SimpleInventory(SLOTSIZE));
}
public BlockStackerScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory) {
super(RegistryManager.BLOCKSTACKER_SCREEN_HANDLER, syncId);
checkSize(inventory, SLOTSIZE);
this.inventory = inventory;
inventory.onOpen(playerInventory.player);
int m;
int l;
for (m = 0; m < 3; ++m) {
for (l = 0; l < 3; ++l) {
this.addSlot(new Slot(inventory, l + m * 3, 62 + l * 18, 17 + m * 18));
}
}
for (m = 0; m < 3; ++m) {
for (l = 0; l < 9; ++l) {
this.addSlot(new Slot(playerInventory, l + m * 9 + 9, 8 + l * 18, 84 + m * 18));
}
}
for (m = 0; m < 9; ++m) {
this.addSlot(new Slot(playerInventory, m, 8 + m * 18, 142));
}
}
@Override
public boolean canUse(PlayerEntity player) {
return this.inventory.canPlayerUse(player);
}
@Override
public ItemStack transferSlot(PlayerEntity player, int invSlot) {
ItemStack newStack = ItemStack.EMPTY;
Slot slot = this.slots.get(invSlot);
if (slot != null && slot.hasStack()) {
ItemStack originalStack = slot.getStack();
newStack = originalStack.copy();
if (invSlot < this.inventory.size()) {
if (!this.insertItem(originalStack, this.inventory.size(), this.slots.size(), true)) {
return ItemStack.EMPTY;
}
} else if (!this.insertItem(originalStack, 0, this.inventory.size(), false)) {
return ItemStack.EMPTY;
}
if (originalStack.isEmpty()) {
slot.setStack(ItemStack.EMPTY);
} else {
slot.markDirty();
}
}
return newStack;
}
}

View File

@ -0,0 +1,133 @@
package de.jottyfan.minecraft.quickiefabric.container;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.Inventories;
import net.minecraft.inventory.Inventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.collection.DefaultedList;
/**
*
* @author jotty
*
* @see https://fabricmc.net/wiki/tutorial:inventory
*
*/
public interface ImplementedInventory extends Inventory {
/**
* Retrieves the item list of this inventory.
* Must return the same instance every time it's called.
*/
DefaultedList<ItemStack> getItems();
/**
* Creates an inventory from the item list.
*/
static ImplementedInventory of(DefaultedList<ItemStack> items) {
return () -> items;
}
/**
* Creates a new inventory with the specified size.
*/
static ImplementedInventory ofSize(int size) {
return of(DefaultedList.ofSize(size, ItemStack.EMPTY));
}
/**
* Returns the inventory size.
*/
@Override
default int size() {
return getItems().size();
}
/**
* Checks if the inventory is empty.
* @return true if this inventory has only empty stacks, false otherwise.
*/
@Override
default boolean isEmpty() {
for (int i = 0; i < size(); i++) {
ItemStack stack = getStack(i);
if (!stack.isEmpty()) {
return false;
}
}
return true;
}
/**
* Retrieves the item in the slot.
*/
@Override
default ItemStack getStack(int slot) {
return getItems().get(slot);
}
/**
* Removes items from an inventory slot.
* @param slot The slot to remove from.
* @param count How many items to remove. If there are less items in the slot than what are requested,
* takes all items in that slot.
*/
@Override
default ItemStack removeStack(int slot, int count) {
ItemStack result = Inventories.splitStack(getItems(), slot, count);
if (!result.isEmpty()) {
markDirty();
}
return result;
}
/**
* Removes all items from an inventory slot.
* @param slot The slot to remove from.
*/
@Override
default ItemStack removeStack(int slot) {
return Inventories.removeStack(getItems(), slot);
}
/**
* Replaces the current stack in an inventory slot with the provided stack.
* @param slot The inventory slot of which to replace the itemstack.
* @param stack The replacing itemstack. If the stack is too big for
* this inventory ({@link Inventory#getMaxCountPerStack()}),
* it gets resized to this inventory's maximum amount.
*/
@Override
default void setStack(int slot, ItemStack stack) {
getItems().set(slot, stack);
if (stack.getCount() > stack.getMaxCount()) {
stack.setCount(stack.getMaxCount());
}
}
/**
* Clears the inventory.
*/
@Override
default void clear() {
getItems().clear();
}
/**
* Marks the state as dirty.
* Must be called after changes in the inventory, so that the game can properly save
* the inventory contents and notify neighboring blocks of inventory changes.
*/
@Override
default void markDirty() {
// Override if you want behavior.
}
/**
* @return true if the player can use the inventory, false otherwise.
*/
@Override
default boolean canPlayerUse(PlayerEntity player) {
return true;
}
}

View File

@ -6,7 +6,6 @@ import java.util.function.Predicate;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import de.jottyfan.minecraft.quickiefabric.blockentity.BlockSpreaderEntity;
import de.jottyfan.minecraft.quickiefabric.blockentity.BlockStackerEntity;
import de.jottyfan.minecraft.quickiefabric.blockentity.DrillBlockDownEntity;
import de.jottyfan.minecraft.quickiefabric.blockentity.DrillBlockEastEntity;
@ -19,6 +18,7 @@ import de.jottyfan.minecraft.quickiefabric.blockentity.MonsterHoarderBlockEntity
import de.jottyfan.minecraft.quickiefabric.blockentity.QuickieFabricBlockEntity;
import de.jottyfan.minecraft.quickiefabric.blocks.QuickieBlocks;
import de.jottyfan.minecraft.quickiefabric.container.BackpackScreenHandler;
import de.jottyfan.minecraft.quickiefabric.container.BlockStackerScreenHandler;
import de.jottyfan.minecraft.quickiefabric.event.BreakBlockCallback;
import de.jottyfan.minecraft.quickiefabric.event.EventBlockBreak;
import de.jottyfan.minecraft.quickiefabric.items.QuickieItems;
@ -72,6 +72,9 @@ public class RegistryManager {
public static final Identifier BACKPACK_IDENTIFIER = new Identifier(QUICKIEFABRIC, "backpack");
public static final ScreenHandlerType<BackpackScreenHandler> BACKPACK_SCREEN_HANDLER = ScreenHandlerRegistry
.registerExtended(RegistryManager.BACKPACK_IDENTIFIER, BackpackScreenHandler::new);
public static final Identifier STACKER_IDENTIFIER = new Identifier(QUICKIEFABRIC, "stacker");
public static final ScreenHandlerType<BlockStackerScreenHandler> BLOCKSTACKER_SCREEN_HANDLER = ScreenHandlerRegistry
.registerSimple(RegistryManager.STACKER_IDENTIFIER, BlockStackerScreenHandler::new);
@SuppressWarnings("unchecked")
public static final ConfiguredFeature<?, ?> CF_ORESULPHOR = new ConfiguredFeature(Feature.ORE, new OreFeatureConfig(
@ -216,8 +219,6 @@ public class RegistryManager {
"blockstackerentity", BlockStackerEntity::new, QuickieBlocks.BLOCKSTACKERUP, QuickieBlocks.BLOCKSTACKERDOWN,
QuickieBlocks.BLOCKSTACKEREAST, QuickieBlocks.BLOCKSTACKERWEST, QuickieBlocks.BLOCKSTACKERNORTH,
QuickieBlocks.BLOCKSTACKERSOUTH);
QuickieFabricBlockEntity.BLOCKSPREADER_ENTITY = (BlockEntityType<BlockSpreaderEntity>) registerBlockEntity(
"blockspreaderentity", BlockSpreaderEntity::new, QuickieBlocks.BLOCKSPREADER);
}
public static final void registerBlocks() {