itemhoarder sucks, but items get lost on harvesting block

This commit is contained in:
Jottyfan
2025-12-28 20:34:43 +01:00
parent 9ad284a95a
commit dc30a395f4
13 changed files with 315 additions and 16 deletions

View File

@@ -21,9 +21,9 @@ import net.minecraft.world.level.storage.loot.LootParams.Builder;
* @author jotty
*
*/
public class BlockEmptyLavahoarder extends Block {
public class EmptyLavahoarder extends Block {
public BlockEmptyLavahoarder(Properties properties) {
public EmptyLavahoarder(Properties properties) {
super(properties);
}
@@ -36,12 +36,12 @@ public class BlockEmptyLavahoarder extends Block {
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
boolean found = BlockLavahoarder.suckLava(level, pos.north());
found = found || BlockLavahoarder.suckLava(level, pos.south());
found = found || BlockLavahoarder.suckLava(level, pos.east());
found = found || BlockLavahoarder.suckLava(level, pos.west());
found = found || BlockLavahoarder.suckLava(level, pos.above());
found = found || BlockLavahoarder.suckLava(level, pos.below());
boolean found = Lavahoarder.suckLava(level, pos.north());
found = found || Lavahoarder.suckLava(level, pos.south());
found = found || Lavahoarder.suckLava(level, pos.east());
found = found || Lavahoarder.suckLava(level, pos.west());
found = found || Lavahoarder.suckLava(level, pos.above());
found = found || Lavahoarder.suckLava(level, pos.below());
if (found) {
level.setBlock(pos, QuicklyBlocks.LAVAHOARDER.defaultBlockState(), 2);
level.scheduleTick(pos, QuicklyBlocks.LAVAHOARDER, 1);
@@ -116,7 +116,7 @@ public class BlockEmptyLavahoarder extends Block {
}
}
if (count > 0) {
BlockLavahoarder.spawnRandomItems(level, pos.above(), count);
Lavahoarder.spawnRandomItems(level, pos.above(), count);
}
} else {
level.scheduleTick(pos, this, 1);

View File

@@ -0,0 +1,67 @@
package de.jottyfan.minecraft.block;
import java.util.ArrayList;
import java.util.List;
import org.jspecify.annotations.Nullable;
import de.jottyfan.minecraft.blockentity.ItemHoarderBlockEntity;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
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.storage.loot.LootParams.Builder;
/**
*
* @author jotty
*
*/
public class Itemhoarder extends Block implements EntityBlock {
public Itemhoarder(Properties properties) {
super(properties.strength(2.5f));
}
@Override
public @Nullable BlockEntity newBlockEntity(BlockPos pos, BlockState blockState) {
return new ItemHoarderBlockEntity(pos, blockState);
}
@Nullable
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level level, BlockState state,
BlockEntityType<T> type) {
return level.isClientSide() ? null : (lvl, pos, st, be) -> {
if (be instanceof ItemHoarderBlockEntity ihbe) {
ItemHoarderBlockEntity.tick(lvl, pos, st, ihbe);
}
};
}
@Override
protected List<ItemStack> getDrops(BlockState state, Builder params) {
List<ItemStack> list = new ArrayList<>();
list.add(new ItemStack(QuicklyBlocks.ITEMHOARDER));
return list;
}
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack tool,
boolean dropExperience) {
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof ItemHoarderBlockEntity) {
ItemHoarderBlockEntity ihbe = (ItemHoarderBlockEntity) blockEntity;
for (ItemStack stack : ihbe.getStacks().values()) {
level.addFreshEntity(new ItemEntity(level, pos.getX(), pos.getY(), pos.getZ(), stack));
}
}
}
}

View File

@@ -27,9 +27,9 @@ import net.minecraft.world.phys.BlockHitResult;
* @author jotty
*
*/
public class BlockLavahoarder extends Block {
public class Lavahoarder extends Block {
public BlockLavahoarder(Properties properties) {
public Lavahoarder(Properties properties) {
super(properties);
}

View File

@@ -31,7 +31,7 @@ import net.minecraft.world.ticks.ScheduledTick;
* @author jotty
*
*/
public class BlockMonsterhoarder extends Block {
public class Monsterhoarder extends Block {
private static final Integer MINSUCKRADIUS = 2;
private static final Integer MAXSUCKRADIUS = 20;
@@ -40,7 +40,7 @@ public class BlockMonsterhoarder extends Block {
private static final IntegerProperty SUCKRADIUS = IntegerProperty.create("suckradius", MINSUCKRADIUS, MAXSUCKRADIUS);
private static final IntegerProperty BURNTICKS = IntegerProperty.create("burnticks", MINBURNTICKS, MAXBURNTICKS);
public BlockMonsterhoarder(Properties properties) {
public Monsterhoarder(Properties properties) {
super(properties.strength(2.5f).lightLevel(state -> state.getValue(SUCKRADIUS)));
registerDefaultState(stateDefinition.any().setValue(SUCKRADIUS, MINSUCKRADIUS).setValue(BURNTICKS, MINBURNTICKS));
}

View File

@@ -3,9 +3,12 @@ package de.jottyfan.minecraft.block;
import java.util.function.Function;
import de.jottyfan.minecraft.Quickly;
import de.jottyfan.minecraft.blockentity.ItemHoarderBlockEntity;
import de.jottyfan.minecraft.item.QuicklyItems;
import de.jottyfan.minecraft.tab.QuicklyTab;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents;
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder.Factory;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries;
@@ -18,6 +21,8 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockBehaviour.Properties;
/**
@@ -40,15 +45,26 @@ public class QuicklyBlocks {
public static final Block CANOLAPLANT = registerBlock("blockcanolaplant", Properties.ofFullCopy(Blocks.WHEAT),
properties -> new BlockPlant(properties, "canolaseed", "canola"));
public static final Block LAVAHOARDER = registerBlock("lavahoarder",
Properties.of().strength(2.5f).lightLevel(state -> 15), properties -> new BlockLavahoarder(properties));
Properties.of().strength(2.5f).lightLevel(_ -> 15), properties -> new Lavahoarder(properties));
public static final Block EMPTYLAVAHOARDER = registerBlock("emptylavahoarder", Properties.of().strength(2.5f),
properties -> new BlockEmptyLavahoarder(properties));
properties -> new EmptyLavahoarder(properties));
public static final Block QUICKIEPOWDER = registerBlock("blockquickiepowder",
properties -> new BlockDrops(properties, new ItemStack(QuicklyItems.QUICKIEPOWDER, 9)));
public static final Block SPEEDPOWDER = registerBlock("blockspeedpowder",
properties -> new BlockDrops(properties, new ItemStack(QuicklyItems.SPEEDPOWDER, 9)));
public static final Block MONSTERHOARDER = registerBlock("monsterhoarder",
properties -> new BlockMonsterhoarder(properties));
properties -> new Monsterhoarder(properties));
public static final Block ITEMHOARDER = registerBlock("itemhoarder", properties -> new Itemhoarder(properties));
public static final BlockEntityType<ItemHoarderBlockEntity> BLOCKENTITY_ITEMHOARDER = (BlockEntityType<ItemHoarderBlockEntity>) registerBlockEntity("itemhoarderblockentity", ItemHoarderBlockEntity::new, ITEMHOARDER);
private static final BlockEntityType<? extends BlockEntity> registerBlockEntity(String name, Factory<? extends BlockEntity> factory, Block block) {
return Registry.register(
BuiltInRegistries.BLOCK_ENTITY_TYPE,
Identifier.fromNamespaceAndPath(Quickly.MOD_ID, name),
FabricBlockEntityTypeBuilder.create(factory, block).build()
);
}
private static final Block registerBlock(String name, Properties properties) {
return QuicklyBlocks.registerBlock(name, properties, p -> new Block(p));
@@ -78,6 +94,7 @@ public class QuicklyBlocks {
block.accept(SPEEDPOWDER);
block.accept(QUICKIEPOWDER);
block.accept(MONSTERHOARDER);
block.accept(ITEMHOARDER);
});
}
}

View File

@@ -0,0 +1,154 @@
package de.jottyfan.minecraft.blockentity;
import java.util.HashMap;
import java.util.Map;
import com.mojang.serialization.Codec;
import de.jottyfan.minecraft.Quickly;
import de.jottyfan.minecraft.block.QuicklyBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.world.Container;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
import net.minecraft.world.phys.AABB;
/**
*
* @author jotty
*
*/
public class ItemHoarderBlockEntity extends BlockEntity implements Container {
public static final Codec<Map<String, ItemStack>> ITEM_STACK_MAP_CODEC =
Codec.unboundedMap(Codec.STRING, ItemStack.CODEC);
private Map<String, ItemStack> stacks = new HashMap<>();
private static final Integer suckradius = 4;
public ItemHoarderBlockEntity(BlockPos pos, BlockState state) {
super(QuicklyBlocks.BLOCKENTITY_ITEMHOARDER, pos, state);
}
private static final String getItemId(Item item) {
return item.getName().getString();
}
public final static boolean setStackToSlots(ItemStack stack, Map<String, ItemStack> stacks) {
if (stack.isEmpty()) {
Quickly.LOGGER.info("FATAL!!! tried to set empty stack. Check your code!");
return false;
}
String key = getItemId(stack.getItem());
ItemStack s = stacks.get(key);
if (s == null) {
stacks.put(key, stack);
Quickly.LOGGER.info("stored {} x {}", stack.getCount(), key);
} else {
stacks.get(key).grow(stack.getCount());
Quickly.LOGGER.info("added {} x {}", stack.getCount(), key);
}
return true;
}
private static final void suck(Level level, BlockPos pos, ItemHoarderBlockEntity be) {
AABB checkArea = new AABB(pos).inflate(suckradius);
for (ItemEntity itemEntity : level.getEntitiesOfClass(ItemEntity.class, checkArea, Entity::isAlive)) {
ItemStack stack = itemEntity.getItem();
if (ItemHoarderBlockEntity.setStackToSlots(stack, be.getStacks())) {
itemEntity.discard();
}
}
}
private static final void dropToHopper(Level level, BlockPos pos, BlockState state, ItemHoarderBlockEntity be) {
// TODO: export by hopper
BlockEntity beBelow = level.getBlockEntity(pos.below());
if (beBelow instanceof Container targetInventory) {
// TODO: fill hopper beyond with item stack if space is left
}
}
public static void tick(Level level, BlockPos pos, BlockState state, ItemHoarderBlockEntity be) {
suck(level, pos, be);
dropToHopper(level, pos, state, be);
}
@Override
protected void saveAdditional(ValueOutput output) {
super.saveAdditional(output);
output.store("items", ITEM_STACK_MAP_CODEC, stacks);
}
@Override
protected void loadAdditional(ValueInput input) {
super.loadAdditional(input);
stacks.clear();
stacks.putAll(input.read("items", ITEM_STACK_MAP_CODEC).orElse(Map.of()));
}
public float getSuckradius() {
return suckradius;
}
@Override
public int getContainerSize() {
return stacks.size() + 1;
}
@Override
public boolean isEmpty() {
return stacks.isEmpty();
}
@Override
public ItemStack getItem(int slot) {
// buggy; do not use this. The map wants to have an item name instead
return ItemStack.EMPTY;
}
@Override
public ItemStack removeItem(int slot, int count) {
// buggy; do not use this. The map wants to have an item name instead
return ItemStack.EMPTY;
}
@Override
public ItemStack removeItemNoUpdate(int slot) {
// buggy; do not use this. The map wants to have an item name instead
return ItemStack.EMPTY;
}
@Override
public void setItem(int slot, ItemStack itemStack) {
if (slot < stacks.size()) {
stacks.get(itemStack.getItem().getName().getString()).grow(itemStack.getCount());
} else if (!itemStack.isEmpty()) {
stacks.put(itemStack.getItem().getName().getString(), itemStack);
}
setChanged();
}
@Override
public boolean stillValid(Player player) {
return true;
}
@Override
public void clearContent() {
stacks.clear();
setChanged();
}
public Map<String, ItemStack> getStacks() {
return stacks;
}
}

View File

@@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "quickly:block/itemhoarder"
}
}
}

View File

@@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "quickly:block/itemhoarder"
}
}

View File

@@ -0,0 +1,6 @@
{
"parent": "block/cube_all",
"textures": {
"all": "quickly:block/itemhoarder"
}
}

View File

@@ -0,0 +1,10 @@
{
"parent": "quickly:block/itemhoarder",
"display": {
"thirdperson": {
"rotation": [ 10, -45, 170 ],
"translation": [ 0, 1.5, -2.75 ],
"scale": [ 0.375, 0.375, 0.375 ]
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@@ -0,0 +1,16 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"ooo",
"obo",
"ooo"
],
"key": {
"o": "quickly:speedingot",
"b": "minecraft:barrel"
},
"result": {
"id": "quickly:itemhoarder",
"count": 1
}
}

View File

@@ -0,0 +1,16 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"ooo",
"oco",
"ooo"
],
"key": {
"o": "quickly:speedingot",
"c": "minecraft:chest"
},
"result": {
"id": "quickly:itemhoarder",
"count": 1
}
}