diff --git a/src/main/java/de/jottyfan/minecraft/block/BlockStacker.java b/src/main/java/de/jottyfan/minecraft/block/BlockStacker.java new file mode 100644 index 0000000..3ef6b40 --- /dev/null +++ b/src/main/java/de/jottyfan/minecraft/block/BlockStacker.java @@ -0,0 +1,84 @@ +package de.jottyfan.minecraft.block; + +import org.jspecify.annotations.Nullable; + +import com.mojang.serialization.MapCodec; + +import de.jottyfan.minecraft.blockentity.BlockStackerEntity; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.EntityBlock; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.entity.BlockEntityTicker; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.StateDefinition.Builder; +import net.minecraft.world.level.block.state.properties.EnumProperty; + +/** + * + * @author jotty + * + */ +public class BlockStacker extends Block implements EntityBlock { + public static final MapCodec CODEC = simpleCodec(BlockStacker::new); + + public static final EnumProperty SOURCE = EnumProperty.create("source", Direction.class, Direction.NORTH, + Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN); + public static final EnumProperty DEST = EnumProperty.create("dest", Direction.class, Direction.NORTH, + Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN); + + public BlockStacker(Properties properties) { + super(properties); + registerDefaultState(stateDefinition.any().setValue(SOURCE, Direction.UP).setValue(DEST, Direction.DOWN)); + } + + @Override + protected void createBlockStateDefinition(Builder builder) { + builder.add(SOURCE, DEST); + } + + @Override + public BlockState getStateForPlacement(BlockPlaceContext context) { + return this.defaultBlockState().setValue(SOURCE, context.getNearestLookingDirection()).setValue(DEST, context.getNearestLookingDirection().getOpposite()); + } + + @Override + public @Nullable BlockEntityTicker getTicker(Level level, BlockState blockState, + BlockEntityType type) { + return (lambdaLevel, pos, state, blockEntity) -> BlockStackerEntity.tick(lambdaLevel, pos, state, blockEntity); + } + + @Override + public @Nullable BlockEntity newBlockEntity(BlockPos pos, BlockState blockState) { + return new BlockStackerEntity(pos, blockState); + } + + public static MapCodec getCodec() { + return CODEC; + } + + public Direction getSource(BlockState state) { + return state.getValue(SOURCE); + } + + public Direction getDest(BlockState state) { + return state.getValue(DEST); + } + + public BlockPos getOffset(BlockState state, EnumProperty sourceOrDest) { + BlockPos pos = new BlockPos(0, 0, 0); + return switch (state.getValue(sourceOrDest)) { + case Direction.UP -> pos.above(); + case Direction.DOWN -> pos.below(); + case Direction.NORTH -> pos.north(); + case Direction.EAST -> pos.east(); + case Direction.SOUTH -> pos.south(); + case Direction.WEST -> pos.west(); + default -> pos; + }; + } +} diff --git a/src/main/java/de/jottyfan/minecraft/block/QuicklyBlocks.java b/src/main/java/de/jottyfan/minecraft/block/QuicklyBlocks.java index da39415..041b862 100644 --- a/src/main/java/de/jottyfan/minecraft/block/QuicklyBlocks.java +++ b/src/main/java/de/jottyfan/minecraft/block/QuicklyBlocks.java @@ -4,6 +4,7 @@ import java.util.function.Function; import de.jottyfan.minecraft.Quickly; import de.jottyfan.minecraft.blockentity.BlockEntityRegister; +import de.jottyfan.minecraft.blockentity.BlockStackerEntity; import de.jottyfan.minecraft.blockentity.DrillBlockEntity; import de.jottyfan.minecraft.blockentity.ItemHoarderBlockEntity; import de.jottyfan.minecraft.item.QuicklyItems; @@ -55,8 +56,8 @@ public class QuicklyBlocks { properties -> new Monsterhoarder(properties)); public static final Block ITEMHOARDER = registerBlock("itemhoarder", properties -> new Itemhoarder(properties)); public static final Block DRILL = registerBlock("drill", properties -> new BlockDrill(properties)); + public static final Block STACKER = registerBlock("blockstacker", properties -> new BlockStacker(properties.strength(2.5f))); - // TODO: add blockstacker // TODO: add salpeter ore, sulfor ore // TODO: merge lavahoarder and emptylavahoarder into one block using a BooleanProperty for the lava fill state @@ -64,6 +65,8 @@ public class QuicklyBlocks { .registerBlockEntity("itemhoarderblockentity", ItemHoarderBlockEntity::new, ITEMHOARDER); public static final BlockEntityType BLOCKENTITY_DRILL = new BlockEntityRegister() .registerBlockEntity("drillblockentity", DrillBlockEntity::new, DRILL); + public static final BlockEntityType BLOCKSTACKER_BLOCKENTITY = new BlockEntityRegister() + .registerBlockEntity("blockstackerentity", BlockStackerEntity::new, STACKER); private static final Block registerBlock(String name, Properties properties) { return QuicklyBlocks.registerBlock(name, properties, p -> new Block(p)); @@ -95,6 +98,7 @@ public class QuicklyBlocks { block.accept(MONSTERHOARDER); block.accept(ITEMHOARDER); block.accept(DRILL); + block.accept(STACKER); }); } } diff --git a/src/main/java/de/jottyfan/minecraft/blockentity/BlockStackerEntity.java b/src/main/java/de/jottyfan/minecraft/blockentity/BlockStackerEntity.java new file mode 100644 index 0000000..dcc780a --- /dev/null +++ b/src/main/java/de/jottyfan/minecraft/blockentity/BlockStackerEntity.java @@ -0,0 +1,168 @@ +package de.jottyfan.minecraft.blockentity; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import org.jspecify.annotations.Nullable; + +import com.mojang.serialization.Codec; + +import de.jottyfan.minecraft.Quickly; +import de.jottyfan.minecraft.block.BlockStacker; +import de.jottyfan.minecraft.block.QuicklyBlocks; +import net.minecraft.core.BlockPos; +import net.minecraft.world.Container; +import net.minecraft.world.entity.SlotAccess; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.entity.BaseContainerBlockEntity; +import net.minecraft.world.level.block.entity.BlockEntity; +import net.minecraft.world.level.block.state.BlockState; + +/** + * + * @author jotty + * + */ +public class BlockStackerEntity extends BlockEntity implements Container { + + public static final Codec> ITEM_STACK_MAP_CODEC = Codec.unboundedMap(Codec.STRING, + ItemStack.CODEC); + + private List inventory = new ArrayList<>(); + + public BlockStackerEntity(BlockPos pos, BlockState blockState) { + super(QuicklyBlocks.BLOCKSTACKER_BLOCKENTITY, pos, blockState); + } + + public static Object tick(Level level, BlockPos pos, BlockState state, T entity) { + pos.below(); + BlockStacker block = (BlockStacker) state.getBlock(); + BlockEntity source = level.getBlockEntity(pos.offset(block.getOffset(state, BlockStacker.SOURCE))); + BlockEntity dest = level.getBlockEntity(pos.offset(block.getOffset(state, BlockStacker.DEST))); + Boolean sourceIsLootable = source instanceof BaseContainerBlockEntity; + Boolean destIsLootable = dest instanceof BaseContainerBlockEntity; + if (sourceIsLootable && destIsLootable) { + BaseContainerBlockEntity lootableSource = (BaseContainerBlockEntity) source; + BaseContainerBlockEntity lootableDest = (BaseContainerBlockEntity) dest; + transferOneStack(lootableSource, lootableDest); + } + return null; + } + + public static final Boolean transferOneStack(BaseContainerBlockEntity source, BaseContainerBlockEntity dest) { + Boolean result = false; + Integer sourceSlot = findItemStackPos(source, false); + if (sourceSlot != null && !Items.AIR.equals(source.getSlot(sourceSlot).get().getItem())) { + ItemStack sourceStack = source.getSlot(sourceSlot).get(); + Integer destSlot = findItemStackPos(dest, sourceStack); + if (destSlot != null) { + ItemStack destStack = dest.getSlot(destSlot).get(); + Integer occupied = destStack.getCount(); + Integer free = destStack.getCount() - occupied; + Integer candidates = sourceStack.getCount(); + Integer travellers = candidates > free ? free : candidates; + if (travellers > 0) { + Quickly.LOGGER.debug("transfer {}/{} of {} from slot {} to slot {} on top of {} ones", travellers, candidates, + sourceStack.getItem().toString(), sourceSlot, destSlot, occupied); + sourceStack.shrink(travellers); + destStack.grow(travellers); + result = true; + } + } else { + Integer destFreeSlot = findItemStackPos(dest, true); + if (destFreeSlot != null) { + Quickly.LOGGER.debug("transfer all of {} from slot {} to slot {}", sourceStack.getItem().toString(), + sourceSlot, destSlot); + dest.setItem(destFreeSlot, new ItemStack(sourceStack.getItem(), sourceStack.getCount())); + sourceStack.shrink(sourceSlot); + result = true; + } + } + } + return result; + } + + private static final Integer findItemStackPos(BaseContainerBlockEntity blockEntity, ItemStack sourceStack) { + Integer counter = blockEntity.getContainerSize(); + while (counter > 0) { + counter--; + @Nullable + SlotAccess slotAccess = blockEntity.getSlot(counter); + if (slotAccess != null) { + ItemStack stack = slotAccess.get(); + if (sourceStack.getItem().equals(stack.getItem())) { + if (stack.getCount() < stack.getCount()) { + return counter; + } + } + } + } + return null; + } + + private static final Integer findItemStackPos(BaseContainerBlockEntity blockEntity, Boolean empty) { + Integer counter = blockEntity.getContainerSize(); + while (counter > 0) { + counter--; + @Nullable + SlotAccess slotAccess = blockEntity.getSlot(counter); + if (slotAccess != null) { + ItemStack stack = slotAccess.get(); + if (empty.equals(ItemStack.EMPTY.equals(stack))) { + return counter; + } + } + } + return null; + } + + @Override + public void clearContent() { + inventory.clear(); + } + + @Override + public int getContainerSize() { + return inventory.size(); + } + + @Override + public boolean isEmpty() { + return false; + } + + @Override + public ItemStack getItem(int slot) { + return inventory.get(slot); + } + + @Override + public ItemStack removeItem(int slot, int count) { + ItemStack stack = inventory.get(slot); + stack.shrink(count); + setChanged(); + return stack; + } + + @Override + public ItemStack removeItemNoUpdate(int slot) { + ItemStack stack = inventory.get(slot); + stack.shrink(stack.getCount()); + return stack; + } + + @Override + public void setItem(int slot, ItemStack itemStack) { + inventory.set(slot, itemStack); + setChanged(); + } + + @Override + public boolean stillValid(Player player) { + return false; + } +} diff --git a/src/main/resources/assets/quickly/blockstates/blockstacker.json b/src/main/resources/assets/quickly/blockstates/blockstacker.json new file mode 100644 index 0000000..954ce9e --- /dev/null +++ b/src/main/resources/assets/quickly/blockstates/blockstacker.json @@ -0,0 +1,10 @@ +{ + "variants": { + "dest=up": { "model": "quickly:block/blockstackerup" }, + "dest=down": { "model": "quickly:block/blockstackerdown" }, + "dest=east": { "model": "quickly:block/blockstackereast" }, + "dest=south": { "model": "quickly:block/blockstackersouth" }, + "dest=west": { "model": "quickly:block/blockstackerwest" }, + "dest=north": { "model": "quickly:block/blockstackernorth" } + } +} diff --git a/src/main/resources/assets/quickly/items/drilleast.json b/src/main/resources/assets/quickly/items/blockstacker.json similarity index 53% rename from src/main/resources/assets/quickly/items/drilleast.json rename to src/main/resources/assets/quickly/items/blockstacker.json index f75faf3..c6679dd 100644 --- a/src/main/resources/assets/quickly/items/drilleast.json +++ b/src/main/resources/assets/quickly/items/blockstacker.json @@ -1,6 +1,6 @@ { "model": { "type": "minecraft:model", - "model": "quickly:block/drilleast" + "model": "quickly:block/blockstackerdown" } } \ No newline at end of file diff --git a/src/main/resources/assets/quickly/items/drillnorth.json b/src/main/resources/assets/quickly/items/drillnorth.json deleted file mode 100644 index 764cc6a..0000000 --- a/src/main/resources/assets/quickly/items/drillnorth.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "model": { - "type": "minecraft:model", - "model": "quickly:block/drillnorth" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/quickly/items/drillsouth.json b/src/main/resources/assets/quickly/items/drillsouth.json deleted file mode 100644 index b43952a..0000000 --- a/src/main/resources/assets/quickly/items/drillsouth.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "model": { - "type": "minecraft:model", - "model": "quickly:block/drillsouth" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/quickly/items/drillwest.json b/src/main/resources/assets/quickly/items/drillwest.json deleted file mode 100644 index c304011..0000000 --- a/src/main/resources/assets/quickly/items/drillwest.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "model": { - "type": "minecraft:model", - "model": "quickly:block/drillwest" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/quickly/lang/de_de.json b/src/main/resources/assets/quickly/lang/de_de.json index 2f77633..5a267ad 100644 --- a/src/main/resources/assets/quickly/lang/de_de.json +++ b/src/main/resources/assets/quickly/lang/de_de.json @@ -6,6 +6,7 @@ "item.quickly.blockcottonplant": "Baumwollpflanze", "item.quickly.blockquickiepowder": "Eilpulverblock", "item.quickly.blockspeedpowder": "Fluchtpulverblock", + "item.quickly.blockstacker": "Stapler", "item.quickly.blockturquoise": "Türkisblock", "item.quickly.canola": "Raps", "item.quickly.canolabottle": "Rapsöl", diff --git a/src/main/resources/assets/quickly/lang/en_us.json b/src/main/resources/assets/quickly/lang/en_us.json index 35972b8..98bf0d3 100644 --- a/src/main/resources/assets/quickly/lang/en_us.json +++ b/src/main/resources/assets/quickly/lang/en_us.json @@ -6,6 +6,7 @@ "item.quickly.blockcottonplant": "cotton plant", "item.quickly.blockquickiepowder": "quickie powder block", "item.quickly.blockspeedpowder": "speed powder block", + "item.quickly.blockstacker": "stacker", "item.quickly.blockturquoise": "block of turquoise", "item.quickly.canola": "canola", "item.quickly.canolabottle": "canola oil", diff --git a/src/main/resources/assets/quickly/models/block/blockstackerdown.json b/src/main/resources/assets/quickly/models/block/blockstackerdown.json new file mode 100644 index 0000000..5212c2e --- /dev/null +++ b/src/main/resources/assets/quickly/models/block/blockstackerdown.json @@ -0,0 +1,8 @@ +{ + "parent": "minecraft:block/cube_bottom_top", + "textures": { + "bottom": "quickly:block/blockstackerout", + "side": "quickly:block/blockstackerdown", + "top": "quickly:block/blockstackerin" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickly/models/block/blockstackereast.json b/src/main/resources/assets/quickly/models/block/blockstackereast.json new file mode 100644 index 0000000..1af2d4a --- /dev/null +++ b/src/main/resources/assets/quickly/models/block/blockstackereast.json @@ -0,0 +1,11 @@ +{ + "parent": "block/cube_directional", + "textures": { + "up": "quickly:block/blockstackerright", + "down": "quickly:block/blockstackerleft", + "north": "quickly:block/blockstackerleft", + "east": "quickly:block/blockstackerout", + "south": "quickly:block/blockstackerright", + "west": "quickly:block/blockstackerin" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickly/models/block/blockstackernorth.json b/src/main/resources/assets/quickly/models/block/blockstackernorth.json new file mode 100644 index 0000000..c7db1ac --- /dev/null +++ b/src/main/resources/assets/quickly/models/block/blockstackernorth.json @@ -0,0 +1,11 @@ +{ + "parent": "block/cube_directional", + "textures": { + "up": "quickly:block/blockstackerup", + "down": "quickly:block/blockstackerup", + "north": "quickly:block/blockstackerout", + "east": "quickly:block/blockstackerup", + "south": "quickly:block/blockstackerin", + "west": "quickly:block/blockstackerup" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickly/models/block/blockstackersouth.json b/src/main/resources/assets/quickly/models/block/blockstackersouth.json new file mode 100644 index 0000000..146a849 --- /dev/null +++ b/src/main/resources/assets/quickly/models/block/blockstackersouth.json @@ -0,0 +1,11 @@ +{ + "parent": "block/cube_directional", + "textures": { + "up": "quickly:block/blockstackerdown", + "down": "quickly:block/blockstackerdown", + "north": "quickly:block/blockstackerin", + "east": "quickly:block/blockstackerdown", + "south": "quickly:block/blockstackerout", + "west": "quickly:block/blockstackerdown" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickly/models/block/blockstackerup.json b/src/main/resources/assets/quickly/models/block/blockstackerup.json new file mode 100644 index 0000000..097f32d --- /dev/null +++ b/src/main/resources/assets/quickly/models/block/blockstackerup.json @@ -0,0 +1,8 @@ +{ + "parent": "block/cube_bottom_top", + "textures": { + "bottom": "quickly:block/blockstackerin", + "side": "quickly:block/blockstackerup", + "top": "quickly:block/blockstackerout" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickly/models/block/blockstackerwest.json b/src/main/resources/assets/quickly/models/block/blockstackerwest.json new file mode 100644 index 0000000..89541c5 --- /dev/null +++ b/src/main/resources/assets/quickly/models/block/blockstackerwest.json @@ -0,0 +1,11 @@ +{ + "parent": "block/cube_directional", + "textures": { + "up": "quickly:block/blockstackerleft", + "down": "quickly:block/blockstackerright", + "north": "quickly:block/blockstackerright", + "east": "quickly:block/blockstackerin", + "south": "quickly:block/blockstackerleft", + "west": "quickly:block/blockstackerout" + } +} \ No newline at end of file diff --git a/src/main/resources/assets/quickly/models/item/blockstacker.json b/src/main/resources/assets/quickly/models/item/blockstacker.json new file mode 100644 index 0000000..909df1e --- /dev/null +++ b/src/main/resources/assets/quickly/models/item/blockstacker.json @@ -0,0 +1,10 @@ +{ + "parent": "quickly: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/quickly/textures/block/blockstackerdown.png b/src/main/resources/assets/quickly/textures/block/blockstackerdown.png new file mode 100644 index 0000000..558ce81 Binary files /dev/null and b/src/main/resources/assets/quickly/textures/block/blockstackerdown.png differ diff --git a/src/main/resources/assets/quickly/textures/block/blockstackerin.png b/src/main/resources/assets/quickly/textures/block/blockstackerin.png new file mode 100644 index 0000000..a9b29e2 Binary files /dev/null and b/src/main/resources/assets/quickly/textures/block/blockstackerin.png differ diff --git a/src/main/resources/assets/quickly/textures/block/blockstackerleft.png b/src/main/resources/assets/quickly/textures/block/blockstackerleft.png new file mode 100644 index 0000000..fb5e280 Binary files /dev/null and b/src/main/resources/assets/quickly/textures/block/blockstackerleft.png differ diff --git a/src/main/resources/assets/quickly/textures/block/blockstackerout.png b/src/main/resources/assets/quickly/textures/block/blockstackerout.png new file mode 100644 index 0000000..45febea Binary files /dev/null and b/src/main/resources/assets/quickly/textures/block/blockstackerout.png differ diff --git a/src/main/resources/assets/quickly/textures/block/blockstackerright.png b/src/main/resources/assets/quickly/textures/block/blockstackerright.png new file mode 100644 index 0000000..6395790 Binary files /dev/null and b/src/main/resources/assets/quickly/textures/block/blockstackerright.png differ diff --git a/src/main/resources/assets/quickly/textures/block/blockstackerup.png b/src/main/resources/assets/quickly/textures/block/blockstackerup.png new file mode 100644 index 0000000..3adebd0 Binary files /dev/null and b/src/main/resources/assets/quickly/textures/block/blockstackerup.png differ diff --git a/src/main/resources/data/quickly/recipe/shaped_blockstacker.json b/src/main/resources/data/quickly/recipe/shaped_blockstacker.json new file mode 100644 index 0000000..7f6ff4d --- /dev/null +++ b/src/main/resources/data/quickly/recipe/shaped_blockstacker.json @@ -0,0 +1,19 @@ +{ + "type": "minecraft:crafting_shaped", + "pattern": [ + "s s", + "scs", + " s " + ], + "key": { + "s": "quickky:speedingot", + "c": [ + "minecraft:chest", + "minecraft:barrel" + ] + }, + "result": { + "id": "quickly:blockstacker", + "count": 4 + } +} \ No newline at end of file