added drill

This commit is contained in:
Jottyfan
2025-12-31 15:39:38 +01:00
parent 50dc4e142d
commit 97faed5b4c
24 changed files with 540 additions and 2 deletions

View File

@@ -0,0 +1,135 @@
package de.jottyfan.minecraft.block;
import java.util.HashMap;
import java.util.Map;
import org.jspecify.annotations.Nullable;
import com.mojang.serialization.MapCodec;
import de.jottyfan.minecraft.blockentity.DrillBlockEntity;
import de.jottyfan.minecraft.item.QuicklyItems;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
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.item.Items;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
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.FallingBlock;
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.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.phys.BlockHitResult;
/**
*
* @author jotty
*
*/
public class BlockDrill extends FallingBlock implements EntityBlock {
public static final MapCodec<BlockDrill> CODEC = simpleCodec(BlockDrill::new);
private static final Integer MAX_FUEL = 255;
public static final IntegerProperty FUEL = IntegerProperty.create("fuel", 0, MAX_FUEL);
public static final EnumProperty<Direction> FACING = BlockStateProperties.FACING;
public BlockDrill(Properties properties) {
super(properties.strength(0.5f));
registerDefaultState(stateDefinition.any().setValue(FUEL, 0).setValue(FACING, Direction.DOWN));
}
@Override
protected void createBlockStateDefinition(Builder<Block, BlockState> builder) {
builder.add(FUEL, FACING);
}
@Override
public BlockState getStateForPlacement(BlockPlaceContext context) {
return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection());
}
@Override
public BlockEntity newBlockEntity(BlockPos pos, BlockState blockState) {
return new DrillBlockEntity(pos, blockState);
}
@Override
public <T extends BlockEntity> @Nullable BlockEntityTicker<T> getTicker(Level level, BlockState blockState,
BlockEntityType<T> type) {
return (world1, pos, state1, be) -> DrillBlockEntity.tick(world1, pos, state1, be);
}
@Override
protected void spawnAfterBreak(BlockState state, ServerLevel level, BlockPos pos, ItemStack tool,
boolean dropExperience) {
Integer fuelLeft = state.getValue(FUEL) / 8; // 8 fuel is one bottle
level.addFreshEntity(
new ItemEntity(level, pos.getX(), pos.getY(), pos.getZ(), new ItemStack(QuicklyItems.CANOLABOTTLE, fuelLeft)));
level.addFreshEntity(new ItemEntity(level, pos.getX(), pos.getY(), pos.getZ(), new ItemStack(QuicklyBlocks.DRILL)));
}
@Override
protected InteractionResult useItemOn(ItemStack itemStack, BlockState state, Level level, BlockPos pos, Player player,
InteractionHand hand, BlockHitResult hitResult) {
Map<Item, Integer> loadings = new HashMap<>();
loadings.put(QuicklyItems.CANOLABOTTLE, 8);
loadings.put(QuicklyItems.CANOLABOTTLESTACK, 72);
Item item = itemStack.getItem();
if (itemStack.isEmpty()) {
if (!level.isClientSide() && player instanceof ServerPlayer serverPlayer) {
serverPlayer.sendSystemMessage(Component.translatable("info.block.drillfuel", state.getValue(FUEL)), false);
}
} else if (QuicklyItems.COPPERSTICK.equals(item)) {
Direction newDirection = hitResult.getDirection();
newDirection = newDirection.equals(Direction.UP) ? Direction.DOWN : newDirection;
Integer fuelLeft = state.getValue(FUEL);
level.addFreshEntity(
new ItemEntity(level, pos.getX(), pos.getY(), pos.getZ(), new ItemStack(QuicklyItems.CANOLABOTTLE, fuelLeft)));
level.setBlockAndUpdate(pos, QuicklyBlocks.DRILL.defaultBlockState().setValue(FACING, newDirection));
} else if (loadings.containsKey(item)) {
Integer fuelWeight = loadings.get(item);
if (fuelWeight != null) {
Integer load = MAX_FUEL - state.getValue(FUEL);
if (load < fuelWeight) {
fuelWeight = load;
}
level.setBlockAndUpdate(pos, state.setValue(FUEL, state.getValue(FUEL) + fuelWeight));
if (item.equals(QuicklyItems.CANOLABOTTLE)) {
level.addFreshEntity(
new ItemEntity(level, pos.getX(), pos.getY(), pos.getZ(), new ItemStack(Items.GLASS_BOTTLE, 1)));
} else if (item.equals(QuicklyItems.CANOLABOTTLESTACK)) {
level.addFreshEntity(
new ItemEntity(level, pos.getX(), pos.getY(), pos.getZ(), new ItemStack(Items.GLASS_BOTTLE, 9)));
}
player.getActiveItem().shrink(1);
}
}
return InteractionResult.SUCCESS;
}
@Override
protected MapCodec<? extends FallingBlock> codec() {
return CODEC;
}
@Override
public int getDustColor(BlockState blockState, BlockGetter level, BlockPos pos) {
return 0;
}
}

View File

@@ -3,6 +3,7 @@ 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.DrillBlockEntity;
import de.jottyfan.minecraft.blockentity.ItemHoarderBlockEntity; 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;
@@ -55,12 +56,14 @@ public class QuicklyBlocks {
public static final Block MONSTERHOARDER = registerBlock("monsterhoarder", public static final Block MONSTERHOARDER = registerBlock("monsterhoarder",
properties -> new Monsterhoarder(properties)); properties -> new Monsterhoarder(properties));
public static final Block ITEMHOARDER = registerBlock("itemhoarder", properties -> new Itemhoarder(properties)); public static final Block ITEMHOARDER = registerBlock("itemhoarder", properties -> new Itemhoarder(properties));
public static final Block DRILL = registerBlock("drill", properties -> new BlockDrill(properties));
// TODO: drill, blockstacker // TODO: add blockstacker
// TODO: salpeter ore, sulfor ore // TODO: add salpeter ore, sulfor ore
// TODO: merge lavahoarder and emptylavahoarder into one block using a BooleanProperty for the lava fill state // TODO: merge lavahoarder and emptylavahoarder into one block using a BooleanProperty for the lava fill state
public static final BlockEntityType<ItemHoarderBlockEntity> BLOCKENTITY_ITEMHOARDER = (BlockEntityType<ItemHoarderBlockEntity>) registerBlockEntity("itemhoarderblockentity", ItemHoarderBlockEntity::new, ITEMHOARDER); public static final BlockEntityType<ItemHoarderBlockEntity> BLOCKENTITY_ITEMHOARDER = (BlockEntityType<ItemHoarderBlockEntity>) registerBlockEntity("itemhoarderblockentity", ItemHoarderBlockEntity::new, ITEMHOARDER);
public static final BlockEntityType<DrillBlockEntity> BLOCKENTITY_DRILL = (BlockEntityType<DrillBlockEntity>) registerBlockEntity("drillblockentity", DrillBlockEntity::new, DRILL);
private static final BlockEntityType<? extends BlockEntity> registerBlockEntity(String name, Factory<? extends BlockEntity> factory, Block block) { private static final BlockEntityType<? extends BlockEntity> registerBlockEntity(String name, Factory<? extends BlockEntity> factory, Block block) {
return Registry.register( return Registry.register(
@@ -99,6 +102,7 @@ public class QuicklyBlocks {
block.accept(QUICKIEPOWDER); block.accept(QUICKIEPOWDER);
block.accept(MONSTERHOARDER); block.accept(MONSTERHOARDER);
block.accept(ITEMHOARDER); block.accept(ITEMHOARDER);
block.accept(DRILL);
}); });
} }
} }

View File

@@ -0,0 +1,142 @@
package de.jottyfan.minecraft.blockentity;
import java.util.ArrayList;
import java.util.List;
import de.jottyfan.minecraft.block.BlockDrill;
import de.jottyfan.minecraft.block.QuicklyBlocks;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
/**
*
* @author jotty
*
*/
public class DrillBlockEntity extends BlockEntity {
private static final Integer MAXDRILLSTEP = 20;
private Integer drillstep;
private final Integer maxDrillStep;
public DrillBlockEntity(BlockPos pos, BlockState state) {
super(QuicklyBlocks.BLOCKENTITY_DRILL, pos, state);
this.maxDrillStep = MAXDRILLSTEP;
}
public static void tick(Level level, BlockPos pos, BlockState state, BlockEntity be) {
if (be instanceof DrillBlockEntity dbe) {
Direction dir = state.getValue(BlockDrill.FACING);
List<BlockPos> list = new ArrayList<>();
if (Direction.DOWN.equals(dir)) {
list = downFrom(pos);
} else if (Direction.EAST.equals(dir)) {
list = directedFrom(pos.east());
} else if (Direction.SOUTH.equals(dir)) {
list = directedFrom(pos.south());
} else if (Direction.WEST.equals(dir)) {
list = directedFrom(pos.west());
} else if (Direction.NORTH.equals(dir)) {
list = directedFrom(pos.north());
}
DrillBlockEntity.tick(level, pos, state, dbe, MAXDRILLSTEP, list);
}
}
public static final List<BlockPos> directedFrom(BlockPos pos) {
List<BlockPos> list = new ArrayList<>();
list.add(pos);
list.add(pos.above());
list.add(pos.above(2));
list.add(pos.above(3));
list.add(pos.below()); // must be last position
return list;
}
public static final List<BlockPos> downFrom(BlockPos pos) {
List<BlockPos> list = new ArrayList<>();
Integer tracesMod = pos.getY() % 8;
tracesMod = tracesMod < 0 ? tracesMod * -1 : tracesMod; // lower that 0 makes it negative
if (tracesMod != 0) {
list.add(pos.north());
}
if (tracesMod != 1) {
list.add(pos.north().west());
}
if (tracesMod != 2) {
list.add(pos.west());
}
if (tracesMod != 3) {
list.add(pos.south().west());
}
if (tracesMod != 4) {
list.add(pos.south());
}
if (tracesMod != 5) {
list.add(pos.south().east());
}
if (tracesMod != 6) {
list.add(pos.east());
}
if (tracesMod != 7) {
list.add(pos.north().east());
}
list.add(pos.below()); // must be last position
return list;
}
protected static final void moveBlockWithEntity(BlockPos from, BlockPos to, Level level) {
BlockEntity be = level.getBlockEntity(from);
BlockState bs = level.getBlockState(from);
if (be != null) {
level.setBlockAndUpdate(from, Blocks.AIR.defaultBlockState());
Integer newFuel = bs.getValue(BlockDrill.FUEL) - 1;
level.setBlockAndUpdate(to, bs.setValue(BlockDrill.FUEL, newFuel));
level.removeBlockEntity(from);
}
}
protected static final Boolean drill(BlockPos pos, List<BlockPos> toList, Level level) {
Boolean lastSuccess = false;
for (BlockPos to : toList) {
if (!level.getBlockState(to).is(Blocks.BEDROCK)) {
level.destroyBlock(to, true);
lastSuccess = pos.below() != to; // no need for the falling one
} else {
lastSuccess = false; // in case that the last one is a bedrock
}
}
return lastSuccess;
}
public static void tick(Level level, BlockPos pos, BlockState state, DrillBlockEntity be, Integer maxDrillStep,
List<BlockPos> drillPosition) {
if (state.getValue(BlockDrill.FUEL) > 0) {
if (be.getDrillstep() < 1) {
be.setDrillstep(maxDrillStep);
if (drill(pos, drillPosition, level)) {
moveBlockWithEntity(pos, drillPosition.get(drillPosition.size() - 1), level);
}
} else {
be.doDrillstep();
}
}
}
public void doDrillstep() {
setDrillstep(getDrillstep() - 1);
}
public Integer getDrillstep() {
return drillstep == null ? maxDrillStep : drillstep;
}
public void setDrillstep(Integer drillstep) {
this.drillstep = drillstep;
}
}

View File

@@ -0,0 +1,10 @@
{
"variants": {
"facing=up": { "model": "quickly:block/drill" },
"facing=down": { "model": "quickly:block/drill" },
"facing=east": { "model": "quickly:block/drilleast" },
"facing=south": { "model": "quickly:block/drillsouth" },
"facing=west": { "model": "quickly:block/drillwest" },
"facing=north": { "model": "quickly:block/drillnorth" }
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,5 @@
{ {
"info.block.drillfuel": "Ladung: %s Bohrungen",
"info.block.itemhoarder": "enthält: %s", "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",
@@ -16,6 +17,7 @@
"item.quickly.copperstub": "Kupferstummel", "item.quickly.copperstub": "Kupferstummel",
"item.quickly.cotton": "Baumwolle", "item.quickly.cotton": "Baumwolle",
"item.quickly.cottonseed": "Baumwollsaat", "item.quickly.cottonseed": "Baumwollsaat",
"item.quickly.drill": "Bohrer",
"item.quickly.emptylavahoarder": "Lavasauger", "item.quickly.emptylavahoarder": "Lavasauger",
"item.quickly.itemhoarder": "Itemsauger", "item.quickly.itemhoarder": "Itemsauger",
"item.quickly.kelpbundle": "Seegrassbündel", "item.quickly.kelpbundle": "Seegrassbündel",

View File

@@ -1,4 +1,5 @@
{ {
"info.block.drillfuel": "Load: %s drills",
"info.block.itemhoarder": "contains: %s", "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",
@@ -16,6 +17,7 @@
"item.quickly.copperstub": "copper stub", "item.quickly.copperstub": "copper stub",
"item.quickly.cotton": "cotton", "item.quickly.cotton": "cotton",
"item.quickly.cottonseed": "cotton seed", "item.quickly.cottonseed": "cotton seed",
"item.quickly.drill": "drill",
"item.quickly.emptylavahoarder": "lava hoarder", "item.quickly.emptylavahoarder": "lava hoarder",
"item.quickly.itemhoarder": "item hoarder", "item.quickly.itemhoarder": "item hoarder",
"item.quickly.kelpbundle": "kelp bundle", "item.quickly.kelpbundle": "kelp bundle",

View File

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

View File

@@ -0,0 +1,45 @@
{
"parent": "block/cube",
"textures": {
"bottom": "quickly:block/drilleast",
"all": "quickly:block/drill"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 16, 16],
"faces": {
"down": {
"uv": [0, 0, 16, 16],
"texture": "#bottom",
"cullface": "down"
},
"up": {
"uv": [0, 0, 16, 16],
"texture": "#bottom",
"cullface": "up"
},
"north": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "north"
},
"south": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "south"
},
"east": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "east"
},
"west": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "west"
}
}
}
]
}

View File

@@ -0,0 +1,45 @@
{
"parent": "block/cube",
"textures": {
"bottom": "quickly:block/drillnorth",
"all": "quickly:block/drill"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 16, 16],
"faces": {
"down": {
"uv": [0, 0, 16, 16],
"texture": "#bottom",
"cullface": "down"
},
"up": {
"uv": [0, 0, 16, 16],
"texture": "#bottom",
"cullface": "up"
},
"north": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "north"
},
"south": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "south"
},
"east": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "east"
},
"west": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "west"
}
}
}
]
}

View File

@@ -0,0 +1,45 @@
{
"parent": "block/cube",
"textures": {
"bottom": "quickly:block/drillsouth",
"all": "quickly:block/drill"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 16, 16],
"faces": {
"down": {
"uv": [0, 0, 16, 16],
"texture": "#bottom",
"cullface": "down"
},
"up": {
"uv": [0, 0, 16, 16],
"texture": "#bottom",
"cullface": "up"
},
"north": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "north"
},
"south": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "south"
},
"east": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "east"
},
"west": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "west"
}
}
}
]
}

View File

@@ -0,0 +1,45 @@
{
"parent": "block/cube",
"textures": {
"bottom": "quickly:block/drillwest",
"all": "quickly:block/drill"
},
"elements": [
{
"from": [0, 0, 0],
"to": [16, 16, 16],
"faces": {
"down": {
"uv": [0, 0, 16, 16],
"texture": "#bottom",
"cullface": "down"
},
"up": {
"uv": [0, 0, 16, 16],
"texture": "#bottom",
"cullface": "up"
},
"north": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "north"
},
"south": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "south"
},
"east": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "east"
},
"west": {
"uv": [0, 0, 16, 16],
"texture": "#all",
"cullface": "west"
}
}
}
]
}

View File

@@ -0,0 +1,10 @@
{
"parent": "quickly:block/drill",
"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: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -0,0 +1,17 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"qbq",
"dqd",
" d "
],
"key": {
"q": "quickly:quickieingot",
"d": "minecraft:diamond",
"b": "minecraft:barrel"
},
"result": {
"id": "quickly:drill",
"count": 1
}
}