diff --git a/.classpath b/.classpath
index 22fc6b2..1efc791 100644
--- a/.classpath
+++ b/.classpath
@@ -1,6 +1,5 @@
-
@@ -18,610 +17,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
diff --git a/.project b/.project
index a1b1dc8..6b24044 100644
--- a/.project
+++ b/.project
@@ -2,21 +2,22 @@
quickiemod
-
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ org.eclipse.buildship.core.gradleprojectbuilder
+
+
+
+
org.eclipse.jdt.core.javanature
org.eclipse.buildship.core.gradleprojectnature
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
- org.eclipse.buildship.core.gradleprojectbuilder
-
-
-
-
-
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index f3eb3df..db08bef 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -1,5 +1,5 @@
#
-#Sat Jun 15 13:57:14 CEST 2024
+#Mon Jun 24 21:17:32 CEST 2024
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.targetPlatform=21
diff --git a/gradle.properties b/gradle.properties
index 45528df..cbc0c06 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -9,7 +9,7 @@ yarn_mappings=1.21+build.2
loader_version=0.15.11
# Mod Properties
-mod_version=1.21.0.1
+mod_version=1.21.0.2
maven_group=de.jottyfan.quickiemod
archives_base_name=quickiemod
diff --git a/src/main/java/de/jottyfan/quickiemod/QuickieMod.java b/src/main/java/de/jottyfan/quickiemod/QuickieMod.java
index 4761c84..0b45dda 100644
--- a/src/main/java/de/jottyfan/quickiemod/QuickieMod.java
+++ b/src/main/java/de/jottyfan/quickiemod/QuickieMod.java
@@ -14,12 +14,14 @@ import net.fabricmc.api.ModInitializer;
public class QuickieMod implements ModInitializer {
public static final String MODID = "quickiemod";
- private static final Logger LOGGER = LoggerFactory.getLogger(MODID);
+ public static final Logger LOGGER = LoggerFactory.getLogger(MODID);
@Override
public void onInitialize() {
LOGGER.info("loading {}", MODID);
+
RegistryManager.registerBlockEntityTypes();
+ RegistryManager.registerScreenHandlerTypes();
RegistryManager.registerItems();
RegistryManager.registerEvents();
RegistryManager.registerBlocks();
diff --git a/src/main/java/de/jottyfan/quickiemod/QuickieModClient.java b/src/main/java/de/jottyfan/quickiemod/QuickieModClient.java
index 7c3be44..95dd0e5 100644
--- a/src/main/java/de/jottyfan/quickiemod/QuickieModClient.java
+++ b/src/main/java/de/jottyfan/quickiemod/QuickieModClient.java
@@ -1,10 +1,13 @@
package de.jottyfan.quickiemod;
import de.jottyfan.quickiemod.blocks.QuickieBlocks;
+import de.jottyfan.quickiemod.container.BlockStackerScreen;
+import de.jottyfan.quickiemod.container.ScreenHandlerTypes;
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.minecraft.client.gui.screen.ingame.HandledScreens;
import net.minecraft.client.render.RenderLayer;
/**
@@ -16,6 +19,7 @@ import net.minecraft.client.render.RenderLayer;
public class QuickieModClient implements ClientModInitializer {
@Override
public void onInitializeClient() {
+// HandledScreens.register(ScreenHandlerTypes.BLOCKSTACKER_SCREEN_HANDLER, BlockStackerScreen::new);
BlockRenderLayerMap.INSTANCE.putBlock(QuickieBlocks.COTTONPLANT.getBlock(), RenderLayer.getCutout());
BlockRenderLayerMap.INSTANCE.putBlock(QuickieBlocks.CANOLAPLANT.getBlock(), RenderLayer.getCutout());
}
diff --git a/src/main/java/de/jottyfan/quickiemod/blockentity/BlockEntityTypes.java b/src/main/java/de/jottyfan/quickiemod/blockentity/BlockEntityTypes.java
index 9f9532f..9f1da77 100644
--- a/src/main/java/de/jottyfan/quickiemod/blockentity/BlockEntityTypes.java
+++ b/src/main/java/de/jottyfan/quickiemod/blockentity/BlockEntityTypes.java
@@ -29,4 +29,9 @@ public class BlockEntityTypes {
BlockEntityType.Builder.create(DrillBlockWestEntity::new, QuickieBlocks.DRILL_WEST.getBlock()).build(null));
public static final BlockEntityType DRILL_NORTH = Registry.register(Registries.BLOCK_ENTITY_TYPE, BlockEntityIdentity.DRILL_NORTH,
BlockEntityType.Builder.create(DrillBlockNorthEntity::new, QuickieBlocks.DRILL_NORTH.getBlock()).build(null));
+ public static final BlockEntityType BLOCKSTACKER_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE,
+ BlockEntityIdentity.BLOCKSTACKERUP,
+ BlockEntityType.Builder.create(BlockStackerEntity::new, QuickieBlocks.BLOCKSTACKERUP.getBlock(), QuickieBlocks.BLOCKSTACKERDOWN.getBlock(),
+ QuickieBlocks.BLOCKSTACKEREAST.getBlock(), QuickieBlocks.BLOCKSTACKERWEST.getBlock(), QuickieBlocks.BLOCKSTACKERNORTH.getBlock(),
+ QuickieBlocks.BLOCKSTACKERSOUTH.getBlock()).build(null));
}
diff --git a/src/main/java/de/jottyfan/quickiemod/blockentity/BlockStackerEntity.java b/src/main/java/de/jottyfan/quickiemod/blockentity/BlockStackerEntity.java
new file mode 100644
index 0000000..09d380b
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/blockentity/BlockStackerEntity.java
@@ -0,0 +1,265 @@
+package de.jottyfan.quickiemod.blockentity;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import de.jottyfan.quickiemod.QuickieMod;
+import de.jottyfan.quickiemod.blocks.help.BlockStacker;
+import de.jottyfan.quickiemod.container.BlockStackerScreenHandler;
+import de.jottyfan.quickiemod.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.registry.RegistryWrapper.WrapperLookup;
+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;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public class BlockStackerEntity extends BlockEntity implements NamedScreenHandlerFactory, ImplementedInventory {
+ private static final Logger LOGGER = LoggerFactory.getLogger(QuickieMod.MODID);
+
+ private final DefaultedList inventory = DefaultedList.ofSize(BlockStackerScreenHandler.SLOTSIZE, ItemStack.EMPTY);
+
+ public BlockStackerEntity(BlockPos blockPos, BlockState blockState) {
+ super(BlockEntityTypes.BLOCKSTACKER_ENTITY, blockPos, blockState);
+ }
+
+ @Override
+ public DefaultedList getItems() {
+ return inventory;
+ }
+
+ public List getWhiteList() {
+ int counter = 0;
+ List list = new ArrayList<>();
+ for (ItemStack stack : inventory) {
+ counter++;
+ if (counter < 10) { // first 9 items are whitelist items
+ list.add(stack);
+ }
+ }
+ return list;
+ }
+
+ public List getBlackList() {
+ int counter = 0;
+ List list = new ArrayList<>();
+ for (ItemStack stack : inventory) {
+ counter++;
+ if (counter > 9) { // second 9 items are blacklist items
+ list.add(stack);
+ }
+ }
+ return list;
+ }
+
+ @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
+ protected void readNbt(NbtCompound nbt, WrapperLookup registryLookup) {
+ super.readNbt(nbt, registryLookup);
+ Inventories.readNbt(nbt, inventory, registryLookup);
+ }
+
+ @Override
+ protected void writeNbt(NbtCompound nbt, WrapperLookup registryLookup) {
+ Inventories.writeNbt(nbt, inventory, registryLookup);
+ super.writeNbt(nbt, registryLookup);
+ }
+
+ /**
+ * 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();
+ BlockStacker block = (BlockStacker) state.getBlock();
+ BlockEntity source = world.getBlockEntity(pos.offset(block.getSourceOffset()));
+ BlockEntity dest = world.getBlockEntity(pos.offset(block.getDestOffset()));
+ Boolean sourceIsLootable = source instanceof LootableContainerBlockEntity;
+ Boolean destIsLootable = dest instanceof LootableContainerBlockEntity;
+ if (sourceIsLootable && destIsLootable) {
+ LootableContainerBlockEntity lootableSource = (LootableContainerBlockEntity) source;
+ LootableContainerBlockEntity lootableDest = (LootableContainerBlockEntity) dest;
+ transferOneStack(lootableSource, lootableDest, entity.getWhiteList(), entity.getBlackList());
+ }
+ }
+ }
+
+ private static final Boolean transferOneStack(LootableContainerBlockEntity source, LootableContainerBlockEntity dest, List whiteList, List blackList) {
+
+ // whitelist behaviour
+ List- checked = new ArrayList<>();
+
+ // this way, we block whitelist items that are in the blacklist
+ for (ItemStack stack : blackList) {
+ if (stack != null && !stack.isEmpty()) {
+ checked.add(stack.getItem());
+ }
+ }
+ Boolean found = false;
+
+ if (hasItems(whiteList)) {
+ Item matchItem = findNextItem(whiteList, checked);
+ while(!found && matchItem != null) {
+ checked.add(matchItem);
+ List
- matchItems = new ArrayList<>();
+ matchItems.add(matchItem);
+ found = transferOneStack(source, dest, matchItems, true);
+ matchItem = findNextItem(whiteList, checked);
+ }
+ } else {
+ // transport all but the items of the blacklist
+ found = transferOneStack(source, dest, checked, false);
+ }
+ return found;
+ }
+
+ private static final Boolean transferOneStack(LootableContainerBlockEntity source, LootableContainerBlockEntity dest,
+ List
- ignoreItems, Boolean whitelist) {
+ Boolean result = false;
+ Integer sourceSlot = findItemStackPos(source, ignoreItems, whitelist);
+ if (sourceSlot != null && !Items.AIR.equals(source.getStack(sourceSlot).getItem())) {
+ ItemStack sourceStack = source.getStack(sourceSlot);
+ Integer destSlot = findItemStackPos(dest, sourceStack);
+ if (destSlot != null) {
+ Integer occupied = dest.getStack(destSlot).getCount();
+ Integer free = dest.getStack(destSlot).getMaxCount() - occupied;
+ 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);
+ 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);
+ dest.setStack(destFreeSlot, source.removeStack(sourceSlot));
+ result = true;
+ }
+ }
+ }
+ return result;
+ }
+
+ private static final Boolean hasItems(List list) {
+ Boolean result = false;
+ for (ItemStack stack : list) {
+ result = result || (stack != null && !stack.isEmpty() && stack.getCount() > 0);
+ }
+ return result;
+ }
+
+ private static final Item findNextItem(List inventory, List
- 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) {
+ Integer counter = lcbe.size();
+ while (counter > 0) {
+ counter--;
+ ItemStack stack = lcbe.getStack(counter);
+ if (sourceStack.getItem().equals(stack.getItem())) {
+ if (stack.getCount() < stack.getMaxCount()) {
+ return counter;
+ }
+ }
+ }
+ return null;
+ }
+
+ private static final Integer findItemStackPos(LootableContainerBlockEntity lcbe, Boolean empty) {
+ Integer counter = lcbe.size();
+ while (counter > 0) {
+ counter--;
+ ItemStack stack = lcbe.getStack(counter);
+ if (empty.equals(ItemStack.EMPTY.equals(stack))) {
+ return counter;
+ }
+ }
+ return null;
+ }
+
+ private static final Integer findItemStackPos(LootableContainerBlockEntity lcbe, List
- filterItems, Boolean whitelist) {
+ if (whitelist == null) {
+ whitelist = true;
+ LOGGER.error("whitelist is null");
+ }
+ if (filterItems == null || filterItems.size() < 1) {
+ if (whitelist) {
+ return null;
+ } else {
+ return findItemStackPos(lcbe, false);
+ }
+ } else {
+ Integer counter = lcbe.size();
+ while (counter > 0) {
+ counter--;
+ ItemStack stack = lcbe.getStack(counter);
+ Boolean found = whitelist ? filterItems.contains(stack.getItem()) : !filterItems.contains(stack.getItem());
+ if (found) {
+ return counter;
+ }
+ }
+ return null;
+ }
+ }
+
+ @Override
+ public int size() {
+ return inventory.size();
+ }
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerDown.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerDown.java
new file mode 100644
index 0000000..e306b03
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerDown.java
@@ -0,0 +1,111 @@
+package de.jottyfan.quickiemod.blocks;
+
+import java.util.List;
+
+import com.mojang.serialization.MapCodec;
+
+import de.jottyfan.quickiemod.blockentity.BlockEntityTypes;
+import de.jottyfan.quickiemod.blockentity.BlockStackerEntity;
+import de.jottyfan.quickiemod.blocks.help.BlockStacker;
+import net.minecraft.block.AbstractBlock;
+import net.minecraft.block.BlockRenderType;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.BlockWithEntity;
+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.LootContextParameterSet.Builder;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.util.ActionResult;
+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;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public class BlockStackerDown extends BlockWithEntity implements BlockStacker {
+
+ public BlockStackerDown() {
+ super(AbstractBlock.Settings.create().hardness(2.5f));
+ }
+
+ @Override
+ public Direction getSourceOffset() {
+ return Direction.UP;
+ }
+
+ @Override
+ public Direction getDestOffset() {
+ return Direction.DOWN;
+ }
+
+ @Override
+ public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
+ return new BlockStackerEntity(pos, state);
+ }
+
+ @Override
+ public BlockRenderType getRenderType(BlockState state) {
+ return BlockRenderType.MODEL;
+ }
+
+ @Override
+ public List getDroppedStacks(BlockState state, Builder builder) {
+ return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKERDOWN.getBlock()));
+ }
+
+ @Override
+ public BlockEntityTicker getTicker(World world, BlockState state,
+ BlockEntityType type) {
+ return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY,
+ (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
+ }
+
+ @Override
+ protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, 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));
+ }
+
+ @Override
+ protected MapCodec extends BlockWithEntity> getCodec() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerEast.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerEast.java
new file mode 100644
index 0000000..605726c
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerEast.java
@@ -0,0 +1,111 @@
+package de.jottyfan.quickiemod.blocks;
+
+import java.util.List;
+
+import com.mojang.serialization.MapCodec;
+
+import de.jottyfan.quickiemod.blockentity.BlockEntityTypes;
+import de.jottyfan.quickiemod.blockentity.BlockStackerEntity;
+import de.jottyfan.quickiemod.blocks.help.BlockStacker;
+import net.minecraft.block.AbstractBlock;
+import net.minecraft.block.BlockRenderType;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.BlockWithEntity;
+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.LootContextParameterSet.Builder;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.util.ActionResult;
+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;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public class BlockStackerEast extends BlockWithEntity implements BlockStacker {
+
+ public BlockStackerEast() {
+ super(AbstractBlock.Settings.create().hardness(2.5f));
+ }
+
+ @Override
+ public Direction getSourceOffset() {
+ return Direction.WEST;
+ }
+
+ @Override
+ public Direction getDestOffset() {
+ return Direction.EAST;
+ }
+
+ @Override
+ public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
+ return new BlockStackerEntity(pos, state);
+ }
+
+ @Override
+ public BlockRenderType getRenderType(BlockState state) {
+ return BlockRenderType.MODEL;
+ }
+
+ @Override
+ public List getDroppedStacks(BlockState state, Builder builder) {
+ return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKEREAST.getBlock()));
+ }
+
+ @Override
+ public BlockEntityTicker getTicker(World world, BlockState state,
+ BlockEntityType type) {
+ return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY,
+ (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
+ }
+
+ @Override
+ protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, 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));
+ }
+
+ @Override
+ protected MapCodec extends BlockWithEntity> getCodec() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerNorth.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerNorth.java
new file mode 100644
index 0000000..c34cda7
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerNorth.java
@@ -0,0 +1,111 @@
+package de.jottyfan.quickiemod.blocks;
+
+import java.util.List;
+
+import com.mojang.serialization.MapCodec;
+
+import de.jottyfan.quickiemod.blockentity.BlockEntityTypes;
+import de.jottyfan.quickiemod.blockentity.BlockStackerEntity;
+import de.jottyfan.quickiemod.blocks.help.BlockStacker;
+import net.minecraft.block.AbstractBlock;
+import net.minecraft.block.BlockRenderType;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.BlockWithEntity;
+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.LootContextParameterSet.Builder;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.util.ActionResult;
+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;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public class BlockStackerNorth extends BlockWithEntity implements BlockStacker {
+
+ public BlockStackerNorth() {
+ super(AbstractBlock.Settings.create().hardness(2.5f));
+ }
+
+ @Override
+ public Direction getSourceOffset() {
+ return Direction.SOUTH;
+ }
+
+ @Override
+ public Direction getDestOffset() {
+ return Direction.NORTH;
+ }
+
+ @Override
+ public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
+ return new BlockStackerEntity(pos, state);
+ }
+
+ @Override
+ public BlockRenderType getRenderType(BlockState state) {
+ return BlockRenderType.MODEL;
+ }
+
+ @Override
+ public List getDroppedStacks(BlockState state, Builder builder) {
+ return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKERNORTH.getBlock()));
+ }
+
+ @Override
+ public BlockEntityTicker getTicker(World world, BlockState state,
+ BlockEntityType type) {
+ return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY,
+ (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
+ }
+
+ @Override
+ protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, 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));
+ }
+
+ @Override
+ protected MapCodec extends BlockWithEntity> getCodec() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerSouth.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerSouth.java
new file mode 100644
index 0000000..afbb7b2
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerSouth.java
@@ -0,0 +1,111 @@
+package de.jottyfan.quickiemod.blocks;
+
+import java.util.List;
+
+import com.mojang.serialization.MapCodec;
+
+import de.jottyfan.quickiemod.blockentity.BlockEntityTypes;
+import de.jottyfan.quickiemod.blockentity.BlockStackerEntity;
+import de.jottyfan.quickiemod.blocks.help.BlockStacker;
+import net.minecraft.block.AbstractBlock;
+import net.minecraft.block.BlockRenderType;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.BlockWithEntity;
+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.LootContextParameterSet.Builder;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.util.ActionResult;
+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;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public class BlockStackerSouth extends BlockWithEntity implements BlockStacker {
+
+ public BlockStackerSouth() {
+ super(AbstractBlock.Settings.create().hardness(2.5f));
+ }
+
+ @Override
+ public Direction getSourceOffset() {
+ return Direction.NORTH;
+ }
+
+ @Override
+ public Direction getDestOffset() {
+ return Direction.SOUTH;
+ }
+
+ @Override
+ public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
+ return new BlockStackerEntity(pos, state);
+ }
+
+ @Override
+ public BlockRenderType getRenderType(BlockState state) {
+ return BlockRenderType.MODEL;
+ }
+
+ @Override
+ public List getDroppedStacks(BlockState state, Builder builder) {
+ return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKERSOUTH.getBlock()));
+ }
+
+ @Override
+ public BlockEntityTicker getTicker(World world, BlockState state,
+ BlockEntityType type) {
+ return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY,
+ (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
+ }
+
+ @Override
+ protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, 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));
+ }
+
+ @Override
+ protected MapCodec extends BlockWithEntity> getCodec() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerUp.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerUp.java
new file mode 100644
index 0000000..67d13e8
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerUp.java
@@ -0,0 +1,111 @@
+package de.jottyfan.quickiemod.blocks;
+
+import java.util.List;
+
+import com.mojang.serialization.MapCodec;
+
+import de.jottyfan.quickiemod.blockentity.BlockEntityTypes;
+import de.jottyfan.quickiemod.blockentity.BlockStackerEntity;
+import de.jottyfan.quickiemod.blocks.help.BlockStacker;
+import net.minecraft.block.AbstractBlock;
+import net.minecraft.block.BlockRenderType;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.BlockWithEntity;
+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.LootContextParameterSet.Builder;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.util.ActionResult;
+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;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public class BlockStackerUp extends BlockWithEntity implements BlockStacker {
+
+ public BlockStackerUp() {
+ super(AbstractBlock.Settings.create().hardness(2.5f));
+ }
+
+ @Override
+ public Direction getSourceOffset() {
+ return Direction.DOWN;
+ }
+
+ @Override
+ public Direction getDestOffset() {
+ return Direction.UP;
+ }
+
+ @Override
+ public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
+ return new BlockStackerEntity(pos, state);
+ }
+
+ @Override
+ public BlockRenderType getRenderType(BlockState state) {
+ return BlockRenderType.MODEL;
+ }
+
+ @Override
+ public List getDroppedStacks(BlockState state, Builder builder) {
+ return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKERUP.getBlock()));
+ }
+
+ @Override
+ public BlockEntityTicker getTicker(World world, BlockState state,
+ BlockEntityType type) {
+ return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY,
+ (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
+ }
+
+ @Override
+ protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, 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));
+ }
+
+ @Override
+ protected MapCodec extends BlockWithEntity> getCodec() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerWest.java b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerWest.java
new file mode 100644
index 0000000..f970db8
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/blocks/BlockStackerWest.java
@@ -0,0 +1,111 @@
+package de.jottyfan.quickiemod.blocks;
+
+import java.util.List;
+
+import com.mojang.serialization.MapCodec;
+
+import de.jottyfan.quickiemod.blockentity.BlockEntityTypes;
+import de.jottyfan.quickiemod.blockentity.BlockStackerEntity;
+import de.jottyfan.quickiemod.blocks.help.BlockStacker;
+import net.minecraft.block.AbstractBlock;
+import net.minecraft.block.BlockRenderType;
+import net.minecraft.block.BlockState;
+import net.minecraft.block.BlockWithEntity;
+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.LootContextParameterSet.Builder;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.util.ActionResult;
+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;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public class BlockStackerWest extends BlockWithEntity implements BlockStacker {
+
+ public BlockStackerWest() {
+ super(AbstractBlock.Settings.create().hardness(2.5f));
+ }
+
+ @Override
+ public List getDroppedStacks(BlockState state, Builder builder) {
+ return List.of(new ItemStack(QuickieBlocks.BLOCKSTACKERWEST.getBlock()));
+ }
+
+ @Override
+ public Direction getSourceOffset() {
+ return Direction.EAST;
+ }
+
+ @Override
+ public Direction getDestOffset() {
+ return Direction.WEST;
+ }
+
+ @Override
+ public BlockEntity createBlockEntity(BlockPos pos, BlockState state) {
+ return new BlockStackerEntity(pos, state);
+ }
+
+ @Override
+ public BlockRenderType getRenderType(BlockState state) {
+ return BlockRenderType.MODEL;
+ }
+
+ @Override
+ public BlockEntityTicker getTicker(World world, BlockState state,
+ BlockEntityType type) {
+ return validateTicker(type, BlockEntityTypes.BLOCKSTACKER_ENTITY,
+ (world1, pos, state1, be) -> BlockStackerEntity.tick(world1, pos, state1, be));
+ }
+
+ @Override
+ protected ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, 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));
+ }
+
+ @Override
+ protected MapCodec extends BlockWithEntity> getCodec() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/QuickieBlocks.java b/src/main/java/de/jottyfan/quickiemod/blocks/QuickieBlocks.java
index 8d83df5..9e34c6a 100644
--- a/src/main/java/de/jottyfan/quickiemod/blocks/QuickieBlocks.java
+++ b/src/main/java/de/jottyfan/quickiemod/blocks/QuickieBlocks.java
@@ -9,6 +9,12 @@ import net.minecraft.block.Block;
*/
public enum QuickieBlocks {
// @formatter:off
+ BLOCKSTACKERUP(new BlockStackerUp(), "blockstackerup"),
+ BLOCKSTACKERDOWN(new BlockStackerDown(), "blockstackerdown"),
+ BLOCKSTACKEREAST(new BlockStackerEast(), "blockstackereast"),
+ BLOCKSTACKERWEST(new BlockStackerWest(), "blockstackerwest"),
+ BLOCKSTACKERNORTH(new BlockStackerNorth(), "blockstackernorth"),
+ BLOCKSTACKERSOUTH(new BlockStackerSouth(), "blockstackersouth"),
DRILL_DOWN(new BlockDrillDown(), "drill"),
DRILL_EAST(new BlockDrillEast(), "drilleast"),
DRILL_SOUTH(new BlockDrillSouth(), "drillsouth"),
diff --git a/src/main/java/de/jottyfan/quickiemod/blocks/help/BlockStacker.java b/src/main/java/de/jottyfan/quickiemod/blocks/help/BlockStacker.java
new file mode 100644
index 0000000..582ea1c
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/blocks/help/BlockStacker.java
@@ -0,0 +1,25 @@
+package de.jottyfan.quickiemod.blocks.help;
+
+import net.minecraft.block.BlockEntityProvider;
+import net.minecraft.util.math.Direction;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public interface BlockStacker extends BlockEntityProvider {
+ /**
+ * define the source offset
+ *
+ * @return the direction of the source offset (1 block beside)
+ */
+ public Direction getSourceOffset();
+
+ /**
+ * define the dest offset
+ *
+ * @return the direction of the dest offset (1 block beside)
+ */
+ public Direction getDestOffset();
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/container/BlockStackerInventory.java b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerInventory.java
new file mode 100644
index 0000000..9238be4
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerInventory.java
@@ -0,0 +1,30 @@
+package de.jottyfan.quickiemod.container;
+
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.inventory.SimpleInventory;
+import net.minecraft.sound.SoundEvents;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public class BlockStackerInventory extends SimpleInventory {
+
+ public BlockStackerInventory(Integer slotsize) {
+ super(slotsize);
+ }
+
+ @Override
+ public void onOpen(PlayerEntity player) {
+ super.onOpen(player);
+ player.playSound(SoundEvents.BLOCK_CHEST_OPEN, 1f, 1f);
+ }
+
+ @Override
+ public void onClose(PlayerEntity player) {
+ super.onClose(player);
+ player.playSound(SoundEvents.BLOCK_CHEST_CLOSE, 1f, 1f);
+ }
+
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreen.java b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreen.java
new file mode 100644
index 0000000..d860c97
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreen.java
@@ -0,0 +1,44 @@
+package de.jottyfan.quickiemod.container;
+
+import de.jottyfan.quickiemod.QuickieMod;
+import net.fabricmc.api.EnvType;
+import net.fabricmc.api.Environment;
+import net.minecraft.client.gui.DrawContext;
+import net.minecraft.client.gui.screen.ingame.HandledScreen;
+import net.minecraft.client.gui.screen.ingame.ScreenHandlerProvider;
+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
+ implements ScreenHandlerProvider {
+ private final static Identifier TEXTURE = Identifier.of(QuickieMod.MODID, "textures/gui/blockstacker.png");
+ private final Integer containerHeight = 222;
+ private final Integer containerWidth = 176;
+
+ public BlockStackerScreen(BlockStackerScreenHandler handler, PlayerInventory inventory, Text title) {
+ super(handler, inventory, title);
+ }
+
+ @Override
+ public void render(DrawContext drawContext, int mouseX, int mouseY, float partialTicks) {
+ this.renderInGameBackground(drawContext);
+ super.render(drawContext, mouseX, mouseY, partialTicks);
+ this.drawMouseoverTooltip(drawContext, mouseX, mouseY);
+ }
+
+ @Override
+ protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) {
+// context.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
+ int guiX = (this.width - this.containerWidth) / 2;
+ int guiY = (this.height - this.containerHeight) / 2;
+ super.renderInGameBackground(context);
+ context.drawTexture(TEXTURE, guiX, guiY, 0, 0, containerWidth, containerHeight);
+ }
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreenHandler.java b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreenHandler.java
new file mode 100644
index 0000000..9d4da6f
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/container/BlockStackerScreenHandler.java
@@ -0,0 +1,97 @@
+package de.jottyfan.quickiemod.container;
+
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.entity.player.PlayerInventory;
+import net.minecraft.inventory.Inventory;
+import net.minecraft.item.ItemStack;
+import net.minecraft.screen.NamedScreenHandlerFactory;
+import net.minecraft.screen.ScreenHandler;
+import net.minecraft.screen.slot.Slot;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public class BlockStackerScreenHandler extends ScreenHandler {
+
+ public static final Integer SLOTSIZE = 18;
+
+ private final Inventory inventory;
+
+ /**
+ * client constructor
+ *
+ * @param syncId
+ * @param playerInventory
+ */
+ public BlockStackerScreenHandler(int syncId, PlayerInventory playerInventory) {
+ this(syncId, playerInventory, new BlockStackerInventory(SLOTSIZE));
+ }
+
+ /**
+ * server constructor
+ *
+ * @param syncId
+ * @param playerInventory
+ * @param inventory
+ */
+ public BlockStackerScreenHandler(int syncId, PlayerInventory playerInventory, Inventory inventory) {
+ super(ScreenHandlerTypes.BLOCKSTACKER_SCREEN_HANDLER, syncId);
+ checkSize(inventory, SLOTSIZE);
+ this.inventory = inventory;
+ inventory.onOpen(playerInventory.player);
+ int m;
+ int l;
+ // whitelist
+ for (m = 0; m < 3; ++m) {
+ for (l = 0; l < 3; ++l) {
+ this.addSlot(new Slot(inventory, l + m * 3, 8 + l * 18, 17 + m * 18));
+ }
+ }
+
+ // blacklist
+ for (m = 0; m < 3; ++m) {
+ for (l = 0; l < 3; ++l) {
+ this.addSlot(new Slot(inventory, l + m * 3 + 9, 116 + 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 quickMove(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;
+ }
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/container/ImplementedInventory.java b/src/main/java/de/jottyfan/quickiemod/container/ImplementedInventory.java
new file mode 100644
index 0000000..add90a5
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/container/ImplementedInventory.java
@@ -0,0 +1,133 @@
+package de.jottyfan.quickiemod.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 getItems();
+
+ /**
+ * Creates an inventory from the item list.
+ */
+ static ImplementedInventory of(DefaultedList 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;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/de/jottyfan/quickiemod/container/ScreenHandlerTypes.java b/src/main/java/de/jottyfan/quickiemod/container/ScreenHandlerTypes.java
new file mode 100644
index 0000000..e82a510
--- /dev/null
+++ b/src/main/java/de/jottyfan/quickiemod/container/ScreenHandlerTypes.java
@@ -0,0 +1,14 @@
+package de.jottyfan.quickiemod.container;
+
+import net.minecraft.resource.featuretoggle.FeatureFlags;
+import net.minecraft.screen.ScreenHandlerType;
+
+/**
+ *
+ * @author jotty
+ *
+ */
+public class ScreenHandlerTypes {
+ public static final ScreenHandlerType BLOCKSTACKER_SCREEN_HANDLER = new ScreenHandlerType<>(BlockStackerScreenHandler::new,
+ FeatureFlags.VANILLA_FEATURES);
+}
diff --git a/src/main/java/de/jottyfan/quickiemod/event/EventBlockBreak.java b/src/main/java/de/jottyfan/quickiemod/event/EventBlockBreak.java
index 7e790c4..19620bf 100644
--- a/src/main/java/de/jottyfan/quickiemod/event/EventBlockBreak.java
+++ b/src/main/java/de/jottyfan/quickiemod/event/EventBlockBreak.java
@@ -66,7 +66,7 @@ public class EventBlockBreak {
List validBlocks = tool.getBlockList(currentBlock);
HarvestRange range = tool.getRange(itemStack);
- LOGGER.info("current tool: {}", tool);
+ LOGGER.debug("current tool: {}", tool);
if (QuickieItems.SPEEDPOWDERAXE.getItem().equals(tool)) {
return breakBlockRecursive(new ArrayList<>(), world, validBlocks, pos, tool, range, BlockBreakDirection.UPWARDS,
diff --git a/src/main/java/de/jottyfan/quickiemod/init/RegistryManager.java b/src/main/java/de/jottyfan/quickiemod/init/RegistryManager.java
index c13c900..02e3f3a 100644
--- a/src/main/java/de/jottyfan/quickiemod/init/RegistryManager.java
+++ b/src/main/java/de/jottyfan/quickiemod/init/RegistryManager.java
@@ -89,6 +89,14 @@ public class RegistryManager {
}
public static final void registerBlockEntityTypes() {
- new BlockEntityTypes();
+ try {
+ Class.forName(BlockEntityTypes.class.getName());
+ LOGGER.info("registering block entity types");
+ } catch (ClassNotFoundException e) {
+ LOGGER.error("class BlockEntityType not loaded", e);
+ }
+ }
+
+ public static final void registerScreenHandlerTypes() {
}
}
diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackerdown.json b/src/main/resources/assets/quickiemod/blockstates/blockstackerdown.json
new file mode 100644
index 0000000..6bb43c7
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/blockstates/blockstackerdown.json
@@ -0,0 +1,7 @@
+{
+ "variants": {
+ "": {
+ "model": "quickiemod:block/blockstackerdown"
+ }
+ }
+}
diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackereast.json b/src/main/resources/assets/quickiemod/blockstates/blockstackereast.json
new file mode 100644
index 0000000..7b1fd09
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/blockstates/blockstackereast.json
@@ -0,0 +1,7 @@
+{
+ "variants": {
+ "": {
+ "model": "quickiemod:block/blockstackereast"
+ }
+ }
+}
diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackernorth.json b/src/main/resources/assets/quickiemod/blockstates/blockstackernorth.json
new file mode 100644
index 0000000..d20bddd
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/blockstates/blockstackernorth.json
@@ -0,0 +1,7 @@
+{
+ "variants": {
+ "": {
+ "model": "quickiemod:block/blockstackernorth"
+ }
+ }
+}
diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackersouth.json b/src/main/resources/assets/quickiemod/blockstates/blockstackersouth.json
new file mode 100644
index 0000000..d18af44
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/blockstates/blockstackersouth.json
@@ -0,0 +1,7 @@
+{
+ "variants": {
+ "": {
+ "model": "quickiemod:block/blockstackersouth"
+ }
+ }
+}
diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackerup.json b/src/main/resources/assets/quickiemod/blockstates/blockstackerup.json
new file mode 100644
index 0000000..dc4b60c
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/blockstates/blockstackerup.json
@@ -0,0 +1,7 @@
+{
+ "variants": {
+ "": {
+ "model": "quickiemod:block/blockstackerup"
+ }
+ }
+}
diff --git a/src/main/resources/assets/quickiemod/blockstates/blockstackerwest.json b/src/main/resources/assets/quickiemod/blockstates/blockstackerwest.json
new file mode 100644
index 0000000..18629ae
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/blockstates/blockstackerwest.json
@@ -0,0 +1,7 @@
+{
+ "variants": {
+ "": {
+ "model": "quickiemod:block/blockstackerwest"
+ }
+ }
+}
diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackerdown.json b/src/main/resources/assets/quickiemod/models/block/blockstackerdown.json
new file mode 100644
index 0000000..1de4eb6
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/block/blockstackerdown.json
@@ -0,0 +1,8 @@
+{
+ "parent": "block/cube_bottom_top",
+ "textures": {
+ "bottom": "quickiemod:block/blockstackerout",
+ "side": "quickiemod:block/blockstackerdown",
+ "top": "quickiemod:block/blockstackerin"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackereast.json b/src/main/resources/assets/quickiemod/models/block/blockstackereast.json
new file mode 100644
index 0000000..7e907bc
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/block/blockstackereast.json
@@ -0,0 +1,11 @@
+{
+ "parent": "block/cube_directional",
+ "textures": {
+ "up": "quickiemod:block/blockstackerright",
+ "down": "quickiemod:block/blockstackerleft",
+ "north": "quickiemod:block/blockstackerleft",
+ "east": "quickiemod:block/blockstackerout",
+ "south": "quickiemod:block/blockstackerright",
+ "west": "quickiemod:block/blockstackerin"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackernorth.json b/src/main/resources/assets/quickiemod/models/block/blockstackernorth.json
new file mode 100644
index 0000000..721b498
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/block/blockstackernorth.json
@@ -0,0 +1,11 @@
+{
+ "parent": "block/cube_directional",
+ "textures": {
+ "up": "quickiemod:block/blockstackerup",
+ "down": "quickiemod:block/blockstackerup",
+ "north": "quickiemod:block/blockstackerout",
+ "east": "quickiemod:block/blockstackerup",
+ "south": "quickiemod:block/blockstackerin",
+ "west": "quickiemod:block/blockstackerup"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackersouth.json b/src/main/resources/assets/quickiemod/models/block/blockstackersouth.json
new file mode 100644
index 0000000..5b9efea
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/block/blockstackersouth.json
@@ -0,0 +1,11 @@
+{
+ "parent": "block/cube_directional",
+ "textures": {
+ "up": "quickiemod:block/blockstackerdown",
+ "down": "quickiemod:block/blockstackerdown",
+ "north": "quickiemod:block/blockstackerin",
+ "east": "quickiemod:block/blockstackerdown",
+ "south": "quickiemod:block/blockstackerout",
+ "west": "quickiemod:block/blockstackerdown"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackerup.json b/src/main/resources/assets/quickiemod/models/block/blockstackerup.json
new file mode 100644
index 0000000..bea5c62
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/block/blockstackerup.json
@@ -0,0 +1,8 @@
+{
+ "parent": "block/cube_bottom_top",
+ "textures": {
+ "bottom": "quickiemod:block/blockstackerin",
+ "side": "quickiemod:block/blockstackerup",
+ "top": "quickiemod:block/blockstackerout"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/block/blockstackerwest.json b/src/main/resources/assets/quickiemod/models/block/blockstackerwest.json
new file mode 100644
index 0000000..76b588e
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/block/blockstackerwest.json
@@ -0,0 +1,11 @@
+{
+ "parent": "block/cube_directional",
+ "textures": {
+ "up": "quickiemod:block/blockstackerleft",
+ "down": "quickiemod:block/blockstackerright",
+ "north": "quickiemod:block/blockstackerright",
+ "east": "quickiemod:block/blockstackerin",
+ "south": "quickiemod:block/blockstackerleft",
+ "west": "quickiemod:block/blockstackerout"
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackerdown.json b/src/main/resources/assets/quickiemod/models/item/blockstackerdown.json
new file mode 100644
index 0000000..62e0d3f
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/item/blockstackerdown.json
@@ -0,0 +1,10 @@
+{
+ "parent": "quickiemod:block/blockstackerdown",
+ "display": {
+ "thirdperson": {
+ "rotation": [ 10, -45, 170 ],
+ "translation": [ 0, 1.5, -2.75 ],
+ "scale": [ 0.375, 0.375, 0.375 ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackereast.json b/src/main/resources/assets/quickiemod/models/item/blockstackereast.json
new file mode 100644
index 0000000..3626d53
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/item/blockstackereast.json
@@ -0,0 +1,10 @@
+{
+ "parent": "quickiemod:block/blockstackerwest",
+ "display": {
+ "thirdperson": {
+ "rotation": [ 10, -45, 170 ],
+ "translation": [ 0, 1.5, -2.75 ],
+ "scale": [ 0.375, 0.375, 0.375 ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackernorth.json b/src/main/resources/assets/quickiemod/models/item/blockstackernorth.json
new file mode 100644
index 0000000..29de363
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/item/blockstackernorth.json
@@ -0,0 +1,10 @@
+{
+ "parent": "quickiemod:block/blockstackernorth",
+ "display": {
+ "thirdperson": {
+ "rotation": [ 10, -45, 170 ],
+ "translation": [ 0, 1.5, -2.75 ],
+ "scale": [ 0.375, 0.375, 0.375 ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackersouth.json b/src/main/resources/assets/quickiemod/models/item/blockstackersouth.json
new file mode 100644
index 0000000..2fdb3f4
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/item/blockstackersouth.json
@@ -0,0 +1,10 @@
+{
+ "parent": "quickiemod:block/blockstackersouth",
+ "display": {
+ "thirdperson": {
+ "rotation": [ 10, -45, 170 ],
+ "translation": [ 0, 1.5, -2.75 ],
+ "scale": [ 0.375, 0.375, 0.375 ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackerup.json b/src/main/resources/assets/quickiemod/models/item/blockstackerup.json
new file mode 100644
index 0000000..db2bd6a
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/item/blockstackerup.json
@@ -0,0 +1,10 @@
+{
+ "parent": "quickiemod:block/blockstackerup",
+ "display": {
+ "thirdperson": {
+ "rotation": [ 10, -45, 170 ],
+ "translation": [ 0, 1.5, -2.75 ],
+ "scale": [ 0.375, 0.375, 0.375 ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/models/item/blockstackerwest.json b/src/main/resources/assets/quickiemod/models/item/blockstackerwest.json
new file mode 100644
index 0000000..18f7e4f
--- /dev/null
+++ b/src/main/resources/assets/quickiemod/models/item/blockstackerwest.json
@@ -0,0 +1,10 @@
+{
+ "parent": "quickiemod:block/blockstackereast",
+ "display": {
+ "thirdperson": {
+ "rotation": [ 10, -45, 170 ],
+ "translation": [ 0, 1.5, -2.75 ],
+ "scale": [ 0.375, 0.375, 0.375 ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerdown.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerdown.png
new file mode 100644
index 0000000..558ce81
Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerdown.png differ
diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerin.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerin.png
new file mode 100644
index 0000000..a9b29e2
Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerin.png differ
diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerleft.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerleft.png
new file mode 100644
index 0000000..fb5e280
Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerleft.png differ
diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerout.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerout.png
new file mode 100644
index 0000000..45febea
Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerout.png differ
diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerright.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerright.png
new file mode 100644
index 0000000..6395790
Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerright.png differ
diff --git a/src/main/resources/assets/quickiemod/textures/block/blockstackerup.png b/src/main/resources/assets/quickiemod/textures/block/blockstackerup.png
new file mode 100644
index 0000000..3adebd0
Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/block/blockstackerup.png differ
diff --git a/src/main/resources/assets/quickiemod/textures/gui/backpack.png b/src/main/resources/assets/quickiemod/textures/gui/backpack.png
new file mode 100644
index 0000000..f24c05b
Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/gui/backpack.png differ
diff --git a/src/main/resources/assets/quickiemod/textures/gui/blockstacker.png b/src/main/resources/assets/quickiemod/textures/gui/blockstacker.png
new file mode 100644
index 0000000..1a10e11
Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/gui/blockstacker.png differ
diff --git a/src/main/resources/assets/quickiemod/textures/gui/slot.png b/src/main/resources/assets/quickiemod/textures/gui/slot.png
new file mode 100644
index 0000000..32b0bfa
Binary files /dev/null and b/src/main/resources/assets/quickiemod/textures/gui/slot.png differ
diff --git a/src/main/resources/data/quickiemod/recipe/shaped_blockstacker.json b/src/main/resources/data/quickiemod/recipe/shaped_blockstacker.json
new file mode 100644
index 0000000..a9fcee0
--- /dev/null
+++ b/src/main/resources/data/quickiemod/recipe/shaped_blockstacker.json
@@ -0,0 +1,20 @@
+{
+ "type": "minecraft:crafting_shaped",
+ "pattern": [
+ "s s",
+ "scs",
+ " s "
+ ],
+ "key": {
+ "s": {
+ "item": "quickiemod:speedingot"
+ },
+ "c": {
+ "item": "minecraft:chest"
+ }
+ },
+ "result": {
+ "id": "quickiemod:blockstackerdown",
+ "count": 4
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerdown_up.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerdown_up.json
new file mode 100644
index 0000000..4c7ed96
--- /dev/null
+++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerdown_up.json
@@ -0,0 +1,12 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "item": "quickiemod:blockstackerup"
+ }
+ ],
+ "result": {
+ "id": "quickiemod:blockstackerdown",
+ "count": 1
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackereast_down.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackereast_down.json
new file mode 100644
index 0000000..e2f8413
--- /dev/null
+++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackereast_down.json
@@ -0,0 +1,12 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "item": "quickiemod:blockstackerdown"
+ }
+ ],
+ "result": {
+ "id": "quickiemod:blockstackereast",
+ "count": 1
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackernorth_west.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackernorth_west.json
new file mode 100644
index 0000000..c78e9e2
--- /dev/null
+++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackernorth_west.json
@@ -0,0 +1,12 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "item": "quickiemod:blockstackerwest"
+ }
+ ],
+ "result": {
+ "id": "quickiemod:blockstackernorth",
+ "count": 1
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackersouth_east.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackersouth_east.json
new file mode 100644
index 0000000..4f1a3c3
--- /dev/null
+++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackersouth_east.json
@@ -0,0 +1,12 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "item": "quickiemod:blockstackereast"
+ }
+ ],
+ "result": {
+ "id": "quickiemod:blockstackersouth",
+ "count": 1
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerup_north.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerup_north.json
new file mode 100644
index 0000000..c95b9bd
--- /dev/null
+++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerup_north.json
@@ -0,0 +1,12 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "item": "quickiemod:blockstackernorth"
+ }
+ ],
+ "result": {
+ "id": "quickiemod:blockstackerup",
+ "count": 1
+ }
+}
\ No newline at end of file
diff --git a/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerwest_south.json b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerwest_south.json
new file mode 100644
index 0000000..89abf70
--- /dev/null
+++ b/src/main/resources/data/quickiemod/recipe/shapeless_blockstackerwest_south.json
@@ -0,0 +1,12 @@
+{
+ "type": "minecraft:crafting_shapeless",
+ "ingredients": [
+ {
+ "item": "quickiemod:blockstackersouth"
+ }
+ ],
+ "result": {
+ "id": "quickiemod:blockstackerwest",
+ "count": 1
+ }
+}
\ No newline at end of file