basic block stacker, but still with bugs
This commit is contained in:
84
src/main/java/de/jottyfan/minecraft/block/BlockStacker.java
Normal file
84
src/main/java/de/jottyfan/minecraft/block/BlockStacker.java
Normal file
@@ -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<BlockStacker> CODEC = simpleCodec(BlockStacker::new);
|
||||
|
||||
public static final EnumProperty<Direction> SOURCE = EnumProperty.create("source", Direction.class, Direction.NORTH,
|
||||
Direction.EAST, Direction.SOUTH, Direction.WEST, Direction.UP, Direction.DOWN);
|
||||
public static final EnumProperty<Direction> 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<Block, BlockState> 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 <T extends BlockEntity> @Nullable BlockEntityTicker<T> getTicker(Level level, BlockState blockState,
|
||||
BlockEntityType<T> 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<BlockStacker> 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<Direction> 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;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -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<DrillBlockEntity> BLOCKENTITY_DRILL = new BlockEntityRegister<DrillBlockEntity>()
|
||||
.registerBlockEntity("drillblockentity", DrillBlockEntity::new, DRILL);
|
||||
public static final BlockEntityType<BlockStackerEntity> BLOCKSTACKER_BLOCKENTITY = new BlockEntityRegister<BlockStackerEntity>()
|
||||
.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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Map<String, ItemStack>> ITEM_STACK_MAP_CODEC = Codec.unboundedMap(Codec.STRING,
|
||||
ItemStack.CODEC);
|
||||
|
||||
private List<ItemStack> inventory = new ArrayList<>();
|
||||
|
||||
public BlockStackerEntity(BlockPos pos, BlockState blockState) {
|
||||
super(QuicklyBlocks.BLOCKSTACKER_BLOCKENTITY, pos, blockState);
|
||||
}
|
||||
|
||||
public static <T extends BlockEntity> 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user