Compare commits

...

5 Commits

Author SHA1 Message Date
Jottyfan
84b3779af2 repaired hopper for itemhoarder 2025-12-30 19:19:03 +01:00
Jottyfan
0aa12478b4 corrected drops on destroyment of block 2025-12-30 18:58:49 +01:00
Jottyfan
cf33fa2474 show content the right way on right click 2025-12-30 18:51:40 +01:00
Jottyfan
e26eeb438e info about items in itemhoarder started 2025-12-29 08:31:57 +01:00
Jottyfan
dc30a395f4 itemhoarder sucks, but items get lost on harvesting block 2025-12-28 20:34:43 +01:00
15 changed files with 357 additions and 16 deletions

View File

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

View File

@@ -0,0 +1,89 @@
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.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
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;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.BlockHitResult;
/**
*
* @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 InteractionResult useWithoutItem(BlockState state, Level level, BlockPos pos, Player player,
BlockHitResult hitResult) {
MutableComponent message = Component.empty();
BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity instanceof ItemHoarderBlockEntity) {
ItemHoarderBlockEntity ihbe = (ItemHoarderBlockEntity) blockEntity;
for (ItemStack stack : ihbe.getStacks().values()) {
MutableComponent line = Component.literal(stack.getCount() + "x ").append(stack.getHoverName());
message.append(Component.literal("\n")).append(line);
}
}
Component complete = Component.translatable("info.block.itemhoarder", message);
if (player instanceof ServerPlayer serverPlayer) {
serverPlayer.displayClientMessage(complete, false);
}
return InteractionResult.SUCCESS;
}
@Override
protected List<ItemStack> getDrops(BlockState state, Builder builder) {
List<ItemStack> list = new ArrayList<>();
list.add(new ItemStack(QuicklyBlocks.ITEMHOARDER));
BlockEntity blockEntity = builder.getOptionalParameter(LootContextParams.BLOCK_ENTITY);
if (blockEntity instanceof ItemHoarderBlockEntity) {
ItemHoarderBlockEntity ihbe = (ItemHoarderBlockEntity) blockEntity;
for (ItemStack stack : ihbe.getStacks().values()) {
list.add(stack);
}
}
return list;
}
}

View File

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

View File

@@ -31,7 +31,7 @@ import net.minecraft.world.ticks.ScheduledTick;
* @author jotty * @author jotty
* *
*/ */
public class BlockMonsterhoarder extends Block { public class Monsterhoarder extends Block {
private static final Integer MINSUCKRADIUS = 2; private static final Integer MINSUCKRADIUS = 2;
private static final Integer MAXSUCKRADIUS = 20; 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 SUCKRADIUS = IntegerProperty.create("suckradius", MINSUCKRADIUS, MAXSUCKRADIUS);
private static final IntegerProperty BURNTICKS = IntegerProperty.create("burnticks", MINBURNTICKS, MAXBURNTICKS); 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))); super(properties.strength(2.5f).lightLevel(state -> state.getValue(SUCKRADIUS)));
registerDefaultState(stateDefinition.any().setValue(SUCKRADIUS, MINSUCKRADIUS).setValue(BURNTICKS, MINBURNTICKS)); 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 java.util.function.Function;
import de.jottyfan.minecraft.Quickly; import de.jottyfan.minecraft.Quickly;
import de.jottyfan.minecraft.blockentity.ItemHoarderBlockEntity;
import de.jottyfan.minecraft.item.QuicklyItems; import de.jottyfan.minecraft.item.QuicklyItems;
import de.jottyfan.minecraft.tab.QuicklyTab; import de.jottyfan.minecraft.tab.QuicklyTab;
import net.fabricmc.fabric.api.itemgroup.v1.ItemGroupEvents; 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.Registry;
import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.core.registries.Registries; 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.Block;
import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SoundType; 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; 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), public static final Block CANOLAPLANT = registerBlock("blockcanolaplant", Properties.ofFullCopy(Blocks.WHEAT),
properties -> new BlockPlant(properties, "canolaseed", "canola")); properties -> new BlockPlant(properties, "canolaseed", "canola"));
public static final Block LAVAHOARDER = registerBlock("lavahoarder", 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), 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", public static final Block QUICKIEPOWDER = registerBlock("blockquickiepowder",
properties -> new BlockDrops(properties, new ItemStack(QuicklyItems.QUICKIEPOWDER, 9))); properties -> new BlockDrops(properties, new ItemStack(QuicklyItems.QUICKIEPOWDER, 9)));
public static final Block SPEEDPOWDER = registerBlock("blockspeedpowder", public static final Block SPEEDPOWDER = registerBlock("blockspeedpowder",
properties -> new BlockDrops(properties, new ItemStack(QuicklyItems.SPEEDPOWDER, 9))); properties -> new BlockDrops(properties, new ItemStack(QuicklyItems.SPEEDPOWDER, 9)));
public static final Block MONSTERHOARDER = registerBlock("monsterhoarder", 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) { private static final Block registerBlock(String name, Properties properties) {
return QuicklyBlocks.registerBlock(name, properties, p -> new Block(p)); return QuicklyBlocks.registerBlock(name, properties, p -> new Block(p));
@@ -78,6 +94,7 @@ public class QuicklyBlocks {
block.accept(SPEEDPOWDER); block.accept(SPEEDPOWDER);
block.accept(QUICKIEPOWDER); block.accept(QUICKIEPOWDER);
block.accept(MONSTERHOARDER); block.accept(MONSTERHOARDER);
block.accept(ITEMHOARDER);
}); });
} }
} }

View File

@@ -0,0 +1,172 @@
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.core.Direction;
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.entity.HopperBlockEntity;
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);
} else {
stacks.get(key).grow(stack.getCount());
}
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 blockEntity) {
BlockEntity beBelow = level.getBlockEntity(pos.below());
if (beBelow instanceof Container targetInventory) {
for (String stackKey : blockEntity.getStacks().keySet()) {
ItemStack stackInSlot = blockEntity.getStack(stackKey);
if (!stackInSlot.isEmpty()) {
ItemStack toInsert = stackInSlot.copy();
int oldCount = toInsert.getCount();
ItemStack remainder = HopperBlockEntity.addItem(blockEntity, targetInventory, toInsert, Direction.UP);
int movedAmount = oldCount - remainder.getCount();
if (movedAmount > 0) {
stackInSlot.shrink(movedAmount);
blockEntity.setChanged();
targetInventory.setChanged();
return;
}
}
}
}
}
private ItemStack getStack(String stackKey) {
return stacks.get(stackKey);
}
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

@@ -1,4 +1,5 @@
{ {
"info.block.itemhoarder": "enthält: %s",
"info.block.monsterhoarder": "Radius: %s, Brenndauer: %s Ticks", "info.block.monsterhoarder": "Radius: %s, Brenndauer: %s Ticks",
"item.quickly.blockcanolaplant": "Rapspflanze", "item.quickly.blockcanolaplant": "Rapspflanze",
"item.quickly.blockcottonplant": "Baumwollpflanze", "item.quickly.blockcottonplant": "Baumwollpflanze",

View File

@@ -1,4 +1,5 @@
{ {
"info.block.itemhoarder": "contains: %s",
"info.block.monsterhoarder": "radius: %s, burn ticks: %s", "info.block.monsterhoarder": "radius: %s, burn ticks: %s",
"item.quickly.blockcanolaplant": "canola plant", "item.quickly.blockcanolaplant": "canola plant",
"item.quickly.blockcottonplant": "cotton plant", "item.quickly.blockcottonplant": "cotton plant",

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
}
}